|
|
1.1 root 1: /* ip_input.c 6.1 83/08/16 */
2:
3: #include "../h/param.h"
4: #include "../h/systm.h"
5: #include "../h/mbuf.h"
6: #include "../h/domain.h"
7: #include "../h/protosw.h"
8: #include "../h/socket.h"
9: #include "../h/errno.h"
10: #include "../h/time.h"
11: #include "../h/kernel.h"
12:
13: #include "../net/if.h"
14: #include "../net/route.h"
15:
16: #include "../netinet/in.h"
17: #include "../netinet/in_pcb.h"
18: #include "../netinet/in_systm.h"
19: #include "../netinet/ip.h"
20: #include "../netinet/ip_var.h"
21: #include "../netinet/ip_icmp.h"
22: #include "../netinet/tcp.h"
23:
24: u_char ip_protox[IPPROTO_MAX];
25: int ipqmaxlen = IFQ_MAXLEN;
26: struct ifnet *ifinet; /* first inet interface */
27:
28: /*
29: * IP initialization: fill in IP protocol switch table.
30: * All protocols not implemented in kernel go to raw IP protocol handler.
31: */
32: ip_init()
33: {
34: register struct protosw *pr;
35: register int i;
36:
37: pr = pffindproto(PF_INET, IPPROTO_RAW);
38: if (pr == 0)
39: panic("ip_init");
40: for (i = 0; i < IPPROTO_MAX; i++)
41: ip_protox[i] = pr - inetsw;
42: for (pr = inetdomain.dom_protosw;
43: pr <= inetdomain.dom_protoswNPROTOSW; pr++)
44: if (pr->pr_family == PF_INET &&
45: pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
46: ip_protox[pr->pr_protocol] = pr - inetsw;
47: ipq.next = ipq.prev = &ipq;
48: ip_id = time.tv_sec & 0xffff;
49: ipintrq.ifq_maxlen = ipqmaxlen;
50: ifinet = if_ifwithaf(AF_INET);
51: }
52:
53: u_char ipcksum = 1;
54: struct ip *ip_reass();
55: struct sockaddr_in ipaddr = { AF_INET };
56:
57: /*
58: * Ip input routine. Checksum and byte swap header. If fragmented
59: * try to reassamble. If complete and fragment queue exists, discard.
60: * Process options. Pass to next level.
61: */
62: ipintr()
63: {
64: register struct ip *ip;
65: register struct mbuf *m;
66: struct mbuf *m0;
67: register int i;
68: register struct ipq *fp;
69: int hlen, s;
70:
71: next:
72: /*
73: * Get next datagram off input queue and get IP header
74: * in first mbuf.
75: */
76: s = splimp();
77: IF_DEQUEUE(&ipintrq, m);
78: splx(s);
79: if (m == 0)
80: return;
81: if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct ip)) &&
82: (m = m_pullup(m, sizeof (struct ip))) == 0) {
83: ipstat.ips_toosmall++;
84: goto next;
85: }
86: ip = mtod(m, struct ip *);
87: if ((hlen = ip->ip_hl << 2) > m->m_len) {
88: if ((m = m_pullup(m, hlen)) == 0) {
89: ipstat.ips_badhlen++;
90: goto next;
91: }
92: ip = mtod(m, struct ip *);
93: }
94: if (ipcksum)
95: if (ip->ip_sum = in_cksum(m, hlen)) {
96: ipstat.ips_badsum++;
97: goto bad;
98: }
99:
100: /*
101: * Convert fields to host representation.
102: */
103: ip->ip_len = ntohs((u_short)ip->ip_len);
104: if (ip->ip_len < hlen) {
105: ipstat.ips_badlen++;
106: goto bad;
107: }
108: ip->ip_id = ntohs(ip->ip_id);
109: ip->ip_off = ntohs((u_short)ip->ip_off);
110:
111: /*
112: * Check that the amount of data in the buffers
113: * is as at least much as the IP header would have us expect.
114: * Trim mbufs if longer than we expect.
115: * Drop packet if shorter than we expect.
116: */
117: i = -ip->ip_len;
118: m0 = m;
119: for (;;) {
120: i += m->m_len;
121: if (m->m_next == 0)
122: break;
123: m = m->m_next;
124: }
125: if (i != 0) {
126: if (i < 0) {
127: ipstat.ips_tooshort++;
128: goto bad;
129: }
130: if (i <= m->m_len)
131: m->m_len -= i;
132: else
133: m_adj(m0, -i);
134: }
135: m = m0;
136:
137: /*
138: * Process options and, if not destined for us,
139: * ship it on. ip_dooptions returns 1 when an
140: * error was detected (causing an icmp message
141: * to be sent).
142: */
143: if (hlen > sizeof (struct ip) && ip_dooptions(ip))
144: goto next;
145:
146: /*
147: * Fast check on the first internet
148: * interface in the list.
149: */
150: if (ifinet) {
151: struct sockaddr_in *sin;
152:
153: sin = (struct sockaddr_in *)&ifinet->if_addr;
154: if (sin->sin_addr.s_addr == ip->ip_dst.s_addr)
155: goto ours;
156: sin = (struct sockaddr_in *)&ifinet->if_broadaddr;
157: if ((ifinet->if_flags & IFF_BROADCAST) &&
158: sin->sin_addr.s_addr == ip->ip_dst.s_addr)
159: goto ours;
160: }
161: /* BEGIN GROT */
162: #include "nd.h"
163: #if NND > 0
164: /*
165: * Diskless machines don't initially know
166: * their address, so take packets from them
167: * if we're acting as a network disk server.
168: */
169: if (in_netof(ip->ip_dst) == INADDR_ANY &&
170: (in_netof(ip->ip_src) == INADDR_ANY &&
171: in_lnaof(ip->ip_src) != INADDR_ANY))
172: goto ours;
173: #endif
174: /* END GROT */
175: ipaddr.sin_addr = ip->ip_dst;
176: if (if_ifwithaddr((struct sockaddr *)&ipaddr) == 0) {
177: ip_forward(ip);
178: goto next;
179: }
180:
181: ours:
182: /*
183: * Look for queue of fragments
184: * of this datagram.
185: */
186: for (fp = ipq.next; fp != &ipq; fp = fp->next)
187: if (ip->ip_id == fp->ipq_id &&
188: ip->ip_src.s_addr == fp->ipq_src.s_addr &&
189: ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
190: ip->ip_p == fp->ipq_p)
191: goto found;
192: fp = 0;
193: found:
194:
195: /*
196: * Adjust ip_len to not reflect header,
197: * set ip_mff if more fragments are expected,
198: * convert offset of this to bytes.
199: */
200: ip->ip_len -= hlen;
201: ((struct ipasfrag *)ip)->ipf_mff = 0;
202: if (ip->ip_off & IP_MF)
203: ((struct ipasfrag *)ip)->ipf_mff = 1;
204: ip->ip_off <<= 3;
205:
206: /*
207: * If datagram marked as having more fragments
208: * or if this is not the first fragment,
209: * attempt reassembly; if it succeeds, proceed.
210: */
211: if (((struct ipasfrag *)ip)->ipf_mff || ip->ip_off) {
212: ip = ip_reass((struct ipasfrag *)ip, fp);
213: if (ip == 0)
214: goto next;
215: hlen = ip->ip_hl << 2;
216: m = dtom(ip);
217: } else
218: if (fp)
219: ip_freef(fp);
220:
221: /*
222: * Switch out to protocol's input routine.
223: */
224: (*inetsw[ip_protox[ip->ip_p]].pr_input)(m);
225: goto next;
226: bad:
227: m_freem(m);
228: goto next;
229: }
230:
231: /*
232: * Take incoming datagram fragment and try to
233: * reassemble it into whole datagram. If a chain for
234: * reassembly of this datagram already exists, then it
235: * is given as fp; otherwise have to make a chain.
236: */
237: struct ip *
238: ip_reass(ip, fp)
239: register struct ipasfrag *ip;
240: register struct ipq *fp;
241: {
242: register struct mbuf *m = dtom(ip);
243: register struct ipasfrag *q;
244: struct mbuf *t;
245: int hlen = ip->ip_hl << 2;
246: int i, next;
247:
248: /*
249: * Presence of header sizes in mbufs
250: * would confuse code below.
251: */
252: m->m_off += hlen;
253: m->m_len -= hlen;
254:
255: /*
256: * If first fragment to arrive, create a reassembly queue.
257: */
258: if (fp == 0) {
259: if ((t = m_get(M_WAIT, MT_FTABLE)) == NULL)
260: goto dropfrag;
261: fp = mtod(t, struct ipq *);
262: insque(fp, &ipq);
263: fp->ipq_ttl = IPFRAGTTL;
264: fp->ipq_p = ip->ip_p;
265: fp->ipq_id = ip->ip_id;
266: fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)fp;
267: fp->ipq_src = ((struct ip *)ip)->ip_src;
268: fp->ipq_dst = ((struct ip *)ip)->ip_dst;
269: q = (struct ipasfrag *)fp;
270: goto insert;
271: }
272:
273: /*
274: * Find a segment which begins after this one does.
275: */
276: for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next)
277: if (q->ip_off > ip->ip_off)
278: break;
279:
280: /*
281: * If there is a preceding segment, it may provide some of
282: * our data already. If so, drop the data from the incoming
283: * segment. If it provides all of our data, drop us.
284: */
285: if (q->ipf_prev != (struct ipasfrag *)fp) {
286: i = q->ipf_prev->ip_off + q->ipf_prev->ip_len - ip->ip_off;
287: if (i > 0) {
288: if (i >= ip->ip_len)
289: goto dropfrag;
290: m_adj(dtom(ip), i);
291: ip->ip_off += i;
292: ip->ip_len -= i;
293: }
294: }
295:
296: /*
297: * While we overlap succeeding segments trim them or,
298: * if they are completely covered, dequeue them.
299: */
300: while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
301: i = (ip->ip_off + ip->ip_len) - q->ip_off;
302: if (i < q->ip_len) {
303: q->ip_len -= i;
304: q->ip_off += i;
305: m_adj(dtom(q), i);
306: break;
307: }
308: q = q->ipf_next;
309: m_freem(dtom(q->ipf_prev));
310: ip_deq(q->ipf_prev);
311: }
312:
313: insert:
314: /*
315: * Stick new segment in its place;
316: * check for complete reassembly.
317: */
318: ip_enq(ip, q->ipf_prev);
319: next = 0;
320: for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) {
321: if (q->ip_off != next)
322: return (0);
323: next += q->ip_len;
324: }
325: if (q->ipf_prev->ipf_mff)
326: return (0);
327:
328: /*
329: * Reassembly is complete; concatenate fragments.
330: */
331: q = fp->ipq_next;
332: m = dtom(q);
333: t = m->m_next;
334: m->m_next = 0;
335: m_cat(m, t);
336: q = q->ipf_next;
337: while (q != (struct ipasfrag *)fp) {
338: t = dtom(q);
339: q = q->ipf_next;
340: m_cat(m, t);
341: }
342:
343: /*
344: * Create header for new ip packet by
345: * modifying header of first packet;
346: * dequeue and discard fragment reassembly header.
347: * Make header visible.
348: */
349: ip = fp->ipq_next;
350: ip->ip_len = next;
351: ((struct ip *)ip)->ip_src = fp->ipq_src;
352: ((struct ip *)ip)->ip_dst = fp->ipq_dst;
353: remque(fp);
354: (void) m_free(dtom(fp));
355: m = dtom(ip);
356: m->m_len += sizeof (struct ipasfrag);
357: m->m_off -= sizeof (struct ipasfrag);
358: return ((struct ip *)ip);
359:
360: dropfrag:
361: m_freem(m);
362: return (0);
363: }
364:
365: /*
366: * Free a fragment reassembly header and all
367: * associated datagrams.
368: */
369: ip_freef(fp)
370: struct ipq *fp;
371: {
372: register struct ipasfrag *q, *p;
373:
374: for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = p) {
375: p = q->ipf_next;
376: ip_deq(q);
377: m_freem(dtom(q));
378: }
379: remque(fp);
380: (void) m_free(dtom(fp));
381: }
382:
383: /*
384: * Put an ip fragment on a reassembly chain.
385: * Like insque, but pointers in middle of structure.
386: */
387: ip_enq(p, prev)
388: register struct ipasfrag *p, *prev;
389: {
390:
391: p->ipf_prev = prev;
392: p->ipf_next = prev->ipf_next;
393: prev->ipf_next->ipf_prev = p;
394: prev->ipf_next = p;
395: }
396:
397: /*
398: * To ip_enq as remque is to insque.
399: */
400: ip_deq(p)
401: register struct ipasfrag *p;
402: {
403:
404: p->ipf_prev->ipf_next = p->ipf_next;
405: p->ipf_next->ipf_prev = p->ipf_prev;
406: }
407:
408: /*
409: * IP timer processing;
410: * if a timer expires on a reassembly
411: * queue, discard it.
412: */
413: ip_slowtimo()
414: {
415: register struct ipq *fp;
416: int s = splnet();
417:
418: fp = ipq.next;
419: if (fp == 0) {
420: splx(s);
421: return;
422: }
423: while (fp != &ipq) {
424: --fp->ipq_ttl;
425: fp = fp->next;
426: if (fp->prev->ipq_ttl == 0)
427: ip_freef(fp->prev);
428: }
429: splx(s);
430: }
431:
432: /*
433: * Drain off all datagram fragments.
434: */
435: ip_drain()
436: {
437:
438: while (ipq.next != &ipq)
439: ip_freef(ipq.next);
440: }
441:
442: /*
443: * Do option processing on a datagram,
444: * possibly discarding it if bad options
445: * are encountered.
446: */
447: ip_dooptions(ip)
448: struct ip *ip;
449: {
450: register u_char *cp;
451: int opt, optlen, cnt, code, type;
452: struct in_addr *sin;
453: register struct ip_timestamp *ipt;
454: register struct ifnet *ifp;
455: struct in_addr t;
456:
457: cp = (u_char *)(ip + 1);
458: cnt = (ip->ip_hl << 2) - sizeof (struct ip);
459: for (; cnt > 0; cnt -= optlen, cp += optlen) {
460: opt = cp[0];
461: if (opt == IPOPT_EOL)
462: break;
463: if (opt == IPOPT_NOP)
464: optlen = 1;
465: else
466: optlen = cp[1];
467: switch (opt) {
468:
469: default:
470: break;
471:
472: /*
473: * Source routing with record.
474: * Find interface with current destination address.
475: * If none on this machine then drop if strictly routed,
476: * or do nothing if loosely routed.
477: * Record interface address and bring up next address
478: * component. If strictly routed make sure next
479: * address on directly accessible net.
480: */
481: case IPOPT_LSRR:
482: case IPOPT_SSRR:
483: if (cp[2] < 4 || cp[2] > optlen - (sizeof (long) - 1))
484: break;
485: sin = (struct in_addr *)(cp + cp[2]);
486: ipaddr.sin_addr = *sin;
487: ifp = if_ifwithaddr((struct sockaddr *)&ipaddr);
488: type = ICMP_UNREACH, code = ICMP_UNREACH_SRCFAIL;
489: if (ifp == 0) {
490: if (opt == IPOPT_SSRR)
491: goto bad;
492: break;
493: }
494: t = ip->ip_dst; ip->ip_dst = *sin; *sin = t;
495: cp[2] += 4;
496: if (cp[2] > optlen - (sizeof (long) - 1))
497: break;
498: ip->ip_dst = sin[1];
499: if (opt == IPOPT_SSRR &&
500: if_ifonnetof(in_netof(ip->ip_dst)) == 0)
501: goto bad;
502: break;
503:
504: case IPOPT_TS:
505: code = cp - (u_char *)ip;
506: type = ICMP_PARAMPROB;
507: ipt = (struct ip_timestamp *)cp;
508: if (ipt->ipt_len < 5)
509: goto bad;
510: if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) {
511: if (++ipt->ipt_oflw == 0)
512: goto bad;
513: break;
514: }
515: sin = (struct in_addr *)(cp+cp[2]);
516: switch (ipt->ipt_flg) {
517:
518: case IPOPT_TS_TSONLY:
519: break;
520:
521: case IPOPT_TS_TSANDADDR:
522: if (ipt->ipt_ptr + 8 > ipt->ipt_len)
523: goto bad;
524: if (ifinet == 0)
525: goto bad; /* ??? */
526: *sin++ = ((struct sockaddr_in *)&ifinet->if_addr)->sin_addr;
527: break;
528:
529: case IPOPT_TS_PRESPEC:
530: ipaddr.sin_addr = *sin;
531: if (if_ifwithaddr((struct sockaddr *)&ipaddr) == 0)
532: continue;
533: if (ipt->ipt_ptr + 8 > ipt->ipt_len)
534: goto bad;
535: ipt->ipt_ptr += 4;
536: break;
537:
538: default:
539: goto bad;
540: }
541: *(n_time *)sin = iptime();
542: ipt->ipt_ptr += 4;
543: }
544: }
545: return (0);
546: bad:
547: icmp_error(ip, type, code);
548: return (1);
549: }
550:
551: /*
552: * Strip out IP options, at higher
553: * level protocol in the kernel.
554: * Second argument is buffer to which options
555: * will be moved, and return value is their length.
556: */
557: ip_stripoptions(ip, mopt)
558: struct ip *ip;
559: struct mbuf *mopt;
560: {
561: register int i;
562: register struct mbuf *m;
563: int olen;
564:
565: olen = (ip->ip_hl<<2) - sizeof (struct ip);
566: m = dtom(ip);
567: ip++;
568: if (mopt) {
569: mopt->m_len = olen;
570: mopt->m_off = MMINOFF;
571: bcopy((caddr_t)ip, mtod(m, caddr_t), (unsigned)olen);
572: }
573: i = m->m_len - (sizeof (struct ip) + olen);
574: bcopy((caddr_t)ip+olen, (caddr_t)ip, (unsigned)i);
575: m->m_len -= olen;
576: }
577:
578: u_char inetctlerrmap[PRC_NCMDS] = {
579: ECONNABORTED, ECONNABORTED, 0, 0,
580: 0, 0, EHOSTDOWN, EHOSTUNREACH,
581: ENETUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
582: EMSGSIZE, 0, 0, 0,
583: 0, 0, 0, 0
584: };
585:
586: ip_ctlinput(cmd, arg)
587: int cmd;
588: caddr_t arg;
589: {
590: struct in_addr *in;
591: int tcp_abort(), udp_abort();
592: extern struct inpcb tcb, udb;
593:
594: if (cmd < 0 || cmd > PRC_NCMDS)
595: return;
596: if (inetctlerrmap[cmd] == 0)
597: return; /* XXX */
598: if (cmd == PRC_IFDOWN)
599: in = &((struct sockaddr_in *)arg)->sin_addr;
600: else if (cmd == PRC_HOSTDEAD || cmd == PRC_HOSTUNREACH)
601: in = (struct in_addr *)arg;
602: else
603: in = &((struct icmp *)arg)->icmp_ip.ip_dst;
604: /* THIS IS VERY QUESTIONABLE, SHOULD HIT ALL PROTOCOLS */
605: in_pcbnotify(&tcb, in, (int)inetctlerrmap[cmd], tcp_abort);
606: in_pcbnotify(&udb, in, (int)inetctlerrmap[cmd], udp_abort);
607: }
608:
609: int ipprintfs = 0;
610: int ipforwarding = 1;
611: /*
612: * Forward a packet. If some error occurs return the sender
613: * and icmp packet. Note we can't always generate a meaningful
614: * icmp message because icmp doesn't have a large enough repetoire
615: * of codes and types.
616: */
617: ip_forward(ip)
618: register struct ip *ip;
619: {
620: register int error, type, code;
621: struct mbuf *mopt, *mcopy;
622:
623: if (ipprintfs)
624: printf("forward: src %x dst %x ttl %x\n", ip->ip_src,
625: ip->ip_dst, ip->ip_ttl);
626: if (ipforwarding == 0) {
627: /* can't tell difference between net and host */
628: type = ICMP_UNREACH, code = ICMP_UNREACH_NET;
629: goto sendicmp;
630: }
631: if (ip->ip_ttl < IPTTLDEC) {
632: type = ICMP_TIMXCEED, code = ICMP_TIMXCEED_INTRANS;
633: goto sendicmp;
634: }
635: ip->ip_ttl -= IPTTLDEC;
636: mopt = m_get(M_DONTWAIT, MT_DATA);
637: if (mopt == NULL) {
638: m_freem(dtom(ip));
639: return;
640: }
641:
642: /*
643: * Save at most 64 bytes of the packet in case
644: * we need to generate an ICMP message to the src.
645: */
646: mcopy = m_copy(dtom(ip), 0, imin(ip->ip_len, 64));
647: ip_stripoptions(ip, mopt);
648:
649: error = ip_output(dtom(ip), mopt, (struct route *)0, IP_FORWARDING);
650: if (error == 0) {
651: if (mcopy)
652: m_freem(mcopy);
653: return;
654: }
655: if (mcopy == NULL)
656: return;
657: ip = mtod(mcopy, struct ip *);
658: type = ICMP_UNREACH, code = 0; /* need ``undefined'' */
659: switch (error) {
660:
661: case ENETUNREACH:
662: case ENETDOWN:
663: code = ICMP_UNREACH_NET;
664: break;
665:
666: case EMSGSIZE:
667: code = ICMP_UNREACH_NEEDFRAG;
668: break;
669:
670: case EPERM:
671: code = ICMP_UNREACH_PORT;
672: break;
673:
674: case ENOBUFS:
675: type = ICMP_SOURCEQUENCH;
676: break;
677:
678: case EHOSTDOWN:
679: case EHOSTUNREACH:
680: code = ICMP_UNREACH_HOST;
681: break;
682: }
683: sendicmp:
684: icmp_error(ip, type, code);
685: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.