1 #ifdef	RCSIDENT
2 static char rcsident[] = "$Header: ip_input.c,v 1.39 85/07/31 09:31:26 walsh Exp $";
3 #endif
4 
5 #include "../h/param.h"
6 #include "../h/mbuf.h"
7 #include "../h/socket.h"
8 #include "../h/socketvar.h"
9 #include "../h/errno.h"
10 #include "../h/protosw.h"
11 #include "../h/domain.h"
12 #include "../h/syslog.h"
13 
14 #include "../net/if.h"
15 #include "../net/route.h"
16 #include "../net/raw_cb.h"
17 
18 #include "../bbnnet/in.h"
19 #include "../bbnnet/net.h"
20 #include "../bbnnet/in_pcb.h"
21 #include "../bbnnet/in_var.h"
22 #include "../bbnnet/ip.h"
23 #include "../bbnnet/icmp.h"
24 #ifdef	HMP
25 #include "../bbnnet/hmp_traps.h"
26 #endif
27 
28 #ifdef	RCSIDENT
29 static char rcsiphdr[] = RCSIPHDR;
30 #endif
31 
32 #define rawreaders(r)	 	((r)->rcb_next != (r))
33 #define any_rawreaders()	rawreaders(&rawcb)
34 
35 #define FIELD_OFF(fld, type) (((char *) (&(((type *) 0)->fld))) - ((char *) 0))
36 
37 struct in_stat otherstat;
38 struct ip_stat ipstat;
39 struct {
40  	struct ipq *n_ip_head;		/* -> top of ip reass. queue */
41 	struct ipq *n_ip_tail;		/* -> end of ip reass. queue */
42 } ipfrags;
43 
44 
45 /*
46  * The protocol layers above IP assume the IP header and the protocol
47  * header are contiguous.  However, need to save the options in case
48  * a connection oriented protocol (RDP/TCP) wants to respond to an
49  * incoming packet (SYN) over the same route if the packet got here
50  * using IP source routing.  This allows connection establishment and
51  * maintenance when the remote end is on a network that is not known
52  * to our gateways.  Only applicable options are Loose/Strict source
53  * routing, so rather than saving them in ip_stripopt() and reinterpreting
54  * them, we'll set up something specific and appropriate here.
55  */
56 
57 int nosum = 0;
58 int	ip_nhops = 0;
59 struct in_addr ip_hops[MAX_IPOPTLEN / sizeof(struct in_addr)];
60 
61 /* use a dispatch table for protocol dispatching */
62 struct ipswitch ipsw[IPPROTO_MAX];
63 
64 extern struct ip *ip_reass();
65 
66 
ip_init()67 ip_init()
68 {
69     register struct protosw *pr;
70     register int i;
71 
72     pr = pffindproto(PF_INET, IPPROTO_IP, SOCK_RAW);
73 
74     /* build our internal switch table */
75     for(i=0; i < IPPROTO_MAX; i++)
76     {
77 	ipsw[i].ipsw_raw = pr;
78 	ipsw[i].ipsw_user = 0;
79 	ipsw[i].ipsw_hlen = sizeof(struct ip);
80     }
81 
82     for(pr = inetdomain.dom_protosw; pr < inetdomain.dom_protoswNPROTOSW; pr++)
83     {
84 	if (pr->pr_protocol >= IPPROTO_MAX)
85 	    panic("ip_init");
86 
87 	if (pr->pr_type == SOCK_RAW)
88 	    ipsw[pr->pr_protocol].ipsw_raw = pr;
89 	else
90 	    ipsw[pr->pr_protocol].ipsw_user = pr;
91     }
92 
93     ipintrq.ifq_maxlen = IFQ_MAXLEN;	/* got a better number? */
94 }
95 
96 /*
97  * Being global might be a little gross, but we just got the interface pointer
98  * passed up the week before 4.3 release.
99  */
100 struct ifnet *inetifp;
101 
102 /*
103  * IP network software interrupt service routine.  Dequeue a message from the
104  * ip input queue, and pass to internal ip input processor (ip_input).
105  */
ipintr()106 ipintr()
107 {
108     extern char *panicstr;
109     register struct mbuf *m;
110     register int s;
111 
112     /*
113      * Half-hearted attempt to prevent recursive panics due to network
114      * bugs since panic calls boot, which lowers spl.  Note that the
115      * drivers will still store packets in mbufs and that some processing
116      * (ARP, Chaosnet) that occurs at splimp() will still proceed.  At
117      * least this should preserve state information for post-mortem.
118      */
119     if (panicstr == NULL)
120     {
121 	for (;;)
122 	{
123 	    /* for 4.3, Berkeley finally changed imp code to queue up messages
124 	     * for ctlinput path, so don't need to check for them here with our
125 	     * old queueing mechanism
126 	     */
127 
128 	    s = splimp();
129 	    IF_DEQUEUEIF (&ipintrq, m, inetifp);
130 	    splx(s);
131 	    if (m == NULL)
132 		return;
133 
134 	    ip_input(m);
135 	}
136     }
137 }
138 
139 /*
140  * IP level input routine
141  *
142  * Called from local net level upon recpt of an internet datagram or fragment.
143  * This routine does fragment reassembly, if necessary, and passes completed
144  * datagrams to higher level protocol processing routines on the basis of the
145  * ip header protocol field.  It is passed a pointer to an mbuf chain
146  * containing the datagram/fragment. The mbuf offset+length are set to point
147  * at the ip header.
148  */
ip_input(mp)149 ip_input(mp)
150 register struct mbuf *mp;
151 {
152     register struct ip *ip;
153     register int hlen;
154     register int i;
155     register struct mbuf *m;
156     register struct ipq *fp;
157     int fragsize = 0;
158     struct in_ifaddr *ia;
159     int j;
160     struct inpcb fwdinp;
161 
162     ipstat.ip_total ++;
163     /*
164      * make sure dtom() macro works by getting header out of mbufs using
165      * pages, also make sure header contiguous in first mbuf.
166      */
167     if ((mp->m_off > MMAXOFF) || (mp->m_len < sizeof(struct ip)))
168     {
169 	/*
170 	 * Might as well avoid doing m_pullup twice.
171 	 * Common case is using cluster for large chunk of data.
172 	 */
173 	if (mp->m_len < FIELD_OFF(ip_p, struct ip) + sizeof(ip->ip_p))
174 	    i = sizeof(struct ip);
175 	else
176 	{
177 	    ip = mtod(mp, struct ip *);
178 	    i = ipsw[ip->ip_p].ipsw_hlen;
179 	}
180 
181 	if ((mp = m_pullup(mp, i)) == NULL)
182 	{
183 	    ipstat.ip_tooshort ++;
184 	    return;
185 	}
186     }
187 
188     ip = mtod(mp, struct ip *);
189 
190     /*
191      * make sure header does not overflow mbuf  (is contiguous)
192      */
193     hlen = ip->ip_hl << IP_HLSHIFT;
194     if (hlen > mp->m_len)
195     {
196 	if ((mp = m_pullup(mp, hlen)) == NULL)
197 	{
198 	    ip_log(ip, "ip header overflow");
199 #ifdef HMPTRAPS
200 	    /* hmp_trap(T_IP_OVFLO, (caddr_t)0,0); */
201 #else
202 	    /* netlog(mp); no longer have mbuf list */
203 #endif
204 	    return;
205 	}
206 	ip = mtod(mp, struct ip *);
207     }
208 
209     /*
210      * Adjust msg length to remove any driver padding.  Make sure that
211      * message length matches ip length.
212      */
213     for (i = 0, m = mp; m->m_next != NULL; m = m->m_next)
214 	i += m->m_len;
215     i -= ntohs((u_short)ip->ip_len) - m->m_len;
216     if (i != 0)
217     {
218 	if (i > (int)m->m_len)
219 	    m_adj(mp, -i);
220 	else if (i < 0)
221 	{
222 	    ip_log(ip, "truncated ip packet");
223 #ifdef HMPTRAPS
224 	    /* hmp_trap(T_IP_TRUNC, (caddr_t)0, 0); */
225 #else
226 	    netlog(mp);
227 #endif
228 	    return;
229 	}
230 	else
231 	    m->m_len -= i;
232     }
233 
234     i = (u_short)ip->ip_sum;
235     ip->ip_sum = 0;
236 
237     /* used to do inline cksum here via sed */
238     if (i != (j = (u_short)in_cksum(dtom(ip), hlen)))
239     {
240 	ipstat.ip_badsum++;
241 	if (!nosum)
242 	{
243 #ifdef HMPTRAPS
244 	    /* hmp_trap(T_IP_CKSUM, (caddr_t)0,0); */
245 #endif
246 	    inet_cksum_err ("ip", ip, (u_long) i, (u_long) j);
247 
248 	    ip->ip_sum = i;
249 	    ic_errmsg (icmp_addr(ip), ip->ip_src,
250 		ICMP_PARM, 0, FIELD_OFF(ip_sum, struct ip),
251 		hlen + ICMP_ERRLEN, (char *) ip);
252 
253 	    netlog(mp);
254 	    return;
255 	}
256     }
257 
258     /*
259      * Make sure this packet is addressed to us before we put fields
260      * in host order and do reassembly (fragments may reach destination
261      * by separate routes.)
262      * Remember that IP source routing option can change ip_dst, so have
263      * to do option processing for all incoming packets with options.
264      * Even if the packet turns out to be for us and we strip them.
265      */
266     fwdinp.inp_route.ro_rt = NULL; /* in case fwd, but no options */
267     ip_nhops = 0;	/* for source routed TCP/RDP... connections */
268     if (hlen > sizeof(struct ip))
269 	/*
270 	 * Any route allocated by ip_opt() 1. will be used by
271 	 * ip_forward(), and 2. will only be needed by ip_forward()
272 	 */
273 	if (! ip_opt (ip, hlen, &fwdinp))
274 	{
275 	    ip_log (ip, "ip option error");
276 	    netlog (mp);
277 	    return;
278 	}
279 
280     /*
281      * if packet is not for us then forward
282      */
283     if ((ia = in_iawithaddr(ip->ip_dst, TRUE)) == NULL)
284     {
285 	ip_forward (&fwdinp, ip, mp, hlen);
286 	return;
287     }
288 
289     ip->ip_len = ntohs((u_short)ip->ip_len);
290     if ((int)(ip->ip_len -= hlen) < 0)
291     {     /* length of data */
292 	ip_log(ip, "ip header length error");
293 #ifdef HMPTRAPS
294 	/* hmp_trap(T_IP_HLEN, (caddr_t)0,0); */
295 #else
296 	netlog(mp);
297 #endif
298 	return;
299     }
300     ip->ip_off = ntohs((u_short)ip->ip_off);
301     ip->ip_mff = ((ip->ip_off & ip_mf) ? TRUE : FALSE);
302     ip->ip_off <<= IP_OFFSHIFT;
303 
304     /* look for chain on reassembly queue with this header */
305 
306     for (fp = ipfrags.n_ip_head; (fp != NULL && (
307 	ip->ip_src.s_addr != fp->iqh.ip_src.s_addr ||
308 	ip->ip_dst.s_addr != fp->iqh.ip_dst.s_addr ||
309 	ip->ip_id != fp->iqh.ip_id ||
310 	ip->ip_p != fp->iqh.ip_p)); fp = fp->iq_next);
311 
312     if (!ip->ip_mff && ip->ip_off == 0)
313     {    /* not fragmented */
314 
315 	if (fp != NULL)
316 	{               /* free existing reass chain */
317 	    struct ip *q;
318 	    struct ip *p;
319 
320 	    q = fp->iqx.ip_next; /* free mbufs assoc. w/chain */
321 	    while (q != (struct ip *)fp)
322 	    {
323 		p = q->ip_next;
324 		m_freem(dtom(q));
325 		q = p;
326 	    }
327 	    ip_freef(fp); /* free header */
328 	}
329 
330 	/*
331 	 * The options aren't of any use to higher level
332 	 * protocols or of any concern to the user process.
333 	 */
334 	if (hlen > sizeof(struct ip))
335 	    ip_stripopt (ip, hlen);
336 
337     }
338     else
339     {
340 	ip = ip_reass(ip, fp, &fragsize);
341 	if (ip == NULL)
342 	    return;
343 	mp = dtom(ip);
344     }
345 
346     /* call next level with completed datagram */
347 
348     /* any raw readers?? */
349     /* if (rawreaders((struct rawcb *)ipsw[ip->ip_p].ipsw_raw->pr_ppcbq)) */
350     if (any_rawreaders())
351     {
352 	otherstat.in_total++;
353 	if (m = m_copy(mp, 0, M_COPYALL))
354 	    ipsw[ip->ip_p].ipsw_raw->pr_input(m);
355     }
356 
357     if (ip->ip_p == IPPROTO_TCP)
358 	/* wish I didn't need this special case for fragsize */
359 	tcp_input(mp, fragsize);
360     else if (ipsw[ip->ip_p].ipsw_user != 0)
361 	/* There's a protocol implementation for these packets */
362 	ipsw[ip->ip_p].ipsw_user->pr_input(mp);
363     else if (ip->ip_p == IPPROTO_ICMP)
364 	/*
365 	 * Since don't want user to get a non-raw ICMP socket, did not make
366 	 * an entry in the protocol jump table; also wanted to be able to
367 	 * make raw ICMP socket.
368 	 */
369 	icmp (mp);
370     else
371     {
372 	/*
373 	 * Don't bother everyone on the net, and remember some other
374 	 * host may support the protocol.
375 	 */
376 	if ((!in_broadcast(ip->ip_src)) && (!in_broadcast(ip->ip_dst)))
377 	    ic_errmsg (icmp_addr(ip), ip->ip_src,
378 		ICMP_UNRCH, ICMP_UNRCH_PR, FIELD_OFF(ip_p, struct ip),
379 		sizeof(struct ip) + ICMP_ERRLEN, (char *) ip);
380 
381 	/* get rid of the packet */
382 	ipstat.ip_drops++;
383 	m_freem(mp);
384     }
385 }
386 
387 
388 /*
389  * We've received an IP fragment.  Try to perform IP reassembly.
390  */
ip_reass(ip,fp,fragsize)391 struct ip *ip_reass(ip, fp, fragsize)
392 register struct ip *ip;
393 register struct ipq *fp;
394 int *fragsize;
395 {
396     register struct ip *q, *savq;
397     register struct mbuf *mp;
398     int hlen;
399     int i;
400 
401     mp = dtom(ip);
402     hlen = ip->ip_hl << IP_HLSHIFT;
403 
404     if (ip->ip_off != 0)
405     {
406 	/*
407 	 * Only the first fragment retains the IP header.
408 	 */
409 	mp->m_off += hlen;
410 	mp->m_len -= hlen;
411     }
412 
413     if (fp == NULL)
414     {
415 	/*
416 	 * This is the first fragment of the IP datagram that we've
417 	 * received.  Set up reassembly q header.
418 	 */
419 	struct mbuf *m;
420 
421 	if ((m = m_get(M_WAIT, MT_FTABLE)) == NULL)
422 	{
423 	    m_freem(mp);
424 	    return(NULL);
425 	}
426 
427 	fp = mtod(m, struct ipq *);
428 	fp->iqx.ip_next = fp->iqx.ip_prev = (struct ip *)fp;
429 	bcopy((caddr_t)ip, (caddr_t)&fp->iqh, sizeof(struct ip));
430 	fp->iqx.ip_ttl	= MAXTTL;
431 	fp->iq_size	= 0;
432 	/*
433 	 * and enter this into the list of fragmented IP datagrams
434 	 */
435 	fp->iq_next	= NULL;
436 	fp->iq_prev	= ipfrags.n_ip_tail;
437 	if (ipfrags.n_ip_head != NULL)
438 	    ipfrags.n_ip_tail->iq_next = fp;
439 	else
440 	    ipfrags.n_ip_head = fp;
441 	ipfrags.n_ip_tail = fp;
442     }
443 
444     /*
445      * Merge fragment into reass.q
446      *
447      * Algorithm:   Match  start  and  end  bytes  of new
448      * fragment  with  fragments  on  the  queue.   If no
449      * overlaps  are  found,  add  new  frag. to the queue.
450      * Otherwise, adjust start and end of new frag.  so  no
451      * overlap   and   add  remainder  to  queue.   If  any
452      * fragments are completely covered by the new one,  or
453      * if  the  new  one is completely duplicated, free the
454      * fragments.
455      */
456     q = fp->iqx.ip_next; /* -> top of reass. chain */
457     ip->ip_end = ip->ip_off + ip->ip_len - 1;
458 
459     /* record the maximum fragment size for TCP */
460 
461     fp->iq_size = MAX(ip->ip_len, fp->iq_size);
462 
463     /* skip frags which new doesn't overlap at end */
464 
465     while ((q != (struct ip *)fp) && (ip->ip_off > q->ip_end))
466 	q = q->ip_next;
467 
468     if (q == (struct ip *)fp)
469     {	/* frag at end of chain */
470 	ip_enq(ip, fp->iqx.ip_prev);
471     }
472     else
473     {			/* frag doesn't overlap any */
474 	if (ip->ip_end < q->ip_off)
475 	{
476 	    ip_enq(ip, q->ip_prev);
477 
478 	    /* new overlaps beginning of next frag only */
479 
480 	}
481 	else if (ip->ip_end < q->ip_end)
482 	{
483 	    if ((i = ip->ip_end-q->ip_off+1) < ip->ip_len)
484 	    {
485 		ip->ip_len -= i;
486 		ip->ip_end -= i;
487 		m_adj(mp, -i);
488 		ip_enq(ip, q->ip_prev);
489 	    }
490 	    else
491 		m_freem(mp);
492 
493 	    /* new overlaps end of previous frag */
494 
495 	}
496 	else
497 	{
498 	    savq = q;
499 	    if (ip->ip_off <= q->ip_off)
500 	    {
501 
502 		/* complete cover */
503 
504 		savq = q->ip_prev;
505 		ip_deq(q);
506 		m_freem(dtom(q));
507 
508 	    }
509 	    else
510 	    {	/* overlap */
511 		if ((i = q->ip_end-ip->ip_off+1)
512 		    < ip->ip_len)
513 		{
514 		    ip->ip_off += i;
515 		    ip->ip_len -= i;
516 		    m_adj(mp, i);
517 		}
518 		else
519 		    ip->ip_len = 0;
520 	    }
521 
522 	    /* new overlaps at beginning of successor frags */
523 
524 	    q = savq->ip_next;
525 	    while ((q != (struct ip *)fp) &&
526 		(ip->ip_len != 0) &&
527 		(q->ip_off <= ip->ip_end))
528 
529 		/* complete cover */
530 
531 		if (q->ip_end <= ip->ip_end)
532 		{
533 		    struct ip *next;
534 
535 		    next = q->ip_next;
536 		    ip_deq(q);
537 		    m_freem(dtom(q));
538 		    q = next;
539 		}
540 		else
541 		{        /* overlap */
542 		    if ((i = ip->ip_end-q->ip_off+1) < ip->ip_len)
543 		    {
544 			ip->ip_len -= i;
545 			ip->ip_end -= i;
546 			m_adj(mp, -i);
547 		    }
548 		    else
549 			ip->ip_len = 0;
550 		    break;
551 		}
552 
553 	    /* enqueue whatever is left of new before successors */
554 
555 	    if (ip->ip_len != 0)
556 	    {
557 		ip_enq(ip, savq);
558 	    }
559 	    else
560 		m_freem(mp);
561 	}
562     }
563 
564     /* check for completed fragment reassembly */
565 
566     if ((i = ip_done(&fp->iqx)) == 0)
567 	return(NULL);
568 
569     ip = fp->iqx.ip_next; /* -> top mbuf */
570     ip->ip_len = i; /* total data length */
571     *fragsize = fp->iq_size;	/* remember for TCP */
572     /* option processing */
573 
574     if ((hlen = ip->ip_hl<<IP_HLSHIFT) > sizeof(struct ip))
575 	ip_stripopt (ip, hlen);
576 
577     ip_mergef(&fp->iqx); /* clean frag chain */
578 
579     /* copy src/dst internet address to header mbuf */
580 
581     ip->ip_src = fp->iqh.ip_src;
582     ip->ip_dst = fp->iqh.ip_dst;
583 
584     ip_freef(fp); /* dequeue header */
585     return(ip);
586 }
587 
588 /*
589  * Let people control gateway action by patching this:
590  */
591 int	ip_forwarding = FALSE;
592 
593 /*
594  * Try to forward the packet.  Act like a gateway.
595  */
596 ip_forward (fwdinp, ip, mp, hlen)
597 struct inpcb	*fwdinp;
598 register struct ip	*ip;
599 struct mbuf	*mp;
600 int hlen;
601 {
602     register int		 type, code;
603     register u_short	 len;
604     register struct mbuf	*mcopy;
605     register unsigned		 icmplen;
606     int error;
607 
608     /*
609      * Also copy forwarded packets, just like copy TCP/UDP/RDP...
610      * packets sent to us so that can debug gateway action problems.
611      * It's easy enough for the user-level program to filter these
612      * out.
613      */
614     if (any_rawreaders())
615 	if (mcopy = m_copy(mp, 0, M_COPYALL))
616 	    raw_ip_input (mcopy);
617 
618     if (ip->ip_ttl)
619 	ip->ip_ttl --;
620 
621     len = ntohs(ip->ip_len);
622     icmplen = MIN(len, hlen + ICMP_ERRLEN);
623 
624     if (ip_forwarding && ip->ip_ttl)
625     {
626 	/*
627 	 * Save chunk of ip packet in case there is an error
628 	 */
629 	mcopy = m_copy (mp, 0, (int)icmplen);
630 
631 	/*
632 	 * The packet is not sourced by the local machine, so
633 	 * save ourselves a useless call to ip_route in ip_send().
634 	 * Also, don't want ip_send to work if sending from
635 	 * 8.7.0.2 to 192.1.11.1 via 8.0.0.16, and 8.0.0.16
636 	 * knows about a default gateway on net 8.  This can
637 	 * cause an ENETUNREACH if 192.1.11 is not a network
638 	 * that default gateway knows about.  [8.0.0.16 is on
639 	 * 192.1.11 and ip_route uses default gateway on net 8
640 	 * while rtalloc uses local interface]
641 	 *
642 	 * This route should be found by rtalloc, so let's do
643 	 * it here.
644 	 */
645 	if (fwdinp->inp_route.ro_rt == NULL)
646 	{
647 	    /* Isn't a source routed packet */
648 	    struct rtentry *rt;
649 	    struct sockaddr_in *sin;
650 
651 	    bzero ((caddr_t) fwdinp, sizeof(*fwdinp));
652 	    sin = (struct sockaddr_in *) &fwdinp->inp_route.ro_dst;
653 	    sin->sin_family = AF_INET;
654 	    sin->sin_addr = ip->ip_dst;
655 	    rtalloc (&fwdinp->inp_route);
656 
657 	    /*
658 	     * Check to see if should send ICMP redirect.  Don't
659 	     * send redirect if source routing was used.
660 	     */
661 	    if ((rt = fwdinp->inp_route.ro_rt) != NULL)
662 	    {
663 		sin = (struct sockaddr_in *) &rt->rt_gateway;
664 		if (! (rt->rt_flags & (RTF_GATEWAY|RTF_HOST)))
665 		    send_redirect (ip, ip->ip_dst, ICMP_REDIR_HOST, icmplen);
666 		else if (iptonet(ip->ip_src) == iptonet(sin->sin_addr))
667 		    send_redirect (ip, sin->sin_addr, ICMP_REDIR_NET, icmplen);
668 	    }
669 	}
670 
671 	if (fwdinp->inp_route.ro_rt == NULL)
672 	{
673 	    /* no way to get there from here */
674 	    m_freem(mp);
675 	    type = ICMP_UNRCH;
676 	    code = ICMP_UNRCH_NET;
677 	}
678 	else
679 	{
680 	    error = ip_send (fwdinp, mp, (int)len, TRUE);
681 	    rtfree(fwdinp->inp_route.ro_rt);
682 	    fwdinp->inp_route.ro_rt = NULL;
683 
684 	    if (! error)
685 	    {
686 		ipstat.ip_forwarded ++;
687 		if (mcopy)
688 		    m_freem(mcopy);
689 		return;
690 	    }
691 
692 	    type = ICMP_UNRCH;
693 	    switch (error)
694 	    {
695 	      case ENETUNREACH:
696 	      case ENETDOWN:
697 		code = ICMP_UNRCH_NET;
698 		break;
699 	      case EMSGSIZE:
700 		code = ICMP_UNRCH_FRAG;
701 		break;
702 	      case EHOSTDOWN:
703 	      case EHOSTUNREACH:
704 		code = ICMP_UNRCH_HOST;
705 		break;
706 
707 	      case ENOBUFS:
708 		type = ICMP_SRCQ;
709 		break;
710 
711 	      default:
712 		log(LOG_INFO, "ip_forward: error %d\n", error);
713 	    }
714 	}
715     }
716     else
717     {
718 	if (ip->ip_ttl == 0)
719 	{
720 	    type = ICMP_TIMEX;
721 	    code = ICMP_TIMEX_XMT;
722 	}
723 	else
724 	{
725 	    type = ICMP_UNRCH;
726 	    code = ICMP_UNRCH_NET;
727 	}
728 	mcopy = mp;
729 	if (fwdinp->inp_route.ro_rt)
730 	{
731 	    /* was source routed by IP option */
732 	    rtfree (fwdinp->inp_route.ro_rt);
733 	    fwdinp->inp_route.ro_rt = NULL;
734 	}
735     }
736 
737     if (mcopy)
738     {
739 	ip = mtod(mcopy, struct ip *);
740 	ic_errmsg (redir_addr(ip), ip->ip_src, type, code, 0, icmplen, (char *) ip);
741 #ifdef HMPTRAPS
742 	/* hmp_trap(T_IP_ADDRS, (caddr_t) 0, 0); */
743 #else
744 	if (ip_forwarding)
745 	    /*
746 	     * If not acting as a gateway, don't want some one else's
747 	     * misconception to flood our console or logfile.  This error
748 	     * can be found through netstat an ip_drops.
749 	     */
750 	    ip_log(ip, "ip forwarding error");
751 	netlog(mcopy);
752 #endif
753     }
754 
755     ipstat.ip_drops++;
756 }
757 
758 
759 /*
760  * Check to see if fragment reassembly is complete
761  */
ip_done(p)762 ip_done(p)
763 register struct ip *p;
764 {
765     register struct ip *q;
766     register next;
767 
768     q = p->ip_next;
769 
770     if (q->ip_off != 0)
771 	return(0);
772     do
773     {
774 	next = q->ip_end + 1;
775 	q = q->ip_next;
776     }
777     while ((q != p) && (q->ip_off == next));
778 
779     if ((q == p) && !(q->ip_prev->ip_mff))        /* all fragments in */
780 	return(next); /* total data length */
781     else
782 	return(0);
783 }
784 
785 /*
786  * Merge mbufs of fragments of completed datagram
787  */
ip_mergef(p)788 ip_mergef(p)
789 register struct ip *p;
790 {
791     register struct mbuf *m, *n;
792     register struct ip *q;
793     int dummy;
794 
795     q = p->ip_next; /* -> bottom of reass chain */
796     n = (struct mbuf *)&dummy; /* dummy for init assignment */
797 
798     while (q != p)
799     {        /* through chain */
800 	/*
801 	 * If free mbuf holding q, cannot access q->ip_next in case
802 	 * that mbuf is used by device code for an incoming packet.
803 	 */
804 	register struct ip *next;
805 
806 	next = q->ip_next;
807 	n->m_next = m = dtom(q);
808 	while (m != NULL)
809 	{
810 	    if (m->m_len != 0)
811 	    {
812 		n = m;
813 		m = m->m_next;
814 	    }
815 	    else /* free null mbufs */
816 		n->m_next = m = m_free(m);
817 	}
818 	q = next;
819     }
820 }
821 
822 /*
823  * Dequeue and free reass.q header
824  */
ip_freef(fp)825 ip_freef(fp)
826 register struct ipq *fp;
827 {
828     if (fp->iq_prev != NULL)
829 	(fp->iq_prev)->iq_next = fp->iq_next;
830     else
831 	ipfrags.n_ip_head = fp->iq_next;
832 
833     if (fp->iq_next != NULL)
834 	(fp->iq_next)->iq_prev = fp->iq_prev;
835     else
836 	ipfrags.n_ip_tail = fp->iq_prev;
837 
838     m_free(dtom(fp));
839 }
840 
841 ip_stripopt (ip, hlen)
842 struct ip	*ip;
843 int hlen;
844 {
845     int optlen;
846 
847     if ((optlen = (hlen - sizeof(struct ip))) > 0)
848     {
849 	struct mbuf *m;
850 	caddr_t end_of_ip, end_of_opt;
851 	unsigned len;
852 
853 	m = dtom(ip);
854 	end_of_ip = (char *) (ip +1);
855 	end_of_opt = end_of_ip + optlen;
856 	len = m->m_len - hlen;
857 	bcopy (end_of_opt, end_of_ip, len);
858 	m->m_len -= optlen;
859     }
860 }
861 
862 /*
863  * Process ip options
864  * FALSE -> options were in error, and an icmp message has been sent
865  */
866 #define OFF_OLEN	1
867 #define OFF_OFFSET	2
868 #define MIN_OFF		4	/* since option is a 1, not 0, based array */
869 
870 /*
871  * Record route in same form as ip_setopt()
872  */
save_rte(option,dst)873 save_rte (option, dst)
874 u_char	*option;
875 struct in_addr dst;
876 {
877     int olen;
878     int off;
879     u_char	*x;
880     struct in_addr *p, *q;
881 
882     if (ip_nhops != 0)
883     {
884 	/* Use both loose and strict source routing? */
885 	log(LOG_INFO, "ip_nhops %d\n", ip_nhops);
886 	ip_nhops = 0;
887 	return;
888     }
889     olen = option[OFF_OLEN];
890     if (olen > sizeof(ip_hops))
891     {
892 	log(LOG_INFO, "save_rte: olen %d\n", olen);
893 	return;
894     }
895     off = option[OFF_OFFSET];
896     p = (struct in_addr *) (&option[off - 1]);
897     q = (struct in_addr *) (&option[MIN_OFF -1]);
898 
899     x = (u_char *) ip_hops;
900     x[0] = IP_NOP_OPT;
901     x[1] = option[0];	/* loose/strict source routing */
902     x[2] = (p - q) * sizeof(struct in_addr) + 3;
903     x[3] = MIN_OFF;
904     ip_nhops ++;	/* = 1 (1 long for opt hdr) */
905     p--;	/* p points at first hop for return route */
906 
907     ip_hops[p-q+2] = (*p);	/* save first hop after return route option */
908     p--;	/* it is in what will be ip_hops[ip_nhops]  */
909 
910     /* record return path as an IP source route */
911     while (p >= q)
912     {
913 	ip_hops[ip_nhops] = (*p);
914 	p--;
915 	ip_nhops ++;
916     }
917     /* remember eventual destination is in the option field */
918     ip_hops[ip_nhops] = dst;
919     ip_nhops ++;
920 }
921 
ip_opt(ip,hlen,fwdinp)922 ip_opt (ip, hlen, fwdinp)
923 register struct ip *ip;
924 struct inpcb *fwdinp;
925 {
926     register u_char	*endopt;
927     register u_char	*option;
928     register int	 olen;
929     register int	 off;
930     int type;
931     int code;
932     struct in_addr nexthop;
933     struct in_ifaddr *ia;
934 
935     endopt = ((u_char *) ip) + hlen;
936     option = (u_char *) (ip +1);
937 
938     while (option < endopt)
939     {
940 	switch (*option)
941 	{
942 	  case IP_END_OPT:
943 	    return (TRUE);
944 
945 	  case IP_NOP_OPT:
946 	    olen = sizeof(u_char);
947 	    break;
948 
949 	  case IP_SEC_OPT:
950 	    olen = option[OFF_OLEN];
951 	    /* so much for security */
952 	    break;
953 
954 	  case IP_LRTE_OPT:
955 	    olen = option[OFF_OLEN];
956 	    off = option[OFF_OFFSET];
957 	    if (off < MIN_OFF)
958 	    {
959 		type = ICMP_PARM;
960 		code = &option[OFF_OFFSET] - ((u_char *) ip);
961 		goto err;
962 	    }
963 	    off--;	/* adjust for use by C */
964 	    if (in_iawithaddr(ip->ip_dst, TRUE) == NULL)
965 		/*
966 		 * With loose routing, may take a few hops
967 		 * to get to current nexthop.
968 		 */
969 		break;
970 
971 	    if (off > (olen - sizeof(struct in_addr)))
972 	    {
973 		/* hints all used up. pkt for us */
974 		save_rte (option, ip->ip_src);
975 		break;
976 	    }
977 
978 	    nexthop = *((struct in_addr *) (option + off));
979 
980 	    /*
981 	     * record outgoing interface
982 	     */
983 	    if (! ip_opt_route(fwdinp, nexthop))
984 	    {
985 		type = ICMP_UNRCH;
986 		/* net? frag? host? */
987 		code = ICMP_UNRCH_SRC;
988 		goto err;
989 	    }
990 	    ip->ip_dst = nexthop;
991 	    option[OFF_OFFSET] += sizeof(struct in_addr);
992 	    if (fwdinp->inp_route.ro_rt == NULL)
993 		/*
994 		 * Destined for ourselves, and we're
995 		 * just going to strip the options off
996 		 */
997 		break;
998 	    *((struct in_addr *) (option + off)) =
999 		IA_INADDR(in_iafromif (fwdinp->inp_route.ro_rt->rt_ifp));
1000 	    break;
1001 
1002 	  case IP_SRTE_OPT:
1003 	    olen = option[OFF_OLEN];
1004 	    off = option[OFF_OFFSET];
1005 	    if (off < MIN_OFF)
1006 	    {
1007 		type = ICMP_PARM;
1008 		code = &option[OFF_OFFSET] - ((u_char *) ip);
1009 		goto err;
1010 	    }
1011 	    off--;	/* adjust for use by C */
1012 	    if (in_iawithaddr(ip->ip_dst, TRUE) == NULL)
1013 	    {
1014 		/* strict path -> someone goofed */
1015 		/* should have come in on us for us */
1016 		type = ICMP_UNRCH;
1017 		code = ICMP_UNRCH_SRC;
1018 		goto err;
1019 	    }
1020 
1021 	    if (off > (olen - sizeof(struct in_addr)))
1022 	    {
1023 		/* hints all used up */
1024 		save_rte (option, ip->ip_src);
1025 		break;
1026 	    }
1027 
1028 	    nexthop = *((struct in_addr *) (option + off));
1029 
1030 	    if ((ia = in_iawithnet(nexthop)) == NULL)
1031 	    {
1032 		/* strict path -> someone goofed
1033 		 * we should be directly connected to
1034 		 * next hop
1035 		 */
1036 		type = ICMP_UNRCH;
1037 		code = ICMP_UNRCH_SRC;
1038 		goto err;
1039 	    }
1040 	    *((struct in_addr *) (option + off)) = IA_INADDR(ia);
1041 
1042 	    ip->ip_dst = nexthop;
1043 
1044 	    option[OFF_OFFSET] += sizeof(struct in_addr);
1045 	    break;
1046 
1047 	  case IP_TIME_OPT:
1048 	    olen = option[OFF_OLEN];
1049 	    off = option[OFF_OFFSET];
1050 	    if (off < MIN_OFF)
1051 	    {
1052 		type = ICMP_PARM;
1053 		code = &option[OFF_OFFSET] - ((u_char *) ip);
1054 		goto err;
1055 	    }
1056 	    off--;	/* adjust for use by C */
1057 	    if (off > (olen - sizeof(u_long)))
1058 	    {
1059 		/* increment overflow count */
1060 		if ((option[3] & 0xf0) == 0xf0)
1061 		{
1062 		    /* overflow overflowed */
1063 		    type = ICMP_PARM;
1064 		    code = &option[OFF_OLEN] - ((u_char *) ip);
1065 		    goto err;
1066 		}
1067 		option[3] += 0x10;
1068 		break;
1069 	    }
1070 
1071 	    if (option[3] & 2)
1072 	    {
1073 		/* want specific host to stamp */
1074 		ia = in_iawithaddr(*((struct in_addr *) (option + off)), FALSE);
1075 		if (ia == NULL)
1076 		    break;
1077 	    }
1078 	    else
1079 		ia = in_ifaddr;
1080 
1081 	    if (option[3] & 1)
1082 	    {
1083 		/* record stamping host */
1084 		*((struct in_addr *) (option + off)) = IA_INADDR (ia);
1085 		off += sizeof(struct in_addr);
1086 		option[OFF_OFFSET] += sizeof(struct in_addr);
1087 	    }
1088 	    if (off > (olen - sizeof(u_long)))
1089 	    {
1090 		option[3] += 0x10;
1091 		break;
1092 	    }
1093 	    *((u_long *) (option + off)) = iptime();
1094 	    option[OFF_OFFSET] += sizeof(u_long);
1095 	    break;
1096 
1097 	  case IP_STRID_OPT:
1098 	    olen = option[OFF_OLEN];
1099 	    break;
1100 
1101 	  case IP_RRTE_OPT:
1102 	    olen = option[OFF_OLEN];
1103 	    off = option[OFF_OFFSET];
1104 	    if (off < MIN_OFF)
1105 	    {
1106 		type = ICMP_PARM;
1107 		code = &option[OFF_OFFSET] - ((u_char *) ip);
1108 		goto err;
1109 	    }
1110 	    off--;	/* adjust for use by C */
1111 	    if (off > (olen - sizeof(u_long)))
1112 		/* no space left for recording route */
1113 		break;
1114 
1115 	    /* record outgoing interface */
1116 	    if (! ip_opt_route(fwdinp, ip->ip_dst))
1117 	    {
1118 		type = ICMP_UNRCH;
1119 		code = ICMP_UNRCH_NET;
1120 		goto err;
1121 	    }
1122 	    option[OFF_OFFSET] += sizeof(struct in_addr);
1123 	    if (fwdinp->inp_route.ro_rt == NULL)
1124 		/*
1125 		 * Destined for us, and we're just
1126 		 * going to strip options off
1127 		 */
1128 		break;
1129 	    *((struct in_addr *) (option + off)) =
1130 		IA_INADDR(in_iafromif (fwdinp->inp_route.ro_rt->rt_ifp));
1131 	    break;
1132 	}
1133 
1134 	option += olen;
1135     }
1136     return (TRUE);
1137 
1138 err :
1139     ic_errmsg (icmp_addr(ip), ip->ip_src,
1140 	type, code, option - ((u_char *) ip), hlen, (char *) ip);
1141     return (FALSE);
1142 }
1143 #undef OFF_OLEN
1144 #undef OFF_OFFSET
1145 #undef MIN_OFF
1146 
1147 
ip_opt_route(fwdinp,dst)1148 ip_opt_route (fwdinp, dst)
1149 register struct inpcb *fwdinp;
1150 struct in_addr dst;
1151 {
1152     register struct sockaddr_in *sin;
1153 
1154     /* in case they use several options involving routing */
1155     if (fwdinp->inp_route.ro_rt)
1156 	return (TRUE);
1157 
1158     bzero ((caddr_t) fwdinp, sizeof(*fwdinp));
1159 
1160     sin = (struct sockaddr_in *) &fwdinp->inp_route.ro_dst;
1161 
1162     /* not sure ip_send cares about this stuff ... */
1163     sin->sin_family = AF_INET;
1164     sin->sin_addr = dst;
1165 
1166     /* Don't allocate route if not forwarding packet.
1167      * This saves us from doing a check in ip_input() to see
1168      * if we should do a rtfree() for an uncommon occurrence.
1169      */
1170 
1171     if (in_iawithaddr(dst, TRUE) != NULL)
1172 	return (TRUE);
1173 
1174     rtalloc (&fwdinp->inp_route);
1175     return (fwdinp->inp_route.ro_rt != NULL);
1176 }
1177 
1178 
1179 /*
1180  * IP fragment reassembly timeout routine.
1181  */
ip_timeo()1182 ip_timeo()
1183 {
1184     register struct ip *p, *q;
1185     register struct ipq *fp, *next;
1186     register int s;
1187 
1188     static int timflag;
1189 
1190     /* check once per sec */
1191 
1192     if (timflag = !timflag)	/* looks strange, doesn't it? */
1193 	return;
1194 
1195 
1196     /* search through reass.q */
1197     s = splnet();
1198     for (fp = ipfrags.n_ip_head; fp != NULL; fp = next)
1199     {
1200 	/*
1201 	 * If fragment times out, mbufs are freed, and can't
1202 	 * use next pointer since mbuf may be grabbed by
1203 	 * an interface at splimp
1204 	 */
1205 	next = fp->iq_next;
1206 
1207 	if (--(fp->iqx.ip_ttl) == 0)
1208 	{  /* time to die */
1209 
1210 	    q = fp->iqx.ip_next; /* free mbufs assoc. w/chain */
1211 	    while (q != (struct ip *)fp)
1212 	    {
1213 		p = q->ip_next;
1214 		/* ### generate timed out in reassembly msg */
1215 #ifdef HMPTRAPS
1216 		/* hmp_trap(T_IP_FDROP, (caddr_t)0,0); */
1217 #else
1218 		m_freem(dtom(q));
1219 #endif
1220 		q = p;
1221 	    }
1222 	    ip_freef(fp); /* free header */
1223 	}
1224     }
1225     splx(s);
1226 }
1227 
1228 /*
1229  * Called at splimp from uipc_mbuf.c
1230  * Network code needs to free up space!  IP fragments dropped.
1231  */
ip_drain()1232 ip_drain()
1233 {
1234     register struct ip *p, *q;
1235     register struct ipq *fp;
1236 
1237     while (fp = ipfrags.n_ip_head)
1238     {
1239 	q = fp->iqx.ip_next;	/* free mbufs assoc w/chain */
1240 	while (q != (struct ip *)fp)
1241 	{
1242 	    p = q->ip_next;
1243 	    m_freem(dtom(q));
1244 	    q = p;
1245 	}
1246 	ip_freef(fp); /* free header */
1247     }
1248 }
1249 
1250 #include "../h/syslog.h"
1251 
inet_cksum_err(protoname,ip,was,should_be)1252 inet_cksum_err (protoname, ip, was, should_be)
1253 char *protoname;
1254 struct ip *ip;
1255 u_long was;
1256 u_long should_be;
1257 {
1258     union { u_long ul; u_char c[4]; } s, d;
1259 
1260     s.ul = ip->ip_src.s_addr;
1261     d.ul = ip->ip_dst.s_addr;
1262     log (LOG_INFO,
1263 	"%s checksum was 0x%x not 0x%x src %d.%d.%d.%d dst %d.%d.%d.%d\n",
1264 	protoname, was, should_be,
1265 	s.c[0], s.c[1], s.c[2], s.c[3],
1266 	d.c[0], d.c[1], d.c[2], d.c[3]);
1267 }
1268 
1269 ip_log(ip, emsg)
1270 struct ip *ip;
1271 char *emsg;
1272 {
1273     union { u_long ul; u_char c[4]; } s, d;
1274 
1275     s.ul = ip->ip_src.s_addr;
1276     d.ul = ip->ip_dst.s_addr;
1277     log(LOG_INFO, "%s: src %d.%d.%d.%d dst %d.%d.%d.%d\n",
1278 	emsg,
1279 	s.c[0], s.c[1], s.c[2], s.c[3],
1280 	d.c[0], d.c[1], d.c[2], d.c[3]);
1281 }
1282 
no_route(msg,from,to)1283 no_route (msg, from, to)
1284 char	*msg;
1285 struct in_addr	 from;
1286 struct in_addr	 to;
1287 {
1288     union { u_long ul; u_char c[4]; } f, t;
1289 
1290     f.ul = from.s_addr;
1291     t.ul = to.s_addr;
1292     log(LOG_INFO, "%s: no route %d.%d.%d.%d -> %d.%d.%d.%d\n",
1293 	msg,
1294 	f.c[0], f.c[1], f.c[2], f.c[3],
1295 	t.c[0], t.c[1], t.c[2], t.c[3]);
1296 }
1297