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