1 /* $OpenBSD: net.c,v 1.20 2015/10/26 14:48:54 mmcc Exp $ */ 2 /* $NetBSD: net.c,v 1.14 1996/10/13 02:29:02 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1992 Regents of the University of California. 6 * All rights reserved. 7 * 8 * This software was developed by the Computer Systems Engineering group 9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10 * contributed to Berkeley. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Lawrence Berkeley Laboratory and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL) 41 */ 42 43 #include <sys/param.h> 44 #include <sys/socket.h> 45 46 #include <net/if.h> 47 #include <netinet/in.h> 48 49 #include <netinet/if_ether.h> 50 #include <netinet/ip.h> 51 #include <netinet/ip_var.h> 52 53 #include "stand.h" 54 #include "net.h" 55 56 /* 57 * Send a packet and wait for a reply, with exponential backoff. 58 * 59 * The send routine must return the actual number of bytes written. 60 * 61 * The receive routine can indicate success by returning the number of 62 * bytes read; it can return 0 to indicate EOF; it can return -1 with a 63 * non-zero errno to indicate failure; finally, it can return -1 with a 64 * zero errno to indicate it isn't done yet. 65 */ 66 ssize_t 67 sendrecv(struct iodesc *d, ssize_t (*sproc)(struct iodesc *, void *, size_t), 68 void *sbuf, size_t ssize, 69 ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t), 70 void *rbuf, size_t rsize) 71 { 72 ssize_t cc; 73 time_t t, tmo, tlast; 74 long tleft; 75 76 #ifdef NET_DEBUG 77 if (debug) 78 printf("sendrecv: called\n"); 79 #endif 80 81 tmo = MINTMO; 82 tlast = tleft = 0; 83 t = getsecs(); 84 for (;;) { 85 if (tleft <= 0) { 86 if (tmo >= MAXTMO) { 87 errno = ETIMEDOUT; 88 return -1; 89 } 90 cc = (*sproc)(d, sbuf, ssize); 91 if (cc < 0 || (size_t)cc < ssize) 92 panic("sendrecv: short write! (%d < %d)", 93 cc, ssize); 94 95 tleft = tmo; 96 tmo <<= 1; 97 if (tmo > MAXTMO) 98 tmo = MAXTMO; 99 tlast = t; 100 } 101 102 /* Try to get a packet and process it. */ 103 cc = (*rproc)(d, rbuf, rsize, tleft); 104 /* Return on data, EOF or real error. */ 105 if (cc != -1 || errno != 0) 106 return (cc); 107 108 /* Timed out or didn't get the packet we're waiting for */ 109 t = getsecs(); 110 tleft -= t - tlast; 111 tlast = t; 112 } 113 } 114 115 /* 116 * Like inet_addr() in the C library, but we only accept base-10. 117 * Return values are in network order. 118 */ 119 u_int32_t 120 inet_addr(const char *cp) 121 { 122 u_long val; 123 int n; 124 char c; 125 u_int parts[4]; 126 u_int *pp = parts; 127 128 for (;;) { 129 /* 130 * Collect number up to ``.''. 131 * Values are specified as for C: 132 * 0x=hex, 0=octal, other=decimal. 133 */ 134 val = 0; 135 while ((c = *cp) != '\0') { 136 if (c >= '0' && c <= '9') { 137 val = (val * 10) + (c - '0'); 138 cp++; 139 continue; 140 } 141 break; 142 } 143 if (*cp == '.') { 144 /* 145 * Internet format: 146 * a.b.c.d 147 * a.b.c (with c treated as 16-bits) 148 * a.b (with b treated as 24 bits) 149 */ 150 if (pp >= parts + 3 || val > 0xff) 151 goto bad; 152 *pp++ = val, cp++; 153 } else 154 break; 155 } 156 /* 157 * Check for trailing characters. 158 */ 159 if (*cp != '\0') 160 goto bad; 161 162 /* 163 * Concoct the address according to 164 * the number of parts specified. 165 */ 166 n = pp - parts + 1; 167 switch (n) { 168 169 case 1: /* a -- 32 bits */ 170 break; 171 172 case 2: /* a.b -- 8.24 bits */ 173 if (val > 0xffffff) 174 goto bad; 175 val |= parts[0] << 24; 176 break; 177 178 case 3: /* a.b.c -- 8.8.16 bits */ 179 if (val > 0xffff) 180 goto bad; 181 val |= (parts[0] << 24) | (parts[1] << 16); 182 break; 183 184 case 4: /* a.b.c.d -- 8.8.8.8 bits */ 185 if (val > 0xff) 186 goto bad; 187 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); 188 break; 189 } 190 191 return (htonl(val)); 192 bad: 193 return (htonl(INADDR_NONE)); 194 } 195 196 const char * 197 inet_ntoa(struct in_addr ia) 198 { 199 return (intoa(ia.s_addr)); 200 } 201 202 /* Similar to inet_ntoa() */ 203 const char * 204 intoa(u_int32_t addr) 205 { 206 char *cp; 207 u_int byte; 208 int n; 209 static char buf[sizeof(".255.255.255.255")]; 210 211 addr = ntohl(addr); 212 cp = &buf[sizeof buf]; 213 *--cp = '\0'; 214 215 n = 4; 216 do { 217 byte = addr & 0xff; 218 *--cp = byte % 10 + '0'; 219 byte /= 10; 220 if (byte > 0) { 221 *--cp = byte % 10 + '0'; 222 byte /= 10; 223 if (byte > 0) 224 *--cp = byte + '0'; 225 } 226 *--cp = '.'; 227 addr >>= 8; 228 } while (--n > 0); 229 230 return (cp+1); 231 } 232 233 static const char * 234 number(const char *s, int *n) 235 { 236 for (*n = 0; isdigit((unsigned char)*s); s++) 237 *n = (*n * 10) + *s - '0'; 238 return s; 239 } 240 241 u_int32_t 242 ip_convertaddr(const char *p) 243 { 244 #define IP_ANYADDR 0 245 u_int32_t addr = 0, n; 246 247 if (p == NULL || *p == '\0') 248 return IP_ANYADDR; 249 p = number(p, &n); 250 addr |= (n << 24) & 0xff000000; 251 if (*p == '\0' || *p++ != '.') 252 return IP_ANYADDR; 253 p = number(p, &n); 254 addr |= (n << 16) & 0xff0000; 255 if (*p == '\0' || *p++ != '.') 256 return IP_ANYADDR; 257 p = number(p, &n); 258 addr |= (n << 8) & 0xff00; 259 if (*p == '\0' || *p++ != '.') 260 return IP_ANYADDR; 261 p = number(p, &n); 262 addr |= n & 0xff; 263 if (*p != '\0') 264 return IP_ANYADDR; 265 266 return htonl(addr); 267 } 268