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