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