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