1 /* $OpenBSD: net.c,v 1.13 2003/08/11 06:23:09 deraadt 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/in.h> 50 #include <netinet/if_ether.h> 51 #include <netinet/in_systm.h> 52 #include <netinet/ip.h> 53 #include <netinet/ip_var.h> 54 #include <netinet/udp.h> 55 #include <netinet/udp_var.h> 56 57 #include "stand.h" 58 #include "net.h" 59 60 /* Caller must leave room for ethernet, ip and udp headers in front!! */ 61 ssize_t 62 sendudp(struct iodesc *d, void *pkt, size_t len) 63 { 64 ssize_t cc; 65 struct ip *ip; 66 struct udpiphdr *ui; 67 struct udphdr *uh; 68 u_char *ea; 69 struct ip tip; 70 71 #ifdef NET_DEBUG 72 if (debug) { 73 printf("sendudp: d=%x called.\n", (u_int)d); 74 if (d) { 75 printf("saddr: %s:%d", 76 inet_ntoa(d->myip), ntohs(d->myport)); 77 printf(" daddr: %s:%d\n", 78 inet_ntoa(d->destip), ntohs(d->destport)); 79 } 80 } 81 #endif 82 83 uh = (struct udphdr *)pkt - 1; 84 ip = (struct ip *)uh - 1; 85 len += sizeof(*ip) + sizeof(*uh); 86 87 bzero(ip, sizeof(*ip) + sizeof(*uh)); 88 89 ip->ip_v = IPVERSION; /* half-char */ 90 ip->ip_hl = sizeof(*ip) >> 2; /* half-char */ 91 ip->ip_len = htons(len); 92 ip->ip_p = IPPROTO_UDP; /* char */ 93 ip->ip_ttl = IP_TTL; /* char */ 94 ip->ip_src = d->myip; 95 ip->ip_dst = d->destip; 96 ip->ip_sum = in_cksum(ip, sizeof(*ip)); /* short, but special */ 97 98 uh->uh_sport = d->myport; 99 uh->uh_dport = d->destport; 100 uh->uh_ulen = htons(len - sizeof(*ip)); 101 102 /* Calculate checksum (must save and restore ip header) */ 103 tip = *ip; 104 ui = (struct udpiphdr *)ip; 105 bzero(ui->ui_x1, sizeof(ui->ui_x1)); 106 ui->ui_len = uh->uh_ulen; 107 uh->uh_sum = in_cksum(ui, len); 108 *ip = tip; 109 110 if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 || 111 netmask == 0 || SAMENET(ip->ip_src, ip->ip_dst, netmask)) 112 ea = arpwhohas(d, ip->ip_dst); 113 else 114 ea = arpwhohas(d, gateip); 115 116 cc = sendether(d, ip, len, ea, ETHERTYPE_IP); 117 if (cc < 0) 118 return (-1); 119 if ((size_t)cc != len) 120 panic("sendudp: bad write (%d != %d)", cc, len); 121 return (cc - (sizeof(*ip) + sizeof(*uh))); 122 } 123 124 /* 125 * Receive a UDP packet and validate it is for us. 126 * Caller leaves room for the headers (Ether, IP, UDP) 127 */ 128 ssize_t 129 readudp(struct iodesc *d, void *pkt, size_t len, time_t tleft) 130 { 131 ssize_t n; 132 size_t hlen; 133 struct ip *ip; 134 struct udphdr *uh; 135 struct udpiphdr *ui; 136 struct ip tip; 137 u_int16_t etype; /* host order */ 138 139 #ifdef NET_DEBUG 140 if (debug) 141 printf("readudp: called\n"); 142 #endif 143 144 uh = (struct udphdr *)pkt - 1; 145 ip = (struct ip *)uh - 1; 146 147 n = readether(d, ip, len + sizeof(*ip) + sizeof(*uh), tleft, &etype); 148 if (n < 0 || (size_t)n < sizeof(*ip) + sizeof(*uh)) 149 return -1; 150 151 /* Ethernet address checks now in readether() */ 152 153 /* Need to respond to ARP requests. */ 154 if (etype == ETHERTYPE_ARP) { 155 struct arphdr *ah = (void *)ip; 156 if (ah->ar_op == htons(ARPOP_REQUEST)) { 157 /* Send ARP reply */ 158 arp_reply(d, ah); 159 } 160 return -1; 161 } 162 163 if (etype != ETHERTYPE_IP) { 164 #ifdef NET_DEBUG 165 if (debug) 166 printf("readudp: not IP. ether_type=%x\n", etype); 167 #endif 168 return -1; 169 } 170 171 /* Check ip header */ 172 if (ip->ip_v != IPVERSION || 173 ip->ip_p != IPPROTO_UDP) { /* half char */ 174 #ifdef NET_DEBUG 175 if (debug) 176 printf("readudp: IP version or not UDP. ip_v=%d ip_p=%d\n", ip->ip_v, ip->ip_p); 177 #endif 178 return -1; 179 } 180 181 hlen = ip->ip_hl << 2; 182 if (hlen < sizeof(*ip) || 183 in_cksum(ip, hlen) != 0) { 184 #ifdef NET_DEBUG 185 if (debug) 186 printf("readudp: short hdr or bad cksum.\n"); 187 #endif 188 return -1; 189 } 190 NTOHS(ip->ip_len); 191 if (n < ip->ip_len) { 192 #ifdef NET_DEBUG 193 if (debug) 194 printf("readudp: bad length %d < %d.\n", n, ip->ip_len); 195 #endif 196 return -1; 197 } 198 if (d->myip.s_addr && ip->ip_dst.s_addr != d->myip.s_addr) { 199 #ifdef NET_DEBUG 200 if (debug) { 201 printf("readudp: bad saddr %s != ", inet_ntoa(d->myip)); 202 printf("%s\n", inet_ntoa(ip->ip_dst)); 203 } 204 #endif 205 return -1; 206 } 207 208 /* If there were ip options, make them go away */ 209 if (hlen != sizeof(*ip)) { 210 bcopy(((u_char *)ip) + hlen, uh, len - hlen); 211 ip->ip_len = sizeof(*ip); 212 n -= hlen - sizeof(*ip); 213 } 214 if (uh->uh_dport != d->myport) { 215 #ifdef NET_DEBUG 216 if (debug) 217 printf("readudp: bad dport %d != %d\n", 218 d->myport, ntohs(uh->uh_dport)); 219 #endif 220 return -1; 221 } 222 223 if (uh->uh_sum) { 224 n = ntohs(uh->uh_ulen) + sizeof(*ip); 225 if (n > RECV_SIZE - ETHER_SIZE) { 226 printf("readudp: huge packet, udp len %ld\n", (long)n); 227 return -1; 228 } 229 230 /* Check checksum (must save and restore ip header) */ 231 tip = *ip; 232 ui = (struct udpiphdr *)ip; 233 bzero(ui->ui_x1, sizeof(ui->ui_x1)); 234 ui->ui_len = uh->uh_ulen; 235 if (in_cksum(ui, n) != 0) { 236 #ifdef NET_DEBUG 237 if (debug) 238 printf("readudp: bad cksum\n"); 239 #endif 240 *ip = tip; 241 return -1; 242 } 243 *ip = tip; 244 } 245 NTOHS(uh->uh_dport); 246 NTOHS(uh->uh_sport); 247 NTOHS(uh->uh_ulen); 248 if (uh->uh_ulen < sizeof(*uh)) { 249 #ifdef NET_DEBUG 250 if (debug) 251 printf("readudp: bad udp len %d < %d\n", 252 uh->uh_ulen, sizeof(*uh)); 253 #endif 254 return -1; 255 } 256 257 n -= sizeof(*ip) + sizeof(*uh); 258 return (n); 259 } 260 261 /* 262 * Send a packet and wait for a reply, with exponential backoff. 263 * 264 * The send routine must return the actual number of bytes written. 265 * 266 * The receive routine can indicate success by returning the number of 267 * bytes read; it can return 0 to indicate EOF; it can return -1 with a 268 * non-zero errno to indicate failure; finally, it can return -1 with a 269 * zero errno to indicate it isn't done yet. 270 */ 271 ssize_t 272 sendrecv(struct iodesc *d, ssize_t (*sproc)(struct iodesc *, void *, size_t), 273 void *sbuf, size_t ssize, 274 ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t), 275 void *rbuf, size_t rsize) 276 { 277 ssize_t cc; 278 time_t t, tmo, tlast; 279 long tleft; 280 281 #ifdef NET_DEBUG 282 if (debug) 283 printf("sendrecv: called\n"); 284 #endif 285 286 tmo = MINTMO; 287 tlast = tleft = 0; 288 t = getsecs(); 289 for (;;) { 290 if (tleft <= 0) { 291 if (tmo >= MAXTMO) { 292 errno = ETIMEDOUT; 293 return -1; 294 } 295 cc = (*sproc)(d, sbuf, ssize); 296 if (cc < 0 || (size_t)cc < ssize) 297 panic("sendrecv: short write! (%d < %d)", 298 cc, ssize); 299 300 tleft = tmo; 301 tmo <<= 1; 302 if (tmo > MAXTMO) 303 tmo = MAXTMO; 304 tlast = t; 305 } 306 307 /* Try to get a packet and process it. */ 308 cc = (*rproc)(d, rbuf, rsize, tleft); 309 /* Return on data, EOF or real error. */ 310 if (cc != -1 || errno != 0) 311 return (cc); 312 313 /* Timed out or didn't get the packet we're waiting for */ 314 t = getsecs(); 315 tleft -= t - tlast; 316 tlast = t; 317 } 318 } 319 320 /* 321 * Like inet_addr() in the C library, but we only accept base-10. 322 * Return values are in network order. 323 */ 324 n_long 325 inet_addr(char *cp) 326 { 327 u_long val; 328 int n; 329 char c; 330 u_int parts[4]; 331 u_int *pp = parts; 332 333 for (;;) { 334 /* 335 * Collect number up to ``.''. 336 * Values are specified as for C: 337 * 0x=hex, 0=octal, other=decimal. 338 */ 339 val = 0; 340 while ((c = *cp) != '\0') { 341 if (c >= '0' && c <= '9') { 342 val = (val * 10) + (c - '0'); 343 cp++; 344 continue; 345 } 346 break; 347 } 348 if (*cp == '.') { 349 /* 350 * Internet format: 351 * a.b.c.d 352 * a.b.c (with c treated as 16-bits) 353 * a.b (with b treated as 24 bits) 354 */ 355 if (pp >= parts + 3 || val > 0xff) 356 goto bad; 357 *pp++ = val, cp++; 358 } else 359 break; 360 } 361 /* 362 * Check for trailing characters. 363 */ 364 if (*cp != '\0') 365 goto bad; 366 367 /* 368 * Concoct the address according to 369 * the number of parts specified. 370 */ 371 n = pp - parts + 1; 372 switch (n) { 373 374 case 1: /* a -- 32 bits */ 375 break; 376 377 case 2: /* a.b -- 8.24 bits */ 378 if (val > 0xffffff) 379 goto bad; 380 val |= parts[0] << 24; 381 break; 382 383 case 3: /* a.b.c -- 8.8.16 bits */ 384 if (val > 0xffff) 385 goto bad; 386 val |= (parts[0] << 24) | (parts[1] << 16); 387 break; 388 389 case 4: /* a.b.c.d -- 8.8.8.8 bits */ 390 if (val > 0xff) 391 goto bad; 392 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); 393 break; 394 } 395 396 return (htonl(val)); 397 bad: 398 return (htonl(INADDR_NONE)); 399 } 400 401 char * 402 inet_ntoa(struct in_addr ia) 403 { 404 return (intoa(ia.s_addr)); 405 } 406 407 /* Similar to inet_ntoa() */ 408 char * 409 intoa(n_long addr) 410 { 411 char *cp; 412 u_int byte; 413 int n; 414 static char buf[sizeof(".255.255.255.255")]; 415 416 NTOHL(addr); 417 cp = &buf[sizeof buf]; 418 *--cp = '\0'; 419 420 n = 4; 421 do { 422 byte = addr & 0xff; 423 *--cp = byte % 10 + '0'; 424 byte /= 10; 425 if (byte > 0) { 426 *--cp = byte % 10 + '0'; 427 byte /= 10; 428 if (byte > 0) 429 *--cp = byte + '0'; 430 } 431 *--cp = '.'; 432 addr >>= 8; 433 } while (--n > 0); 434 435 return (cp+1); 436 } 437 438 static char * 439 number(char *s, int *n) 440 { 441 for (*n = 0; isdigit(*s); s++) 442 *n = (*n * 10) + *s - '0'; 443 return s; 444 } 445 446 n_long 447 ip_convertaddr(char *p) 448 { 449 #define IP_ANYADDR 0 450 n_long addr = 0, n; 451 452 if (p == (char *)0 || *p == '\0') 453 return IP_ANYADDR; 454 p = number(p, &n); 455 addr |= (n << 24) & 0xff000000; 456 if (*p == '\0' || *p++ != '.') 457 return IP_ANYADDR; 458 p = number(p, &n); 459 addr |= (n << 16) & 0xff0000; 460 if (*p == '\0' || *p++ != '.') 461 return IP_ANYADDR; 462 p = number(p, &n); 463 addr |= (n << 8) & 0xff00; 464 if (*p == '\0' || *p++ != '.') 465 return IP_ANYADDR; 466 p = number(p, &n); 467 addr |= n & 0xff; 468 if (*p != '\0') 469 return IP_ANYADDR; 470 471 return htonl(addr); 472 } 473