|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1988, 1993 ! 3: * The Regents of the University of California. All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 ! 34: * ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp ! 35: */ ! 36: ! 37: /* ! 38: * Changes and additions relating to SLiRP are ! 39: * Copyright (c) 1995 Danny Gasparovski. ! 40: * ! 41: * Please read the file COPYRIGHT for the ! 42: * terms and conditions of the copyright. ! 43: */ ! 44: ! 45: #include <slirp.h> ! 46: #include "ip_icmp.h" ! 47: ! 48: int ip_defttl; ! 49: struct ipstat ipstat; ! 50: struct ipq ipq; ! 51: ! 52: /* ! 53: * IP initialization: fill in IP protocol switch table. ! 54: * All protocols not implemented in kernel go to raw IP protocol handler. ! 55: */ ! 56: void ! 57: ip_init() ! 58: { ! 59: ipq.next = ipq.prev = (ipqp_32)&ipq; ! 60: ip_id = tt.tv_sec & 0xffff; ! 61: udp_init(); ! 62: tcp_init(); ! 63: ip_defttl = IPDEFTTL; ! 64: } ! 65: ! 66: /* ! 67: * Ip input routine. Checksum and byte swap header. If fragmented ! 68: * try to reassemble. Process options. Pass to next level. ! 69: */ ! 70: void ! 71: ip_input(m) ! 72: struct mbuf *m; ! 73: { ! 74: register struct ip *ip; ! 75: int hlen; ! 76: ! 77: DEBUG_CALL("ip_input"); ! 78: DEBUG_ARG("m = %lx", (long)m); ! 79: DEBUG_ARG("m_len = %d", m->m_len); ! 80: ! 81: ipstat.ips_total++; ! 82: ! 83: if (m->m_len < sizeof (struct ip)) { ! 84: ipstat.ips_toosmall++; ! 85: return; ! 86: } ! 87: ! 88: ip = mtod(m, struct ip *); ! 89: ! 90: if (ip->ip_v != IPVERSION) { ! 91: ipstat.ips_badvers++; ! 92: goto bad; ! 93: } ! 94: ! 95: hlen = ip->ip_hl << 2; ! 96: if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */ ! 97: ipstat.ips_badhlen++; /* or packet too short */ ! 98: goto bad; ! 99: } ! 100: ! 101: /* keep ip header intact for ICMP reply ! 102: * ip->ip_sum = cksum(m, hlen); ! 103: * if (ip->ip_sum) { ! 104: */ ! 105: if(cksum(m,hlen)) { ! 106: ipstat.ips_badsum++; ! 107: goto bad; ! 108: } ! 109: ! 110: /* ! 111: * Convert fields to host representation. ! 112: */ ! 113: NTOHS(ip->ip_len); ! 114: if (ip->ip_len < hlen) { ! 115: ipstat.ips_badlen++; ! 116: goto bad; ! 117: } ! 118: NTOHS(ip->ip_id); ! 119: NTOHS(ip->ip_off); ! 120: ! 121: /* ! 122: * Check that the amount of data in the buffers ! 123: * is as at least much as the IP header would have us expect. ! 124: * Trim mbufs if longer than we expect. ! 125: * Drop packet if shorter than we expect. ! 126: */ ! 127: if (m->m_len < ip->ip_len) { ! 128: ipstat.ips_tooshort++; ! 129: goto bad; ! 130: } ! 131: /* Should drop packet if mbuf too long? hmmm... */ ! 132: if (m->m_len > ip->ip_len) ! 133: m_adj(m, ip->ip_len - m->m_len); ! 134: ! 135: /* check ip_ttl for a correct ICMP reply */ ! 136: if(ip->ip_ttl==0 || ip->ip_ttl==1) { ! 137: icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl"); ! 138: goto bad; ! 139: } ! 140: ! 141: /* ! 142: * Process options and, if not destined for us, ! 143: * ship it on. ip_dooptions returns 1 when an ! 144: * error was detected (causing an icmp message ! 145: * to be sent and the original packet to be freed). ! 146: */ ! 147: /* We do no IP options */ ! 148: /* if (hlen > sizeof (struct ip) && ip_dooptions(m)) ! 149: * goto next; ! 150: */ ! 151: /* ! 152: * If offset or IP_MF are set, must reassemble. ! 153: * Otherwise, nothing need be done. ! 154: * (We could look in the reassembly queue to see ! 155: * if the packet was previously fragmented, ! 156: * but it's not worth the time; just let them time out.) ! 157: * ! 158: * XXX This should fail, don't fragment yet ! 159: */ ! 160: if (ip->ip_off &~ IP_DF) { ! 161: register struct ipq *fp; ! 162: /* ! 163: * Look for queue of fragments ! 164: * of this datagram. ! 165: */ ! 166: for (fp = (struct ipq *) ipq.next; fp != &ipq; ! 167: fp = (struct ipq *) fp->next) ! 168: if (ip->ip_id == fp->ipq_id && ! 169: ip->ip_src.s_addr == fp->ipq_src.s_addr && ! 170: ip->ip_dst.s_addr == fp->ipq_dst.s_addr && ! 171: ip->ip_p == fp->ipq_p) ! 172: goto found; ! 173: fp = 0; ! 174: found: ! 175: ! 176: /* ! 177: * Adjust ip_len to not reflect header, ! 178: * set ip_mff if more fragments are expected, ! 179: * convert offset of this to bytes. ! 180: */ ! 181: ip->ip_len -= hlen; ! 182: if (ip->ip_off & IP_MF) ! 183: ((struct ipasfrag *)ip)->ipf_mff |= 1; ! 184: else ! 185: ((struct ipasfrag *)ip)->ipf_mff &= ~1; ! 186: ! 187: ip->ip_off <<= 3; ! 188: ! 189: /* ! 190: * If datagram marked as having more fragments ! 191: * or if this is not the first fragment, ! 192: * attempt reassembly; if it succeeds, proceed. ! 193: */ ! 194: if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { ! 195: ipstat.ips_fragments++; ! 196: ip = ip_reass((struct ipasfrag *)ip, fp); ! 197: if (ip == 0) ! 198: return; ! 199: ipstat.ips_reassembled++; ! 200: m = dtom(ip); ! 201: } else ! 202: if (fp) ! 203: ip_freef(fp); ! 204: ! 205: } else ! 206: ip->ip_len -= hlen; ! 207: ! 208: /* ! 209: * Switch out to protocol's input routine. ! 210: */ ! 211: ipstat.ips_delivered++; ! 212: switch (ip->ip_p) { ! 213: case IPPROTO_TCP: ! 214: tcp_input(m, hlen, (struct socket *)NULL); ! 215: break; ! 216: case IPPROTO_UDP: ! 217: udp_input(m, hlen); ! 218: break; ! 219: case IPPROTO_ICMP: ! 220: icmp_input(m, hlen); ! 221: break; ! 222: default: ! 223: ipstat.ips_noproto++; ! 224: m_free(m); ! 225: } ! 226: return; ! 227: bad: ! 228: m_freem(m); ! 229: return; ! 230: } ! 231: ! 232: /* ! 233: * Take incoming datagram fragment and try to ! 234: * reassemble it into whole datagram. If a chain for ! 235: * reassembly of this datagram already exists, then it ! 236: * is given as fp; otherwise have to make a chain. ! 237: */ ! 238: struct ip * ! 239: ip_reass(ip, fp) ! 240: register struct ipasfrag *ip; ! 241: register struct ipq *fp; ! 242: { ! 243: register struct mbuf *m = dtom(ip); ! 244: register struct ipasfrag *q; ! 245: int hlen = ip->ip_hl << 2; ! 246: int i, next; ! 247: ! 248: DEBUG_CALL("ip_reass"); ! 249: DEBUG_ARG("ip = %lx", (long)ip); ! 250: DEBUG_ARG("fp = %lx", (long)fp); ! 251: DEBUG_ARG("m = %lx", (long)m); ! 252: ! 253: /* ! 254: * Presence of header sizes in mbufs ! 255: * would confuse code below. ! 256: * Fragment m_data is concatenated. ! 257: */ ! 258: m->m_data += hlen; ! 259: m->m_len -= hlen; ! 260: ! 261: /* ! 262: * If first fragment to arrive, create a reassembly queue. ! 263: */ ! 264: if (fp == 0) { ! 265: struct mbuf *t; ! 266: if ((t = m_get()) == NULL) goto dropfrag; ! 267: fp = mtod(t, struct ipq *); ! 268: insque_32(fp, &ipq); ! 269: fp->ipq_ttl = IPFRAGTTL; ! 270: fp->ipq_p = ip->ip_p; ! 271: fp->ipq_id = ip->ip_id; ! 272: fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp; ! 273: fp->ipq_src = ((struct ip *)ip)->ip_src; ! 274: fp->ipq_dst = ((struct ip *)ip)->ip_dst; ! 275: q = (struct ipasfrag *)fp; ! 276: goto insert; ! 277: } ! 278: ! 279: /* ! 280: * Find a segment which begins after this one does. ! 281: */ ! 282: for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp; ! 283: q = (struct ipasfrag *)q->ipf_next) ! 284: if (q->ip_off > ip->ip_off) ! 285: break; ! 286: ! 287: /* ! 288: * If there is a preceding segment, it may provide some of ! 289: * our data already. If so, drop the data from the incoming ! 290: * segment. If it provides all of our data, drop us. ! 291: */ ! 292: if (q->ipf_prev != (ipasfragp_32)fp) { ! 293: i = ((struct ipasfrag *)(q->ipf_prev))->ip_off + ! 294: ((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off; ! 295: if (i > 0) { ! 296: if (i >= ip->ip_len) ! 297: goto dropfrag; ! 298: m_adj(dtom(ip), i); ! 299: ip->ip_off += i; ! 300: ip->ip_len -= i; ! 301: } ! 302: } ! 303: ! 304: /* ! 305: * While we overlap succeeding segments trim them or, ! 306: * if they are completely covered, dequeue them. ! 307: */ ! 308: while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) { ! 309: i = (ip->ip_off + ip->ip_len) - q->ip_off; ! 310: if (i < q->ip_len) { ! 311: q->ip_len -= i; ! 312: q->ip_off += i; ! 313: m_adj(dtom(q), i); ! 314: break; ! 315: } ! 316: q = (struct ipasfrag *) q->ipf_next; ! 317: m_freem(dtom((struct ipasfrag *) q->ipf_prev)); ! 318: ip_deq((struct ipasfrag *) q->ipf_prev); ! 319: } ! 320: ! 321: insert: ! 322: /* ! 323: * Stick new segment in its place; ! 324: * check for complete reassembly. ! 325: */ ! 326: ip_enq(ip, (struct ipasfrag *) q->ipf_prev); ! 327: next = 0; ! 328: for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp; ! 329: q = (struct ipasfrag *) q->ipf_next) { ! 330: if (q->ip_off != next) ! 331: return (0); ! 332: next += q->ip_len; ! 333: } ! 334: if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1) ! 335: return (0); ! 336: ! 337: /* ! 338: * Reassembly is complete; concatenate fragments. ! 339: */ ! 340: q = (struct ipasfrag *) fp->ipq_next; ! 341: m = dtom(q); ! 342: ! 343: q = (struct ipasfrag *) q->ipf_next; ! 344: while (q != (struct ipasfrag *)fp) { ! 345: struct mbuf *t; ! 346: t = dtom(q); ! 347: m_cat(m, t); ! 348: q = (struct ipasfrag *) q->ipf_next; ! 349: } ! 350: ! 351: /* ! 352: * Create header for new ip packet by ! 353: * modifying header of first packet; ! 354: * dequeue and discard fragment reassembly header. ! 355: * Make header visible. ! 356: */ ! 357: ip = (struct ipasfrag *) fp->ipq_next; ! 358: ! 359: /* ! 360: * If the fragments concatenated to an mbuf that's ! 361: * bigger than the total size of the fragment, then and ! 362: * m_ext buffer was alloced. But fp->ipq_next points to ! 363: * the old buffer (in the mbuf), so we must point ip ! 364: * into the new buffer. ! 365: */ ! 366: if (m->m_flags & M_EXT) { ! 367: int delta; ! 368: delta = (char *)ip - m->m_dat; ! 369: ip = (struct ipasfrag *)(m->m_ext + delta); ! 370: } ! 371: ! 372: /* DEBUG_ARG("ip = %lx", (long)ip); ! 373: * ip=(struct ipasfrag *)m->m_data; */ ! 374: ! 375: ip->ip_len = next; ! 376: ip->ipf_mff &= ~1; ! 377: ((struct ip *)ip)->ip_src = fp->ipq_src; ! 378: ((struct ip *)ip)->ip_dst = fp->ipq_dst; ! 379: remque_32(fp); ! 380: (void) m_free(dtom(fp)); ! 381: m = dtom(ip); ! 382: m->m_len += (ip->ip_hl << 2); ! 383: m->m_data -= (ip->ip_hl << 2); ! 384: ! 385: return ((struct ip *)ip); ! 386: ! 387: dropfrag: ! 388: ipstat.ips_fragdropped++; ! 389: m_freem(m); ! 390: return (0); ! 391: } ! 392: ! 393: /* ! 394: * Free a fragment reassembly header and all ! 395: * associated datagrams. ! 396: */ ! 397: void ! 398: ip_freef(fp) ! 399: struct ipq *fp; ! 400: { ! 401: register struct ipasfrag *q, *p; ! 402: ! 403: for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp; ! 404: q = p) { ! 405: p = (struct ipasfrag *) q->ipf_next; ! 406: ip_deq(q); ! 407: m_freem(dtom(q)); ! 408: } ! 409: remque_32(fp); ! 410: (void) m_free(dtom(fp)); ! 411: } ! 412: ! 413: /* ! 414: * Put an ip fragment on a reassembly chain. ! 415: * Like insque, but pointers in middle of structure. ! 416: */ ! 417: void ! 418: ip_enq(p, prev) ! 419: register struct ipasfrag *p, *prev; ! 420: { ! 421: DEBUG_CALL("ip_enq"); ! 422: DEBUG_ARG("prev = %lx", (long)prev); ! 423: p->ipf_prev = (ipasfragp_32) prev; ! 424: p->ipf_next = prev->ipf_next; ! 425: ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p; ! 426: prev->ipf_next = (ipasfragp_32) p; ! 427: } ! 428: ! 429: /* ! 430: * To ip_enq as remque is to insque. ! 431: */ ! 432: void ! 433: ip_deq(p) ! 434: register struct ipasfrag *p; ! 435: { ! 436: ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next; ! 437: ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev; ! 438: } ! 439: ! 440: /* ! 441: * IP timer processing; ! 442: * if a timer expires on a reassembly ! 443: * queue, discard it. ! 444: */ ! 445: void ! 446: ip_slowtimo() ! 447: { ! 448: register struct ipq *fp; ! 449: ! 450: DEBUG_CALL("ip_slowtimo"); ! 451: ! 452: fp = (struct ipq *) ipq.next; ! 453: if (fp == 0) ! 454: return; ! 455: ! 456: while (fp != &ipq) { ! 457: --fp->ipq_ttl; ! 458: fp = (struct ipq *) fp->next; ! 459: if (((struct ipq *)(fp->prev))->ipq_ttl == 0) { ! 460: ipstat.ips_fragtimeout++; ! 461: ip_freef((struct ipq *) fp->prev); ! 462: } ! 463: } ! 464: } ! 465: ! 466: /* ! 467: * Do option processing on a datagram, ! 468: * possibly discarding it if bad options are encountered, ! 469: * or forwarding it if source-routed. ! 470: * Returns 1 if packet has been forwarded/freed, ! 471: * 0 if the packet should be processed further. ! 472: */ ! 473: ! 474: #ifdef notdef ! 475: ! 476: int ! 477: ip_dooptions(m) ! 478: struct mbuf *m; ! 479: { ! 480: register struct ip *ip = mtod(m, struct ip *); ! 481: register u_char *cp; ! 482: register struct ip_timestamp *ipt; ! 483: register struct in_ifaddr *ia; ! 484: /* int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; */ ! 485: int opt, optlen, cnt, off, code, type, forward = 0; ! 486: struct in_addr *sin, dst; ! 487: typedef u_int32_t n_time; ! 488: n_time ntime; ! 489: ! 490: dst = ip->ip_dst; ! 491: cp = (u_char *)(ip + 1); ! 492: cnt = (ip->ip_hl << 2) - sizeof (struct ip); ! 493: for (; cnt > 0; cnt -= optlen, cp += optlen) { ! 494: opt = cp[IPOPT_OPTVAL]; ! 495: if (opt == IPOPT_EOL) ! 496: break; ! 497: if (opt == IPOPT_NOP) ! 498: optlen = 1; ! 499: else { ! 500: optlen = cp[IPOPT_OLEN]; ! 501: if (optlen <= 0 || optlen > cnt) { ! 502: code = &cp[IPOPT_OLEN] - (u_char *)ip; ! 503: goto bad; ! 504: } ! 505: } ! 506: switch (opt) { ! 507: ! 508: default: ! 509: break; ! 510: ! 511: /* ! 512: * Source routing with record. ! 513: * Find interface with current destination address. ! 514: * If none on this machine then drop if strictly routed, ! 515: * or do nothing if loosely routed. ! 516: * Record interface address and bring up next address ! 517: * component. If strictly routed make sure next ! 518: * address is on directly accessible net. ! 519: */ ! 520: case IPOPT_LSRR: ! 521: case IPOPT_SSRR: ! 522: if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { ! 523: code = &cp[IPOPT_OFFSET] - (u_char *)ip; ! 524: goto bad; ! 525: } ! 526: ipaddr.sin_addr = ip->ip_dst; ! 527: ia = (struct in_ifaddr *) ! 528: ifa_ifwithaddr((struct sockaddr *)&ipaddr); ! 529: if (ia == 0) { ! 530: if (opt == IPOPT_SSRR) { ! 531: type = ICMP_UNREACH; ! 532: code = ICMP_UNREACH_SRCFAIL; ! 533: goto bad; ! 534: } ! 535: /* ! 536: * Loose routing, and not at next destination ! 537: * yet; nothing to do except forward. ! 538: */ ! 539: break; ! 540: } ! 541: off--; / * 0 origin * / ! 542: if (off > optlen - sizeof(struct in_addr)) { ! 543: /* ! 544: * End of source route. Should be for us. ! 545: */ ! 546: save_rte(cp, ip->ip_src); ! 547: break; ! 548: } ! 549: /* ! 550: * locate outgoing interface ! 551: */ ! 552: bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, ! 553: sizeof(ipaddr.sin_addr)); ! 554: if (opt == IPOPT_SSRR) { ! 555: #define INA struct in_ifaddr * ! 556: #define SA struct sockaddr * ! 557: if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0) ! 558: ia = (INA)ifa_ifwithnet((SA)&ipaddr); ! 559: } else ! 560: ia = ip_rtaddr(ipaddr.sin_addr); ! 561: if (ia == 0) { ! 562: type = ICMP_UNREACH; ! 563: code = ICMP_UNREACH_SRCFAIL; ! 564: goto bad; ! 565: } ! 566: ip->ip_dst = ipaddr.sin_addr; ! 567: bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), ! 568: (caddr_t)(cp + off), sizeof(struct in_addr)); ! 569: cp[IPOPT_OFFSET] += sizeof(struct in_addr); ! 570: /* ! 571: * Let ip_intr's mcast routing check handle mcast pkts ! 572: */ ! 573: forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr)); ! 574: break; ! 575: ! 576: case IPOPT_RR: ! 577: if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { ! 578: code = &cp[IPOPT_OFFSET] - (u_char *)ip; ! 579: goto bad; ! 580: } ! 581: /* ! 582: * If no space remains, ignore. ! 583: */ ! 584: off--; * 0 origin * ! 585: if (off > optlen - sizeof(struct in_addr)) ! 586: break; ! 587: bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr, ! 588: sizeof(ipaddr.sin_addr)); ! 589: /* ! 590: * locate outgoing interface; if we're the destination, ! 591: * use the incoming interface (should be same). ! 592: */ ! 593: if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 && ! 594: (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { ! 595: type = ICMP_UNREACH; ! 596: code = ICMP_UNREACH_HOST; ! 597: goto bad; ! 598: } ! 599: bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), ! 600: (caddr_t)(cp + off), sizeof(struct in_addr)); ! 601: cp[IPOPT_OFFSET] += sizeof(struct in_addr); ! 602: break; ! 603: ! 604: case IPOPT_TS: ! 605: code = cp - (u_char *)ip; ! 606: ipt = (struct ip_timestamp *)cp; ! 607: if (ipt->ipt_len < 5) ! 608: goto bad; ! 609: if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) { ! 610: if (++ipt->ipt_oflw == 0) ! 611: goto bad; ! 612: break; ! 613: } ! 614: sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); ! 615: switch (ipt->ipt_flg) { ! 616: ! 617: case IPOPT_TS_TSONLY: ! 618: break; ! 619: ! 620: case IPOPT_TS_TSANDADDR: ! 621: if (ipt->ipt_ptr + sizeof(n_time) + ! 622: sizeof(struct in_addr) > ipt->ipt_len) ! 623: goto bad; ! 624: ipaddr.sin_addr = dst; ! 625: ia = (INA)ifaof_ i f p foraddr((SA)&ipaddr, ! 626: m->m_pkthdr.rcvif); ! 627: if (ia == 0) ! 628: continue; ! 629: bcopy((caddr_t)&IA_SIN(ia)->sin_addr, ! 630: (caddr_t)sin, sizeof(struct in_addr)); ! 631: ipt->ipt_ptr += sizeof(struct in_addr); ! 632: break; ! 633: ! 634: case IPOPT_TS_PRESPEC: ! 635: if (ipt->ipt_ptr + sizeof(n_time) + ! 636: sizeof(struct in_addr) > ipt->ipt_len) ! 637: goto bad; ! 638: bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr, ! 639: sizeof(struct in_addr)); ! 640: if (ifa_ifwithaddr((SA)&ipaddr) == 0) ! 641: continue; ! 642: ipt->ipt_ptr += sizeof(struct in_addr); ! 643: break; ! 644: ! 645: default: ! 646: goto bad; ! 647: } ! 648: ntime = iptime(); ! 649: bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1, ! 650: sizeof(n_time)); ! 651: ipt->ipt_ptr += sizeof(n_time); ! 652: } ! 653: } ! 654: if (forward) { ! 655: ip_forward(m, 1); ! 656: return (1); ! 657: } ! 658: } ! 659: } ! 660: return (0); ! 661: bad: ! 662: /* ip->ip_len -= ip->ip_hl << 2; XXX icmp_error adds in hdr length */ ! 663: ! 664: /* Not yet */ ! 665: icmp_error(m, type, code, 0, 0); ! 666: ! 667: ipstat.ips_badoptions++; ! 668: return (1); ! 669: } ! 670: ! 671: #endif /* notdef */ ! 672: ! 673: /* ! 674: * Strip out IP options, at higher ! 675: * level protocol in the kernel. ! 676: * Second argument is buffer to which options ! 677: * will be moved, and return value is their length. ! 678: * (XXX) should be deleted; last arg currently ignored. ! 679: */ ! 680: void ! 681: ip_stripoptions(m, mopt) ! 682: register struct mbuf *m; ! 683: struct mbuf *mopt; ! 684: { ! 685: register int i; ! 686: struct ip *ip = mtod(m, struct ip *); ! 687: register caddr_t opts; ! 688: int olen; ! 689: ! 690: olen = (ip->ip_hl<<2) - sizeof (struct ip); ! 691: opts = (caddr_t)(ip + 1); ! 692: i = m->m_len - (sizeof (struct ip) + olen); ! 693: memcpy(opts, opts + olen, (unsigned)i); ! 694: m->m_len -= olen; ! 695: ! 696: ip->ip_hl = sizeof(struct ip) >> 2; ! 697: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.