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