1 /* 2 * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)ip_input.c 7.14 (Berkeley) 09/20/89 18 */ 19 20 #include "param.h" 21 #include "systm.h" 22 #include "malloc.h" 23 #include "mbuf.h" 24 #include "domain.h" 25 #include "protosw.h" 26 #include "socket.h" 27 #include "errno.h" 28 #include "time.h" 29 #include "kernel.h" 30 31 #include "../net/if.h" 32 #include "../net/route.h" 33 34 #include "in.h" 35 #include "in_pcb.h" 36 #include "in_systm.h" 37 #include "in_var.h" 38 #include "ip.h" 39 #include "ip_var.h" 40 #include "ip_icmp.h" 41 #include "tcp.h" 42 43 #ifndef IPFORWARDING 44 #ifdef GATEWAY 45 #define IPFORWARDING 1 46 #else /* GATEWAY */ 47 #define IPFORWARDING 0 48 #endif /* GATEWAY */ 49 #endif /* IPFORWARDING */ 50 #ifndef IPSENDREDIRECTS 51 #define IPSENDREDIRECTS 1 52 #endif 53 int ipprintfs = 0; 54 int ipforwarding = IPFORWARDING; 55 extern int in_interfaces; 56 int ipsendredirects = IPSENDREDIRECTS; 57 58 u_char ip_protox[IPPROTO_MAX]; 59 int ipqmaxlen = IFQ_MAXLEN; 60 struct in_ifaddr *in_ifaddr; /* first inet address */ 61 62 /* 63 * We need to save the IP options in case a protocol wants to respond 64 * to an incoming packet over the same route if the packet got here 65 * using IP source routing. This allows connection establishment and 66 * maintenance when the remote end is on a network that is not known 67 * to us. 68 */ 69 int ip_nhops = 0; 70 static struct ip_srcrt { 71 struct in_addr dst; /* final destination */ 72 char nop; /* one NOP to align */ 73 char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */ 74 struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)]; 75 } ip_srcrt; 76 77 /* 78 * IP initialization: fill in IP protocol switch table. 79 * All protocols not implemented in kernel go to raw IP protocol handler. 80 */ 81 ip_init() 82 { 83 register struct protosw *pr; 84 register int i; 85 86 pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); 87 if (pr == 0) 88 panic("ip_init"); 89 for (i = 0; i < IPPROTO_MAX; i++) 90 ip_protox[i] = pr - inetsw; 91 for (pr = inetdomain.dom_protosw; 92 pr < inetdomain.dom_protoswNPROTOSW; pr++) 93 if (pr->pr_domain->dom_family == PF_INET && 94 pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) 95 ip_protox[pr->pr_protocol] = pr - inetsw; 96 ipq.next = ipq.prev = &ipq; 97 ip_id = time.tv_sec & 0xffff; 98 ipintrq.ifq_maxlen = ipqmaxlen; 99 } 100 101 struct ip *ip_reass(); 102 struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; 103 struct route ipforward_rt; 104 105 /* 106 * Ip input routine. Checksum and byte swap header. If fragmented 107 * try to reassamble. If complete and fragment queue exists, discard. 108 * Process options. Pass to next level. 109 */ 110 ipintr() 111 { 112 register struct ip *ip; 113 register struct mbuf *m; 114 register struct ipq *fp; 115 register struct in_ifaddr *ia; 116 int hlen, s; 117 118 next: 119 /* 120 * Get next datagram off input queue and get IP header 121 * in first mbuf. 122 */ 123 s = splimp(); 124 IF_DEQUEUE(&ipintrq, m); 125 splx(s); 126 if (m == 0) 127 return; 128 if ((m->m_flags & M_PKTHDR) == 0) 129 panic("ipintr no HDR"); 130 /* 131 * If no IP addresses have been set yet but the interfaces 132 * are receiving, can't do anything with incoming packets yet. 133 */ 134 if (in_ifaddr == NULL) 135 goto bad; 136 ipstat.ips_total++; 137 if ((m->m_flags & M_EXT || m->m_len < sizeof (struct ip)) && 138 (m = m_pullup(m, sizeof (struct ip))) == 0) { 139 ipstat.ips_toosmall++; 140 goto next; 141 } 142 ip = mtod(m, struct ip *); 143 hlen = ip->ip_hl << 2; 144 if (hlen < sizeof(struct ip)) { /* minimum header length */ 145 ipstat.ips_badhlen++; 146 goto bad; 147 } 148 if (hlen > m->m_len) { 149 if ((m = m_pullup(m, hlen)) == 0) { 150 ipstat.ips_badhlen++; 151 goto next; 152 } 153 ip = mtod(m, struct ip *); 154 } 155 if (ip->ip_sum = in_cksum(m, hlen)) { 156 ipstat.ips_badsum++; 157 goto bad; 158 } 159 160 /* 161 * Convert fields to host representation. 162 */ 163 ip->ip_len = ntohs((u_short)ip->ip_len); 164 if (ip->ip_len < hlen) { 165 ipstat.ips_badlen++; 166 goto bad; 167 } 168 ip->ip_id = ntohs(ip->ip_id); 169 ip->ip_off = ntohs((u_short)ip->ip_off); 170 171 /* 172 * Check that the amount of data in the buffers 173 * is as at least much as the IP header would have us expect. 174 * Trim mbufs if longer than we expect. 175 * Drop packet if shorter than we expect. 176 */ 177 if (m->m_pkthdr.len < ip->ip_len) { 178 ipstat.ips_tooshort++; 179 goto bad; 180 } 181 if (m->m_pkthdr.len > ip->ip_len) { 182 if (m->m_len == m->m_pkthdr.len) { 183 m->m_len = ip->ip_len; 184 m->m_pkthdr.len = ip->ip_len; 185 } else 186 m_adj(m, ip->ip_len - m->m_pkthdr.len); 187 } 188 189 /* 190 * Process options and, if not destined for us, 191 * ship it on. ip_dooptions returns 1 when an 192 * error was detected (causing an icmp message 193 * to be sent and the original packet to be freed). 194 */ 195 ip_nhops = 0; /* for source routed packets */ 196 if (hlen > sizeof (struct ip) && ip_dooptions(m)) 197 goto next; 198 199 /* 200 * Check our list of addresses, to see if the packet is for us. 201 */ 202 for (ia = in_ifaddr; ia; ia = ia->ia_next) { 203 #define satosin(sa) ((struct sockaddr_in *)(sa)) 204 205 if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr) 206 goto ours; 207 if ( 208 #ifdef DIRECTED_BROADCAST 209 ia->ia_ifp == m->m_pkthdr.rcvif && 210 #endif 211 (ia->ia_ifp->if_flags & IFF_BROADCAST)) { 212 u_long t; 213 214 if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == 215 ip->ip_dst.s_addr) 216 goto ours; 217 if (ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr) 218 goto ours; 219 /* 220 * Look for all-0's host part (old broadcast addr), 221 * either for subnet or net. 222 */ 223 t = ntohl(ip->ip_dst.s_addr); 224 if (t == ia->ia_subnet) 225 goto ours; 226 if (t == ia->ia_net) 227 goto ours; 228 } 229 } 230 if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST) 231 goto ours; 232 if (ip->ip_dst.s_addr == INADDR_ANY) 233 goto ours; 234 235 /* 236 * Not for us; forward if possible and desirable. 237 */ 238 if (ipforwarding == 0 239 #ifndef GATEWAY 240 || in_interfaces <= 1 241 #endif 242 ) { 243 ipstat.ips_cantforward++; 244 m_freem(m); 245 } else 246 ip_forward(m); 247 goto next; 248 249 ours: 250 /* 251 * If offset or IP_MF are set, must reassemble. 252 * Otherwise, nothing need be done. 253 * (We could look in the reassembly queue to see 254 * if the packet was previously fragmented, 255 * but it's not worth the time; just let them time out.) 256 */ 257 if (ip->ip_off &~ IP_DF) { 258 /* 259 * Look for queue of fragments 260 * of this datagram. 261 */ 262 for (fp = ipq.next; fp != &ipq; fp = fp->next) 263 if (ip->ip_id == fp->ipq_id && 264 ip->ip_src.s_addr == fp->ipq_src.s_addr && 265 ip->ip_dst.s_addr == fp->ipq_dst.s_addr && 266 ip->ip_p == fp->ipq_p) 267 goto found; 268 fp = 0; 269 found: 270 271 /* 272 * Adjust ip_len to not reflect header, 273 * set ip_mff if more fragments are expected, 274 * convert offset of this to bytes. 275 */ 276 ip->ip_len -= hlen; 277 ((struct ipasfrag *)ip)->ipf_mff = 0; 278 if (ip->ip_off & IP_MF) 279 ((struct ipasfrag *)ip)->ipf_mff = 1; 280 ip->ip_off <<= 3; 281 282 /* 283 * If datagram marked as having more fragments 284 * or if this is not the first fragment, 285 * attempt reassembly; if it succeeds, proceed. 286 */ 287 if (((struct ipasfrag *)ip)->ipf_mff || ip->ip_off) { 288 ipstat.ips_fragments++; 289 ip = ip_reass((struct ipasfrag *)ip, fp); 290 if (ip == 0) 291 goto next; 292 else 293 ipstat.ips_reassembled++; 294 m = dtom(ip); 295 } else 296 if (fp) 297 ip_freef(fp); 298 } else 299 ip->ip_len -= hlen; 300 301 /* 302 * Switch out to protocol's input routine. 303 */ 304 ipstat.ips_delivered++; 305 (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen); 306 goto next; 307 bad: 308 m_freem(m); 309 goto next; 310 } 311 312 /* 313 * Take incoming datagram fragment and try to 314 * reassemble it into whole datagram. If a chain for 315 * reassembly of this datagram already exists, then it 316 * is given as fp; otherwise have to make a chain. 317 */ 318 struct ip * 319 ip_reass(ip, fp) 320 register struct ipasfrag *ip; 321 register struct ipq *fp; 322 { 323 register struct mbuf *m = dtom(ip); 324 register struct ipasfrag *q; 325 struct mbuf *t; 326 int hlen = ip->ip_hl << 2; 327 int i, next; 328 329 /* 330 * Presence of header sizes in mbufs 331 * would confuse code below. 332 */ 333 m->m_data += hlen; 334 m->m_len -= hlen; 335 336 /* 337 * If first fragment to arrive, create a reassembly queue. 338 */ 339 if (fp == 0) { 340 if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL) 341 goto dropfrag; 342 fp = mtod(t, struct ipq *); 343 insque(fp, &ipq); 344 fp->ipq_ttl = IPFRAGTTL; 345 fp->ipq_p = ip->ip_p; 346 fp->ipq_id = ip->ip_id; 347 fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)fp; 348 fp->ipq_src = ((struct ip *)ip)->ip_src; 349 fp->ipq_dst = ((struct ip *)ip)->ip_dst; 350 q = (struct ipasfrag *)fp; 351 goto insert; 352 } 353 354 /* 355 * Find a segment which begins after this one does. 356 */ 357 for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) 358 if (q->ip_off > ip->ip_off) 359 break; 360 361 /* 362 * If there is a preceding segment, it may provide some of 363 * our data already. If so, drop the data from the incoming 364 * segment. If it provides all of our data, drop us. 365 */ 366 if (q->ipf_prev != (struct ipasfrag *)fp) { 367 i = q->ipf_prev->ip_off + q->ipf_prev->ip_len - ip->ip_off; 368 if (i > 0) { 369 if (i >= ip->ip_len) 370 goto dropfrag; 371 m_adj(dtom(ip), i); 372 ip->ip_off += i; 373 ip->ip_len -= i; 374 } 375 } 376 377 /* 378 * While we overlap succeeding segments trim them or, 379 * if they are completely covered, dequeue them. 380 */ 381 while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) { 382 i = (ip->ip_off + ip->ip_len) - q->ip_off; 383 if (i < q->ip_len) { 384 q->ip_len -= i; 385 q->ip_off += i; 386 m_adj(dtom(q), i); 387 break; 388 } 389 q = q->ipf_next; 390 m_freem(dtom(q->ipf_prev)); 391 ip_deq(q->ipf_prev); 392 } 393 394 insert: 395 /* 396 * Stick new segment in its place; 397 * check for complete reassembly. 398 */ 399 ip_enq(ip, q->ipf_prev); 400 next = 0; 401 for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) { 402 if (q->ip_off != next) 403 return (0); 404 next += q->ip_len; 405 } 406 if (q->ipf_prev->ipf_mff) 407 return (0); 408 409 /* 410 * Reassembly is complete; concatenate fragments. 411 */ 412 q = fp->ipq_next; 413 m = dtom(q); 414 t = m->m_next; 415 m->m_next = 0; 416 m_cat(m, t); 417 q = q->ipf_next; 418 while (q != (struct ipasfrag *)fp) { 419 t = dtom(q); 420 q = q->ipf_next; 421 m_cat(m, t); 422 } 423 424 /* 425 * Create header for new ip packet by 426 * modifying header of first packet; 427 * dequeue and discard fragment reassembly header. 428 * Make header visible. 429 */ 430 ip = fp->ipq_next; 431 ip->ip_len = next; 432 ((struct ip *)ip)->ip_src = fp->ipq_src; 433 ((struct ip *)ip)->ip_dst = fp->ipq_dst; 434 remque(fp); 435 (void) m_free(dtom(fp)); 436 m = dtom(ip); 437 m->m_len += (ip->ip_hl << 2); 438 m->m_data -= (ip->ip_hl << 2); 439 return ((struct ip *)ip); 440 441 dropfrag: 442 ipstat.ips_fragdropped++; 443 m_freem(m); 444 return (0); 445 } 446 447 /* 448 * Free a fragment reassembly header and all 449 * associated datagrams. 450 */ 451 ip_freef(fp) 452 struct ipq *fp; 453 { 454 register struct ipasfrag *q, *p; 455 456 for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = p) { 457 p = q->ipf_next; 458 ip_deq(q); 459 m_freem(dtom(q)); 460 } 461 remque(fp); 462 (void) m_free(dtom(fp)); 463 } 464 465 /* 466 * Put an ip fragment on a reassembly chain. 467 * Like insque, but pointers in middle of structure. 468 */ 469 ip_enq(p, prev) 470 register struct ipasfrag *p, *prev; 471 { 472 473 p->ipf_prev = prev; 474 p->ipf_next = prev->ipf_next; 475 prev->ipf_next->ipf_prev = p; 476 prev->ipf_next = p; 477 } 478 479 /* 480 * To ip_enq as remque is to insque. 481 */ 482 ip_deq(p) 483 register struct ipasfrag *p; 484 { 485 486 p->ipf_prev->ipf_next = p->ipf_next; 487 p->ipf_next->ipf_prev = p->ipf_prev; 488 } 489 490 /* 491 * IP timer processing; 492 * if a timer expires on a reassembly 493 * queue, discard it. 494 */ 495 ip_slowtimo() 496 { 497 register struct ipq *fp; 498 int s = splnet(); 499 500 fp = ipq.next; 501 if (fp == 0) { 502 splx(s); 503 return; 504 } 505 while (fp != &ipq) { 506 --fp->ipq_ttl; 507 fp = fp->next; 508 if (fp->prev->ipq_ttl == 0) { 509 ipstat.ips_fragtimeout++; 510 ip_freef(fp->prev); 511 } 512 } 513 splx(s); 514 } 515 516 /* 517 * Drain off all datagram fragments. 518 */ 519 ip_drain() 520 { 521 522 while (ipq.next != &ipq) { 523 ipstat.ips_fragdropped++; 524 ip_freef(ipq.next); 525 } 526 } 527 528 extern struct in_ifaddr *ifptoia(); 529 struct in_ifaddr *ip_rtaddr(); 530 531 /* 532 * Do option processing on a datagram, 533 * possibly discarding it if bad options 534 * are encountered. 535 */ 536 ip_dooptions(m) 537 struct mbuf *m; 538 { 539 register struct ip *ip = mtod(m, struct ip *); 540 register u_char *cp; 541 register struct ip_timestamp *ipt; 542 register struct in_ifaddr *ia; 543 int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; 544 struct in_addr *sin; 545 n_time ntime; 546 547 cp = (u_char *)(ip + 1); 548 cnt = (ip->ip_hl << 2) - sizeof (struct ip); 549 for (; cnt > 0; cnt -= optlen, cp += optlen) { 550 opt = cp[IPOPT_OPTVAL]; 551 if (opt == IPOPT_EOL) 552 break; 553 if (opt == IPOPT_NOP) 554 optlen = 1; 555 else { 556 optlen = cp[IPOPT_OLEN]; 557 if (optlen <= 0 || optlen > cnt) { 558 code = &cp[IPOPT_OLEN] - (u_char *)ip; 559 goto bad; 560 } 561 } 562 switch (opt) { 563 564 default: 565 break; 566 567 /* 568 * Source routing with record. 569 * Find interface with current destination address. 570 * If none on this machine then drop if strictly routed, 571 * or do nothing if loosely routed. 572 * Record interface address and bring up next address 573 * component. If strictly routed make sure next 574 * address on directly accessible net. 575 */ 576 case IPOPT_LSRR: 577 case IPOPT_SSRR: 578 if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { 579 code = &cp[IPOPT_OFFSET] - (u_char *)ip; 580 goto bad; 581 } 582 ipaddr.sin_addr = ip->ip_dst; 583 ia = (struct in_ifaddr *) 584 ifa_ifwithaddr((struct sockaddr *)&ipaddr); 585 if (ia == 0) { 586 if (opt == IPOPT_SSRR) { 587 type = ICMP_UNREACH; 588 code = ICMP_UNREACH_SRCFAIL; 589 goto bad; 590 } 591 /* 592 * Loose routing, and not at next destination 593 * yet; nothing to do except forward. 594 */ 595 break; 596 } 597 off--; /* 0 origin */ 598 if (off > optlen - sizeof(struct in_addr)) { 599 /* 600 * End of source route. Should be for us. 601 */ 602 save_rte(cp, ip->ip_src); 603 break; 604 } 605 /* 606 * locate outgoing interface 607 */ 608 bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, 609 sizeof(ipaddr.sin_addr)); 610 if ((opt == IPOPT_SSRR && 611 in_iaonnetof(in_netof(ipaddr.sin_addr)) == 0) || 612 (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { 613 type = ICMP_UNREACH; 614 code = ICMP_UNREACH_SRCFAIL; 615 goto bad; 616 } 617 ip->ip_dst = ipaddr.sin_addr; 618 bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), 619 (caddr_t)(cp + off), sizeof(struct in_addr)); 620 cp[IPOPT_OFFSET] += sizeof(struct in_addr); 621 forward = 1; 622 break; 623 624 case IPOPT_RR: 625 if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { 626 code = &cp[IPOPT_OFFSET] - (u_char *)ip; 627 goto bad; 628 } 629 /* 630 * If no space remains, ignore. 631 */ 632 off--; /* 0 origin */ 633 if (off > optlen - sizeof(struct in_addr)) 634 break; 635 bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr, 636 sizeof(ipaddr.sin_addr)); 637 /* 638 * locate outgoing interface; if we're the destination, 639 * use the incoming interface (should be same). 640 */ 641 if ((ia = 642 (struct in_ifaddr *)ifa_ifwithaddr( 643 (struct sockaddr *)&ipaddr)) == 0 && 644 (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { 645 type = ICMP_UNREACH; 646 code = ICMP_UNREACH_HOST; 647 goto bad; 648 } 649 bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), 650 (caddr_t)(cp + off), sizeof(struct in_addr)); 651 cp[IPOPT_OFFSET] += sizeof(struct in_addr); 652 break; 653 654 case IPOPT_TS: 655 code = cp - (u_char *)ip; 656 ipt = (struct ip_timestamp *)cp; 657 if (ipt->ipt_len < 5) 658 goto bad; 659 if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) { 660 if (++ipt->ipt_oflw == 0) 661 goto bad; 662 break; 663 } 664 sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); 665 switch (ipt->ipt_flg) { 666 667 case IPOPT_TS_TSONLY: 668 break; 669 670 case IPOPT_TS_TSANDADDR: 671 if (ipt->ipt_ptr + sizeof(n_time) + 672 sizeof(struct in_addr) > ipt->ipt_len) 673 goto bad; 674 ia = ifptoia(m->m_pkthdr.rcvif); 675 bcopy((caddr_t)&IA_SIN(ia)->sin_addr, 676 (caddr_t)sin, sizeof(struct in_addr)); 677 ipt->ipt_ptr += sizeof(struct in_addr); 678 break; 679 680 case IPOPT_TS_PRESPEC: 681 if (ipt->ipt_ptr + sizeof(n_time) + 682 sizeof(struct in_addr) > ipt->ipt_len) 683 goto bad; 684 bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr, 685 sizeof(struct in_addr)); 686 if (ifa_ifwithaddr((struct sockaddr *)&ipaddr) == 0) 687 continue; 688 ipt->ipt_ptr += sizeof(struct in_addr); 689 break; 690 691 default: 692 goto bad; 693 } 694 ntime = iptime(); 695 bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1, 696 sizeof(n_time)); 697 ipt->ipt_ptr += sizeof(n_time); 698 } 699 } 700 if (forward) { 701 ip_forward(m); 702 return (1); 703 } else 704 return (0); 705 bad: 706 icmp_error(m, type, code); 707 return (1); 708 } 709 710 /* 711 * Given address of next destination (final or next hop), 712 * return internet address info of interface to be used to get there. 713 */ 714 struct in_ifaddr * 715 ip_rtaddr(dst) 716 struct in_addr dst; 717 { 718 register struct sockaddr_in *sin; 719 register struct in_ifaddr *ia; 720 721 sin = (struct sockaddr_in *) &ipforward_rt.ro_dst; 722 723 if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) { 724 if (ipforward_rt.ro_rt) { 725 RTFREE(ipforward_rt.ro_rt); 726 ipforward_rt.ro_rt = 0; 727 } 728 sin->sin_family = AF_INET; 729 sin->sin_len = sizeof(*sin); 730 sin->sin_addr = dst; 731 732 rtalloc(&ipforward_rt); 733 } 734 if (ipforward_rt.ro_rt == 0) 735 return ((struct in_ifaddr *)0); 736 /* 737 * Find address associated with outgoing interface. 738 */ 739 for (ia = in_ifaddr; ia; ia = ia->ia_next) 740 if (ia->ia_ifp == ipforward_rt.ro_rt->rt_ifp) 741 break; 742 return (ia); 743 } 744 745 /* 746 * Save incoming source route for use in replies, 747 * to be picked up later by ip_srcroute if the receiver is interested. 748 */ 749 save_rte(option, dst) 750 u_char *option; 751 struct in_addr dst; 752 { 753 unsigned olen; 754 755 olen = option[IPOPT_OLEN]; 756 if (ipprintfs) 757 printf("save_rte: olen %d\n", olen); 758 if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst))) 759 return; 760 bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen); 761 ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr); 762 ip_srcrt.dst = dst; 763 } 764 765 /* 766 * Retrieve incoming source route for use in replies, 767 * in the same form used by setsockopt. 768 * The first hop is placed before the options, will be removed later. 769 */ 770 struct mbuf * 771 ip_srcroute() 772 { 773 register struct in_addr *p, *q; 774 register struct mbuf *m; 775 776 if (ip_nhops == 0) 777 return ((struct mbuf *)0); 778 m = m_get(M_DONTWAIT, MT_SOOPTS); 779 if (m == 0) 780 return ((struct mbuf *)0); 781 782 #define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt)) 783 784 /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */ 785 m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) + 786 OPTSIZ; 787 if (ipprintfs) 788 printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len); 789 790 /* 791 * First save first hop for return route 792 */ 793 p = &ip_srcrt.route[ip_nhops - 1]; 794 *(mtod(m, struct in_addr *)) = *p--; 795 if (ipprintfs) 796 printf(" hops %X", ntohl(*mtod(m, struct in_addr *))); 797 798 /* 799 * Copy option fields and padding (nop) to mbuf. 800 */ 801 ip_srcrt.nop = IPOPT_NOP; 802 ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF; 803 bcopy((caddr_t)&ip_srcrt.nop, 804 mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ); 805 q = (struct in_addr *)(mtod(m, caddr_t) + 806 sizeof(struct in_addr) + OPTSIZ); 807 #undef OPTSIZ 808 /* 809 * Record return path as an IP source route, 810 * reversing the path (pointers are now aligned). 811 */ 812 while (p >= ip_srcrt.route) { 813 if (ipprintfs) 814 printf(" %X", ntohl(*q)); 815 *q++ = *p--; 816 } 817 /* 818 * Last hop goes to final destination. 819 */ 820 *q = ip_srcrt.dst; 821 if (ipprintfs) 822 printf(" %X\n", ntohl(*q)); 823 return (m); 824 } 825 826 /* 827 * Strip out IP options, at higher 828 * level protocol in the kernel. 829 * Second argument is buffer to which options 830 * will be moved, and return value is their length. 831 * XXX should be deleted; last arg currently ignored. 832 */ 833 ip_stripoptions(m, mopt) 834 register struct mbuf *m; 835 struct mbuf *mopt; 836 { 837 register int i; 838 struct ip *ip = mtod(m, struct ip *); 839 register caddr_t opts; 840 int olen; 841 842 olen = (ip->ip_hl<<2) - sizeof (struct ip); 843 opts = (caddr_t)(ip + 1); 844 i = m->m_len - (sizeof (struct ip) + olen); 845 bcopy(opts + olen, opts, (unsigned)i); 846 m->m_len -= olen; 847 if (m->m_flags & M_PKTHDR) 848 m->m_pkthdr.len -= olen; 849 ip->ip_hl = sizeof(struct ip) >> 2; 850 } 851 852 u_char inetctlerrmap[PRC_NCMDS] = { 853 0, 0, 0, 0, 854 0, 0, EHOSTDOWN, EHOSTUNREACH, 855 ENETUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, 856 EMSGSIZE, EHOSTUNREACH, 0, 0, 857 0, 0, 0, 0, 858 ENOPROTOOPT 859 }; 860 861 /* 862 * Forward a packet. If some error occurs return the sender 863 * an icmp packet. Note we can't always generate a meaningful 864 * icmp message because icmp doesn't have a large enough repertoire 865 * of codes and types. 866 * 867 * If not forwarding (possibly because we have only a single external 868 * network), just drop the packet. This could be confusing if ipforwarding 869 * was zero but some routing protocol was advancing us as a gateway 870 * to somewhere. However, we must let the routing protocol deal with that. 871 */ 872 ip_forward(m) 873 struct mbuf *m; 874 { 875 register struct ip *ip = mtod(m, struct ip *); 876 register int error, type = 0, code; 877 register struct sockaddr_in *sin; 878 struct mbuf *mcopy; 879 struct in_addr dest; 880 881 dest.s_addr = 0; 882 if (ipprintfs) 883 printf("forward: src %x dst %x ttl %x\n", ip->ip_src, 884 ip->ip_dst, ip->ip_ttl); 885 if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) { 886 ipstat.ips_cantforward++; 887 m_freem(m); 888 return; 889 } 890 ip->ip_id = htons(ip->ip_id); 891 if (ip->ip_ttl <= IPTTLDEC) { 892 type = ICMP_TIMXCEED, code = ICMP_TIMXCEED_INTRANS; 893 goto sendicmp; 894 } 895 ip->ip_ttl -= IPTTLDEC; 896 897 /* 898 * Save at most 64 bytes of the packet in case 899 * we need to generate an ICMP message to the src. 900 */ 901 mcopy = m_copy(m, 0, imin((int)ip->ip_len, 64)); 902 903 sin = (struct sockaddr_in *)&ipforward_rt.ro_dst; 904 if (ipforward_rt.ro_rt == 0 || 905 ip->ip_dst.s_addr != sin->sin_addr.s_addr) { 906 if (ipforward_rt.ro_rt) { 907 RTFREE(ipforward_rt.ro_rt); 908 ipforward_rt.ro_rt = 0; 909 } 910 sin->sin_family = AF_INET; 911 sin->sin_len = sizeof(*sin); 912 sin->sin_addr = ip->ip_dst; 913 914 rtalloc(&ipforward_rt); 915 } 916 /* 917 * If forwarding packet using same interface that it came in on, 918 * perhaps should send a redirect to sender to shortcut a hop. 919 * Only send redirect if source is sending directly to us, 920 * and if packet was not source routed (or has any options). 921 * Also, don't send redirect if forwarding using a default route 922 * or a route modfied by a redirect. 923 */ 924 #define satosin(sa) ((struct sockaddr_in *)(sa)) 925 if (ipforward_rt.ro_rt && 926 ipforward_rt.ro_rt->rt_ifp == m->m_pkthdr.rcvif && 927 (ipforward_rt.ro_rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && 928 satosin(rt_key(ipforward_rt.ro_rt))->sin_addr.s_addr != 0 && 929 ipsendredirects && ip->ip_hl == (sizeof(struct ip) >> 2)) { 930 struct in_ifaddr *ia; 931 u_long src = ntohl(ip->ip_src.s_addr); 932 u_long dst = ntohl(ip->ip_dst.s_addr); 933 934 if ((ia = ifptoia(m->m_pkthdr.rcvif)) && 935 (src & ia->ia_subnetmask) == ia->ia_subnet) { 936 if (ipforward_rt.ro_rt->rt_flags & RTF_GATEWAY) 937 dest = satosin(ipforward_rt.ro_rt->rt_gateway)->sin_addr; 938 else 939 dest = ip->ip_dst; 940 /* 941 * If the destination is reached by a route to host, 942 * is on a subnet of a local net, or is directly 943 * on the attached net (!), use host redirect. 944 * (We may be the correct first hop for other subnets.) 945 */ 946 type = ICMP_REDIRECT; 947 code = ICMP_REDIRECT_NET; 948 if ((ipforward_rt.ro_rt->rt_flags & RTF_HOST) || 949 (ipforward_rt.ro_rt->rt_flags & RTF_GATEWAY) == 0) 950 code = ICMP_REDIRECT_HOST; 951 else for (ia = in_ifaddr; ia = ia->ia_next; ) 952 if ((dst & ia->ia_netmask) == ia->ia_net) { 953 if (ia->ia_subnetmask != ia->ia_netmask) 954 code = ICMP_REDIRECT_HOST; 955 break; 956 } 957 if (ipprintfs) 958 printf("redirect (%d) to %x\n", code, dest); 959 } 960 } 961 962 error = ip_output(m, (struct mbuf *)0, &ipforward_rt, IP_FORWARDING); 963 if (error) 964 ipstat.ips_cantforward++; 965 else if (type) 966 ipstat.ips_redirectsent++; 967 else { 968 if (mcopy) 969 m_freem(mcopy); 970 ipstat.ips_forward++; 971 return; 972 } 973 if (mcopy == NULL) 974 return; 975 ip = mtod(mcopy, struct ip *); 976 type = ICMP_UNREACH; 977 switch (error) { 978 979 case 0: /* forwarded, but need redirect */ 980 type = ICMP_REDIRECT; 981 /* code set above */ 982 break; 983 984 case ENETUNREACH: 985 case ENETDOWN: 986 if (in_localaddr(ip->ip_dst)) 987 code = ICMP_UNREACH_HOST; 988 else 989 code = ICMP_UNREACH_NET; 990 break; 991 992 case EMSGSIZE: 993 code = ICMP_UNREACH_NEEDFRAG; 994 ipstat.ips_cantfrag++; 995 break; 996 997 case EPERM: 998 code = ICMP_UNREACH_PORT; 999 break; 1000 1001 case ENOBUFS: 1002 type = ICMP_SOURCEQUENCH; 1003 code = 0; 1004 break; 1005 1006 case EHOSTDOWN: 1007 case EHOSTUNREACH: 1008 code = ICMP_UNREACH_HOST; 1009 break; 1010 } 1011 sendicmp: 1012 icmp_error(mcopy, type, code, dest); 1013 } 1014