Home | History | Annotate | Line # | Download | only in netinet
ip_input.c revision 1.44
      1  1.44   thorpej /*	$NetBSD: ip_input.c,v 1.44 1997/01/11 05:21:10 thorpej Exp $	*/
      2  1.14       cgd 
      3   1.1       cgd /*
      4  1.13   mycroft  * Copyright (c) 1982, 1986, 1988, 1993
      5  1.13   mycroft  *	The Regents of the University of California.  All rights reserved.
      6   1.1       cgd  *
      7   1.1       cgd  * Redistribution and use in source and binary forms, with or without
      8   1.1       cgd  * modification, are permitted provided that the following conditions
      9   1.1       cgd  * are met:
     10   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     11   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     12   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     14   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     15   1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     16   1.1       cgd  *    must display the following acknowledgement:
     17   1.1       cgd  *	This product includes software developed by the University of
     18   1.1       cgd  *	California, Berkeley and its contributors.
     19   1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     20   1.1       cgd  *    may be used to endorse or promote products derived from this software
     21   1.1       cgd  *    without specific prior written permission.
     22   1.1       cgd  *
     23   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33   1.1       cgd  * SUCH DAMAGE.
     34   1.1       cgd  *
     35  1.14       cgd  *	@(#)ip_input.c	8.2 (Berkeley) 1/4/94
     36   1.1       cgd  */
     37   1.1       cgd 
     38   1.5   mycroft #include <sys/param.h>
     39   1.5   mycroft #include <sys/systm.h>
     40   1.5   mycroft #include <sys/malloc.h>
     41   1.5   mycroft #include <sys/mbuf.h>
     42   1.5   mycroft #include <sys/domain.h>
     43   1.5   mycroft #include <sys/protosw.h>
     44   1.5   mycroft #include <sys/socket.h>
     45  1.44   thorpej #include <sys/socketvar.h>
     46   1.5   mycroft #include <sys/errno.h>
     47   1.5   mycroft #include <sys/time.h>
     48   1.5   mycroft #include <sys/kernel.h>
     49  1.28  christos #include <sys/proc.h>
     50  1.28  christos 
     51  1.28  christos #include <vm/vm.h>
     52  1.28  christos #include <sys/sysctl.h>
     53   1.1       cgd 
     54   1.5   mycroft #include <net/if.h>
     55  1.44   thorpej #include <net/if_dl.h>
     56   1.5   mycroft #include <net/route.h>
     57   1.1       cgd 
     58   1.5   mycroft #include <netinet/in.h>
     59   1.5   mycroft #include <netinet/in_systm.h>
     60   1.5   mycroft #include <netinet/ip.h>
     61   1.5   mycroft #include <netinet/in_pcb.h>
     62   1.5   mycroft #include <netinet/in_var.h>
     63   1.5   mycroft #include <netinet/ip_var.h>
     64   1.5   mycroft #include <netinet/ip_icmp.h>
     65   1.1       cgd 
     66  1.36       mrg #ifdef PFIL_HOOKS
     67  1.36       mrg #include <net/pfil.h>
     68  1.36       mrg #endif /* PFIL_HOOKS */
     69  1.36       mrg 
     70  1.44   thorpej /* XXX should really put this in libkern.h */
     71  1.44   thorpej #define	offsetof(type, member)	((size_t)(&((type *)0)->member))
     72  1.44   thorpej 
     73   1.1       cgd #ifndef	IPFORWARDING
     74   1.1       cgd #ifdef GATEWAY
     75   1.1       cgd #define	IPFORWARDING	1	/* forward IP packets not for us */
     76   1.1       cgd #else /* GATEWAY */
     77   1.1       cgd #define	IPFORWARDING	0	/* don't forward IP packets not for us */
     78   1.1       cgd #endif /* GATEWAY */
     79   1.1       cgd #endif /* IPFORWARDING */
     80   1.1       cgd #ifndef	IPSENDREDIRECTS
     81   1.1       cgd #define	IPSENDREDIRECTS	1
     82   1.1       cgd #endif
     83  1.26   thorpej #ifndef IPFORWSRCRT
     84  1.26   thorpej #define	IPFORWSRCRT	1	/* allow source-routed packets */
     85  1.26   thorpej #endif
     86  1.27   thorpej /*
     87  1.27   thorpej  * Note: DIRECTED_BROADCAST is handled this way so that previous
     88  1.27   thorpej  * configuration using this option will Just Work.
     89  1.27   thorpej  */
     90  1.27   thorpej #ifndef IPDIRECTEDBCAST
     91  1.27   thorpej #ifdef DIRECTED_BROADCAST
     92  1.27   thorpej #define IPDIRECTEDBCAST	1
     93  1.27   thorpej #else
     94  1.27   thorpej #define	IPDIRECTEDBCAST	0
     95  1.27   thorpej #endif /* DIRECTED_BROADCAST */
     96  1.27   thorpej #endif /* IPDIRECTEDBCAST */
     97   1.1       cgd int	ipforwarding = IPFORWARDING;
     98   1.1       cgd int	ipsendredirects = IPSENDREDIRECTS;
     99  1.13   mycroft int	ip_defttl = IPDEFTTL;
    100  1.26   thorpej int	ip_forwsrcrt = IPFORWSRCRT;
    101  1.27   thorpej int	ip_directedbcast = IPDIRECTEDBCAST;
    102   1.1       cgd #ifdef DIAGNOSTIC
    103   1.1       cgd int	ipprintfs = 0;
    104   1.1       cgd #endif
    105   1.1       cgd 
    106   1.1       cgd extern	struct domain inetdomain;
    107   1.1       cgd extern	struct protosw inetsw[];
    108   1.1       cgd u_char	ip_protox[IPPROTO_MAX];
    109   1.1       cgd int	ipqmaxlen = IFQ_MAXLEN;
    110  1.22   mycroft struct	in_ifaddrhead in_ifaddr;
    111  1.13   mycroft struct	ifqueue ipintrq;
    112   1.1       cgd 
    113   1.1       cgd /*
    114   1.1       cgd  * We need to save the IP options in case a protocol wants to respond
    115   1.1       cgd  * to an incoming packet over the same route if the packet got here
    116   1.1       cgd  * using IP source routing.  This allows connection establishment and
    117   1.1       cgd  * maintenance when the remote end is on a network that is not known
    118   1.1       cgd  * to us.
    119   1.1       cgd  */
    120   1.1       cgd int	ip_nhops = 0;
    121   1.1       cgd static	struct ip_srcrt {
    122   1.1       cgd 	struct	in_addr dst;			/* final destination */
    123   1.1       cgd 	char	nop;				/* one NOP to align */
    124   1.1       cgd 	char	srcopt[IPOPT_OFFSET + 1];	/* OPTVAL, OLEN and OFFSET */
    125   1.1       cgd 	struct	in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)];
    126   1.1       cgd } ip_srcrt;
    127   1.1       cgd 
    128  1.13   mycroft static void save_rte __P((u_char *, struct in_addr));
    129  1.35   mycroft 
    130   1.1       cgd /*
    131   1.1       cgd  * IP initialization: fill in IP protocol switch table.
    132   1.1       cgd  * All protocols not implemented in kernel go to raw IP protocol handler.
    133   1.1       cgd  */
    134   1.8   mycroft void
    135   1.1       cgd ip_init()
    136   1.1       cgd {
    137   1.1       cgd 	register struct protosw *pr;
    138   1.1       cgd 	register int i;
    139   1.1       cgd 
    140   1.1       cgd 	pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
    141   1.1       cgd 	if (pr == 0)
    142   1.1       cgd 		panic("ip_init");
    143   1.1       cgd 	for (i = 0; i < IPPROTO_MAX; i++)
    144   1.1       cgd 		ip_protox[i] = pr - inetsw;
    145   1.1       cgd 	for (pr = inetdomain.dom_protosw;
    146   1.1       cgd 	    pr < inetdomain.dom_protoswNPROTOSW; pr++)
    147   1.1       cgd 		if (pr->pr_domain->dom_family == PF_INET &&
    148   1.1       cgd 		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
    149   1.1       cgd 			ip_protox[pr->pr_protocol] = pr - inetsw;
    150  1.25       cgd 	LIST_INIT(&ipq);
    151   1.1       cgd 	ip_id = time.tv_sec & 0xffff;
    152   1.1       cgd 	ipintrq.ifq_maxlen = ipqmaxlen;
    153  1.22   mycroft 	TAILQ_INIT(&in_ifaddr);
    154   1.1       cgd }
    155   1.1       cgd 
    156   1.1       cgd struct	sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET };
    157   1.1       cgd struct	route ipforward_rt;
    158   1.1       cgd 
    159   1.1       cgd /*
    160   1.1       cgd  * Ip input routine.  Checksum and byte swap header.  If fragmented
    161   1.1       cgd  * try to reassemble.  Process options.  Pass to next level.
    162   1.1       cgd  */
    163   1.8   mycroft void
    164   1.1       cgd ipintr()
    165   1.1       cgd {
    166  1.33       mrg 	register struct ip *ip = NULL;
    167   1.1       cgd 	register struct mbuf *m;
    168   1.1       cgd 	register struct ipq *fp;
    169   1.1       cgd 	register struct in_ifaddr *ia;
    170  1.25       cgd 	struct ipqent *ipqe;
    171  1.35   mycroft 	int hlen = 0, mff, len, s;
    172  1.36       mrg #ifdef PFIL_HOOKS
    173  1.33       mrg 	struct packet_filter_hook *pfh;
    174  1.33       mrg 	struct mbuf *m0;
    175  1.43       mrg 	int rv;
    176  1.36       mrg #endif /* PFIL_HOOKS */
    177   1.1       cgd 
    178   1.1       cgd next:
    179   1.1       cgd 	/*
    180   1.1       cgd 	 * Get next datagram off input queue and get IP header
    181   1.1       cgd 	 * in first mbuf.
    182   1.1       cgd 	 */
    183   1.1       cgd 	s = splimp();
    184   1.1       cgd 	IF_DEQUEUE(&ipintrq, m);
    185   1.1       cgd 	splx(s);
    186  1.13   mycroft 	if (m == 0)
    187   1.1       cgd 		return;
    188   1.1       cgd #ifdef	DIAGNOSTIC
    189   1.1       cgd 	if ((m->m_flags & M_PKTHDR) == 0)
    190   1.1       cgd 		panic("ipintr no HDR");
    191   1.1       cgd #endif
    192   1.1       cgd 	/*
    193   1.1       cgd 	 * If no IP addresses have been set yet but the interfaces
    194   1.1       cgd 	 * are receiving, can't do anything with incoming packets yet.
    195   1.1       cgd 	 */
    196  1.22   mycroft 	if (in_ifaddr.tqh_first == 0)
    197   1.1       cgd 		goto bad;
    198   1.1       cgd 	ipstat.ips_total++;
    199   1.1       cgd 	if (m->m_len < sizeof (struct ip) &&
    200   1.1       cgd 	    (m = m_pullup(m, sizeof (struct ip))) == 0) {
    201   1.1       cgd 		ipstat.ips_toosmall++;
    202   1.1       cgd 		goto next;
    203   1.1       cgd 	}
    204   1.1       cgd 	ip = mtod(m, struct ip *);
    205  1.13   mycroft 	if (ip->ip_v != IPVERSION) {
    206  1.13   mycroft 		ipstat.ips_badvers++;
    207  1.13   mycroft 		goto bad;
    208  1.13   mycroft 	}
    209   1.1       cgd 	hlen = ip->ip_hl << 2;
    210   1.1       cgd 	if (hlen < sizeof(struct ip)) {	/* minimum header length */
    211   1.1       cgd 		ipstat.ips_badhlen++;
    212   1.1       cgd 		goto bad;
    213   1.1       cgd 	}
    214   1.1       cgd 	if (hlen > m->m_len) {
    215   1.1       cgd 		if ((m = m_pullup(m, hlen)) == 0) {
    216   1.1       cgd 			ipstat.ips_badhlen++;
    217   1.1       cgd 			goto next;
    218   1.1       cgd 		}
    219   1.1       cgd 		ip = mtod(m, struct ip *);
    220   1.1       cgd 	}
    221  1.28  christos 	if ((ip->ip_sum = in_cksum(m, hlen)) != 0) {
    222   1.1       cgd 		ipstat.ips_badsum++;
    223   1.1       cgd 		goto bad;
    224   1.1       cgd 	}
    225   1.1       cgd 
    226   1.1       cgd 	/*
    227   1.1       cgd 	 * Convert fields to host representation.
    228   1.1       cgd 	 */
    229   1.1       cgd 	NTOHS(ip->ip_len);
    230   1.1       cgd 	NTOHS(ip->ip_id);
    231   1.1       cgd 	NTOHS(ip->ip_off);
    232  1.35   mycroft 	len = ip->ip_len;
    233   1.1       cgd 
    234   1.1       cgd 	/*
    235   1.1       cgd 	 * Check that the amount of data in the buffers
    236   1.1       cgd 	 * is as at least much as the IP header would have us expect.
    237   1.1       cgd 	 * Trim mbufs if longer than we expect.
    238   1.1       cgd 	 * Drop packet if shorter than we expect.
    239   1.1       cgd 	 */
    240  1.35   mycroft 	if (m->m_pkthdr.len < len) {
    241   1.1       cgd 		ipstat.ips_tooshort++;
    242   1.1       cgd 		goto bad;
    243   1.1       cgd 	}
    244  1.35   mycroft 	if (m->m_pkthdr.len > len) {
    245   1.1       cgd 		if (m->m_len == m->m_pkthdr.len) {
    246  1.35   mycroft 			m->m_len = len;
    247  1.35   mycroft 			m->m_pkthdr.len = len;
    248   1.1       cgd 		} else
    249  1.35   mycroft 			m_adj(m, len - m->m_pkthdr.len);
    250   1.1       cgd 	}
    251   1.1       cgd 
    252  1.36       mrg #ifdef PFIL_HOOKS
    253  1.33       mrg 	/*
    254  1.33       mrg 	 * Run through list of hooks for input packets.
    255  1.33       mrg 	 */
    256  1.33       mrg 	m0 = m;
    257  1.33       mrg 	for (pfh = pfil_hook_get(PFIL_IN); pfh; pfh = pfh->pfil_link.le_next)
    258  1.33       mrg 		if (pfh->pfil_func) {
    259  1.43       mrg 			rv = pfh->pfil_func(ip, hlen, m->m_pkthdr.rcvif, 0, &m0);
    260  1.43       mrg 			ip = mtod(m = m0, struct ip *);
    261  1.43       mrg 			if (rv)
    262  1.40     veego 				goto next;
    263  1.33       mrg 		}
    264  1.36       mrg #endif /* PFIL_HOOKS */
    265  1.33       mrg 
    266   1.1       cgd 	/*
    267   1.1       cgd 	 * Process options and, if not destined for us,
    268   1.1       cgd 	 * ship it on.  ip_dooptions returns 1 when an
    269   1.1       cgd 	 * error was detected (causing an icmp message
    270   1.1       cgd 	 * to be sent and the original packet to be freed).
    271   1.1       cgd 	 */
    272   1.1       cgd 	ip_nhops = 0;		/* for source routed packets */
    273   1.1       cgd 	if (hlen > sizeof (struct ip) && ip_dooptions(m))
    274   1.1       cgd 		goto next;
    275   1.1       cgd 
    276   1.1       cgd 	/*
    277   1.1       cgd 	 * Check our list of addresses, to see if the packet is for us.
    278   1.1       cgd 	 */
    279  1.22   mycroft 	for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) {
    280  1.35   mycroft 		if (in_hosteq(ip->ip_dst, ia->ia_addr.sin_addr))
    281   1.1       cgd 			goto ours;
    282  1.27   thorpej 		if (((ip_directedbcast == 0) || (ip_directedbcast &&
    283  1.27   thorpej 		    ia->ia_ifp == m->m_pkthdr.rcvif)) &&
    284   1.1       cgd 		    (ia->ia_ifp->if_flags & IFF_BROADCAST)) {
    285  1.35   mycroft 			if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) ||
    286  1.35   mycroft 			    in_hosteq(ip->ip_dst, ia->ia_netbroadcast) ||
    287  1.20   mycroft 			    /*
    288  1.20   mycroft 			     * Look for all-0's host part (old broadcast addr),
    289  1.20   mycroft 			     * either for subnet or net.
    290  1.20   mycroft 			     */
    291  1.20   mycroft 			    ip->ip_dst.s_addr == ia->ia_subnet ||
    292  1.18   mycroft 			    ip->ip_dst.s_addr == ia->ia_net)
    293   1.1       cgd 				goto ours;
    294   1.1       cgd 		}
    295   1.1       cgd 	}
    296  1.18   mycroft 	if (IN_MULTICAST(ip->ip_dst.s_addr)) {
    297   1.4   hpeyerl 		struct in_multi *inm;
    298   1.4   hpeyerl #ifdef MROUTING
    299   1.4   hpeyerl 		extern struct socket *ip_mrouter;
    300  1.10    brezak 
    301  1.10    brezak 		if (m->m_flags & M_EXT) {
    302  1.10    brezak 			if ((m = m_pullup(m, hlen)) == 0) {
    303  1.10    brezak 				ipstat.ips_toosmall++;
    304  1.10    brezak 				goto next;
    305  1.10    brezak 			}
    306  1.10    brezak 			ip = mtod(m, struct ip *);
    307  1.10    brezak 		}
    308   1.4   hpeyerl 
    309   1.4   hpeyerl 		if (ip_mrouter) {
    310   1.4   hpeyerl 			/*
    311   1.4   hpeyerl 			 * If we are acting as a multicast router, all
    312   1.4   hpeyerl 			 * incoming multicast packets are passed to the
    313   1.4   hpeyerl 			 * kernel-level multicast forwarding function.
    314   1.4   hpeyerl 			 * The packet is returned (relatively) intact; if
    315   1.4   hpeyerl 			 * ip_mforward() returns a non-zero value, the packet
    316   1.4   hpeyerl 			 * must be discarded, else it may be accepted below.
    317   1.4   hpeyerl 			 *
    318   1.4   hpeyerl 			 * (The IP ident field is put in the same byte order
    319   1.4   hpeyerl 			 * as expected when ip_mforward() is called from
    320   1.4   hpeyerl 			 * ip_output().)
    321   1.4   hpeyerl 			 */
    322   1.4   hpeyerl 			ip->ip_id = htons(ip->ip_id);
    323  1.13   mycroft 			if (ip_mforward(m, m->m_pkthdr.rcvif) != 0) {
    324  1.13   mycroft 				ipstat.ips_cantforward++;
    325   1.4   hpeyerl 				m_freem(m);
    326   1.4   hpeyerl 				goto next;
    327   1.4   hpeyerl 			}
    328   1.4   hpeyerl 			ip->ip_id = ntohs(ip->ip_id);
    329   1.4   hpeyerl 
    330   1.4   hpeyerl 			/*
    331   1.4   hpeyerl 			 * The process-level routing demon needs to receive
    332   1.4   hpeyerl 			 * all multicast IGMP packets, whether or not this
    333   1.4   hpeyerl 			 * host belongs to their destination groups.
    334   1.4   hpeyerl 			 */
    335   1.4   hpeyerl 			if (ip->ip_p == IPPROTO_IGMP)
    336   1.4   hpeyerl 				goto ours;
    337  1.13   mycroft 			ipstat.ips_forward++;
    338   1.4   hpeyerl 		}
    339   1.4   hpeyerl #endif
    340   1.4   hpeyerl 		/*
    341   1.4   hpeyerl 		 * See if we belong to the destination multicast group on the
    342   1.4   hpeyerl 		 * arrival interface.
    343   1.4   hpeyerl 		 */
    344   1.4   hpeyerl 		IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm);
    345   1.4   hpeyerl 		if (inm == NULL) {
    346  1.13   mycroft 			ipstat.ips_cantforward++;
    347   1.4   hpeyerl 			m_freem(m);
    348   1.4   hpeyerl 			goto next;
    349   1.4   hpeyerl 		}
    350   1.4   hpeyerl 		goto ours;
    351   1.4   hpeyerl 	}
    352  1.19   mycroft 	if (ip->ip_dst.s_addr == INADDR_BROADCAST ||
    353  1.35   mycroft 	    in_nullhost(ip->ip_dst))
    354   1.1       cgd 		goto ours;
    355   1.1       cgd 
    356   1.1       cgd 	/*
    357   1.1       cgd 	 * Not for us; forward if possible and desirable.
    358   1.1       cgd 	 */
    359   1.1       cgd 	if (ipforwarding == 0) {
    360   1.1       cgd 		ipstat.ips_cantforward++;
    361   1.1       cgd 		m_freem(m);
    362   1.1       cgd 	} else
    363   1.1       cgd 		ip_forward(m, 0);
    364   1.1       cgd 	goto next;
    365   1.1       cgd 
    366   1.1       cgd ours:
    367   1.1       cgd 	/*
    368   1.1       cgd 	 * If offset or IP_MF are set, must reassemble.
    369   1.1       cgd 	 * Otherwise, nothing need be done.
    370   1.1       cgd 	 * (We could look in the reassembly queue to see
    371   1.1       cgd 	 * if the packet was previously fragmented,
    372   1.1       cgd 	 * but it's not worth the time; just let them time out.)
    373   1.1       cgd 	 */
    374  1.37     perry 	if (ip->ip_off & ~(IP_DF|IP_RF)) {
    375   1.1       cgd 		if (m->m_flags & M_EXT) {		/* XXX */
    376   1.1       cgd 			if ((m = m_pullup(m, sizeof (struct ip))) == 0) {
    377   1.1       cgd 				ipstat.ips_toosmall++;
    378   1.1       cgd 				goto next;
    379   1.1       cgd 			}
    380   1.1       cgd 			ip = mtod(m, struct ip *);
    381   1.1       cgd 		}
    382   1.1       cgd 		/*
    383   1.1       cgd 		 * Look for queue of fragments
    384   1.1       cgd 		 * of this datagram.
    385   1.1       cgd 		 */
    386  1.25       cgd 		for (fp = ipq.lh_first; fp != NULL; fp = fp->ipq_q.le_next)
    387   1.1       cgd 			if (ip->ip_id == fp->ipq_id &&
    388  1.35   mycroft 			    in_hosteq(ip->ip_src, fp->ipq_src) &&
    389  1.35   mycroft 			    in_hosteq(ip->ip_dst, fp->ipq_dst) &&
    390   1.1       cgd 			    ip->ip_p == fp->ipq_p)
    391   1.1       cgd 				goto found;
    392   1.1       cgd 		fp = 0;
    393   1.1       cgd found:
    394   1.1       cgd 
    395   1.1       cgd 		/*
    396   1.1       cgd 		 * Adjust ip_len to not reflect header,
    397  1.25       cgd 		 * set ipqe_mff if more fragments are expected,
    398   1.1       cgd 		 * convert offset of this to bytes.
    399   1.1       cgd 		 */
    400   1.1       cgd 		ip->ip_len -= hlen;
    401  1.25       cgd 		mff = (ip->ip_off & IP_MF) != 0;
    402  1.25       cgd 		if (mff) {
    403  1.16       cgd 		        /*
    404  1.16       cgd 		         * Make sure that fragments have a data length
    405  1.16       cgd 			 * that's a non-zero multiple of 8 bytes.
    406  1.16       cgd 		         */
    407  1.17       cgd 			if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) {
    408  1.16       cgd 				ipstat.ips_badfrags++;
    409  1.16       cgd 				goto bad;
    410  1.16       cgd 			}
    411  1.16       cgd 		}
    412   1.1       cgd 		ip->ip_off <<= 3;
    413   1.1       cgd 
    414   1.1       cgd 		/*
    415   1.1       cgd 		 * If datagram marked as having more fragments
    416   1.1       cgd 		 * or if this is not the first fragment,
    417   1.1       cgd 		 * attempt reassembly; if it succeeds, proceed.
    418   1.1       cgd 		 */
    419  1.25       cgd 		if (mff || ip->ip_off) {
    420   1.1       cgd 			ipstat.ips_fragments++;
    421  1.25       cgd 			MALLOC(ipqe, struct ipqent *, sizeof (struct ipqent),
    422  1.25       cgd 			    M_IPQ, M_NOWAIT);
    423  1.25       cgd 			if (ipqe == NULL) {
    424  1.25       cgd 				ipstat.ips_rcvmemdrop++;
    425  1.25       cgd 				goto bad;
    426  1.25       cgd 			}
    427  1.25       cgd 			ipqe->ipqe_mff = mff;
    428  1.25       cgd 			ipqe->ipqe_ip = ip;
    429  1.25       cgd 			ip = ip_reass(ipqe, fp);
    430   1.1       cgd 			if (ip == 0)
    431   1.1       cgd 				goto next;
    432  1.13   mycroft 			ipstat.ips_reassembled++;
    433   1.1       cgd 			m = dtom(ip);
    434   1.1       cgd 		} else
    435   1.1       cgd 			if (fp)
    436   1.1       cgd 				ip_freef(fp);
    437   1.1       cgd 	} else
    438   1.1       cgd 		ip->ip_len -= hlen;
    439   1.1       cgd 
    440   1.1       cgd 	/*
    441   1.1       cgd 	 * Switch out to protocol's input routine.
    442   1.1       cgd 	 */
    443   1.1       cgd 	ipstat.ips_delivered++;
    444   1.1       cgd 	(*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
    445   1.1       cgd 	goto next;
    446   1.1       cgd bad:
    447   1.1       cgd 	m_freem(m);
    448   1.1       cgd 	goto next;
    449   1.1       cgd }
    450   1.1       cgd 
    451   1.1       cgd /*
    452   1.1       cgd  * Take incoming datagram fragment and try to
    453   1.1       cgd  * reassemble it into whole datagram.  If a chain for
    454   1.1       cgd  * reassembly of this datagram already exists, then it
    455   1.1       cgd  * is given as fp; otherwise have to make a chain.
    456   1.1       cgd  */
    457   1.1       cgd struct ip *
    458  1.25       cgd ip_reass(ipqe, fp)
    459  1.25       cgd 	register struct ipqent *ipqe;
    460   1.1       cgd 	register struct ipq *fp;
    461   1.1       cgd {
    462  1.25       cgd 	register struct mbuf *m = dtom(ipqe->ipqe_ip);
    463  1.25       cgd 	register struct ipqent *nq, *p, *q;
    464  1.25       cgd 	struct ip *ip;
    465   1.1       cgd 	struct mbuf *t;
    466  1.25       cgd 	int hlen = ipqe->ipqe_ip->ip_hl << 2;
    467   1.1       cgd 	int i, next;
    468   1.1       cgd 
    469   1.1       cgd 	/*
    470   1.1       cgd 	 * Presence of header sizes in mbufs
    471   1.1       cgd 	 * would confuse code below.
    472   1.1       cgd 	 */
    473   1.1       cgd 	m->m_data += hlen;
    474   1.1       cgd 	m->m_len -= hlen;
    475   1.1       cgd 
    476   1.1       cgd 	/*
    477   1.1       cgd 	 * If first fragment to arrive, create a reassembly queue.
    478   1.1       cgd 	 */
    479   1.1       cgd 	if (fp == 0) {
    480   1.1       cgd 		if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL)
    481   1.1       cgd 			goto dropfrag;
    482   1.1       cgd 		fp = mtod(t, struct ipq *);
    483  1.25       cgd 		LIST_INSERT_HEAD(&ipq, fp, ipq_q);
    484   1.1       cgd 		fp->ipq_ttl = IPFRAGTTL;
    485  1.25       cgd 		fp->ipq_p = ipqe->ipqe_ip->ip_p;
    486  1.25       cgd 		fp->ipq_id = ipqe->ipqe_ip->ip_id;
    487  1.25       cgd 		LIST_INIT(&fp->ipq_fragq);
    488  1.25       cgd 		fp->ipq_src = ipqe->ipqe_ip->ip_src;
    489  1.25       cgd 		fp->ipq_dst = ipqe->ipqe_ip->ip_dst;
    490  1.25       cgd 		p = NULL;
    491   1.1       cgd 		goto insert;
    492   1.1       cgd 	}
    493   1.1       cgd 
    494   1.1       cgd 	/*
    495   1.1       cgd 	 * Find a segment which begins after this one does.
    496   1.1       cgd 	 */
    497  1.25       cgd 	for (p = NULL, q = fp->ipq_fragq.lh_first; q != NULL;
    498  1.25       cgd 	    p = q, q = q->ipqe_q.le_next)
    499  1.25       cgd 		if (q->ipqe_ip->ip_off > ipqe->ipqe_ip->ip_off)
    500   1.1       cgd 			break;
    501   1.1       cgd 
    502   1.1       cgd 	/*
    503   1.1       cgd 	 * If there is a preceding segment, it may provide some of
    504   1.1       cgd 	 * our data already.  If so, drop the data from the incoming
    505   1.1       cgd 	 * segment.  If it provides all of our data, drop us.
    506   1.1       cgd 	 */
    507  1.25       cgd 	if (p != NULL) {
    508  1.25       cgd 		i = p->ipqe_ip->ip_off + p->ipqe_ip->ip_len -
    509  1.25       cgd 		    ipqe->ipqe_ip->ip_off;
    510   1.1       cgd 		if (i > 0) {
    511  1.25       cgd 			if (i >= ipqe->ipqe_ip->ip_len)
    512   1.1       cgd 				goto dropfrag;
    513  1.25       cgd 			m_adj(dtom(ipqe->ipqe_ip), i);
    514  1.25       cgd 			ipqe->ipqe_ip->ip_off += i;
    515  1.25       cgd 			ipqe->ipqe_ip->ip_len -= i;
    516   1.1       cgd 		}
    517   1.1       cgd 	}
    518   1.1       cgd 
    519   1.1       cgd 	/*
    520   1.1       cgd 	 * While we overlap succeeding segments trim them or,
    521   1.1       cgd 	 * if they are completely covered, dequeue them.
    522   1.1       cgd 	 */
    523  1.25       cgd 	for (; q != NULL && ipqe->ipqe_ip->ip_off + ipqe->ipqe_ip->ip_len >
    524  1.25       cgd 	    q->ipqe_ip->ip_off; q = nq) {
    525  1.25       cgd 		i = (ipqe->ipqe_ip->ip_off + ipqe->ipqe_ip->ip_len) -
    526  1.25       cgd 		    q->ipqe_ip->ip_off;
    527  1.25       cgd 		if (i < q->ipqe_ip->ip_len) {
    528  1.25       cgd 			q->ipqe_ip->ip_len -= i;
    529  1.25       cgd 			q->ipqe_ip->ip_off += i;
    530  1.25       cgd 			m_adj(dtom(q->ipqe_ip), i);
    531   1.1       cgd 			break;
    532   1.1       cgd 		}
    533  1.25       cgd 		nq = q->ipqe_q.le_next;
    534  1.25       cgd 		m_freem(dtom(q->ipqe_ip));
    535  1.25       cgd 		LIST_REMOVE(q, ipqe_q);
    536  1.25       cgd 		FREE(q, M_IPQ);
    537   1.1       cgd 	}
    538   1.1       cgd 
    539   1.1       cgd insert:
    540   1.1       cgd 	/*
    541   1.1       cgd 	 * Stick new segment in its place;
    542   1.1       cgd 	 * check for complete reassembly.
    543   1.1       cgd 	 */
    544  1.25       cgd 	if (p == NULL) {
    545  1.25       cgd 		LIST_INSERT_HEAD(&fp->ipq_fragq, ipqe, ipqe_q);
    546  1.25       cgd 	} else {
    547  1.25       cgd 		LIST_INSERT_AFTER(p, ipqe, ipqe_q);
    548  1.25       cgd 	}
    549   1.1       cgd 	next = 0;
    550  1.25       cgd 	for (p = NULL, q = fp->ipq_fragq.lh_first; q != NULL;
    551  1.25       cgd 	    p = q, q = q->ipqe_q.le_next) {
    552  1.25       cgd 		if (q->ipqe_ip->ip_off != next)
    553   1.1       cgd 			return (0);
    554  1.25       cgd 		next += q->ipqe_ip->ip_len;
    555   1.1       cgd 	}
    556  1.25       cgd 	if (p->ipqe_mff)
    557   1.1       cgd 		return (0);
    558   1.1       cgd 
    559   1.1       cgd 	/*
    560  1.41   thorpej 	 * Reassembly is complete.  Check for a bogus message size and
    561  1.41   thorpej 	 * concatenate fragments.
    562   1.1       cgd 	 */
    563  1.25       cgd 	q = fp->ipq_fragq.lh_first;
    564  1.25       cgd 	ip = q->ipqe_ip;
    565  1.41   thorpej 	if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) {
    566  1.41   thorpej 		ipstat.ips_toolong++;
    567  1.41   thorpej 		ip_freef(fp);
    568  1.41   thorpej 		return (0);
    569  1.41   thorpej 	}
    570  1.25       cgd 	m = dtom(q->ipqe_ip);
    571   1.1       cgd 	t = m->m_next;
    572   1.1       cgd 	m->m_next = 0;
    573   1.1       cgd 	m_cat(m, t);
    574  1.25       cgd 	nq = q->ipqe_q.le_next;
    575  1.25       cgd 	FREE(q, M_IPQ);
    576  1.25       cgd 	for (q = nq; q != NULL; q = nq) {
    577  1.25       cgd 		t = dtom(q->ipqe_ip);
    578  1.25       cgd 		nq = q->ipqe_q.le_next;
    579  1.25       cgd 		FREE(q, M_IPQ);
    580   1.1       cgd 		m_cat(m, t);
    581   1.1       cgd 	}
    582   1.1       cgd 
    583   1.1       cgd 	/*
    584   1.1       cgd 	 * Create header for new ip packet by
    585   1.1       cgd 	 * modifying header of first packet;
    586   1.1       cgd 	 * dequeue and discard fragment reassembly header.
    587   1.1       cgd 	 * Make header visible.
    588   1.1       cgd 	 */
    589   1.1       cgd 	ip->ip_len = next;
    590  1.25       cgd 	ip->ip_src = fp->ipq_src;
    591  1.25       cgd 	ip->ip_dst = fp->ipq_dst;
    592  1.25       cgd 	LIST_REMOVE(fp, ipq_q);
    593   1.1       cgd 	(void) m_free(dtom(fp));
    594   1.1       cgd 	m->m_len += (ip->ip_hl << 2);
    595   1.1       cgd 	m->m_data -= (ip->ip_hl << 2);
    596   1.1       cgd 	/* some debugging cruft by sklower, below, will go away soon */
    597   1.1       cgd 	if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
    598   1.1       cgd 		register int plen = 0;
    599   1.1       cgd 		for (t = m; m; m = m->m_next)
    600   1.1       cgd 			plen += m->m_len;
    601   1.1       cgd 		t->m_pkthdr.len = plen;
    602   1.1       cgd 	}
    603  1.25       cgd 	return (ip);
    604   1.1       cgd 
    605   1.1       cgd dropfrag:
    606   1.1       cgd 	ipstat.ips_fragdropped++;
    607   1.1       cgd 	m_freem(m);
    608  1.25       cgd 	FREE(ipqe, M_IPQ);
    609   1.1       cgd 	return (0);
    610   1.1       cgd }
    611   1.1       cgd 
    612   1.1       cgd /*
    613   1.1       cgd  * Free a fragment reassembly header and all
    614   1.1       cgd  * associated datagrams.
    615   1.1       cgd  */
    616   1.8   mycroft void
    617   1.1       cgd ip_freef(fp)
    618   1.1       cgd 	struct ipq *fp;
    619   1.1       cgd {
    620  1.25       cgd 	register struct ipqent *q, *p;
    621   1.1       cgd 
    622  1.25       cgd 	for (q = fp->ipq_fragq.lh_first; q != NULL; q = p) {
    623  1.25       cgd 		p = q->ipqe_q.le_next;
    624  1.25       cgd 		m_freem(dtom(q->ipqe_ip));
    625  1.25       cgd 		LIST_REMOVE(q, ipqe_q);
    626  1.25       cgd 		FREE(q, M_IPQ);
    627   1.1       cgd 	}
    628  1.25       cgd 	LIST_REMOVE(fp, ipq_q);
    629   1.1       cgd 	(void) m_free(dtom(fp));
    630   1.1       cgd }
    631   1.1       cgd 
    632   1.1       cgd /*
    633   1.1       cgd  * IP timer processing;
    634   1.1       cgd  * if a timer expires on a reassembly
    635   1.1       cgd  * queue, discard it.
    636   1.1       cgd  */
    637   1.8   mycroft void
    638   1.1       cgd ip_slowtimo()
    639   1.1       cgd {
    640  1.25       cgd 	register struct ipq *fp, *nfp;
    641  1.24   mycroft 	int s = splsoftnet();
    642   1.1       cgd 
    643  1.25       cgd 	for (fp = ipq.lh_first; fp != NULL; fp = nfp) {
    644  1.25       cgd 		nfp = fp->ipq_q.le_next;
    645  1.25       cgd 		if (--fp->ipq_ttl == 0) {
    646   1.1       cgd 			ipstat.ips_fragtimeout++;
    647  1.25       cgd 			ip_freef(fp);
    648   1.1       cgd 		}
    649   1.1       cgd 	}
    650   1.1       cgd 	splx(s);
    651   1.1       cgd }
    652   1.1       cgd 
    653   1.1       cgd /*
    654   1.1       cgd  * Drain off all datagram fragments.
    655   1.1       cgd  */
    656   1.8   mycroft void
    657   1.1       cgd ip_drain()
    658   1.1       cgd {
    659   1.1       cgd 
    660  1.25       cgd 	while (ipq.lh_first != NULL) {
    661   1.1       cgd 		ipstat.ips_fragdropped++;
    662  1.25       cgd 		ip_freef(ipq.lh_first);
    663   1.1       cgd 	}
    664   1.1       cgd }
    665   1.1       cgd 
    666   1.1       cgd /*
    667   1.1       cgd  * Do option processing on a datagram,
    668   1.1       cgd  * possibly discarding it if bad options are encountered,
    669   1.1       cgd  * or forwarding it if source-routed.
    670   1.1       cgd  * Returns 1 if packet has been forwarded/freed,
    671   1.1       cgd  * 0 if the packet should be processed further.
    672   1.1       cgd  */
    673   1.8   mycroft int
    674   1.1       cgd ip_dooptions(m)
    675   1.1       cgd 	struct mbuf *m;
    676   1.1       cgd {
    677   1.1       cgd 	register struct ip *ip = mtod(m, struct ip *);
    678   1.1       cgd 	register u_char *cp;
    679   1.1       cgd 	register struct ip_timestamp *ipt;
    680   1.1       cgd 	register struct in_ifaddr *ia;
    681   1.1       cgd 	int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;
    682  1.13   mycroft 	struct in_addr *sin, dst;
    683   1.1       cgd 	n_time ntime;
    684   1.1       cgd 
    685  1.13   mycroft 	dst = ip->ip_dst;
    686   1.1       cgd 	cp = (u_char *)(ip + 1);
    687   1.1       cgd 	cnt = (ip->ip_hl << 2) - sizeof (struct ip);
    688   1.1       cgd 	for (; cnt > 0; cnt -= optlen, cp += optlen) {
    689   1.1       cgd 		opt = cp[IPOPT_OPTVAL];
    690   1.1       cgd 		if (opt == IPOPT_EOL)
    691   1.1       cgd 			break;
    692   1.1       cgd 		if (opt == IPOPT_NOP)
    693   1.1       cgd 			optlen = 1;
    694   1.1       cgd 		else {
    695   1.1       cgd 			optlen = cp[IPOPT_OLEN];
    696   1.1       cgd 			if (optlen <= 0 || optlen > cnt) {
    697   1.1       cgd 				code = &cp[IPOPT_OLEN] - (u_char *)ip;
    698   1.1       cgd 				goto bad;
    699   1.1       cgd 			}
    700   1.1       cgd 		}
    701   1.1       cgd 		switch (opt) {
    702   1.1       cgd 
    703   1.1       cgd 		default:
    704   1.1       cgd 			break;
    705   1.1       cgd 
    706   1.1       cgd 		/*
    707   1.1       cgd 		 * Source routing with record.
    708   1.1       cgd 		 * Find interface with current destination address.
    709   1.1       cgd 		 * If none on this machine then drop if strictly routed,
    710   1.1       cgd 		 * or do nothing if loosely routed.
    711   1.1       cgd 		 * Record interface address and bring up next address
    712   1.1       cgd 		 * component.  If strictly routed make sure next
    713   1.1       cgd 		 * address is on directly accessible net.
    714   1.1       cgd 		 */
    715   1.1       cgd 		case IPOPT_LSRR:
    716   1.1       cgd 		case IPOPT_SSRR:
    717   1.1       cgd 			if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
    718   1.1       cgd 				code = &cp[IPOPT_OFFSET] - (u_char *)ip;
    719   1.1       cgd 				goto bad;
    720   1.1       cgd 			}
    721   1.1       cgd 			ipaddr.sin_addr = ip->ip_dst;
    722  1.19   mycroft 			ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr)));
    723   1.1       cgd 			if (ia == 0) {
    724   1.1       cgd 				if (opt == IPOPT_SSRR) {
    725   1.1       cgd 					type = ICMP_UNREACH;
    726   1.1       cgd 					code = ICMP_UNREACH_SRCFAIL;
    727   1.1       cgd 					goto bad;
    728   1.1       cgd 				}
    729   1.1       cgd 				/*
    730   1.1       cgd 				 * Loose routing, and not at next destination
    731   1.1       cgd 				 * yet; nothing to do except forward.
    732   1.1       cgd 				 */
    733   1.1       cgd 				break;
    734   1.1       cgd 			}
    735   1.1       cgd 			off--;			/* 0 origin */
    736   1.1       cgd 			if (off > optlen - sizeof(struct in_addr)) {
    737   1.1       cgd 				/*
    738   1.1       cgd 				 * End of source route.  Should be for us.
    739   1.1       cgd 				 */
    740   1.1       cgd 				save_rte(cp, ip->ip_src);
    741   1.1       cgd 				break;
    742   1.1       cgd 			}
    743   1.1       cgd 			/*
    744   1.1       cgd 			 * locate outgoing interface
    745   1.1       cgd 			 */
    746   1.1       cgd 			bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,
    747   1.1       cgd 			    sizeof(ipaddr.sin_addr));
    748   1.1       cgd 			if (opt == IPOPT_SSRR) {
    749   1.1       cgd #define	INA	struct in_ifaddr *
    750   1.1       cgd #define	SA	struct sockaddr *
    751  1.29       mrg 			    ia = (INA)ifa_ifwithladdr((SA)&ipaddr);
    752   1.1       cgd 			} else
    753   1.1       cgd 				ia = ip_rtaddr(ipaddr.sin_addr);
    754   1.1       cgd 			if (ia == 0) {
    755   1.1       cgd 				type = ICMP_UNREACH;
    756   1.1       cgd 				code = ICMP_UNREACH_SRCFAIL;
    757   1.1       cgd 				goto bad;
    758   1.1       cgd 			}
    759   1.1       cgd 			ip->ip_dst = ipaddr.sin_addr;
    760  1.20   mycroft 			bcopy((caddr_t)&ia->ia_addr.sin_addr,
    761   1.1       cgd 			    (caddr_t)(cp + off), sizeof(struct in_addr));
    762   1.1       cgd 			cp[IPOPT_OFFSET] += sizeof(struct in_addr);
    763  1.13   mycroft 			/*
    764  1.13   mycroft 			 * Let ip_intr's mcast routing check handle mcast pkts
    765  1.13   mycroft 			 */
    766  1.18   mycroft 			forward = !IN_MULTICAST(ip->ip_dst.s_addr);
    767   1.1       cgd 			break;
    768   1.1       cgd 
    769   1.1       cgd 		case IPOPT_RR:
    770   1.1       cgd 			if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
    771   1.1       cgd 				code = &cp[IPOPT_OFFSET] - (u_char *)ip;
    772   1.1       cgd 				goto bad;
    773   1.1       cgd 			}
    774   1.1       cgd 			/*
    775   1.1       cgd 			 * If no space remains, ignore.
    776   1.1       cgd 			 */
    777   1.1       cgd 			off--;			/* 0 origin */
    778   1.1       cgd 			if (off > optlen - sizeof(struct in_addr))
    779   1.1       cgd 				break;
    780   1.1       cgd 			bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
    781   1.1       cgd 			    sizeof(ipaddr.sin_addr));
    782   1.1       cgd 			/*
    783   1.1       cgd 			 * locate outgoing interface; if we're the destination,
    784   1.1       cgd 			 * use the incoming interface (should be same).
    785   1.1       cgd 			 */
    786   1.1       cgd 			if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
    787   1.1       cgd 			    (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
    788   1.1       cgd 				type = ICMP_UNREACH;
    789   1.1       cgd 				code = ICMP_UNREACH_HOST;
    790   1.1       cgd 				goto bad;
    791   1.1       cgd 			}
    792  1.20   mycroft 			bcopy((caddr_t)&ia->ia_addr.sin_addr,
    793   1.1       cgd 			    (caddr_t)(cp + off), sizeof(struct in_addr));
    794   1.1       cgd 			cp[IPOPT_OFFSET] += sizeof(struct in_addr);
    795   1.1       cgd 			break;
    796   1.1       cgd 
    797   1.1       cgd 		case IPOPT_TS:
    798   1.1       cgd 			code = cp - (u_char *)ip;
    799   1.1       cgd 			ipt = (struct ip_timestamp *)cp;
    800   1.1       cgd 			if (ipt->ipt_len < 5)
    801   1.1       cgd 				goto bad;
    802  1.15       cgd 			if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) {
    803   1.1       cgd 				if (++ipt->ipt_oflw == 0)
    804   1.1       cgd 					goto bad;
    805   1.1       cgd 				break;
    806   1.1       cgd 			}
    807   1.1       cgd 			sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
    808   1.1       cgd 			switch (ipt->ipt_flg) {
    809   1.1       cgd 
    810   1.1       cgd 			case IPOPT_TS_TSONLY:
    811   1.1       cgd 				break;
    812   1.1       cgd 
    813   1.1       cgd 			case IPOPT_TS_TSANDADDR:
    814   1.1       cgd 				if (ipt->ipt_ptr + sizeof(n_time) +
    815   1.1       cgd 				    sizeof(struct in_addr) > ipt->ipt_len)
    816   1.1       cgd 					goto bad;
    817  1.13   mycroft 				ipaddr.sin_addr = dst;
    818  1.13   mycroft 				ia = (INA)ifaof_ifpforaddr((SA)&ipaddr,
    819  1.13   mycroft 							    m->m_pkthdr.rcvif);
    820  1.13   mycroft 				if (ia == 0)
    821  1.13   mycroft 					continue;
    822  1.20   mycroft 				bcopy((caddr_t)&ia->ia_addr.sin_addr,
    823   1.1       cgd 				    (caddr_t)sin, sizeof(struct in_addr));
    824   1.1       cgd 				ipt->ipt_ptr += sizeof(struct in_addr);
    825   1.1       cgd 				break;
    826   1.1       cgd 
    827   1.1       cgd 			case IPOPT_TS_PRESPEC:
    828   1.1       cgd 				if (ipt->ipt_ptr + sizeof(n_time) +
    829   1.1       cgd 				    sizeof(struct in_addr) > ipt->ipt_len)
    830   1.1       cgd 					goto bad;
    831   1.1       cgd 				bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,
    832   1.1       cgd 				    sizeof(struct in_addr));
    833   1.1       cgd 				if (ifa_ifwithaddr((SA)&ipaddr) == 0)
    834   1.1       cgd 					continue;
    835   1.1       cgd 				ipt->ipt_ptr += sizeof(struct in_addr);
    836   1.1       cgd 				break;
    837   1.1       cgd 
    838   1.1       cgd 			default:
    839   1.1       cgd 				goto bad;
    840   1.1       cgd 			}
    841   1.1       cgd 			ntime = iptime();
    842   1.1       cgd 			bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,
    843   1.1       cgd 			    sizeof(n_time));
    844   1.1       cgd 			ipt->ipt_ptr += sizeof(n_time);
    845   1.1       cgd 		}
    846   1.1       cgd 	}
    847   1.1       cgd 	if (forward) {
    848  1.26   thorpej 		if (ip_forwsrcrt == 0) {
    849  1.26   thorpej 			type = ICMP_UNREACH;
    850  1.26   thorpej 			code = ICMP_UNREACH_SRCFAIL;
    851  1.26   thorpej 			goto bad;
    852  1.26   thorpej 		}
    853   1.1       cgd 		ip_forward(m, 1);
    854   1.1       cgd 		return (1);
    855  1.13   mycroft 	}
    856  1.13   mycroft 	return (0);
    857   1.1       cgd bad:
    858  1.13   mycroft 	ip->ip_len -= ip->ip_hl << 2;   /* XXX icmp_error adds in hdr length */
    859  1.13   mycroft 	icmp_error(m, type, code, 0, 0);
    860  1.13   mycroft 	ipstat.ips_badoptions++;
    861   1.1       cgd 	return (1);
    862   1.1       cgd }
    863   1.1       cgd 
    864   1.1       cgd /*
    865   1.1       cgd  * Given address of next destination (final or next hop),
    866   1.1       cgd  * return internet address info of interface to be used to get there.
    867   1.1       cgd  */
    868   1.1       cgd struct in_ifaddr *
    869   1.1       cgd ip_rtaddr(dst)
    870   1.1       cgd 	 struct in_addr dst;
    871   1.1       cgd {
    872   1.1       cgd 	register struct sockaddr_in *sin;
    873   1.1       cgd 
    874  1.19   mycroft 	sin = satosin(&ipforward_rt.ro_dst);
    875   1.1       cgd 
    876  1.35   mycroft 	if (ipforward_rt.ro_rt == 0 || !in_hosteq(dst, sin->sin_addr)) {
    877   1.1       cgd 		if (ipforward_rt.ro_rt) {
    878   1.1       cgd 			RTFREE(ipforward_rt.ro_rt);
    879   1.1       cgd 			ipforward_rt.ro_rt = 0;
    880   1.1       cgd 		}
    881   1.1       cgd 		sin->sin_family = AF_INET;
    882   1.1       cgd 		sin->sin_len = sizeof(*sin);
    883   1.1       cgd 		sin->sin_addr = dst;
    884   1.1       cgd 
    885   1.1       cgd 		rtalloc(&ipforward_rt);
    886   1.1       cgd 	}
    887   1.1       cgd 	if (ipforward_rt.ro_rt == 0)
    888   1.1       cgd 		return ((struct in_ifaddr *)0);
    889  1.19   mycroft 	return (ifatoia(ipforward_rt.ro_rt->rt_ifa));
    890   1.1       cgd }
    891   1.1       cgd 
    892   1.1       cgd /*
    893   1.1       cgd  * Save incoming source route for use in replies,
    894   1.1       cgd  * to be picked up later by ip_srcroute if the receiver is interested.
    895   1.1       cgd  */
    896  1.13   mycroft void
    897   1.1       cgd save_rte(option, dst)
    898   1.1       cgd 	u_char *option;
    899   1.1       cgd 	struct in_addr dst;
    900   1.1       cgd {
    901   1.1       cgd 	unsigned olen;
    902   1.1       cgd 
    903   1.1       cgd 	olen = option[IPOPT_OLEN];
    904   1.1       cgd #ifdef DIAGNOSTIC
    905   1.1       cgd 	if (ipprintfs)
    906  1.39  christos 		printf("save_rte: olen %d\n", olen);
    907   1.1       cgd #endif
    908   1.1       cgd 	if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
    909   1.1       cgd 		return;
    910   1.1       cgd 	bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen);
    911   1.1       cgd 	ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
    912   1.1       cgd 	ip_srcrt.dst = dst;
    913   1.1       cgd }
    914   1.1       cgd 
    915   1.1       cgd /*
    916   1.1       cgd  * Retrieve incoming source route for use in replies,
    917   1.1       cgd  * in the same form used by setsockopt.
    918   1.1       cgd  * The first hop is placed before the options, will be removed later.
    919   1.1       cgd  */
    920   1.1       cgd struct mbuf *
    921   1.1       cgd ip_srcroute()
    922   1.1       cgd {
    923   1.1       cgd 	register struct in_addr *p, *q;
    924   1.1       cgd 	register struct mbuf *m;
    925   1.1       cgd 
    926   1.1       cgd 	if (ip_nhops == 0)
    927   1.1       cgd 		return ((struct mbuf *)0);
    928   1.1       cgd 	m = m_get(M_DONTWAIT, MT_SOOPTS);
    929   1.1       cgd 	if (m == 0)
    930   1.1       cgd 		return ((struct mbuf *)0);
    931   1.1       cgd 
    932  1.13   mycroft #define OPTSIZ	(sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt))
    933   1.1       cgd 
    934   1.1       cgd 	/* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */
    935   1.1       cgd 	m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) +
    936   1.1       cgd 	    OPTSIZ;
    937   1.1       cgd #ifdef DIAGNOSTIC
    938   1.1       cgd 	if (ipprintfs)
    939  1.39  christos 		printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len);
    940   1.1       cgd #endif
    941   1.1       cgd 
    942   1.1       cgd 	/*
    943   1.1       cgd 	 * First save first hop for return route
    944   1.1       cgd 	 */
    945   1.1       cgd 	p = &ip_srcrt.route[ip_nhops - 1];
    946   1.1       cgd 	*(mtod(m, struct in_addr *)) = *p--;
    947   1.1       cgd #ifdef DIAGNOSTIC
    948   1.1       cgd 	if (ipprintfs)
    949  1.39  christos 		printf(" hops %x", ntohl(mtod(m, struct in_addr *)->s_addr));
    950   1.1       cgd #endif
    951   1.1       cgd 
    952   1.1       cgd 	/*
    953   1.1       cgd 	 * Copy option fields and padding (nop) to mbuf.
    954   1.1       cgd 	 */
    955   1.1       cgd 	ip_srcrt.nop = IPOPT_NOP;
    956   1.1       cgd 	ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
    957   1.1       cgd 	bcopy((caddr_t)&ip_srcrt.nop,
    958   1.1       cgd 	    mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ);
    959   1.1       cgd 	q = (struct in_addr *)(mtod(m, caddr_t) +
    960   1.1       cgd 	    sizeof(struct in_addr) + OPTSIZ);
    961   1.1       cgd #undef OPTSIZ
    962   1.1       cgd 	/*
    963   1.1       cgd 	 * Record return path as an IP source route,
    964   1.1       cgd 	 * reversing the path (pointers are now aligned).
    965   1.1       cgd 	 */
    966   1.1       cgd 	while (p >= ip_srcrt.route) {
    967   1.1       cgd #ifdef DIAGNOSTIC
    968   1.1       cgd 		if (ipprintfs)
    969  1.39  christos 			printf(" %x", ntohl(q->s_addr));
    970   1.1       cgd #endif
    971   1.1       cgd 		*q++ = *p--;
    972   1.1       cgd 	}
    973   1.1       cgd 	/*
    974   1.1       cgd 	 * Last hop goes to final destination.
    975   1.1       cgd 	 */
    976   1.1       cgd 	*q = ip_srcrt.dst;
    977   1.1       cgd #ifdef DIAGNOSTIC
    978   1.1       cgd 	if (ipprintfs)
    979  1.39  christos 		printf(" %x\n", ntohl(q->s_addr));
    980   1.1       cgd #endif
    981   1.1       cgd 	return (m);
    982   1.1       cgd }
    983   1.1       cgd 
    984   1.1       cgd /*
    985   1.1       cgd  * Strip out IP options, at higher
    986   1.1       cgd  * level protocol in the kernel.
    987   1.1       cgd  * Second argument is buffer to which options
    988   1.1       cgd  * will be moved, and return value is their length.
    989   1.1       cgd  * XXX should be deleted; last arg currently ignored.
    990   1.1       cgd  */
    991   1.8   mycroft void
    992   1.1       cgd ip_stripoptions(m, mopt)
    993   1.1       cgd 	register struct mbuf *m;
    994   1.1       cgd 	struct mbuf *mopt;
    995   1.1       cgd {
    996   1.1       cgd 	register int i;
    997   1.1       cgd 	struct ip *ip = mtod(m, struct ip *);
    998   1.1       cgd 	register caddr_t opts;
    999   1.1       cgd 	int olen;
   1000   1.1       cgd 
   1001   1.1       cgd 	olen = (ip->ip_hl<<2) - sizeof (struct ip);
   1002   1.1       cgd 	opts = (caddr_t)(ip + 1);
   1003   1.1       cgd 	i = m->m_len - (sizeof (struct ip) + olen);
   1004   1.1       cgd 	bcopy(opts  + olen, opts, (unsigned)i);
   1005   1.1       cgd 	m->m_len -= olen;
   1006   1.1       cgd 	if (m->m_flags & M_PKTHDR)
   1007   1.1       cgd 		m->m_pkthdr.len -= olen;
   1008   1.1       cgd 	ip->ip_hl = sizeof(struct ip) >> 2;
   1009   1.1       cgd }
   1010   1.1       cgd 
   1011  1.23   mycroft int inetctlerrmap[PRC_NCMDS] = {
   1012   1.1       cgd 	0,		0,		0,		0,
   1013   1.1       cgd 	0,		EMSGSIZE,	EHOSTDOWN,	EHOSTUNREACH,
   1014   1.1       cgd 	EHOSTUNREACH,	EHOSTUNREACH,	ECONNREFUSED,	ECONNREFUSED,
   1015   1.1       cgd 	EMSGSIZE,	EHOSTUNREACH,	0,		0,
   1016   1.1       cgd 	0,		0,		0,		0,
   1017   1.1       cgd 	ENOPROTOOPT
   1018   1.1       cgd };
   1019   1.1       cgd 
   1020   1.1       cgd /*
   1021   1.1       cgd  * Forward a packet.  If some error occurs return the sender
   1022   1.1       cgd  * an icmp packet.  Note we can't always generate a meaningful
   1023   1.1       cgd  * icmp message because icmp doesn't have a large enough repertoire
   1024   1.1       cgd  * of codes and types.
   1025   1.1       cgd  *
   1026   1.1       cgd  * If not forwarding, just drop the packet.  This could be confusing
   1027   1.1       cgd  * if ipforwarding was zero but some routing protocol was advancing
   1028   1.1       cgd  * us as a gateway to somewhere.  However, we must let the routing
   1029   1.1       cgd  * protocol deal with that.
   1030   1.1       cgd  *
   1031   1.1       cgd  * The srcrt parameter indicates whether the packet is being forwarded
   1032   1.1       cgd  * via a source route.
   1033   1.1       cgd  */
   1034  1.13   mycroft void
   1035   1.1       cgd ip_forward(m, srcrt)
   1036   1.1       cgd 	struct mbuf *m;
   1037   1.1       cgd 	int srcrt;
   1038   1.1       cgd {
   1039   1.1       cgd 	register struct ip *ip = mtod(m, struct ip *);
   1040   1.1       cgd 	register struct sockaddr_in *sin;
   1041   1.1       cgd 	register struct rtentry *rt;
   1042  1.28  christos 	int error, type = 0, code = 0;
   1043   1.1       cgd 	struct mbuf *mcopy;
   1044  1.13   mycroft 	n_long dest;
   1045  1.13   mycroft 	struct ifnet *destifp;
   1046   1.1       cgd 
   1047  1.13   mycroft 	dest = 0;
   1048   1.1       cgd #ifdef DIAGNOSTIC
   1049   1.1       cgd 	if (ipprintfs)
   1050  1.39  christos 		printf("forward: src %x dst %x ttl %x\n",
   1051  1.35   mycroft 		    ip->ip_src.s_addr, ip->ip_dst.s_addr, ip->ip_ttl);
   1052   1.1       cgd #endif
   1053   1.1       cgd 	if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) {
   1054   1.1       cgd 		ipstat.ips_cantforward++;
   1055   1.1       cgd 		m_freem(m);
   1056   1.1       cgd 		return;
   1057   1.1       cgd 	}
   1058   1.1       cgd 	HTONS(ip->ip_id);
   1059   1.1       cgd 	if (ip->ip_ttl <= IPTTLDEC) {
   1060  1.13   mycroft 		icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0);
   1061   1.1       cgd 		return;
   1062   1.1       cgd 	}
   1063   1.1       cgd 	ip->ip_ttl -= IPTTLDEC;
   1064   1.1       cgd 
   1065  1.19   mycroft 	sin = satosin(&ipforward_rt.ro_dst);
   1066   1.1       cgd 	if ((rt = ipforward_rt.ro_rt) == 0 ||
   1067  1.35   mycroft 	    !in_hosteq(ip->ip_dst, sin->sin_addr)) {
   1068   1.1       cgd 		if (ipforward_rt.ro_rt) {
   1069   1.1       cgd 			RTFREE(ipforward_rt.ro_rt);
   1070   1.1       cgd 			ipforward_rt.ro_rt = 0;
   1071   1.1       cgd 		}
   1072   1.1       cgd 		sin->sin_family = AF_INET;
   1073  1.35   mycroft 		sin->sin_len = sizeof(struct sockaddr_in);
   1074   1.1       cgd 		sin->sin_addr = ip->ip_dst;
   1075   1.1       cgd 
   1076   1.1       cgd 		rtalloc(&ipforward_rt);
   1077   1.1       cgd 		if (ipforward_rt.ro_rt == 0) {
   1078  1.13   mycroft 			icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
   1079   1.1       cgd 			return;
   1080   1.1       cgd 		}
   1081   1.1       cgd 		rt = ipforward_rt.ro_rt;
   1082   1.1       cgd 	}
   1083   1.1       cgd 
   1084   1.1       cgd 	/*
   1085  1.34   mycroft 	 * Save at most 68 bytes of the packet in case
   1086   1.1       cgd 	 * we need to generate an ICMP message to the src.
   1087   1.1       cgd 	 */
   1088  1.34   mycroft 	mcopy = m_copy(m, 0, imin((int)ip->ip_len, 68));
   1089   1.1       cgd 
   1090   1.1       cgd 	/*
   1091   1.1       cgd 	 * If forwarding packet using same interface that it came in on,
   1092   1.1       cgd 	 * perhaps should send a redirect to sender to shortcut a hop.
   1093   1.1       cgd 	 * Only send redirect if source is sending directly to us,
   1094   1.1       cgd 	 * and if packet was not source routed (or has any options).
   1095   1.1       cgd 	 * Also, don't send redirect if forwarding using a default route
   1096   1.1       cgd 	 * or a route modified by a redirect.
   1097   1.1       cgd 	 */
   1098   1.1       cgd 	if (rt->rt_ifp == m->m_pkthdr.rcvif &&
   1099   1.1       cgd 	    (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
   1100  1.35   mycroft 	    !in_nullhost(satosin(rt_key(rt))->sin_addr) &&
   1101   1.1       cgd 	    ipsendredirects && !srcrt) {
   1102  1.19   mycroft 		if (rt->rt_ifa &&
   1103  1.19   mycroft 		    (ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_subnetmask) ==
   1104  1.19   mycroft 		    ifatoia(rt->rt_ifa)->ia_subnet) {
   1105   1.1       cgd 		    if (rt->rt_flags & RTF_GATEWAY)
   1106  1.13   mycroft 			dest = satosin(rt->rt_gateway)->sin_addr.s_addr;
   1107   1.1       cgd 		    else
   1108  1.13   mycroft 			dest = ip->ip_dst.s_addr;
   1109  1.13   mycroft 		    /* Router requirements says to only send host redirects */
   1110   1.1       cgd 		    type = ICMP_REDIRECT;
   1111  1.13   mycroft 		    code = ICMP_REDIRECT_HOST;
   1112   1.1       cgd #ifdef DIAGNOSTIC
   1113   1.1       cgd 		    if (ipprintfs)
   1114  1.39  christos 		    	printf("redirect (%d) to %x\n", code, (u_int32_t)dest);
   1115   1.1       cgd #endif
   1116   1.1       cgd 		}
   1117   1.1       cgd 	}
   1118   1.1       cgd 
   1119  1.27   thorpej 	error = ip_output(m, (struct mbuf *)0, &ipforward_rt,
   1120  1.27   thorpej 	    (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), 0);
   1121   1.1       cgd 	if (error)
   1122   1.1       cgd 		ipstat.ips_cantforward++;
   1123   1.1       cgd 	else {
   1124   1.1       cgd 		ipstat.ips_forward++;
   1125   1.1       cgd 		if (type)
   1126   1.1       cgd 			ipstat.ips_redirectsent++;
   1127   1.1       cgd 		else {
   1128   1.1       cgd 			if (mcopy)
   1129   1.1       cgd 				m_freem(mcopy);
   1130   1.1       cgd 			return;
   1131   1.1       cgd 		}
   1132   1.1       cgd 	}
   1133   1.1       cgd 	if (mcopy == NULL)
   1134   1.1       cgd 		return;
   1135  1.13   mycroft 	destifp = NULL;
   1136  1.13   mycroft 
   1137   1.1       cgd 	switch (error) {
   1138   1.1       cgd 
   1139   1.1       cgd 	case 0:				/* forwarded, but need redirect */
   1140   1.1       cgd 		/* type, code set above */
   1141   1.1       cgd 		break;
   1142   1.1       cgd 
   1143   1.1       cgd 	case ENETUNREACH:		/* shouldn't happen, checked above */
   1144   1.1       cgd 	case EHOSTUNREACH:
   1145   1.1       cgd 	case ENETDOWN:
   1146   1.1       cgd 	case EHOSTDOWN:
   1147   1.1       cgd 	default:
   1148   1.1       cgd 		type = ICMP_UNREACH;
   1149   1.1       cgd 		code = ICMP_UNREACH_HOST;
   1150   1.1       cgd 		break;
   1151   1.1       cgd 
   1152   1.1       cgd 	case EMSGSIZE:
   1153   1.1       cgd 		type = ICMP_UNREACH;
   1154   1.1       cgd 		code = ICMP_UNREACH_NEEDFRAG;
   1155  1.13   mycroft 		if (ipforward_rt.ro_rt)
   1156  1.13   mycroft 			destifp = ipforward_rt.ro_rt->rt_ifp;
   1157   1.1       cgd 		ipstat.ips_cantfrag++;
   1158   1.1       cgd 		break;
   1159   1.1       cgd 
   1160   1.1       cgd 	case ENOBUFS:
   1161   1.1       cgd 		type = ICMP_SOURCEQUENCH;
   1162   1.1       cgd 		code = 0;
   1163   1.1       cgd 		break;
   1164   1.1       cgd 	}
   1165  1.13   mycroft 	icmp_error(mcopy, type, code, dest, destifp);
   1166  1.44   thorpej }
   1167  1.44   thorpej 
   1168  1.44   thorpej void
   1169  1.44   thorpej ip_savecontrol(inp, mp, ip, m)
   1170  1.44   thorpej 	register struct inpcb *inp;
   1171  1.44   thorpej 	register struct mbuf **mp;
   1172  1.44   thorpej 	register struct ip *ip;
   1173  1.44   thorpej 	register struct mbuf *m;
   1174  1.44   thorpej {
   1175  1.44   thorpej 
   1176  1.44   thorpej 	if (inp->inp_socket->so_options & SO_TIMESTAMP) {
   1177  1.44   thorpej 		struct timeval tv;
   1178  1.44   thorpej 
   1179  1.44   thorpej 		microtime(&tv);
   1180  1.44   thorpej 		*mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
   1181  1.44   thorpej 		    SCM_TIMESTAMP, SOL_SOCKET);
   1182  1.44   thorpej 		if (*mp)
   1183  1.44   thorpej 			mp = &(*mp)->m_next;
   1184  1.44   thorpej 	}
   1185  1.44   thorpej 	if (inp->inp_flags & INP_RECVDSTADDR) {
   1186  1.44   thorpej 		*mp = sbcreatecontrol((caddr_t) &ip->ip_dst,
   1187  1.44   thorpej 		    sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
   1188  1.44   thorpej 		if (*mp)
   1189  1.44   thorpej 			mp = &(*mp)->m_next;
   1190  1.44   thorpej 	}
   1191  1.44   thorpej #ifdef notyet
   1192  1.44   thorpej 	/*
   1193  1.44   thorpej 	 * XXX
   1194  1.44   thorpej 	 * Moving these out of udp_input() made them even more broken
   1195  1.44   thorpej 	 * than they already were.
   1196  1.44   thorpej 	 *	- fenner (at) parc.xerox.com
   1197  1.44   thorpej 	 */
   1198  1.44   thorpej 	/* options were tossed already */
   1199  1.44   thorpej 	if (inp->inp_flags & INP_RECVOPTS) {
   1200  1.44   thorpej 		*mp = sbcreatecontrol((caddr_t) opts_deleted_above,
   1201  1.44   thorpej 		    sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP);
   1202  1.44   thorpej 		if (*mp)
   1203  1.44   thorpej 			mp = &(*mp)->m_next;
   1204  1.44   thorpej 	}
   1205  1.44   thorpej 	/* ip_srcroute doesn't do what we want here, need to fix */
   1206  1.44   thorpej 	if (inp->inp_flags & INP_RECVRETOPTS) {
   1207  1.44   thorpej 		*mp = sbcreatecontrol((caddr_t) ip_srcroute(),
   1208  1.44   thorpej 		    sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP);
   1209  1.44   thorpej 		if (*mp)
   1210  1.44   thorpej 			mp = &(*mp)->m_next;
   1211  1.44   thorpej 	}
   1212  1.44   thorpej #endif
   1213  1.44   thorpej 	if (inp->inp_flags & INP_RECVIF) {
   1214  1.44   thorpej 		struct sockaddr_dl sdl;
   1215  1.44   thorpej 
   1216  1.44   thorpej 		sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data[0]);
   1217  1.44   thorpej 		sdl.sdl_family = AF_LINK;
   1218  1.44   thorpej 		sdl.sdl_index = m->m_pkthdr.rcvif ?
   1219  1.44   thorpej 		    m->m_pkthdr.rcvif->if_index : 0;
   1220  1.44   thorpej 		sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0;
   1221  1.44   thorpej 		*mp = sbcreatecontrol((caddr_t) &sdl, sdl.sdl_len,
   1222  1.44   thorpej 		    IP_RECVIF, IPPROTO_IP);
   1223  1.44   thorpej 		if (*mp)
   1224  1.44   thorpej 			mp = &(*mp)->m_next;
   1225  1.44   thorpej 	}
   1226  1.13   mycroft }
   1227  1.13   mycroft 
   1228  1.13   mycroft int
   1229  1.13   mycroft ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
   1230  1.13   mycroft 	int *name;
   1231  1.13   mycroft 	u_int namelen;
   1232  1.13   mycroft 	void *oldp;
   1233  1.13   mycroft 	size_t *oldlenp;
   1234  1.13   mycroft 	void *newp;
   1235  1.13   mycroft 	size_t newlen;
   1236  1.13   mycroft {
   1237  1.13   mycroft 	/* All sysctl names at this level are terminal. */
   1238  1.13   mycroft 	if (namelen != 1)
   1239  1.13   mycroft 		return (ENOTDIR);
   1240  1.13   mycroft 
   1241  1.13   mycroft 	switch (name[0]) {
   1242  1.13   mycroft 	case IPCTL_FORWARDING:
   1243  1.13   mycroft 		return (sysctl_int(oldp, oldlenp, newp, newlen, &ipforwarding));
   1244  1.13   mycroft 	case IPCTL_SENDREDIRECTS:
   1245  1.13   mycroft 		return (sysctl_int(oldp, oldlenp, newp, newlen,
   1246  1.13   mycroft 			&ipsendredirects));
   1247  1.13   mycroft 	case IPCTL_DEFTTL:
   1248  1.13   mycroft 		return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_defttl));
   1249  1.13   mycroft #ifdef notyet
   1250  1.13   mycroft 	case IPCTL_DEFMTU:
   1251  1.13   mycroft 		return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));
   1252  1.13   mycroft #endif
   1253  1.26   thorpej 	case IPCTL_FORWSRCRT:
   1254  1.26   thorpej 		/*
   1255  1.26   thorpej 		 * Don't allow this to change in a secure environment.
   1256  1.26   thorpej 		 */
   1257  1.26   thorpej 		if (securelevel > 0)
   1258  1.26   thorpej 			return (EPERM);
   1259  1.26   thorpej 		return (sysctl_int(oldp, oldlenp, newp, newlen,
   1260  1.26   thorpej 		    &ip_forwsrcrt));
   1261  1.27   thorpej 	case IPCTL_DIRECTEDBCAST:
   1262  1.27   thorpej 		return (sysctl_int(oldp, oldlenp, newp, newlen,
   1263  1.27   thorpej 		    &ip_directedbcast));
   1264  1.13   mycroft 	default:
   1265  1.13   mycroft 		return (EOPNOTSUPP);
   1266  1.13   mycroft 	}
   1267  1.13   mycroft 	/* NOTREACHED */
   1268   1.1       cgd }
   1269