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