|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)ip_input.c 7.17 (Berkeley) 7/25/90
21: */
22:
23: #include "param.h"
24: #include "systm.h"
25: #include "malloc.h"
26: #include "mbuf.h"
27: #include "domain.h"
28: #include "protosw.h"
29: #include "socket.h"
30: #include "errno.h"
31: #include "time.h"
32: #include "kernel.h"
33:
34: #include "../net/if.h"
35: #include "../net/route.h"
36:
37: #include "in.h"
38: #include "in_systm.h"
39: #include "ip.h"
40: #include "in_pcb.h"
41: #include "in_var.h"
42: #include "ip_var.h"
43: #include "ip_icmp.h"
44:
45: #ifndef IPFORWARDING
46: #ifdef GATEWAY
47: #define IPFORWARDING 1 /* forward IP packets not for us */
48: #else /* GATEWAY */
49: #define IPFORWARDING 0 /* don't forward IP packets not for us */
50: #endif /* GATEWAY */
51: #endif /* IPFORWARDING */
52: #ifndef IPSENDREDIRECTS
53: #define IPSENDREDIRECTS 1
54: #endif
55: int ipforwarding = IPFORWARDING;
56: int ipsendredirects = IPSENDREDIRECTS;
57: #ifdef DEBUG
58: int ipprintfs = 0;
59: #endif
60:
61: u_char ip_protox[IPPROTO_MAX];
62: int ipqmaxlen = IFQ_MAXLEN;
63: struct in_ifaddr *in_ifaddr; /* first inet address */
64:
65: /*
66: * We need to save the IP options in case a protocol wants to respond
67: * to an incoming packet over the same route if the packet got here
68: * using IP source routing. This allows connection establishment and
69: * maintenance when the remote end is on a network that is not known
70: * to us.
71: */
72: int ip_nhops = 0;
73: static struct ip_srcrt {
74: struct in_addr dst; /* final destination */
75: char nop; /* one NOP to align */
76: char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */
77: struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)];
78: } ip_srcrt;
79:
80: #ifdef GATEWAY
81: extern int if_index;
82: u_long *ip_ifmatrix;
83: #endif
84:
85: /*
86: * IP initialization: fill in IP protocol switch table.
87: * All protocols not implemented in kernel go to raw IP protocol handler.
88: */
89: ip_init()
90: {
91: register struct protosw *pr;
92: register int i;
93:
94: pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
95: if (pr == 0)
96: panic("ip_init");
97: for (i = 0; i < IPPROTO_MAX; i++)
98: ip_protox[i] = pr - inetsw;
99: for (pr = inetdomain.dom_protosw;
100: pr < inetdomain.dom_protoswNPROTOSW; pr++)
101: if (pr->pr_domain->dom_family == PF_INET &&
102: pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
103: ip_protox[pr->pr_protocol] = pr - inetsw;
104: ipq.next = ipq.prev = &ipq;
105: ip_id = time.tv_sec & 0xffff;
106: ipintrq.ifq_maxlen = ipqmaxlen;
107: #ifdef GATEWAY
108: i = (if_index + 1) * (if_index + 1) * sizeof (u_long);
109: if ((ip_ifmatrix = (u_long *) malloc(i, M_RTABLE, M_WAITOK)) == 0)
110: panic("no memory for ip_ifmatrix");
111: #endif
112: }
113:
114: struct ip *ip_reass();
115: struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET };
116: struct route ipforward_rt;
117:
118: /*
119: * Ip input routine. Checksum and byte swap header. If fragmented
120: * try to reassemble. Process options. Pass to next level.
121: */
122: ipintr()
123: {
124: register struct ip *ip;
125: register struct mbuf *m;
126: register struct ipq *fp;
127: register struct in_ifaddr *ia;
128: int hlen, s;
129:
130: next:
131: /*
132: * Get next datagram off input queue and get IP header
133: * in first mbuf.
134: */
135: s = splimp();
136: IF_DEQUEUE(&ipintrq, m);
137: splx(s);
138: if (m == 0)
139: return;
140: #ifdef DIAGNOSTIC
141: if ((m->m_flags & M_PKTHDR) == 0)
142: panic("ipintr no HDR");
143: #endif
144: /*
145: * If no IP addresses have been set yet but the interfaces
146: * are receiving, can't do anything with incoming packets yet.
147: */
148: if (in_ifaddr == NULL)
149: goto bad;
150: ipstat.ips_total++;
151: if (m->m_len < sizeof (struct ip) &&
152: (m = m_pullup(m, sizeof (struct ip))) == 0) {
153: ipstat.ips_toosmall++;
154: goto next;
155: }
156: ip = mtod(m, struct ip *);
157: hlen = ip->ip_hl << 2;
158: if (hlen < sizeof(struct ip)) { /* minimum header length */
159: ipstat.ips_badhlen++;
160: goto bad;
161: }
162: if (hlen > m->m_len) {
163: if ((m = m_pullup(m, hlen)) == 0) {
164: ipstat.ips_badhlen++;
165: goto next;
166: }
167: ip = mtod(m, struct ip *);
168: }
169: if (ip->ip_sum = in_cksum(m, hlen)) {
170: ipstat.ips_badsum++;
171: goto bad;
172: }
173:
174: /*
175: * Convert fields to host representation.
176: */
177: NTOHS(ip->ip_len);
178: if (ip->ip_len < hlen) {
179: ipstat.ips_badlen++;
180: goto bad;
181: }
182: NTOHS(ip->ip_id);
183: NTOHS(ip->ip_off);
184:
185: /*
186: * Check that the amount of data in the buffers
187: * is as at least much as the IP header would have us expect.
188: * Trim mbufs if longer than we expect.
189: * Drop packet if shorter than we expect.
190: */
191: if (m->m_pkthdr.len < ip->ip_len) {
192: ipstat.ips_tooshort++;
193: goto bad;
194: }
195: if (m->m_pkthdr.len > ip->ip_len) {
196: if (m->m_len == m->m_pkthdr.len) {
197: m->m_len = ip->ip_len;
198: m->m_pkthdr.len = ip->ip_len;
199: } else
200: m_adj(m, ip->ip_len - m->m_pkthdr.len);
201: }
202:
203: /*
204: * Process options and, if not destined for us,
205: * ship it on. ip_dooptions returns 1 when an
206: * error was detected (causing an icmp message
207: * to be sent and the original packet to be freed).
208: */
209: ip_nhops = 0; /* for source routed packets */
210: if (hlen > sizeof (struct ip) && ip_dooptions(m))
211: goto next;
212:
213: /*
214: * Check our list of addresses, to see if the packet is for us.
215: */
216: for (ia = in_ifaddr; ia; ia = ia->ia_next) {
217: #define satosin(sa) ((struct sockaddr_in *)(sa))
218:
219: if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr)
220: goto ours;
221: if (
222: #ifdef DIRECTED_BROADCAST
223: ia->ia_ifp == m->m_pkthdr.rcvif &&
224: #endif
225: (ia->ia_ifp->if_flags & IFF_BROADCAST)) {
226: u_long t;
227:
228: if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
229: ip->ip_dst.s_addr)
230: goto ours;
231: if (ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr)
232: goto ours;
233: /*
234: * Look for all-0's host part (old broadcast addr),
235: * either for subnet or net.
236: */
237: t = ntohl(ip->ip_dst.s_addr);
238: if (t == ia->ia_subnet)
239: goto ours;
240: if (t == ia->ia_net)
241: goto ours;
242: }
243: }
244: if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST)
245: goto ours;
246: if (ip->ip_dst.s_addr == INADDR_ANY)
247: goto ours;
248:
249: /*
250: * Not for us; forward if possible and desirable.
251: */
252: if (ipforwarding == 0) {
253: ipstat.ips_cantforward++;
254: m_freem(m);
255: } else
256: ip_forward(m, 0);
257: goto next;
258:
259: ours:
260: /*
261: * If offset or IP_MF are set, must reassemble.
262: * Otherwise, nothing need be done.
263: * (We could look in the reassembly queue to see
264: * if the packet was previously fragmented,
265: * but it's not worth the time; just let them time out.)
266: */
267: if (ip->ip_off &~ IP_DF) {
268: if (m->m_flags & M_EXT) { /* XXX */
269: if ((m = m_pullup(m, sizeof (struct ip))) == 0) {
270: ipstat.ips_toosmall++;
271: goto next;
272: }
273: ip = mtod(m, struct ip *);
274: }
275: /*
276: * Look for queue of fragments
277: * of this datagram.
278: */
279: for (fp = ipq.next; fp != &ipq; fp = fp->next)
280: if (ip->ip_id == fp->ipq_id &&
281: ip->ip_src.s_addr == fp->ipq_src.s_addr &&
282: ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
283: ip->ip_p == fp->ipq_p)
284: goto found;
285: fp = 0;
286: found:
287:
288: /*
289: * Adjust ip_len to not reflect header,
290: * set ip_mff if more fragments are expected,
291: * convert offset of this to bytes.
292: */
293: ip->ip_len -= hlen;
294: ((struct ipasfrag *)ip)->ipf_mff = 0;
295: if (ip->ip_off & IP_MF)
296: ((struct ipasfrag *)ip)->ipf_mff = 1;
297: ip->ip_off <<= 3;
298:
299: /*
300: * If datagram marked as having more fragments
301: * or if this is not the first fragment,
302: * attempt reassembly; if it succeeds, proceed.
303: */
304: if (((struct ipasfrag *)ip)->ipf_mff || ip->ip_off) {
305: ipstat.ips_fragments++;
306: ip = ip_reass((struct ipasfrag *)ip, fp);
307: if (ip == 0)
308: goto next;
309: else
310: ipstat.ips_reassembled++;
311: m = dtom(ip);
312: } else
313: if (fp)
314: ip_freef(fp);
315: } else
316: ip->ip_len -= hlen;
317:
318: /*
319: * Switch out to protocol's input routine.
320: */
321: ipstat.ips_delivered++;
322: (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
323: goto next;
324: bad:
325: m_freem(m);
326: goto next;
327: }
328:
329: /*
330: * Take incoming datagram fragment and try to
331: * reassemble it into whole datagram. If a chain for
332: * reassembly of this datagram already exists, then it
333: * is given as fp; otherwise have to make a chain.
334: */
335: struct ip *
336: ip_reass(ip, fp)
337: register struct ipasfrag *ip;
338: register struct ipq *fp;
339: {
340: register struct mbuf *m = dtom(ip);
341: register struct ipasfrag *q;
342: struct mbuf *t;
343: int hlen = ip->ip_hl << 2;
344: int i, next;
345:
346: /*
347: * Presence of header sizes in mbufs
348: * would confuse code below.
349: */
350: m->m_data += hlen;
351: m->m_len -= hlen;
352:
353: /*
354: * If first fragment to arrive, create a reassembly queue.
355: */
356: if (fp == 0) {
357: if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL)
358: goto dropfrag;
359: fp = mtod(t, struct ipq *);
360: insque(fp, &ipq);
361: fp->ipq_ttl = IPFRAGTTL;
362: fp->ipq_p = ip->ip_p;
363: fp->ipq_id = ip->ip_id;
364: fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)fp;
365: fp->ipq_src = ((struct ip *)ip)->ip_src;
366: fp->ipq_dst = ((struct ip *)ip)->ip_dst;
367: q = (struct ipasfrag *)fp;
368: goto insert;
369: }
370:
371: /*
372: * Find a segment which begins after this one does.
373: */
374: for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next)
375: if (q->ip_off > ip->ip_off)
376: break;
377:
378: /*
379: * If there is a preceding segment, it may provide some of
380: * our data already. If so, drop the data from the incoming
381: * segment. If it provides all of our data, drop us.
382: */
383: if (q->ipf_prev != (struct ipasfrag *)fp) {
384: i = q->ipf_prev->ip_off + q->ipf_prev->ip_len - ip->ip_off;
385: if (i > 0) {
386: if (i >= ip->ip_len)
387: goto dropfrag;
388: m_adj(dtom(ip), i);
389: ip->ip_off += i;
390: ip->ip_len -= i;
391: }
392: }
393:
394: /*
395: * While we overlap succeeding segments trim them or,
396: * if they are completely covered, dequeue them.
397: */
398: while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
399: i = (ip->ip_off + ip->ip_len) - q->ip_off;
400: if (i < q->ip_len) {
401: q->ip_len -= i;
402: q->ip_off += i;
403: m_adj(dtom(q), i);
404: break;
405: }
406: q = q->ipf_next;
407: m_freem(dtom(q->ipf_prev));
408: ip_deq(q->ipf_prev);
409: }
410:
411: insert:
412: /*
413: * Stick new segment in its place;
414: * check for complete reassembly.
415: */
416: ip_enq(ip, q->ipf_prev);
417: next = 0;
418: for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) {
419: if (q->ip_off != next)
420: return (0);
421: next += q->ip_len;
422: }
423: if (q->ipf_prev->ipf_mff)
424: return (0);
425:
426: /*
427: * Reassembly is complete; concatenate fragments.
428: */
429: q = fp->ipq_next;
430: m = dtom(q);
431: t = m->m_next;
432: m->m_next = 0;
433: m_cat(m, t);
434: q = q->ipf_next;
435: while (q != (struct ipasfrag *)fp) {
436: t = dtom(q);
437: q = q->ipf_next;
438: m_cat(m, t);
439: }
440:
441: /*
442: * Create header for new ip packet by
443: * modifying header of first packet;
444: * dequeue and discard fragment reassembly header.
445: * Make header visible.
446: */
447: ip = fp->ipq_next;
448: ip->ip_len = next;
449: ((struct ip *)ip)->ip_src = fp->ipq_src;
450: ((struct ip *)ip)->ip_dst = fp->ipq_dst;
451: remque(fp);
452: (void) m_free(dtom(fp));
453: m = dtom(ip);
454: m->m_len += (ip->ip_hl << 2);
455: m->m_data -= (ip->ip_hl << 2);
456: return ((struct ip *)ip);
457:
458: dropfrag:
459: ipstat.ips_fragdropped++;
460: m_freem(m);
461: return (0);
462: }
463:
464: /*
465: * Free a fragment reassembly header and all
466: * associated datagrams.
467: */
468: ip_freef(fp)
469: struct ipq *fp;
470: {
471: register struct ipasfrag *q, *p;
472:
473: for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = p) {
474: p = q->ipf_next;
475: ip_deq(q);
476: m_freem(dtom(q));
477: }
478: remque(fp);
479: (void) m_free(dtom(fp));
480: }
481:
482: /*
483: * Put an ip fragment on a reassembly chain.
484: * Like insque, but pointers in middle of structure.
485: */
486: ip_enq(p, prev)
487: register struct ipasfrag *p, *prev;
488: {
489:
490: p->ipf_prev = prev;
491: p->ipf_next = prev->ipf_next;
492: prev->ipf_next->ipf_prev = p;
493: prev->ipf_next = p;
494: }
495:
496: /*
497: * To ip_enq as remque is to insque.
498: */
499: ip_deq(p)
500: register struct ipasfrag *p;
501: {
502:
503: p->ipf_prev->ipf_next = p->ipf_next;
504: p->ipf_next->ipf_prev = p->ipf_prev;
505: }
506:
507: /*
508: * IP timer processing;
509: * if a timer expires on a reassembly
510: * queue, discard it.
511: */
512: ip_slowtimo()
513: {
514: register struct ipq *fp;
515: int s = splnet();
516:
517: fp = ipq.next;
518: if (fp == 0) {
519: splx(s);
520: return;
521: }
522: while (fp != &ipq) {
523: --fp->ipq_ttl;
524: fp = fp->next;
525: if (fp->prev->ipq_ttl == 0) {
526: ipstat.ips_fragtimeout++;
527: ip_freef(fp->prev);
528: }
529: }
530: splx(s);
531: }
532:
533: /*
534: * Drain off all datagram fragments.
535: */
536: ip_drain()
537: {
538:
539: while (ipq.next != &ipq) {
540: ipstat.ips_fragdropped++;
541: ip_freef(ipq.next);
542: }
543: }
544:
545: extern struct in_ifaddr *ifptoia();
546: struct in_ifaddr *ip_rtaddr();
547:
548: /*
549: * Do option processing on a datagram,
550: * possibly discarding it if bad options are encountered,
551: * or forwarding it if source-routed.
552: * Returns 1 if packet has been forwarded/freed,
553: * 0 if the packet should be processed further.
554: */
555: ip_dooptions(m)
556: struct mbuf *m;
557: {
558: register struct ip *ip = mtod(m, struct ip *);
559: register u_char *cp;
560: register struct ip_timestamp *ipt;
561: register struct in_ifaddr *ia;
562: int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;
563: struct in_addr *sin;
564: n_time ntime;
565:
566: cp = (u_char *)(ip + 1);
567: cnt = (ip->ip_hl << 2) - sizeof (struct ip);
568: for (; cnt > 0; cnt -= optlen, cp += optlen) {
569: opt = cp[IPOPT_OPTVAL];
570: if (opt == IPOPT_EOL)
571: break;
572: if (opt == IPOPT_NOP)
573: optlen = 1;
574: else {
575: optlen = cp[IPOPT_OLEN];
576: if (optlen <= 0 || optlen > cnt) {
577: code = &cp[IPOPT_OLEN] - (u_char *)ip;
578: goto bad;
579: }
580: }
581: switch (opt) {
582:
583: default:
584: break;
585:
586: /*
587: * Source routing with record.
588: * Find interface with current destination address.
589: * If none on this machine then drop if strictly routed,
590: * or do nothing if loosely routed.
591: * Record interface address and bring up next address
592: * component. If strictly routed make sure next
593: * address is on directly accessible net.
594: */
595: case IPOPT_LSRR:
596: case IPOPT_SSRR:
597: if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
598: code = &cp[IPOPT_OFFSET] - (u_char *)ip;
599: goto bad;
600: }
601: ipaddr.sin_addr = ip->ip_dst;
602: ia = (struct in_ifaddr *)
603: ifa_ifwithaddr((struct sockaddr *)&ipaddr);
604: if (ia == 0) {
605: if (opt == IPOPT_SSRR) {
606: type = ICMP_UNREACH;
607: code = ICMP_UNREACH_SRCFAIL;
608: goto bad;
609: }
610: /*
611: * Loose routing, and not at next destination
612: * yet; nothing to do except forward.
613: */
614: break;
615: }
616: off--; /* 0 origin */
617: if (off > optlen - sizeof(struct in_addr)) {
618: /*
619: * End of source route. Should be for us.
620: */
621: save_rte(cp, ip->ip_src);
622: break;
623: }
624: /*
625: * locate outgoing interface
626: */
627: bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,
628: sizeof(ipaddr.sin_addr));
629: if (opt == IPOPT_SSRR) {
630: #define INA struct in_ifaddr *
631: #define SA struct sockaddr *
632: if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
633: ia = in_iaonnetof(in_netof(ipaddr.sin_addr));
634: } else
635: ia = ip_rtaddr(ipaddr.sin_addr);
636: if (ia == 0) {
637: type = ICMP_UNREACH;
638: code = ICMP_UNREACH_SRCFAIL;
639: goto bad;
640: }
641: ip->ip_dst = ipaddr.sin_addr;
642: bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
643: (caddr_t)(cp + off), sizeof(struct in_addr));
644: cp[IPOPT_OFFSET] += sizeof(struct in_addr);
645: forward = 1;
646: break;
647:
648: case IPOPT_RR:
649: if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
650: code = &cp[IPOPT_OFFSET] - (u_char *)ip;
651: goto bad;
652: }
653: /*
654: * If no space remains, ignore.
655: */
656: off--; /* 0 origin */
657: if (off > optlen - sizeof(struct in_addr))
658: break;
659: bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
660: sizeof(ipaddr.sin_addr));
661: /*
662: * locate outgoing interface; if we're the destination,
663: * use the incoming interface (should be same).
664: */
665: if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
666: (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
667: type = ICMP_UNREACH;
668: code = ICMP_UNREACH_HOST;
669: goto bad;
670: }
671: bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
672: (caddr_t)(cp + off), sizeof(struct in_addr));
673: cp[IPOPT_OFFSET] += sizeof(struct in_addr);
674: break;
675:
676: case IPOPT_TS:
677: code = cp - (u_char *)ip;
678: ipt = (struct ip_timestamp *)cp;
679: if (ipt->ipt_len < 5)
680: goto bad;
681: if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) {
682: if (++ipt->ipt_oflw == 0)
683: goto bad;
684: break;
685: }
686: sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
687: switch (ipt->ipt_flg) {
688:
689: case IPOPT_TS_TSONLY:
690: break;
691:
692: case IPOPT_TS_TSANDADDR:
693: if (ipt->ipt_ptr + sizeof(n_time) +
694: sizeof(struct in_addr) > ipt->ipt_len)
695: goto bad;
696: ia = ifptoia(m->m_pkthdr.rcvif);
697: bcopy((caddr_t)&IA_SIN(ia)->sin_addr,
698: (caddr_t)sin, sizeof(struct in_addr));
699: ipt->ipt_ptr += sizeof(struct in_addr);
700: break;
701:
702: case IPOPT_TS_PRESPEC:
703: if (ipt->ipt_ptr + sizeof(n_time) +
704: sizeof(struct in_addr) > ipt->ipt_len)
705: goto bad;
706: bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,
707: sizeof(struct in_addr));
708: if (ifa_ifwithaddr((SA)&ipaddr) == 0)
709: continue;
710: ipt->ipt_ptr += sizeof(struct in_addr);
711: break;
712:
713: default:
714: goto bad;
715: }
716: ntime = iptime();
717: bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,
718: sizeof(n_time));
719: ipt->ipt_ptr += sizeof(n_time);
720: }
721: }
722: if (forward) {
723: ip_forward(m, 1);
724: return (1);
725: } else
726: return (0);
727: bad:
728: icmp_error(m, type, code);
729: return (1);
730: }
731:
732: /*
733: * Given address of next destination (final or next hop),
734: * return internet address info of interface to be used to get there.
735: */
736: struct in_ifaddr *
737: ip_rtaddr(dst)
738: struct in_addr dst;
739: {
740: register struct sockaddr_in *sin;
741:
742: sin = (struct sockaddr_in *) &ipforward_rt.ro_dst;
743:
744: if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) {
745: if (ipforward_rt.ro_rt) {
746: RTFREE(ipforward_rt.ro_rt);
747: ipforward_rt.ro_rt = 0;
748: }
749: sin->sin_family = AF_INET;
750: sin->sin_len = sizeof(*sin);
751: sin->sin_addr = dst;
752:
753: rtalloc(&ipforward_rt);
754: }
755: if (ipforward_rt.ro_rt == 0)
756: return ((struct in_ifaddr *)0);
757: return ((struct in_ifaddr *) ipforward_rt.ro_rt->rt_ifa);
758: }
759:
760: /*
761: * Save incoming source route for use in replies,
762: * to be picked up later by ip_srcroute if the receiver is interested.
763: */
764: save_rte(option, dst)
765: u_char *option;
766: struct in_addr dst;
767: {
768: unsigned olen;
769:
770: olen = option[IPOPT_OLEN];
771: #ifdef DEBUG
772: if (ipprintfs)
773: printf("save_rte: olen %d\n", olen);
774: #endif
775: if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
776: return;
777: bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen);
778: ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
779: ip_srcrt.dst = dst;
780: }
781:
782: /*
783: * Retrieve incoming source route for use in replies,
784: * in the same form used by setsockopt.
785: * The first hop is placed before the options, will be removed later.
786: */
787: struct mbuf *
788: ip_srcroute()
789: {
790: register struct in_addr *p, *q;
791: register struct mbuf *m;
792:
793: if (ip_nhops == 0)
794: return ((struct mbuf *)0);
795: m = m_get(M_DONTWAIT, MT_SOOPTS);
796: if (m == 0)
797: return ((struct mbuf *)0);
798:
799: #define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt))
800:
801: /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */
802: m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) +
803: OPTSIZ;
804: #ifdef DEBUG
805: if (ipprintfs)
806: printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len);
807: #endif
808:
809: /*
810: * First save first hop for return route
811: */
812: p = &ip_srcrt.route[ip_nhops - 1];
813: *(mtod(m, struct in_addr *)) = *p--;
814: #ifdef DEBUG
815: if (ipprintfs)
816: printf(" hops %X", ntohl(*mtod(m, struct in_addr *)));
817: #endif
818:
819: /*
820: * Copy option fields and padding (nop) to mbuf.
821: */
822: ip_srcrt.nop = IPOPT_NOP;
823: ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
824: bcopy((caddr_t)&ip_srcrt.nop,
825: mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ);
826: q = (struct in_addr *)(mtod(m, caddr_t) +
827: sizeof(struct in_addr) + OPTSIZ);
828: #undef OPTSIZ
829: /*
830: * Record return path as an IP source route,
831: * reversing the path (pointers are now aligned).
832: */
833: while (p >= ip_srcrt.route) {
834: #ifdef DEBUG
835: if (ipprintfs)
836: printf(" %X", ntohl(*q));
837: #endif
838: *q++ = *p--;
839: }
840: /*
841: * Last hop goes to final destination.
842: */
843: *q = ip_srcrt.dst;
844: #ifdef DEBUG
845: if (ipprintfs)
846: printf(" %X\n", ntohl(*q));
847: #endif
848: return (m);
849: }
850:
851: /*
852: * Strip out IP options, at higher
853: * level protocol in the kernel.
854: * Second argument is buffer to which options
855: * will be moved, and return value is their length.
856: * XXX should be deleted; last arg currently ignored.
857: */
858: ip_stripoptions(m, mopt)
859: register struct mbuf *m;
860: struct mbuf *mopt;
861: {
862: register int i;
863: struct ip *ip = mtod(m, struct ip *);
864: register caddr_t opts;
865: int olen;
866:
867: olen = (ip->ip_hl<<2) - sizeof (struct ip);
868: opts = (caddr_t)(ip + 1);
869: i = m->m_len - (sizeof (struct ip) + olen);
870: bcopy(opts + olen, opts, (unsigned)i);
871: m->m_len -= olen;
872: if (m->m_flags & M_PKTHDR)
873: m->m_pkthdr.len -= olen;
874: ip->ip_hl = sizeof(struct ip) >> 2;
875: }
876:
877: u_char inetctlerrmap[PRC_NCMDS] = {
878: 0, 0, 0, 0,
879: 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
880: EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
881: EMSGSIZE, EHOSTUNREACH, 0, 0,
882: 0, 0, 0, 0,
883: ENOPROTOOPT
884: };
885:
886: /*
887: * Forward a packet. If some error occurs return the sender
888: * an icmp packet. Note we can't always generate a meaningful
889: * icmp message because icmp doesn't have a large enough repertoire
890: * of codes and types.
891: *
892: * If not forwarding, just drop the packet. This could be confusing
893: * if ipforwarding was zero but some routing protocol was advancing
894: * us as a gateway to somewhere. However, we must let the routing
895: * protocol deal with that.
896: *
897: * The srcrt parameter indicates whether the packet is being forwarded
898: * via a source route.
899: */
900: ip_forward(m, srcrt)
901: struct mbuf *m;
902: int srcrt;
903: {
904: register struct ip *ip = mtod(m, struct ip *);
905: register struct sockaddr_in *sin;
906: register struct rtentry *rt;
907: int error, type = 0, code;
908: struct mbuf *mcopy;
909: struct in_addr dest;
910:
911: dest.s_addr = 0;
912: #ifdef DEBUG
913: if (ipprintfs)
914: printf("forward: src %x dst %x ttl %x\n", ip->ip_src,
915: ip->ip_dst, ip->ip_ttl);
916: #endif
917: if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) {
918: ipstat.ips_cantforward++;
919: m_freem(m);
920: return;
921: }
922: HTONS(ip->ip_id);
923: if (ip->ip_ttl <= IPTTLDEC) {
924: icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest);
925: return;
926: }
927: ip->ip_ttl -= IPTTLDEC;
928:
929: sin = (struct sockaddr_in *)&ipforward_rt.ro_dst;
930: if ((rt = ipforward_rt.ro_rt) == 0 ||
931: ip->ip_dst.s_addr != sin->sin_addr.s_addr) {
932: if (ipforward_rt.ro_rt) {
933: RTFREE(ipforward_rt.ro_rt);
934: ipforward_rt.ro_rt = 0;
935: }
936: sin->sin_family = AF_INET;
937: sin->sin_len = sizeof(*sin);
938: sin->sin_addr = ip->ip_dst;
939:
940: rtalloc(&ipforward_rt);
941: if (ipforward_rt.ro_rt == 0) {
942: icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest);
943: return;
944: }
945: rt = ipforward_rt.ro_rt;
946: }
947:
948: /*
949: * Save at most 64 bytes of the packet in case
950: * we need to generate an ICMP message to the src.
951: */
952: mcopy = m_copy(m, 0, imin((int)ip->ip_len, 64));
953:
954: #ifdef GATEWAY
955: ip_ifmatrix[rt->rt_ifp->if_index +
956: if_index * m->m_pkthdr.rcvif->if_index]++;
957: #endif
958: /*
959: * If forwarding packet using same interface that it came in on,
960: * perhaps should send a redirect to sender to shortcut a hop.
961: * Only send redirect if source is sending directly to us,
962: * and if packet was not source routed (or has any options).
963: * Also, don't send redirect if forwarding using a default route
964: * or a route modified by a redirect.
965: */
966: #define satosin(sa) ((struct sockaddr_in *)(sa))
967: if (rt->rt_ifp == m->m_pkthdr.rcvif &&
968: (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
969: satosin(rt_key(rt))->sin_addr.s_addr != 0 &&
970: ipsendredirects && !srcrt) {
971: struct in_ifaddr *ia;
972: u_long src = ntohl(ip->ip_src.s_addr);
973: u_long dst = ntohl(ip->ip_dst.s_addr);
974:
975: if ((ia = ifptoia(m->m_pkthdr.rcvif)) &&
976: (src & ia->ia_subnetmask) == ia->ia_subnet) {
977: if (rt->rt_flags & RTF_GATEWAY)
978: dest = satosin(rt->rt_gateway)->sin_addr;
979: else
980: dest = ip->ip_dst;
981: /*
982: * If the destination is reached by a route to host,
983: * is on a subnet of a local net, or is directly
984: * on the attached net (!), use host redirect.
985: * (We may be the correct first hop for other subnets.)
986: */
987: #define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa))
988: type = ICMP_REDIRECT;
989: if ((rt->rt_flags & RTF_HOST) ||
990: (rt->rt_flags & RTF_GATEWAY) == 0)
991: code = ICMP_REDIRECT_HOST;
992: else if (RTA(rt)->ia_subnetmask != RTA(rt)->ia_netmask &&
993: (dst & RTA(rt)->ia_netmask) == RTA(rt)->ia_net)
994: code = ICMP_REDIRECT_HOST;
995: else
996: code = ICMP_REDIRECT_NET;
997: #ifdef DEBUG
998: if (ipprintfs)
999: printf("redirect (%d) to %x\n", code, dest.s_addr);
1000: #endif
1001: }
1002: }
1003:
1004: error = ip_output(m, (struct mbuf *)0, &ipforward_rt, IP_FORWARDING);
1005: if (error)
1006: ipstat.ips_cantforward++;
1007: else {
1008: ipstat.ips_forward++;
1009: if (type)
1010: ipstat.ips_redirectsent++;
1011: else {
1012: if (mcopy)
1013: m_freem(mcopy);
1014: return;
1015: }
1016: }
1017: if (mcopy == NULL)
1018: return;
1019: switch (error) {
1020:
1021: case 0: /* forwarded, but need redirect */
1022: /* type, code set above */
1023: break;
1024:
1025: case ENETUNREACH: /* shouldn't happen, checked above */
1026: case EHOSTUNREACH:
1027: case ENETDOWN:
1028: case EHOSTDOWN:
1029: default:
1030: type = ICMP_UNREACH;
1031: code = ICMP_UNREACH_HOST;
1032: break;
1033:
1034: case EMSGSIZE:
1035: type = ICMP_UNREACH;
1036: code = ICMP_UNREACH_NEEDFRAG;
1037: ipstat.ips_cantfrag++;
1038: break;
1039:
1040: case ENOBUFS:
1041: type = ICMP_SOURCEQUENCH;
1042: code = 0;
1043: break;
1044: }
1045: icmp_error(mcopy, type, code, dest);
1046: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.