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