Home | History | Annotate | Line # | Download | only in netinet
ip_input.c revision 1.130.2.15
      1  1.130.2.11   nathanw /*	$NetBSD: ip_input.c,v 1.130.2.15 2002/11/11 22:15:23 nathanw Exp $	*/
      2        1.89    itojun 
      3        1.89    itojun /*
      4        1.89    itojun  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
      5        1.89    itojun  * All rights reserved.
      6  1.130.2.10   nathanw  *
      7        1.89    itojun  * Redistribution and use in source and binary forms, with or without
      8        1.89    itojun  * modification, are permitted provided that the following conditions
      9        1.89    itojun  * are met:
     10        1.89    itojun  * 1. Redistributions of source code must retain the above copyright
     11        1.89    itojun  *    notice, this list of conditions and the following disclaimer.
     12        1.89    itojun  * 2. Redistributions in binary form must reproduce the above copyright
     13        1.89    itojun  *    notice, this list of conditions and the following disclaimer in the
     14        1.89    itojun  *    documentation and/or other materials provided with the distribution.
     15        1.89    itojun  * 3. Neither the name of the project nor the names of its contributors
     16        1.89    itojun  *    may be used to endorse or promote products derived from this software
     17        1.89    itojun  *    without specific prior written permission.
     18  1.130.2.10   nathanw  *
     19        1.89    itojun  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     20        1.89    itojun  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21        1.89    itojun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22        1.89    itojun  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     23        1.89    itojun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24        1.89    itojun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25        1.89    itojun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26        1.89    itojun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27        1.89    itojun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28        1.89    itojun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29        1.89    itojun  * SUCH DAMAGE.
     30        1.89    itojun  */
     31        1.76   thorpej 
     32        1.76   thorpej /*-
     33        1.76   thorpej  * Copyright (c) 1998 The NetBSD Foundation, Inc.
     34        1.76   thorpej  * All rights reserved.
     35        1.76   thorpej  *
     36        1.76   thorpej  * This code is derived from software contributed to The NetBSD Foundation
     37        1.76   thorpej  * by Public Access Networks Corporation ("Panix").  It was developed under
     38        1.76   thorpej  * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
     39        1.76   thorpej  *
     40        1.76   thorpej  * Redistribution and use in source and binary forms, with or without
     41        1.76   thorpej  * modification, are permitted provided that the following conditions
     42        1.76   thorpej  * are met:
     43        1.76   thorpej  * 1. Redistributions of source code must retain the above copyright
     44        1.76   thorpej  *    notice, this list of conditions and the following disclaimer.
     45        1.76   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     46        1.76   thorpej  *    notice, this list of conditions and the following disclaimer in the
     47        1.76   thorpej  *    documentation and/or other materials provided with the distribution.
     48        1.76   thorpej  * 3. All advertising materials mentioning features or use of this software
     49        1.76   thorpej  *    must display the following acknowledgement:
     50        1.76   thorpej  *	This product includes software developed by the NetBSD
     51        1.76   thorpej  *	Foundation, Inc. and its contributors.
     52        1.76   thorpej  * 4. Neither the name of The NetBSD Foundation nor the names of its
     53        1.76   thorpej  *    contributors may be used to endorse or promote products derived
     54        1.76   thorpej  *    from this software without specific prior written permission.
     55        1.76   thorpej  *
     56        1.76   thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     57        1.76   thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     58        1.76   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     59        1.76   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     60        1.76   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     61        1.76   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     62        1.76   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     63        1.76   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     64        1.76   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     65        1.76   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     66        1.76   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     67        1.76   thorpej  */
     68        1.14       cgd 
     69         1.1       cgd /*
     70        1.13   mycroft  * Copyright (c) 1982, 1986, 1988, 1993
     71        1.13   mycroft  *	The Regents of the University of California.  All rights reserved.
     72         1.1       cgd  *
     73         1.1       cgd  * Redistribution and use in source and binary forms, with or without
     74         1.1       cgd  * modification, are permitted provided that the following conditions
     75         1.1       cgd  * are met:
     76         1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     77         1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     78         1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     79         1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     80         1.1       cgd  *    documentation and/or other materials provided with the distribution.
     81         1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     82         1.1       cgd  *    must display the following acknowledgement:
     83         1.1       cgd  *	This product includes software developed by the University of
     84         1.1       cgd  *	California, Berkeley and its contributors.
     85         1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     86         1.1       cgd  *    may be used to endorse or promote products derived from this software
     87         1.1       cgd  *    without specific prior written permission.
     88         1.1       cgd  *
     89         1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     90         1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     91         1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     92         1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     93         1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     94         1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     95         1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     96         1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     97         1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     98         1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     99         1.1       cgd  * SUCH DAMAGE.
    100         1.1       cgd  *
    101        1.14       cgd  *	@(#)ip_input.c	8.2 (Berkeley) 1/4/94
    102         1.1       cgd  */
    103        1.55    scottr 
    104   1.130.2.5   nathanw #include <sys/cdefs.h>
    105  1.130.2.11   nathanw __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.130.2.15 2002/11/11 22:15:23 nathanw Exp $");
    106   1.130.2.5   nathanw 
    107        1.62      matt #include "opt_gateway.h"
    108        1.69       mrg #include "opt_pfil_hooks.h"
    109        1.91   thorpej #include "opt_ipsec.h"
    110        1.55    scottr #include "opt_mrouting.h"
    111   1.130.2.2   nathanw #include "opt_inet_csum.h"
    112         1.1       cgd 
    113         1.5   mycroft #include <sys/param.h>
    114         1.5   mycroft #include <sys/systm.h>
    115         1.5   mycroft #include <sys/malloc.h>
    116         1.5   mycroft #include <sys/mbuf.h>
    117         1.5   mycroft #include <sys/domain.h>
    118         1.5   mycroft #include <sys/protosw.h>
    119         1.5   mycroft #include <sys/socket.h>
    120        1.44   thorpej #include <sys/socketvar.h>
    121         1.5   mycroft #include <sys/errno.h>
    122         1.5   mycroft #include <sys/time.h>
    123         1.5   mycroft #include <sys/kernel.h>
    124        1.72   thorpej #include <sys/pool.h>
    125        1.28  christos #include <sys/sysctl.h>
    126         1.1       cgd 
    127         1.5   mycroft #include <net/if.h>
    128        1.44   thorpej #include <net/if_dl.h>
    129         1.5   mycroft #include <net/route.h>
    130        1.45       mrg #include <net/pfil.h>
    131         1.1       cgd 
    132         1.5   mycroft #include <netinet/in.h>
    133         1.5   mycroft #include <netinet/in_systm.h>
    134         1.5   mycroft #include <netinet/ip.h>
    135         1.5   mycroft #include <netinet/in_pcb.h>
    136         1.5   mycroft #include <netinet/in_var.h>
    137         1.5   mycroft #include <netinet/ip_var.h>
    138         1.5   mycroft #include <netinet/ip_icmp.h>
    139        1.89    itojun /* just for gif_ttl */
    140        1.89    itojun #include <netinet/in_gif.h>
    141        1.89    itojun #include "gif.h"
    142   1.130.2.7   nathanw #include <net/if_gre.h>
    143   1.130.2.7   nathanw #include "gre.h"
    144       1.111  jdolecek 
    145       1.111  jdolecek #ifdef MROUTING
    146       1.111  jdolecek #include <netinet/ip_mroute.h>
    147       1.111  jdolecek #endif
    148        1.89    itojun 
    149        1.89    itojun #ifdef IPSEC
    150        1.89    itojun #include <netinet6/ipsec.h>
    151        1.89    itojun #include <netkey/key.h>
    152        1.89    itojun #endif
    153        1.44   thorpej 
    154         1.1       cgd #ifndef	IPFORWARDING
    155         1.1       cgd #ifdef GATEWAY
    156         1.1       cgd #define	IPFORWARDING	1	/* forward IP packets not for us */
    157         1.1       cgd #else /* GATEWAY */
    158         1.1       cgd #define	IPFORWARDING	0	/* don't forward IP packets not for us */
    159         1.1       cgd #endif /* GATEWAY */
    160         1.1       cgd #endif /* IPFORWARDING */
    161         1.1       cgd #ifndef	IPSENDREDIRECTS
    162         1.1       cgd #define	IPSENDREDIRECTS	1
    163         1.1       cgd #endif
    164        1.26   thorpej #ifndef IPFORWSRCRT
    165        1.47       cjs #define	IPFORWSRCRT	1	/* forward source-routed packets */
    166        1.47       cjs #endif
    167        1.47       cjs #ifndef IPALLOWSRCRT
    168        1.48       mrg #define	IPALLOWSRCRT	1	/* allow source-routed packets */
    169        1.26   thorpej #endif
    170        1.53       kml #ifndef IPMTUDISC
    171  1.130.2.10   nathanw #define IPMTUDISC	1
    172        1.53       kml #endif
    173        1.60       kml #ifndef IPMTUDISCTIMEOUT
    174        1.61       kml #define IPMTUDISCTIMEOUT (10 * 60)	/* as per RFC 1191 */
    175        1.60       kml #endif
    176        1.53       kml 
    177        1.27   thorpej /*
    178        1.27   thorpej  * Note: DIRECTED_BROADCAST is handled this way so that previous
    179        1.27   thorpej  * configuration using this option will Just Work.
    180        1.27   thorpej  */
    181        1.27   thorpej #ifndef IPDIRECTEDBCAST
    182        1.27   thorpej #ifdef DIRECTED_BROADCAST
    183        1.27   thorpej #define IPDIRECTEDBCAST	1
    184        1.27   thorpej #else
    185        1.27   thorpej #define	IPDIRECTEDBCAST	0
    186        1.27   thorpej #endif /* DIRECTED_BROADCAST */
    187        1.27   thorpej #endif /* IPDIRECTEDBCAST */
    188         1.1       cgd int	ipforwarding = IPFORWARDING;
    189         1.1       cgd int	ipsendredirects = IPSENDREDIRECTS;
    190        1.13   mycroft int	ip_defttl = IPDEFTTL;
    191        1.26   thorpej int	ip_forwsrcrt = IPFORWSRCRT;
    192        1.27   thorpej int	ip_directedbcast = IPDIRECTEDBCAST;
    193        1.47       cjs int	ip_allowsrcrt = IPALLOWSRCRT;
    194        1.53       kml int	ip_mtudisc = IPMTUDISC;
    195  1.130.2.13   nathanw int	ip_mtudisc_timeout = IPMTUDISCTIMEOUT;
    196         1.1       cgd #ifdef DIAGNOSTIC
    197         1.1       cgd int	ipprintfs = 0;
    198         1.1       cgd #endif
    199         1.1       cgd 
    200        1.60       kml struct rttimer_queue *ip_mtudisc_timeout_q = NULL;
    201        1.60       kml 
    202         1.1       cgd extern	struct domain inetdomain;
    203         1.1       cgd int	ipqmaxlen = IFQ_MAXLEN;
    204  1.130.2.10   nathanw u_long	in_ifaddrhash;				/* size of hash table - 1 */
    205  1.130.2.10   nathanw int	in_ifaddrentries;			/* total number of addrs */
    206        1.22   mycroft struct	in_ifaddrhead in_ifaddr;
    207        1.57       tls struct	in_ifaddrhashhead *in_ifaddrhashtbl;
    208        1.13   mycroft struct	ifqueue ipintrq;
    209        1.63      matt struct	ipstat	ipstat;
    210        1.63      matt u_int16_t	ip_id;
    211        1.75   thorpej 
    212       1.121   thorpej #ifdef PFIL_HOOKS
    213       1.121   thorpej struct pfil_head inet_pfil_hook;
    214       1.121   thorpej #endif
    215       1.121   thorpej 
    216        1.63      matt struct ipqhead ipq;
    217        1.75   thorpej int	ipq_locked;
    218   1.130.2.1   nathanw int	ip_nfragpackets = 0;
    219   1.130.2.2   nathanw int	ip_maxfragpackets = 200;
    220        1.75   thorpej 
    221        1.75   thorpej static __inline int ipq_lock_try __P((void));
    222        1.75   thorpej static __inline void ipq_unlock __P((void));
    223        1.75   thorpej 
    224        1.75   thorpej static __inline int
    225        1.75   thorpej ipq_lock_try()
    226        1.75   thorpej {
    227        1.75   thorpej 	int s;
    228        1.75   thorpej 
    229   1.130.2.2   nathanw 	/*
    230  1.130.2.10   nathanw 	 * Use splvm() -- we're blocking things that would cause
    231   1.130.2.2   nathanw 	 * mbuf allocation.
    232   1.130.2.2   nathanw 	 */
    233   1.130.2.2   nathanw 	s = splvm();
    234        1.75   thorpej 	if (ipq_locked) {
    235        1.75   thorpej 		splx(s);
    236        1.75   thorpej 		return (0);
    237        1.75   thorpej 	}
    238        1.75   thorpej 	ipq_locked = 1;
    239        1.75   thorpej 	splx(s);
    240        1.75   thorpej 	return (1);
    241        1.75   thorpej }
    242        1.75   thorpej 
    243        1.75   thorpej static __inline void
    244        1.75   thorpej ipq_unlock()
    245        1.75   thorpej {
    246        1.75   thorpej 	int s;
    247        1.75   thorpej 
    248   1.130.2.2   nathanw 	s = splvm();
    249        1.75   thorpej 	ipq_locked = 0;
    250        1.75   thorpej 	splx(s);
    251        1.75   thorpej }
    252        1.75   thorpej 
    253        1.75   thorpej #ifdef DIAGNOSTIC
    254        1.75   thorpej #define	IPQ_LOCK()							\
    255        1.75   thorpej do {									\
    256        1.75   thorpej 	if (ipq_lock_try() == 0) {					\
    257        1.75   thorpej 		printf("%s:%d: ipq already locked\n", __FILE__, __LINE__); \
    258        1.75   thorpej 		panic("ipq_lock");					\
    259        1.75   thorpej 	}								\
    260  1.130.2.15   nathanw } while (/*CONSTCOND*/ 0)
    261        1.75   thorpej #define	IPQ_LOCK_CHECK()						\
    262        1.75   thorpej do {									\
    263        1.75   thorpej 	if (ipq_locked == 0) {						\
    264        1.75   thorpej 		printf("%s:%d: ipq lock not held\n", __FILE__, __LINE__); \
    265        1.75   thorpej 		panic("ipq lock check");				\
    266        1.75   thorpej 	}								\
    267  1.130.2.15   nathanw } while (/*CONSTCOND*/ 0)
    268        1.75   thorpej #else
    269        1.75   thorpej #define	IPQ_LOCK()		(void) ipq_lock_try()
    270        1.75   thorpej #define	IPQ_LOCK_CHECK()	/* nothing */
    271        1.75   thorpej #endif
    272        1.75   thorpej 
    273        1.75   thorpej #define	IPQ_UNLOCK()		ipq_unlock()
    274         1.1       cgd 
    275        1.72   thorpej struct pool ipqent_pool;
    276        1.72   thorpej 
    277   1.130.2.2   nathanw #ifdef INET_CSUM_COUNTERS
    278   1.130.2.2   nathanw #include <sys/device.h>
    279   1.130.2.2   nathanw 
    280   1.130.2.2   nathanw struct evcnt ip_hwcsum_bad = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
    281   1.130.2.2   nathanw     NULL, "inet", "hwcsum bad");
    282   1.130.2.2   nathanw struct evcnt ip_hwcsum_ok = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
    283   1.130.2.2   nathanw     NULL, "inet", "hwcsum ok");
    284   1.130.2.2   nathanw struct evcnt ip_swcsum = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
    285   1.130.2.2   nathanw     NULL, "inet", "swcsum");
    286   1.130.2.2   nathanw 
    287   1.130.2.2   nathanw #define	INET_CSUM_COUNTER_INCR(ev)	(ev)->ev_count++
    288   1.130.2.2   nathanw 
    289   1.130.2.2   nathanw #else
    290   1.130.2.2   nathanw 
    291   1.130.2.2   nathanw #define	INET_CSUM_COUNTER_INCR(ev)	/* nothing */
    292   1.130.2.2   nathanw 
    293   1.130.2.2   nathanw #endif /* INET_CSUM_COUNTERS */
    294   1.130.2.2   nathanw 
    295         1.1       cgd /*
    296         1.1       cgd  * We need to save the IP options in case a protocol wants to respond
    297         1.1       cgd  * to an incoming packet over the same route if the packet got here
    298         1.1       cgd  * using IP source routing.  This allows connection establishment and
    299         1.1       cgd  * maintenance when the remote end is on a network that is not known
    300         1.1       cgd  * to us.
    301         1.1       cgd  */
    302         1.1       cgd int	ip_nhops = 0;
    303         1.1       cgd static	struct ip_srcrt {
    304         1.1       cgd 	struct	in_addr dst;			/* final destination */
    305         1.1       cgd 	char	nop;				/* one NOP to align */
    306         1.1       cgd 	char	srcopt[IPOPT_OFFSET + 1];	/* OPTVAL, OLEN and OFFSET */
    307         1.1       cgd 	struct	in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)];
    308         1.1       cgd } ip_srcrt;
    309         1.1       cgd 
    310        1.13   mycroft static void save_rte __P((u_char *, struct in_addr));
    311        1.35   mycroft 
    312         1.1       cgd /*
    313         1.1       cgd  * IP initialization: fill in IP protocol switch table.
    314         1.1       cgd  * All protocols not implemented in kernel go to raw IP protocol handler.
    315         1.1       cgd  */
    316         1.8   mycroft void
    317         1.1       cgd ip_init()
    318         1.1       cgd {
    319       1.109  augustss 	struct protosw *pr;
    320       1.109  augustss 	int i;
    321         1.1       cgd 
    322        1.72   thorpej 	pool_init(&ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl",
    323   1.130.2.8   nathanw 	    NULL);
    324        1.72   thorpej 
    325         1.1       cgd 	pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
    326         1.1       cgd 	if (pr == 0)
    327         1.1       cgd 		panic("ip_init");
    328         1.1       cgd 	for (i = 0; i < IPPROTO_MAX; i++)
    329         1.1       cgd 		ip_protox[i] = pr - inetsw;
    330         1.1       cgd 	for (pr = inetdomain.dom_protosw;
    331         1.1       cgd 	    pr < inetdomain.dom_protoswNPROTOSW; pr++)
    332         1.1       cgd 		if (pr->pr_domain->dom_family == PF_INET &&
    333         1.1       cgd 		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
    334         1.1       cgd 			ip_protox[pr->pr_protocol] = pr - inetsw;
    335        1.25       cgd 	LIST_INIT(&ipq);
    336         1.1       cgd 	ip_id = time.tv_sec & 0xffff;
    337         1.1       cgd 	ipintrq.ifq_maxlen = ipqmaxlen;
    338        1.22   mycroft 	TAILQ_INIT(&in_ifaddr);
    339       1.120        ad 	in_ifaddrhashtbl = hashinit(IN_IFADDR_HASH_SIZE, HASH_LIST, M_IFADDR,
    340       1.120        ad 	    M_WAITOK, &in_ifaddrhash);
    341  1.130.2.15   nathanw 	ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout);
    342        1.73   thorpej #ifdef GATEWAY
    343        1.73   thorpej 	ipflow_init();
    344        1.73   thorpej #endif
    345       1.121   thorpej 
    346       1.121   thorpej #ifdef PFIL_HOOKS
    347       1.121   thorpej 	/* Register our Packet Filter hook. */
    348       1.126   thorpej 	inet_pfil_hook.ph_type = PFIL_TYPE_AF;
    349       1.126   thorpej 	inet_pfil_hook.ph_af   = AF_INET;
    350       1.121   thorpej 	i = pfil_head_register(&inet_pfil_hook);
    351       1.121   thorpej 	if (i != 0)
    352       1.121   thorpej 		printf("ip_init: WARNING: unable to register pfil hook, "
    353       1.121   thorpej 		    "error %d\n", i);
    354       1.121   thorpej #endif /* PFIL_HOOKS */
    355   1.130.2.2   nathanw 
    356   1.130.2.2   nathanw #ifdef INET_CSUM_COUNTERS
    357   1.130.2.2   nathanw 	evcnt_attach_static(&ip_hwcsum_bad);
    358   1.130.2.2   nathanw 	evcnt_attach_static(&ip_hwcsum_ok);
    359   1.130.2.2   nathanw 	evcnt_attach_static(&ip_swcsum);
    360   1.130.2.2   nathanw #endif /* INET_CSUM_COUNTERS */
    361         1.1       cgd }
    362         1.1       cgd 
    363         1.1       cgd struct	sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET };
    364         1.1       cgd struct	route ipforward_rt;
    365         1.1       cgd 
    366         1.1       cgd /*
    367        1.89    itojun  * IP software interrupt routine
    368        1.89    itojun  */
    369        1.89    itojun void
    370        1.89    itojun ipintr()
    371        1.89    itojun {
    372        1.89    itojun 	int s;
    373        1.89    itojun 	struct mbuf *m;
    374        1.89    itojun 
    375        1.89    itojun 	while (1) {
    376   1.130.2.2   nathanw 		s = splnet();
    377        1.89    itojun 		IF_DEQUEUE(&ipintrq, m);
    378        1.89    itojun 		splx(s);
    379        1.89    itojun 		if (m == 0)
    380        1.89    itojun 			return;
    381        1.89    itojun 		ip_input(m);
    382        1.89    itojun 	}
    383        1.89    itojun }
    384        1.89    itojun 
    385        1.89    itojun /*
    386         1.1       cgd  * Ip input routine.  Checksum and byte swap header.  If fragmented
    387         1.1       cgd  * try to reassemble.  Process options.  Pass to next level.
    388         1.1       cgd  */
    389         1.8   mycroft void
    390        1.89    itojun ip_input(struct mbuf *m)
    391         1.1       cgd {
    392       1.109  augustss 	struct ip *ip = NULL;
    393       1.109  augustss 	struct ipq *fp;
    394       1.109  augustss 	struct in_ifaddr *ia;
    395       1.109  augustss 	struct ifaddr *ifa;
    396        1.25       cgd 	struct ipqent *ipqe;
    397        1.89    itojun 	int hlen = 0, mff, len;
    398       1.100    itojun 	int downmatch;
    399         1.1       cgd 
    400         1.1       cgd #ifdef	DIAGNOSTIC
    401         1.1       cgd 	if ((m->m_flags & M_PKTHDR) == 0)
    402         1.1       cgd 		panic("ipintr no HDR");
    403         1.1       cgd #endif
    404        1.89    itojun #ifdef IPSEC
    405        1.89    itojun 	/*
    406        1.89    itojun 	 * should the inner packet be considered authentic?
    407        1.89    itojun 	 * see comment in ah4_input().
    408        1.89    itojun 	 */
    409        1.89    itojun 	if (m) {
    410        1.89    itojun 		m->m_flags &= ~M_AUTHIPHDR;
    411        1.89    itojun 		m->m_flags &= ~M_AUTHIPDGM;
    412        1.89    itojun 	}
    413        1.89    itojun #endif
    414         1.1       cgd 	/*
    415         1.1       cgd 	 * If no IP addresses have been set yet but the interfaces
    416         1.1       cgd 	 * are receiving, can't do anything with incoming packets yet.
    417         1.1       cgd 	 */
    418   1.130.2.5   nathanw 	if (TAILQ_FIRST(&in_ifaddr) == 0)
    419         1.1       cgd 		goto bad;
    420         1.1       cgd 	ipstat.ips_total++;
    421  1.130.2.11   nathanw 	/*
    422  1.130.2.11   nathanw 	 * If the IP header is not aligned, slurp it up into a new
    423  1.130.2.11   nathanw 	 * mbuf with space for link headers, in the event we forward
    424  1.130.2.11   nathanw 	 * it.  Otherwise, if it is aligned, make sure the entire
    425  1.130.2.11   nathanw 	 * base IP header is in the first mbuf of the chain.
    426  1.130.2.11   nathanw 	 */
    427  1.130.2.11   nathanw 	if (IP_HDR_ALIGNED_P(mtod(m, caddr_t)) == 0) {
    428  1.130.2.11   nathanw 		if ((m = m_copyup(m, sizeof(struct ip),
    429  1.130.2.11   nathanw 				  (max_linkhdr + 3) & ~3)) == NULL) {
    430  1.130.2.11   nathanw 			/* XXXJRT new stat, please */
    431  1.130.2.11   nathanw 			ipstat.ips_toosmall++;
    432  1.130.2.11   nathanw 			return;
    433  1.130.2.11   nathanw 		}
    434  1.130.2.11   nathanw 	} else if (__predict_false(m->m_len < sizeof (struct ip))) {
    435  1.130.2.11   nathanw 		if ((m = m_pullup(m, sizeof (struct ip))) == NULL) {
    436  1.130.2.11   nathanw 			ipstat.ips_toosmall++;
    437  1.130.2.11   nathanw 			return;
    438  1.130.2.11   nathanw 		}
    439         1.1       cgd 	}
    440         1.1       cgd 	ip = mtod(m, struct ip *);
    441        1.13   mycroft 	if (ip->ip_v != IPVERSION) {
    442        1.13   mycroft 		ipstat.ips_badvers++;
    443        1.13   mycroft 		goto bad;
    444        1.13   mycroft 	}
    445         1.1       cgd 	hlen = ip->ip_hl << 2;
    446         1.1       cgd 	if (hlen < sizeof(struct ip)) {	/* minimum header length */
    447         1.1       cgd 		ipstat.ips_badhlen++;
    448         1.1       cgd 		goto bad;
    449         1.1       cgd 	}
    450         1.1       cgd 	if (hlen > m->m_len) {
    451         1.1       cgd 		if ((m = m_pullup(m, hlen)) == 0) {
    452         1.1       cgd 			ipstat.ips_badhlen++;
    453        1.89    itojun 			return;
    454         1.1       cgd 		}
    455         1.1       cgd 		ip = mtod(m, struct ip *);
    456         1.1       cgd 	}
    457        1.98   thorpej 
    458        1.85       hwr 	/*
    459        1.99   thorpej 	 * RFC1122: packets with a multicast source address are
    460        1.98   thorpej 	 * not allowed.
    461        1.85       hwr 	 */
    462        1.85       hwr 	if (IN_MULTICAST(ip->ip_src.s_addr)) {
    463       1.130    itojun 		ipstat.ips_badaddr++;
    464        1.85       hwr 		goto bad;
    465       1.129    itojun 	}
    466       1.129    itojun 
    467       1.129    itojun 	/* 127/8 must not appear on wire - RFC1122 */
    468       1.129    itojun 	if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
    469       1.129    itojun 	    (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
    470       1.130    itojun 		if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
    471       1.130    itojun 			ipstat.ips_badaddr++;
    472       1.129    itojun 			goto bad;
    473       1.130    itojun 		}
    474        1.85       hwr 	}
    475        1.85       hwr 
    476   1.130.2.2   nathanw 	switch (m->m_pkthdr.csum_flags &
    477   1.130.2.4   nathanw 		((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_IPv4) |
    478   1.130.2.2   nathanw 		 M_CSUM_IPv4_BAD)) {
    479   1.130.2.2   nathanw 	case M_CSUM_IPv4|M_CSUM_IPv4_BAD:
    480   1.130.2.2   nathanw 		INET_CSUM_COUNTER_INCR(&ip_hwcsum_bad);
    481   1.130.2.2   nathanw 		goto badcsum;
    482   1.130.2.2   nathanw 
    483   1.130.2.2   nathanw 	case M_CSUM_IPv4:
    484   1.130.2.2   nathanw 		/* Checksum was okay. */
    485   1.130.2.2   nathanw 		INET_CSUM_COUNTER_INCR(&ip_hwcsum_ok);
    486   1.130.2.2   nathanw 		break;
    487   1.130.2.2   nathanw 
    488   1.130.2.2   nathanw 	default:
    489   1.130.2.2   nathanw 		/* Must compute it ourselves. */
    490   1.130.2.2   nathanw 		INET_CSUM_COUNTER_INCR(&ip_swcsum);
    491   1.130.2.2   nathanw 		if (in_cksum(m, hlen) != 0)
    492   1.130.2.2   nathanw 			goto bad;
    493   1.130.2.2   nathanw 		break;
    494         1.1       cgd 	}
    495         1.1       cgd 
    496       1.121   thorpej 	/* Retrieve the packet length. */
    497       1.121   thorpej 	len = ntohs(ip->ip_len);
    498        1.81     proff 
    499        1.81     proff 	/*
    500        1.81     proff 	 * Check for additional length bogosity
    501        1.81     proff 	 */
    502        1.84     proff 	if (len < hlen) {
    503        1.81     proff 	 	ipstat.ips_badlen++;
    504        1.81     proff 		goto bad;
    505        1.81     proff 	}
    506         1.1       cgd 
    507         1.1       cgd 	/*
    508         1.1       cgd 	 * Check that the amount of data in the buffers
    509         1.1       cgd 	 * is as at least much as the IP header would have us expect.
    510         1.1       cgd 	 * Trim mbufs if longer than we expect.
    511         1.1       cgd 	 * Drop packet if shorter than we expect.
    512         1.1       cgd 	 */
    513        1.35   mycroft 	if (m->m_pkthdr.len < len) {
    514         1.1       cgd 		ipstat.ips_tooshort++;
    515         1.1       cgd 		goto bad;
    516         1.1       cgd 	}
    517        1.35   mycroft 	if (m->m_pkthdr.len > len) {
    518         1.1       cgd 		if (m->m_len == m->m_pkthdr.len) {
    519        1.35   mycroft 			m->m_len = len;
    520        1.35   mycroft 			m->m_pkthdr.len = len;
    521         1.1       cgd 		} else
    522        1.35   mycroft 			m_adj(m, len - m->m_pkthdr.len);
    523         1.1       cgd 	}
    524         1.1       cgd 
    525        1.94    itojun #ifdef IPSEC
    526  1.130.2.10   nathanw 	/* ipflow (IP fast forwarding) is not compatible with IPsec. */
    527        1.94    itojun 	m->m_flags &= ~M_CANFASTFWD;
    528        1.94    itojun #else
    529        1.64   thorpej 	/*
    530        1.64   thorpej 	 * Assume that we can create a fast-forward IP flow entry
    531        1.64   thorpej 	 * based on this packet.
    532        1.64   thorpej 	 */
    533        1.64   thorpej 	m->m_flags |= M_CANFASTFWD;
    534        1.94    itojun #endif
    535        1.64   thorpej 
    536        1.36       mrg #ifdef PFIL_HOOKS
    537        1.33       mrg 	/*
    538        1.64   thorpej 	 * Run through list of hooks for input packets.  If there are any
    539        1.64   thorpej 	 * filters which require that additional packets in the flow are
    540        1.64   thorpej 	 * not fast-forwarded, they must clear the M_CANFASTFWD flag.
    541        1.64   thorpej 	 * Note that filters must _never_ set this flag, as another filter
    542        1.64   thorpej 	 * in the list may have previously cleared it.
    543        1.33       mrg 	 */
    544       1.127    itojun 	/*
    545       1.127    itojun 	 * let ipfilter look at packet on the wire,
    546       1.127    itojun 	 * not the decapsulated packet.
    547       1.127    itojun 	 */
    548       1.127    itojun #ifdef IPSEC
    549   1.130.2.3   nathanw 	if (!ipsec_getnhist(m))
    550       1.127    itojun #else
    551       1.127    itojun 	if (1)
    552       1.127    itojun #endif
    553       1.127    itojun 	{
    554       1.127    itojun 		if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif,
    555       1.127    itojun 				   PFIL_IN) != 0)
    556       1.121   thorpej 		return;
    557       1.127    itojun 		if (m == NULL)
    558       1.127    itojun 			return;
    559       1.127    itojun 		ip = mtod(m, struct ip *);
    560   1.130.2.6   nathanw 		hlen = ip->ip_hl << 2;
    561       1.127    itojun 	}
    562        1.36       mrg #endif /* PFIL_HOOKS */
    563       1.123   thorpej 
    564       1.123   thorpej #ifdef ALTQ
    565       1.123   thorpej 	/* XXX Temporary until ALTQ is changed to use a pfil hook */
    566       1.123   thorpej 	if (altq_input != NULL && (*altq_input)(m, AF_INET) == 0) {
    567       1.123   thorpej 		/* packet dropped by traffic conditioner */
    568       1.123   thorpej 		return;
    569       1.123   thorpej 	}
    570       1.123   thorpej #endif
    571       1.121   thorpej 
    572       1.121   thorpej 	/*
    573         1.1       cgd 	 * Process options and, if not destined for us,
    574         1.1       cgd 	 * ship it on.  ip_dooptions returns 1 when an
    575         1.1       cgd 	 * error was detected (causing an icmp message
    576         1.1       cgd 	 * to be sent and the original packet to be freed).
    577         1.1       cgd 	 */
    578         1.1       cgd 	ip_nhops = 0;		/* for source routed packets */
    579         1.1       cgd 	if (hlen > sizeof (struct ip) && ip_dooptions(m))
    580        1.89    itojun 		return;
    581         1.1       cgd 
    582         1.1       cgd 	/*
    583         1.1       cgd 	 * Check our list of addresses, to see if the packet is for us.
    584       1.100    itojun 	 *
    585       1.100    itojun 	 * Traditional 4.4BSD did not consult IFF_UP at all.
    586       1.100    itojun 	 * The behavior here is to treat addresses on !IFF_UP interface
    587       1.100    itojun 	 * as not mine.
    588         1.1       cgd 	 */
    589       1.100    itojun 	downmatch = 0;
    590   1.130.2.5   nathanw 	LIST_FOREACH(ia, &IN_IFADDR_HASH(ip->ip_dst.s_addr), ia_hash) {
    591        1.97    itojun 		if (in_hosteq(ia->ia_addr.sin_addr, ip->ip_dst)) {
    592        1.97    itojun 			if ((ia->ia_ifp->if_flags & IFF_UP) != 0)
    593        1.97    itojun 				break;
    594       1.100    itojun 			else
    595       1.100    itojun 				downmatch++;
    596        1.97    itojun 		}
    597        1.97    itojun 	}
    598        1.86   thorpej 	if (ia != NULL)
    599        1.86   thorpej 		goto ours;
    600        1.57       tls 	if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) {
    601   1.130.2.5   nathanw 		TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrlist, ifa_list) {
    602   1.130.2.5   nathanw 			if (ifa->ifa_addr->sa_family != AF_INET)
    603   1.130.2.5   nathanw 				continue;
    604        1.57       tls 			ia = ifatoia(ifa);
    605        1.35   mycroft 			if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) ||
    606        1.35   mycroft 			    in_hosteq(ip->ip_dst, ia->ia_netbroadcast) ||
    607        1.20   mycroft 			    /*
    608        1.20   mycroft 			     * Look for all-0's host part (old broadcast addr),
    609        1.20   mycroft 			     * either for subnet or net.
    610        1.20   mycroft 			     */
    611        1.20   mycroft 			    ip->ip_dst.s_addr == ia->ia_subnet ||
    612        1.18   mycroft 			    ip->ip_dst.s_addr == ia->ia_net)
    613         1.1       cgd 				goto ours;
    614        1.57       tls 			/*
    615        1.57       tls 			 * An interface with IP address zero accepts
    616        1.57       tls 			 * all packets that arrive on that interface.
    617        1.57       tls 			 */
    618        1.57       tls 			if (in_nullhost(ia->ia_addr.sin_addr))
    619        1.57       tls 				goto ours;
    620         1.1       cgd 		}
    621         1.1       cgd 	}
    622        1.18   mycroft 	if (IN_MULTICAST(ip->ip_dst.s_addr)) {
    623         1.4   hpeyerl 		struct in_multi *inm;
    624         1.4   hpeyerl #ifdef MROUTING
    625         1.4   hpeyerl 		extern struct socket *ip_mrouter;
    626        1.10    brezak 
    627   1.130.2.9   thorpej 		if (M_READONLY(m)) {
    628        1.10    brezak 			if ((m = m_pullup(m, hlen)) == 0) {
    629        1.10    brezak 				ipstat.ips_toosmall++;
    630        1.89    itojun 				return;
    631        1.10    brezak 			}
    632        1.10    brezak 			ip = mtod(m, struct ip *);
    633        1.10    brezak 		}
    634         1.4   hpeyerl 
    635         1.4   hpeyerl 		if (ip_mrouter) {
    636         1.4   hpeyerl 			/*
    637         1.4   hpeyerl 			 * If we are acting as a multicast router, all
    638         1.4   hpeyerl 			 * incoming multicast packets are passed to the
    639         1.4   hpeyerl 			 * kernel-level multicast forwarding function.
    640         1.4   hpeyerl 			 * The packet is returned (relatively) intact; if
    641         1.4   hpeyerl 			 * ip_mforward() returns a non-zero value, the packet
    642         1.4   hpeyerl 			 * must be discarded, else it may be accepted below.
    643         1.4   hpeyerl 			 *
    644         1.4   hpeyerl 			 * (The IP ident field is put in the same byte order
    645         1.4   hpeyerl 			 * as expected when ip_mforward() is called from
    646         1.4   hpeyerl 			 * ip_output().)
    647         1.4   hpeyerl 			 */
    648        1.13   mycroft 			if (ip_mforward(m, m->m_pkthdr.rcvif) != 0) {
    649        1.13   mycroft 				ipstat.ips_cantforward++;
    650         1.4   hpeyerl 				m_freem(m);
    651        1.89    itojun 				return;
    652         1.4   hpeyerl 			}
    653         1.4   hpeyerl 
    654         1.4   hpeyerl 			/*
    655         1.4   hpeyerl 			 * The process-level routing demon needs to receive
    656         1.4   hpeyerl 			 * all multicast IGMP packets, whether or not this
    657         1.4   hpeyerl 			 * host belongs to their destination groups.
    658         1.4   hpeyerl 			 */
    659         1.4   hpeyerl 			if (ip->ip_p == IPPROTO_IGMP)
    660         1.4   hpeyerl 				goto ours;
    661        1.13   mycroft 			ipstat.ips_forward++;
    662         1.4   hpeyerl 		}
    663         1.4   hpeyerl #endif
    664         1.4   hpeyerl 		/*
    665         1.4   hpeyerl 		 * See if we belong to the destination multicast group on the
    666         1.4   hpeyerl 		 * arrival interface.
    667         1.4   hpeyerl 		 */
    668         1.4   hpeyerl 		IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm);
    669         1.4   hpeyerl 		if (inm == NULL) {
    670        1.13   mycroft 			ipstat.ips_cantforward++;
    671         1.4   hpeyerl 			m_freem(m);
    672        1.89    itojun 			return;
    673         1.4   hpeyerl 		}
    674         1.4   hpeyerl 		goto ours;
    675         1.4   hpeyerl 	}
    676        1.19   mycroft 	if (ip->ip_dst.s_addr == INADDR_BROADCAST ||
    677        1.35   mycroft 	    in_nullhost(ip->ip_dst))
    678         1.1       cgd 		goto ours;
    679         1.1       cgd 
    680         1.1       cgd 	/*
    681         1.1       cgd 	 * Not for us; forward if possible and desirable.
    682         1.1       cgd 	 */
    683         1.1       cgd 	if (ipforwarding == 0) {
    684         1.1       cgd 		ipstat.ips_cantforward++;
    685         1.1       cgd 		m_freem(m);
    686       1.100    itojun 	} else {
    687       1.100    itojun 		/*
    688       1.100    itojun 		 * If ip_dst matched any of my address on !IFF_UP interface,
    689       1.100    itojun 		 * and there's no IFF_UP interface that matches ip_dst,
    690       1.100    itojun 		 * send icmp unreach.  Forwarding it will result in in-kernel
    691       1.100    itojun 		 * forwarding loop till TTL goes to 0.
    692       1.100    itojun 		 */
    693       1.100    itojun 		if (downmatch) {
    694       1.100    itojun 			icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
    695       1.100    itojun 			ipstat.ips_cantforward++;
    696       1.100    itojun 			return;
    697       1.100    itojun 		}
    698   1.130.2.7   nathanw #ifdef IPSEC
    699   1.130.2.7   nathanw 		if (ipsec4_in_reject(m, NULL)) {
    700   1.130.2.7   nathanw 			ipsecstat.in_polvio++;
    701   1.130.2.7   nathanw 			goto bad;
    702   1.130.2.7   nathanw 		}
    703   1.130.2.7   nathanw #endif
    704   1.130.2.7   nathanw 
    705         1.1       cgd 		ip_forward(m, 0);
    706       1.100    itojun 	}
    707        1.89    itojun 	return;
    708         1.1       cgd 
    709         1.1       cgd ours:
    710         1.1       cgd 	/*
    711         1.1       cgd 	 * If offset or IP_MF are set, must reassemble.
    712         1.1       cgd 	 * Otherwise, nothing need be done.
    713         1.1       cgd 	 * (We could look in the reassembly queue to see
    714         1.1       cgd 	 * if the packet was previously fragmented,
    715         1.1       cgd 	 * but it's not worth the time; just let them time out.)
    716         1.1       cgd 	 */
    717  1.130.2.12   nathanw 	if (ip->ip_off & ~htons(IP_DF|IP_RF)) {
    718  1.130.2.12   nathanw 		if (M_READONLY(m)) {
    719  1.130.2.12   nathanw 			if ((m = m_pullup(m, hlen)) == NULL) {
    720  1.130.2.12   nathanw 				ipstat.ips_toosmall++;
    721  1.130.2.12   nathanw 				goto bad;
    722  1.130.2.12   nathanw 			}
    723  1.130.2.12   nathanw 			ip = mtod(m, struct ip *);
    724  1.130.2.12   nathanw 		}
    725  1.130.2.12   nathanw 
    726         1.1       cgd 		/*
    727         1.1       cgd 		 * Look for queue of fragments
    728         1.1       cgd 		 * of this datagram.
    729         1.1       cgd 		 */
    730        1.75   thorpej 		IPQ_LOCK();
    731   1.130.2.5   nathanw 		LIST_FOREACH(fp, &ipq, ipq_q)
    732         1.1       cgd 			if (ip->ip_id == fp->ipq_id &&
    733        1.35   mycroft 			    in_hosteq(ip->ip_src, fp->ipq_src) &&
    734        1.35   mycroft 			    in_hosteq(ip->ip_dst, fp->ipq_dst) &&
    735         1.1       cgd 			    ip->ip_p == fp->ipq_p)
    736         1.1       cgd 				goto found;
    737         1.1       cgd 		fp = 0;
    738         1.1       cgd found:
    739         1.1       cgd 
    740         1.1       cgd 		/*
    741         1.1       cgd 		 * Adjust ip_len to not reflect header,
    742        1.25       cgd 		 * set ipqe_mff if more fragments are expected,
    743         1.1       cgd 		 * convert offset of this to bytes.
    744         1.1       cgd 		 */
    745  1.130.2.12   nathanw 		ip->ip_len = htons(ntohs(ip->ip_len) - hlen);
    746  1.130.2.12   nathanw 		mff = (ip->ip_off & htons(IP_MF)) != 0;
    747        1.25       cgd 		if (mff) {
    748        1.16       cgd 		        /*
    749        1.16       cgd 		         * Make sure that fragments have a data length
    750        1.16       cgd 			 * that's a non-zero multiple of 8 bytes.
    751        1.16       cgd 		         */
    752  1.130.2.12   nathanw 			if (ntohs(ip->ip_len) == 0 ||
    753  1.130.2.12   nathanw 			    (ntohs(ip->ip_len) & 0x7) != 0) {
    754        1.16       cgd 				ipstat.ips_badfrags++;
    755        1.75   thorpej 				IPQ_UNLOCK();
    756        1.16       cgd 				goto bad;
    757        1.16       cgd 			}
    758        1.16       cgd 		}
    759  1.130.2.12   nathanw 		ip->ip_off = htons((ntohs(ip->ip_off) & IP_OFFMASK) << 3);
    760         1.1       cgd 
    761         1.1       cgd 		/*
    762         1.1       cgd 		 * If datagram marked as having more fragments
    763         1.1       cgd 		 * or if this is not the first fragment,
    764         1.1       cgd 		 * attempt reassembly; if it succeeds, proceed.
    765         1.1       cgd 		 */
    766  1.130.2.12   nathanw 		if (mff || ip->ip_off != htons(0)) {
    767         1.1       cgd 			ipstat.ips_fragments++;
    768        1.72   thorpej 			ipqe = pool_get(&ipqent_pool, PR_NOWAIT);
    769        1.25       cgd 			if (ipqe == NULL) {
    770        1.25       cgd 				ipstat.ips_rcvmemdrop++;
    771        1.75   thorpej 				IPQ_UNLOCK();
    772        1.25       cgd 				goto bad;
    773        1.25       cgd 			}
    774        1.25       cgd 			ipqe->ipqe_mff = mff;
    775        1.50   thorpej 			ipqe->ipqe_m = m;
    776        1.25       cgd 			ipqe->ipqe_ip = ip;
    777        1.50   thorpej 			m = ip_reass(ipqe, fp);
    778        1.75   thorpej 			if (m == 0) {
    779        1.75   thorpej 				IPQ_UNLOCK();
    780        1.89    itojun 				return;
    781        1.75   thorpej 			}
    782        1.13   mycroft 			ipstat.ips_reassembled++;
    783        1.50   thorpej 			ip = mtod(m, struct ip *);
    784        1.74   thorpej 			hlen = ip->ip_hl << 2;
    785  1.130.2.12   nathanw 			ip->ip_len = htons(ntohs(ip->ip_len) + hlen);
    786         1.1       cgd 		} else
    787         1.1       cgd 			if (fp)
    788         1.1       cgd 				ip_freef(fp);
    789        1.75   thorpej 		IPQ_UNLOCK();
    790        1.79   mycroft 	}
    791       1.128    itojun 
    792       1.128    itojun #ifdef IPSEC
    793       1.128    itojun 	/*
    794       1.128    itojun 	 * enforce IPsec policy checking if we are seeing last header.
    795       1.128    itojun 	 * note that we do not visit this with protocols with pcb layer
    796       1.128    itojun 	 * code - like udp/tcp/raw ip.
    797       1.128    itojun 	 */
    798       1.128    itojun 	if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0 &&
    799       1.128    itojun 	    ipsec4_in_reject(m, NULL)) {
    800       1.128    itojun 		ipsecstat.in_polvio++;
    801       1.128    itojun 		goto bad;
    802       1.128    itojun 	}
    803       1.128    itojun #endif
    804         1.1       cgd 
    805         1.1       cgd 	/*
    806         1.1       cgd 	 * Switch out to protocol's input routine.
    807         1.1       cgd 	 */
    808        1.82     aidan #if IFA_STATS
    809       1.122    itojun 	if (ia && ip)
    810  1.130.2.12   nathanw 		ia->ia_ifa.ifa_data.ifad_inbytes += ntohs(ip->ip_len);
    811        1.82     aidan #endif
    812         1.1       cgd 	ipstat.ips_delivered++;
    813        1.89    itojun     {
    814        1.89    itojun 	int off = hlen, nh = ip->ip_p;
    815        1.89    itojun 
    816        1.89    itojun 	(*inetsw[ip_protox[nh]].pr_input)(m, off, nh);
    817        1.89    itojun 	return;
    818        1.89    itojun     }
    819         1.1       cgd bad:
    820         1.1       cgd 	m_freem(m);
    821   1.130.2.2   nathanw 	return;
    822   1.130.2.2   nathanw 
    823   1.130.2.2   nathanw badcsum:
    824   1.130.2.2   nathanw 	ipstat.ips_badsum++;
    825   1.130.2.2   nathanw 	m_freem(m);
    826         1.1       cgd }
    827         1.1       cgd 
    828         1.1       cgd /*
    829         1.1       cgd  * Take incoming datagram fragment and try to
    830         1.1       cgd  * reassemble it into whole datagram.  If a chain for
    831         1.1       cgd  * reassembly of this datagram already exists, then it
    832         1.1       cgd  * is given as fp; otherwise have to make a chain.
    833         1.1       cgd  */
    834        1.50   thorpej struct mbuf *
    835        1.25       cgd ip_reass(ipqe, fp)
    836       1.109  augustss 	struct ipqent *ipqe;
    837       1.109  augustss 	struct ipq *fp;
    838         1.1       cgd {
    839       1.109  augustss 	struct mbuf *m = ipqe->ipqe_m;
    840       1.109  augustss 	struct ipqent *nq, *p, *q;
    841        1.25       cgd 	struct ip *ip;
    842         1.1       cgd 	struct mbuf *t;
    843        1.25       cgd 	int hlen = ipqe->ipqe_ip->ip_hl << 2;
    844         1.1       cgd 	int i, next;
    845         1.1       cgd 
    846        1.75   thorpej 	IPQ_LOCK_CHECK();
    847        1.75   thorpej 
    848         1.1       cgd 	/*
    849         1.1       cgd 	 * Presence of header sizes in mbufs
    850         1.1       cgd 	 * would confuse code below.
    851         1.1       cgd 	 */
    852         1.1       cgd 	m->m_data += hlen;
    853         1.1       cgd 	m->m_len -= hlen;
    854         1.1       cgd 
    855         1.1       cgd 	/*
    856         1.1       cgd 	 * If first fragment to arrive, create a reassembly queue.
    857         1.1       cgd 	 */
    858         1.1       cgd 	if (fp == 0) {
    859   1.130.2.1   nathanw 		/*
    860   1.130.2.1   nathanw 		 * Enforce upper bound on number of fragmented packets
    861   1.130.2.1   nathanw 		 * for which we attempt reassembly;
    862   1.130.2.1   nathanw 		 * If maxfrag is 0, never accept fragments.
    863   1.130.2.1   nathanw 		 * If maxfrag is -1, accept all fragments without limitation.
    864   1.130.2.1   nathanw 		 */
    865   1.130.2.1   nathanw 		if (ip_maxfragpackets < 0)
    866   1.130.2.1   nathanw 			;
    867   1.130.2.1   nathanw 		else if (ip_nfragpackets >= ip_maxfragpackets)
    868   1.130.2.1   nathanw 			goto dropfrag;
    869   1.130.2.1   nathanw 		ip_nfragpackets++;
    870        1.50   thorpej 		MALLOC(fp, struct ipq *, sizeof (struct ipq),
    871        1.50   thorpej 		    M_FTABLE, M_NOWAIT);
    872        1.50   thorpej 		if (fp == NULL)
    873         1.1       cgd 			goto dropfrag;
    874        1.25       cgd 		LIST_INSERT_HEAD(&ipq, fp, ipq_q);
    875         1.1       cgd 		fp->ipq_ttl = IPFRAGTTL;
    876        1.25       cgd 		fp->ipq_p = ipqe->ipqe_ip->ip_p;
    877        1.25       cgd 		fp->ipq_id = ipqe->ipqe_ip->ip_id;
    878  1.130.2.10   nathanw 		TAILQ_INIT(&fp->ipq_fragq);
    879        1.25       cgd 		fp->ipq_src = ipqe->ipqe_ip->ip_src;
    880        1.25       cgd 		fp->ipq_dst = ipqe->ipqe_ip->ip_dst;
    881        1.25       cgd 		p = NULL;
    882         1.1       cgd 		goto insert;
    883         1.1       cgd 	}
    884         1.1       cgd 
    885         1.1       cgd 	/*
    886         1.1       cgd 	 * Find a segment which begins after this one does.
    887         1.1       cgd 	 */
    888  1.130.2.10   nathanw 	for (p = NULL, q = TAILQ_FIRST(&fp->ipq_fragq); q != NULL;
    889  1.130.2.10   nathanw 	    p = q, q = TAILQ_NEXT(q, ipqe_q))
    890  1.130.2.12   nathanw 		if (ntohs(q->ipqe_ip->ip_off) > ntohs(ipqe->ipqe_ip->ip_off))
    891         1.1       cgd 			break;
    892         1.1       cgd 
    893         1.1       cgd 	/*
    894         1.1       cgd 	 * If there is a preceding segment, it may provide some of
    895         1.1       cgd 	 * our data already.  If so, drop the data from the incoming
    896         1.1       cgd 	 * segment.  If it provides all of our data, drop us.
    897         1.1       cgd 	 */
    898        1.25       cgd 	if (p != NULL) {
    899  1.130.2.12   nathanw 		i = ntohs(p->ipqe_ip->ip_off) + ntohs(p->ipqe_ip->ip_len) -
    900  1.130.2.12   nathanw 		    ntohs(ipqe->ipqe_ip->ip_off);
    901         1.1       cgd 		if (i > 0) {
    902  1.130.2.12   nathanw 			if (i >= ntohs(ipqe->ipqe_ip->ip_len))
    903         1.1       cgd 				goto dropfrag;
    904        1.50   thorpej 			m_adj(ipqe->ipqe_m, i);
    905  1.130.2.12   nathanw 			ipqe->ipqe_ip->ip_off =
    906  1.130.2.12   nathanw 			    htons(ntohs(ipqe->ipqe_ip->ip_off) + i);
    907  1.130.2.12   nathanw 			ipqe->ipqe_ip->ip_len =
    908  1.130.2.12   nathanw 			    htons(ntohs(ipqe->ipqe_ip->ip_len) - i);
    909         1.1       cgd 		}
    910         1.1       cgd 	}
    911         1.1       cgd 
    912         1.1       cgd 	/*
    913         1.1       cgd 	 * While we overlap succeeding segments trim them or,
    914         1.1       cgd 	 * if they are completely covered, dequeue them.
    915         1.1       cgd 	 */
    916  1.130.2.12   nathanw 	for (; q != NULL &&
    917  1.130.2.12   nathanw 	    ntohs(ipqe->ipqe_ip->ip_off) + ntohs(ipqe->ipqe_ip->ip_len) >
    918  1.130.2.12   nathanw 	    ntohs(q->ipqe_ip->ip_off); q = nq) {
    919  1.130.2.12   nathanw 		i = (ntohs(ipqe->ipqe_ip->ip_off) +
    920  1.130.2.12   nathanw 		    ntohs(ipqe->ipqe_ip->ip_len)) - ntohs(q->ipqe_ip->ip_off);
    921  1.130.2.12   nathanw 		if (i < ntohs(q->ipqe_ip->ip_len)) {
    922  1.130.2.12   nathanw 			q->ipqe_ip->ip_len =
    923  1.130.2.12   nathanw 			    htons(ntohs(q->ipqe_ip->ip_len) - i);
    924  1.130.2.12   nathanw 			q->ipqe_ip->ip_off =
    925  1.130.2.12   nathanw 			    htons(ntohs(q->ipqe_ip->ip_off) + i);
    926        1.50   thorpej 			m_adj(q->ipqe_m, i);
    927         1.1       cgd 			break;
    928         1.1       cgd 		}
    929  1.130.2.10   nathanw 		nq = TAILQ_NEXT(q, ipqe_q);
    930        1.50   thorpej 		m_freem(q->ipqe_m);
    931  1.130.2.10   nathanw 		TAILQ_REMOVE(&fp->ipq_fragq, q, ipqe_q);
    932        1.72   thorpej 		pool_put(&ipqent_pool, q);
    933         1.1       cgd 	}
    934         1.1       cgd 
    935         1.1       cgd insert:
    936         1.1       cgd 	/*
    937         1.1       cgd 	 * Stick new segment in its place;
    938         1.1       cgd 	 * check for complete reassembly.
    939         1.1       cgd 	 */
    940        1.25       cgd 	if (p == NULL) {
    941  1.130.2.10   nathanw 		TAILQ_INSERT_HEAD(&fp->ipq_fragq, ipqe, ipqe_q);
    942        1.25       cgd 	} else {
    943  1.130.2.10   nathanw 		TAILQ_INSERT_AFTER(&fp->ipq_fragq, p, ipqe, ipqe_q);
    944        1.25       cgd 	}
    945         1.1       cgd 	next = 0;
    946  1.130.2.10   nathanw 	for (p = NULL, q = TAILQ_FIRST(&fp->ipq_fragq); q != NULL;
    947  1.130.2.10   nathanw 	    p = q, q = TAILQ_NEXT(q, ipqe_q)) {
    948  1.130.2.12   nathanw 		if (ntohs(q->ipqe_ip->ip_off) != next)
    949         1.1       cgd 			return (0);
    950  1.130.2.12   nathanw 		next += ntohs(q->ipqe_ip->ip_len);
    951         1.1       cgd 	}
    952        1.25       cgd 	if (p->ipqe_mff)
    953         1.1       cgd 		return (0);
    954         1.1       cgd 
    955         1.1       cgd 	/*
    956        1.41   thorpej 	 * Reassembly is complete.  Check for a bogus message size and
    957        1.41   thorpej 	 * concatenate fragments.
    958         1.1       cgd 	 */
    959  1.130.2.10   nathanw 	q = TAILQ_FIRST(&fp->ipq_fragq);
    960        1.25       cgd 	ip = q->ipqe_ip;
    961        1.41   thorpej 	if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) {
    962        1.41   thorpej 		ipstat.ips_toolong++;
    963        1.41   thorpej 		ip_freef(fp);
    964        1.41   thorpej 		return (0);
    965        1.41   thorpej 	}
    966        1.50   thorpej 	m = q->ipqe_m;
    967         1.1       cgd 	t = m->m_next;
    968         1.1       cgd 	m->m_next = 0;
    969         1.1       cgd 	m_cat(m, t);
    970  1.130.2.10   nathanw 	nq = TAILQ_NEXT(q, ipqe_q);
    971        1.72   thorpej 	pool_put(&ipqent_pool, q);
    972        1.25       cgd 	for (q = nq; q != NULL; q = nq) {
    973        1.50   thorpej 		t = q->ipqe_m;
    974  1.130.2.10   nathanw 		nq = TAILQ_NEXT(q, ipqe_q);
    975        1.72   thorpej 		pool_put(&ipqent_pool, q);
    976         1.1       cgd 		m_cat(m, t);
    977         1.1       cgd 	}
    978         1.1       cgd 
    979         1.1       cgd 	/*
    980         1.1       cgd 	 * Create header for new ip packet by
    981         1.1       cgd 	 * modifying header of first packet;
    982         1.1       cgd 	 * dequeue and discard fragment reassembly header.
    983         1.1       cgd 	 * Make header visible.
    984         1.1       cgd 	 */
    985  1.130.2.12   nathanw 	ip->ip_len = htons(next);
    986        1.25       cgd 	ip->ip_src = fp->ipq_src;
    987        1.25       cgd 	ip->ip_dst = fp->ipq_dst;
    988        1.25       cgd 	LIST_REMOVE(fp, ipq_q);
    989        1.50   thorpej 	FREE(fp, M_FTABLE);
    990   1.130.2.1   nathanw 	ip_nfragpackets--;
    991         1.1       cgd 	m->m_len += (ip->ip_hl << 2);
    992         1.1       cgd 	m->m_data -= (ip->ip_hl << 2);
    993         1.1       cgd 	/* some debugging cruft by sklower, below, will go away soon */
    994         1.1       cgd 	if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
    995       1.109  augustss 		int plen = 0;
    996        1.50   thorpej 		for (t = m; t; t = t->m_next)
    997        1.50   thorpej 			plen += t->m_len;
    998        1.50   thorpej 		m->m_pkthdr.len = plen;
    999         1.1       cgd 	}
   1000        1.50   thorpej 	return (m);
   1001         1.1       cgd 
   1002         1.1       cgd dropfrag:
   1003         1.1       cgd 	ipstat.ips_fragdropped++;
   1004         1.1       cgd 	m_freem(m);
   1005        1.72   thorpej 	pool_put(&ipqent_pool, ipqe);
   1006         1.1       cgd 	return (0);
   1007         1.1       cgd }
   1008         1.1       cgd 
   1009         1.1       cgd /*
   1010         1.1       cgd  * Free a fragment reassembly header and all
   1011         1.1       cgd  * associated datagrams.
   1012         1.1       cgd  */
   1013         1.8   mycroft void
   1014         1.1       cgd ip_freef(fp)
   1015         1.1       cgd 	struct ipq *fp;
   1016         1.1       cgd {
   1017       1.109  augustss 	struct ipqent *q, *p;
   1018         1.1       cgd 
   1019        1.75   thorpej 	IPQ_LOCK_CHECK();
   1020        1.75   thorpej 
   1021  1.130.2.10   nathanw 	for (q = TAILQ_FIRST(&fp->ipq_fragq); q != NULL; q = p) {
   1022  1.130.2.10   nathanw 		p = TAILQ_NEXT(q, ipqe_q);
   1023        1.50   thorpej 		m_freem(q->ipqe_m);
   1024  1.130.2.10   nathanw 		TAILQ_REMOVE(&fp->ipq_fragq, q, ipqe_q);
   1025        1.72   thorpej 		pool_put(&ipqent_pool, q);
   1026         1.1       cgd 	}
   1027        1.25       cgd 	LIST_REMOVE(fp, ipq_q);
   1028        1.50   thorpej 	FREE(fp, M_FTABLE);
   1029   1.130.2.1   nathanw 	ip_nfragpackets--;
   1030         1.1       cgd }
   1031         1.1       cgd 
   1032         1.1       cgd /*
   1033         1.1       cgd  * IP timer processing;
   1034         1.1       cgd  * if a timer expires on a reassembly
   1035         1.1       cgd  * queue, discard it.
   1036         1.1       cgd  */
   1037         1.8   mycroft void
   1038         1.1       cgd ip_slowtimo()
   1039         1.1       cgd {
   1040       1.109  augustss 	struct ipq *fp, *nfp;
   1041        1.24   mycroft 	int s = splsoftnet();
   1042         1.1       cgd 
   1043        1.75   thorpej 	IPQ_LOCK();
   1044   1.130.2.5   nathanw 	for (fp = LIST_FIRST(&ipq); fp != NULL; fp = nfp) {
   1045   1.130.2.5   nathanw 		nfp = LIST_NEXT(fp, ipq_q);
   1046        1.25       cgd 		if (--fp->ipq_ttl == 0) {
   1047         1.1       cgd 			ipstat.ips_fragtimeout++;
   1048        1.25       cgd 			ip_freef(fp);
   1049         1.1       cgd 		}
   1050         1.1       cgd 	}
   1051   1.130.2.1   nathanw 	/*
   1052   1.130.2.1   nathanw 	 * If we are over the maximum number of fragments
   1053   1.130.2.1   nathanw 	 * (due to the limit being lowered), drain off
   1054   1.130.2.1   nathanw 	 * enough to get down to the new limit.
   1055   1.130.2.1   nathanw 	 */
   1056   1.130.2.1   nathanw 	if (ip_maxfragpackets < 0)
   1057   1.130.2.1   nathanw 		;
   1058   1.130.2.1   nathanw 	else {
   1059   1.130.2.5   nathanw 		while (ip_nfragpackets > ip_maxfragpackets && LIST_FIRST(&ipq))
   1060   1.130.2.5   nathanw 			ip_freef(LIST_FIRST(&ipq));
   1061   1.130.2.1   nathanw 	}
   1062        1.75   thorpej 	IPQ_UNLOCK();
   1063        1.63      matt #ifdef GATEWAY
   1064        1.63      matt 	ipflow_slowtimo();
   1065        1.63      matt #endif
   1066         1.1       cgd 	splx(s);
   1067         1.1       cgd }
   1068         1.1       cgd 
   1069         1.1       cgd /*
   1070         1.1       cgd  * Drain off all datagram fragments.
   1071         1.1       cgd  */
   1072         1.8   mycroft void
   1073         1.1       cgd ip_drain()
   1074         1.1       cgd {
   1075         1.1       cgd 
   1076        1.75   thorpej 	/*
   1077        1.75   thorpej 	 * We may be called from a device's interrupt context.  If
   1078        1.75   thorpej 	 * the ipq is already busy, just bail out now.
   1079        1.75   thorpej 	 */
   1080        1.75   thorpej 	if (ipq_lock_try() == 0)
   1081        1.75   thorpej 		return;
   1082        1.75   thorpej 
   1083   1.130.2.5   nathanw 	while (LIST_FIRST(&ipq) != NULL) {
   1084         1.1       cgd 		ipstat.ips_fragdropped++;
   1085   1.130.2.5   nathanw 		ip_freef(LIST_FIRST(&ipq));
   1086         1.1       cgd 	}
   1087        1.75   thorpej 
   1088        1.75   thorpej 	IPQ_UNLOCK();
   1089         1.1       cgd }
   1090         1.1       cgd 
   1091         1.1       cgd /*
   1092         1.1       cgd  * Do option processing on a datagram,
   1093         1.1       cgd  * possibly discarding it if bad options are encountered,
   1094         1.1       cgd  * or forwarding it if source-routed.
   1095         1.1       cgd  * Returns 1 if packet has been forwarded/freed,
   1096         1.1       cgd  * 0 if the packet should be processed further.
   1097         1.1       cgd  */
   1098         1.8   mycroft int
   1099         1.1       cgd ip_dooptions(m)
   1100         1.1       cgd 	struct mbuf *m;
   1101         1.1       cgd {
   1102       1.109  augustss 	struct ip *ip = mtod(m, struct ip *);
   1103       1.109  augustss 	u_char *cp, *cp0;
   1104       1.109  augustss 	struct ip_timestamp *ipt;
   1105       1.109  augustss 	struct in_ifaddr *ia;
   1106         1.1       cgd 	int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;
   1107       1.104   thorpej 	struct in_addr dst;
   1108         1.1       cgd 	n_time ntime;
   1109         1.1       cgd 
   1110        1.13   mycroft 	dst = ip->ip_dst;
   1111         1.1       cgd 	cp = (u_char *)(ip + 1);
   1112         1.1       cgd 	cnt = (ip->ip_hl << 2) - sizeof (struct ip);
   1113         1.1       cgd 	for (; cnt > 0; cnt -= optlen, cp += optlen) {
   1114         1.1       cgd 		opt = cp[IPOPT_OPTVAL];
   1115         1.1       cgd 		if (opt == IPOPT_EOL)
   1116         1.1       cgd 			break;
   1117         1.1       cgd 		if (opt == IPOPT_NOP)
   1118         1.1       cgd 			optlen = 1;
   1119         1.1       cgd 		else {
   1120       1.113    itojun 			if (cnt < IPOPT_OLEN + sizeof(*cp)) {
   1121       1.113    itojun 				code = &cp[IPOPT_OLEN] - (u_char *)ip;
   1122       1.113    itojun 				goto bad;
   1123       1.113    itojun 			}
   1124         1.1       cgd 			optlen = cp[IPOPT_OLEN];
   1125       1.114    itojun 			if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt) {
   1126         1.1       cgd 				code = &cp[IPOPT_OLEN] - (u_char *)ip;
   1127         1.1       cgd 				goto bad;
   1128         1.1       cgd 			}
   1129         1.1       cgd 		}
   1130         1.1       cgd 		switch (opt) {
   1131         1.1       cgd 
   1132         1.1       cgd 		default:
   1133         1.1       cgd 			break;
   1134         1.1       cgd 
   1135         1.1       cgd 		/*
   1136         1.1       cgd 		 * Source routing with record.
   1137         1.1       cgd 		 * Find interface with current destination address.
   1138         1.1       cgd 		 * If none on this machine then drop if strictly routed,
   1139         1.1       cgd 		 * or do nothing if loosely routed.
   1140         1.1       cgd 		 * Record interface address and bring up next address
   1141         1.1       cgd 		 * component.  If strictly routed make sure next
   1142         1.1       cgd 		 * address is on directly accessible net.
   1143         1.1       cgd 		 */
   1144         1.1       cgd 		case IPOPT_LSRR:
   1145         1.1       cgd 		case IPOPT_SSRR:
   1146        1.47       cjs 			if (ip_allowsrcrt == 0) {
   1147        1.47       cjs 				type = ICMP_UNREACH;
   1148        1.47       cjs 				code = ICMP_UNREACH_NET_PROHIB;
   1149        1.47       cjs 				goto bad;
   1150        1.47       cjs 			}
   1151       1.114    itojun 			if (optlen < IPOPT_OFFSET + sizeof(*cp)) {
   1152       1.114    itojun 				code = &cp[IPOPT_OLEN] - (u_char *)ip;
   1153       1.114    itojun 				goto bad;
   1154       1.114    itojun 			}
   1155         1.1       cgd 			if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
   1156         1.1       cgd 				code = &cp[IPOPT_OFFSET] - (u_char *)ip;
   1157         1.1       cgd 				goto bad;
   1158         1.1       cgd 			}
   1159         1.1       cgd 			ipaddr.sin_addr = ip->ip_dst;
   1160        1.19   mycroft 			ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr)));
   1161         1.1       cgd 			if (ia == 0) {
   1162         1.1       cgd 				if (opt == IPOPT_SSRR) {
   1163         1.1       cgd 					type = ICMP_UNREACH;
   1164         1.1       cgd 					code = ICMP_UNREACH_SRCFAIL;
   1165         1.1       cgd 					goto bad;
   1166         1.1       cgd 				}
   1167         1.1       cgd 				/*
   1168         1.1       cgd 				 * Loose routing, and not at next destination
   1169         1.1       cgd 				 * yet; nothing to do except forward.
   1170         1.1       cgd 				 */
   1171         1.1       cgd 				break;
   1172         1.1       cgd 			}
   1173         1.1       cgd 			off--;			/* 0 origin */
   1174       1.112  sommerfe 			if ((off + sizeof(struct in_addr)) > optlen) {
   1175         1.1       cgd 				/*
   1176         1.1       cgd 				 * End of source route.  Should be for us.
   1177         1.1       cgd 				 */
   1178         1.1       cgd 				save_rte(cp, ip->ip_src);
   1179         1.1       cgd 				break;
   1180         1.1       cgd 			}
   1181         1.1       cgd 			/*
   1182         1.1       cgd 			 * locate outgoing interface
   1183         1.1       cgd 			 */
   1184         1.1       cgd 			bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,
   1185         1.1       cgd 			    sizeof(ipaddr.sin_addr));
   1186        1.96   thorpej 			if (opt == IPOPT_SSRR)
   1187        1.96   thorpej 				ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr)));
   1188        1.96   thorpej 			else
   1189         1.1       cgd 				ia = ip_rtaddr(ipaddr.sin_addr);
   1190         1.1       cgd 			if (ia == 0) {
   1191         1.1       cgd 				type = ICMP_UNREACH;
   1192         1.1       cgd 				code = ICMP_UNREACH_SRCFAIL;
   1193         1.1       cgd 				goto bad;
   1194         1.1       cgd 			}
   1195         1.1       cgd 			ip->ip_dst = ipaddr.sin_addr;
   1196        1.20   mycroft 			bcopy((caddr_t)&ia->ia_addr.sin_addr,
   1197         1.1       cgd 			    (caddr_t)(cp + off), sizeof(struct in_addr));
   1198         1.1       cgd 			cp[IPOPT_OFFSET] += sizeof(struct in_addr);
   1199        1.13   mycroft 			/*
   1200        1.13   mycroft 			 * Let ip_intr's mcast routing check handle mcast pkts
   1201        1.13   mycroft 			 */
   1202        1.18   mycroft 			forward = !IN_MULTICAST(ip->ip_dst.s_addr);
   1203         1.1       cgd 			break;
   1204         1.1       cgd 
   1205         1.1       cgd 		case IPOPT_RR:
   1206       1.114    itojun 			if (optlen < IPOPT_OFFSET + sizeof(*cp)) {
   1207       1.114    itojun 				code = &cp[IPOPT_OLEN] - (u_char *)ip;
   1208       1.114    itojun 				goto bad;
   1209       1.114    itojun 			}
   1210         1.1       cgd 			if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
   1211         1.1       cgd 				code = &cp[IPOPT_OFFSET] - (u_char *)ip;
   1212         1.1       cgd 				goto bad;
   1213         1.1       cgd 			}
   1214         1.1       cgd 			/*
   1215         1.1       cgd 			 * If no space remains, ignore.
   1216         1.1       cgd 			 */
   1217         1.1       cgd 			off--;			/* 0 origin */
   1218       1.112  sommerfe 			if ((off + sizeof(struct in_addr)) > optlen)
   1219         1.1       cgd 				break;
   1220         1.1       cgd 			bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
   1221         1.1       cgd 			    sizeof(ipaddr.sin_addr));
   1222         1.1       cgd 			/*
   1223         1.1       cgd 			 * locate outgoing interface; if we're the destination,
   1224         1.1       cgd 			 * use the incoming interface (should be same).
   1225         1.1       cgd 			 */
   1226        1.96   thorpej 			if ((ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr))))
   1227        1.96   thorpej 			    == NULL &&
   1228        1.96   thorpej 			    (ia = ip_rtaddr(ipaddr.sin_addr)) == NULL) {
   1229         1.1       cgd 				type = ICMP_UNREACH;
   1230         1.1       cgd 				code = ICMP_UNREACH_HOST;
   1231         1.1       cgd 				goto bad;
   1232         1.1       cgd 			}
   1233        1.20   mycroft 			bcopy((caddr_t)&ia->ia_addr.sin_addr,
   1234         1.1       cgd 			    (caddr_t)(cp + off), sizeof(struct in_addr));
   1235         1.1       cgd 			cp[IPOPT_OFFSET] += sizeof(struct in_addr);
   1236         1.1       cgd 			break;
   1237         1.1       cgd 
   1238         1.1       cgd 		case IPOPT_TS:
   1239         1.1       cgd 			code = cp - (u_char *)ip;
   1240         1.1       cgd 			ipt = (struct ip_timestamp *)cp;
   1241       1.114    itojun 			if (ipt->ipt_len < 4 || ipt->ipt_len > 40) {
   1242       1.114    itojun 				code = (u_char *)&ipt->ipt_len - (u_char *)ip;
   1243         1.1       cgd 				goto bad;
   1244       1.114    itojun 			}
   1245       1.114    itojun 			if (ipt->ipt_ptr < 5) {
   1246       1.114    itojun 				code = (u_char *)&ipt->ipt_ptr - (u_char *)ip;
   1247       1.114    itojun 				goto bad;
   1248       1.114    itojun 			}
   1249        1.15       cgd 			if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) {
   1250       1.114    itojun 				if (++ipt->ipt_oflw == 0) {
   1251       1.114    itojun 					code = (u_char *)&ipt->ipt_ptr -
   1252       1.114    itojun 					    (u_char *)ip;
   1253         1.1       cgd 					goto bad;
   1254       1.114    itojun 				}
   1255         1.1       cgd 				break;
   1256         1.1       cgd 			}
   1257       1.104   thorpej 			cp0 = (cp + ipt->ipt_ptr - 1);
   1258         1.1       cgd 			switch (ipt->ipt_flg) {
   1259         1.1       cgd 
   1260         1.1       cgd 			case IPOPT_TS_TSONLY:
   1261         1.1       cgd 				break;
   1262         1.1       cgd 
   1263         1.1       cgd 			case IPOPT_TS_TSANDADDR:
   1264        1.66   thorpej 				if (ipt->ipt_ptr - 1 + sizeof(n_time) +
   1265       1.114    itojun 				    sizeof(struct in_addr) > ipt->ipt_len) {
   1266       1.114    itojun 					code = (u_char *)&ipt->ipt_ptr -
   1267       1.114    itojun 					    (u_char *)ip;
   1268         1.1       cgd 					goto bad;
   1269       1.114    itojun 				}
   1270        1.13   mycroft 				ipaddr.sin_addr = dst;
   1271        1.96   thorpej 				ia = ifatoia(ifaof_ifpforaddr(sintosa(&ipaddr),
   1272        1.96   thorpej 				    m->m_pkthdr.rcvif));
   1273        1.13   mycroft 				if (ia == 0)
   1274        1.13   mycroft 					continue;
   1275       1.104   thorpej 				bcopy(&ia->ia_addr.sin_addr,
   1276       1.104   thorpej 				    cp0, sizeof(struct in_addr));
   1277         1.1       cgd 				ipt->ipt_ptr += sizeof(struct in_addr);
   1278         1.1       cgd 				break;
   1279         1.1       cgd 
   1280         1.1       cgd 			case IPOPT_TS_PRESPEC:
   1281        1.66   thorpej 				if (ipt->ipt_ptr - 1 + sizeof(n_time) +
   1282       1.114    itojun 				    sizeof(struct in_addr) > ipt->ipt_len) {
   1283       1.114    itojun 					code = (u_char *)&ipt->ipt_ptr -
   1284       1.114    itojun 					    (u_char *)ip;
   1285         1.1       cgd 					goto bad;
   1286       1.114    itojun 				}
   1287       1.104   thorpej 				bcopy(cp0, &ipaddr.sin_addr,
   1288         1.1       cgd 				    sizeof(struct in_addr));
   1289        1.96   thorpej 				if (ifatoia(ifa_ifwithaddr(sintosa(&ipaddr)))
   1290        1.96   thorpej 				    == NULL)
   1291         1.1       cgd 					continue;
   1292         1.1       cgd 				ipt->ipt_ptr += sizeof(struct in_addr);
   1293         1.1       cgd 				break;
   1294         1.1       cgd 
   1295         1.1       cgd 			default:
   1296       1.114    itojun 				/* XXX can't take &ipt->ipt_flg */
   1297       1.114    itojun 				code = (u_char *)&ipt->ipt_ptr -
   1298       1.114    itojun 				    (u_char *)ip + 1;
   1299         1.1       cgd 				goto bad;
   1300         1.1       cgd 			}
   1301         1.1       cgd 			ntime = iptime();
   1302       1.107   thorpej 			cp0 = (u_char *) &ntime; /* XXX grumble, GCC... */
   1303       1.107   thorpej 			bcopy(cp0, (caddr_t)cp + ipt->ipt_ptr - 1,
   1304         1.1       cgd 			    sizeof(n_time));
   1305         1.1       cgd 			ipt->ipt_ptr += sizeof(n_time);
   1306         1.1       cgd 		}
   1307         1.1       cgd 	}
   1308         1.1       cgd 	if (forward) {
   1309        1.26   thorpej 		if (ip_forwsrcrt == 0) {
   1310        1.26   thorpej 			type = ICMP_UNREACH;
   1311        1.26   thorpej 			code = ICMP_UNREACH_SRCFAIL;
   1312        1.26   thorpej 			goto bad;
   1313        1.26   thorpej 		}
   1314         1.1       cgd 		ip_forward(m, 1);
   1315         1.1       cgd 		return (1);
   1316        1.13   mycroft 	}
   1317        1.13   mycroft 	return (0);
   1318         1.1       cgd bad:
   1319        1.13   mycroft 	icmp_error(m, type, code, 0, 0);
   1320        1.13   mycroft 	ipstat.ips_badoptions++;
   1321         1.1       cgd 	return (1);
   1322         1.1       cgd }
   1323         1.1       cgd 
   1324         1.1       cgd /*
   1325         1.1       cgd  * Given address of next destination (final or next hop),
   1326         1.1       cgd  * return internet address info of interface to be used to get there.
   1327         1.1       cgd  */
   1328         1.1       cgd struct in_ifaddr *
   1329         1.1       cgd ip_rtaddr(dst)
   1330         1.1       cgd 	 struct in_addr dst;
   1331         1.1       cgd {
   1332       1.109  augustss 	struct sockaddr_in *sin;
   1333         1.1       cgd 
   1334        1.19   mycroft 	sin = satosin(&ipforward_rt.ro_dst);
   1335         1.1       cgd 
   1336        1.35   mycroft 	if (ipforward_rt.ro_rt == 0 || !in_hosteq(dst, sin->sin_addr)) {
   1337         1.1       cgd 		if (ipforward_rt.ro_rt) {
   1338         1.1       cgd 			RTFREE(ipforward_rt.ro_rt);
   1339         1.1       cgd 			ipforward_rt.ro_rt = 0;
   1340         1.1       cgd 		}
   1341         1.1       cgd 		sin->sin_family = AF_INET;
   1342         1.1       cgd 		sin->sin_len = sizeof(*sin);
   1343         1.1       cgd 		sin->sin_addr = dst;
   1344         1.1       cgd 
   1345         1.1       cgd 		rtalloc(&ipforward_rt);
   1346         1.1       cgd 	}
   1347         1.1       cgd 	if (ipforward_rt.ro_rt == 0)
   1348         1.1       cgd 		return ((struct in_ifaddr *)0);
   1349        1.19   mycroft 	return (ifatoia(ipforward_rt.ro_rt->rt_ifa));
   1350         1.1       cgd }
   1351         1.1       cgd 
   1352         1.1       cgd /*
   1353         1.1       cgd  * Save incoming source route for use in replies,
   1354         1.1       cgd  * to be picked up later by ip_srcroute if the receiver is interested.
   1355         1.1       cgd  */
   1356        1.13   mycroft void
   1357         1.1       cgd save_rte(option, dst)
   1358         1.1       cgd 	u_char *option;
   1359         1.1       cgd 	struct in_addr dst;
   1360         1.1       cgd {
   1361         1.1       cgd 	unsigned olen;
   1362         1.1       cgd 
   1363         1.1       cgd 	olen = option[IPOPT_OLEN];
   1364         1.1       cgd #ifdef DIAGNOSTIC
   1365         1.1       cgd 	if (ipprintfs)
   1366        1.39  christos 		printf("save_rte: olen %d\n", olen);
   1367        1.89    itojun #endif /* 0 */
   1368         1.1       cgd 	if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
   1369         1.1       cgd 		return;
   1370         1.1       cgd 	bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen);
   1371         1.1       cgd 	ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
   1372         1.1       cgd 	ip_srcrt.dst = dst;
   1373         1.1       cgd }
   1374         1.1       cgd 
   1375         1.1       cgd /*
   1376         1.1       cgd  * Retrieve incoming source route for use in replies,
   1377         1.1       cgd  * in the same form used by setsockopt.
   1378         1.1       cgd  * The first hop is placed before the options, will be removed later.
   1379         1.1       cgd  */
   1380         1.1       cgd struct mbuf *
   1381         1.1       cgd ip_srcroute()
   1382         1.1       cgd {
   1383       1.109  augustss 	struct in_addr *p, *q;
   1384       1.109  augustss 	struct mbuf *m;
   1385         1.1       cgd 
   1386         1.1       cgd 	if (ip_nhops == 0)
   1387         1.1       cgd 		return ((struct mbuf *)0);
   1388         1.1       cgd 	m = m_get(M_DONTWAIT, MT_SOOPTS);
   1389         1.1       cgd 	if (m == 0)
   1390         1.1       cgd 		return ((struct mbuf *)0);
   1391         1.1       cgd 
   1392        1.13   mycroft #define OPTSIZ	(sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt))
   1393         1.1       cgd 
   1394         1.1       cgd 	/* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */
   1395         1.1       cgd 	m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) +
   1396         1.1       cgd 	    OPTSIZ;
   1397         1.1       cgd #ifdef DIAGNOSTIC
   1398         1.1       cgd 	if (ipprintfs)
   1399        1.39  christos 		printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len);
   1400         1.1       cgd #endif
   1401         1.1       cgd 
   1402         1.1       cgd 	/*
   1403         1.1       cgd 	 * First save first hop for return route
   1404         1.1       cgd 	 */
   1405         1.1       cgd 	p = &ip_srcrt.route[ip_nhops - 1];
   1406         1.1       cgd 	*(mtod(m, struct in_addr *)) = *p--;
   1407         1.1       cgd #ifdef DIAGNOSTIC
   1408         1.1       cgd 	if (ipprintfs)
   1409        1.39  christos 		printf(" hops %x", ntohl(mtod(m, struct in_addr *)->s_addr));
   1410         1.1       cgd #endif
   1411         1.1       cgd 
   1412         1.1       cgd 	/*
   1413         1.1       cgd 	 * Copy option fields and padding (nop) to mbuf.
   1414         1.1       cgd 	 */
   1415         1.1       cgd 	ip_srcrt.nop = IPOPT_NOP;
   1416         1.1       cgd 	ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
   1417         1.1       cgd 	bcopy((caddr_t)&ip_srcrt.nop,
   1418         1.1       cgd 	    mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ);
   1419         1.1       cgd 	q = (struct in_addr *)(mtod(m, caddr_t) +
   1420         1.1       cgd 	    sizeof(struct in_addr) + OPTSIZ);
   1421         1.1       cgd #undef OPTSIZ
   1422         1.1       cgd 	/*
   1423         1.1       cgd 	 * Record return path as an IP source route,
   1424         1.1       cgd 	 * reversing the path (pointers are now aligned).
   1425         1.1       cgd 	 */
   1426         1.1       cgd 	while (p >= ip_srcrt.route) {
   1427         1.1       cgd #ifdef DIAGNOSTIC
   1428         1.1       cgd 		if (ipprintfs)
   1429        1.39  christos 			printf(" %x", ntohl(q->s_addr));
   1430         1.1       cgd #endif
   1431         1.1       cgd 		*q++ = *p--;
   1432         1.1       cgd 	}
   1433         1.1       cgd 	/*
   1434         1.1       cgd 	 * Last hop goes to final destination.
   1435         1.1       cgd 	 */
   1436         1.1       cgd 	*q = ip_srcrt.dst;
   1437         1.1       cgd #ifdef DIAGNOSTIC
   1438         1.1       cgd 	if (ipprintfs)
   1439        1.39  christos 		printf(" %x\n", ntohl(q->s_addr));
   1440         1.1       cgd #endif
   1441         1.1       cgd 	return (m);
   1442         1.1       cgd }
   1443         1.1       cgd 
   1444         1.1       cgd /*
   1445         1.1       cgd  * Strip out IP options, at higher
   1446         1.1       cgd  * level protocol in the kernel.
   1447         1.1       cgd  * Second argument is buffer to which options
   1448         1.1       cgd  * will be moved, and return value is their length.
   1449         1.1       cgd  * XXX should be deleted; last arg currently ignored.
   1450         1.1       cgd  */
   1451         1.8   mycroft void
   1452         1.1       cgd ip_stripoptions(m, mopt)
   1453       1.109  augustss 	struct mbuf *m;
   1454         1.1       cgd 	struct mbuf *mopt;
   1455         1.1       cgd {
   1456       1.109  augustss 	int i;
   1457         1.1       cgd 	struct ip *ip = mtod(m, struct ip *);
   1458       1.109  augustss 	caddr_t opts;
   1459         1.1       cgd 	int olen;
   1460         1.1       cgd 
   1461        1.79   mycroft 	olen = (ip->ip_hl << 2) - sizeof (struct ip);
   1462         1.1       cgd 	opts = (caddr_t)(ip + 1);
   1463         1.1       cgd 	i = m->m_len - (sizeof (struct ip) + olen);
   1464         1.1       cgd 	bcopy(opts  + olen, opts, (unsigned)i);
   1465         1.1       cgd 	m->m_len -= olen;
   1466         1.1       cgd 	if (m->m_flags & M_PKTHDR)
   1467         1.1       cgd 		m->m_pkthdr.len -= olen;
   1468  1.130.2.12   nathanw 	ip->ip_len = htons(ntohs(ip->ip_len) - olen);
   1469        1.79   mycroft 	ip->ip_hl = sizeof (struct ip) >> 2;
   1470         1.1       cgd }
   1471         1.1       cgd 
   1472   1.130.2.5   nathanw const int inetctlerrmap[PRC_NCMDS] = {
   1473         1.1       cgd 	0,		0,		0,		0,
   1474         1.1       cgd 	0,		EMSGSIZE,	EHOSTDOWN,	EHOSTUNREACH,
   1475         1.1       cgd 	EHOSTUNREACH,	EHOSTUNREACH,	ECONNREFUSED,	ECONNREFUSED,
   1476         1.1       cgd 	EMSGSIZE,	EHOSTUNREACH,	0,		0,
   1477         1.1       cgd 	0,		0,		0,		0,
   1478         1.1       cgd 	ENOPROTOOPT
   1479         1.1       cgd };
   1480         1.1       cgd 
   1481         1.1       cgd /*
   1482         1.1       cgd  * Forward a packet.  If some error occurs return the sender
   1483         1.1       cgd  * an icmp packet.  Note we can't always generate a meaningful
   1484         1.1       cgd  * icmp message because icmp doesn't have a large enough repertoire
   1485         1.1       cgd  * of codes and types.
   1486         1.1       cgd  *
   1487         1.1       cgd  * If not forwarding, just drop the packet.  This could be confusing
   1488         1.1       cgd  * if ipforwarding was zero but some routing protocol was advancing
   1489         1.1       cgd  * us as a gateway to somewhere.  However, we must let the routing
   1490         1.1       cgd  * protocol deal with that.
   1491         1.1       cgd  *
   1492         1.1       cgd  * The srcrt parameter indicates whether the packet is being forwarded
   1493         1.1       cgd  * via a source route.
   1494         1.1       cgd  */
   1495        1.13   mycroft void
   1496         1.1       cgd ip_forward(m, srcrt)
   1497         1.1       cgd 	struct mbuf *m;
   1498         1.1       cgd 	int srcrt;
   1499         1.1       cgd {
   1500       1.109  augustss 	struct ip *ip = mtod(m, struct ip *);
   1501       1.109  augustss 	struct sockaddr_in *sin;
   1502       1.109  augustss 	struct rtentry *rt;
   1503        1.28  christos 	int error, type = 0, code = 0;
   1504         1.1       cgd 	struct mbuf *mcopy;
   1505        1.13   mycroft 	n_long dest;
   1506        1.13   mycroft 	struct ifnet *destifp;
   1507        1.89    itojun #ifdef IPSEC
   1508        1.89    itojun 	struct ifnet dummyifp;
   1509        1.89    itojun #endif
   1510         1.1       cgd 
   1511   1.130.2.2   nathanw 	/*
   1512   1.130.2.2   nathanw 	 * Clear any in-bound checksum flags for this packet.
   1513   1.130.2.2   nathanw 	 */
   1514   1.130.2.2   nathanw 	m->m_pkthdr.csum_flags = 0;
   1515   1.130.2.2   nathanw 
   1516        1.13   mycroft 	dest = 0;
   1517         1.1       cgd #ifdef DIAGNOSTIC
   1518         1.1       cgd 	if (ipprintfs)
   1519        1.70   thorpej 		printf("forward: src %2.2x dst %2.2x ttl %x\n",
   1520        1.70   thorpej 		    ntohl(ip->ip_src.s_addr),
   1521        1.70   thorpej 		    ntohl(ip->ip_dst.s_addr), ip->ip_ttl);
   1522         1.1       cgd #endif
   1523        1.93  sommerfe 	if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) {
   1524         1.1       cgd 		ipstat.ips_cantforward++;
   1525         1.1       cgd 		m_freem(m);
   1526         1.1       cgd 		return;
   1527         1.1       cgd 	}
   1528         1.1       cgd 	if (ip->ip_ttl <= IPTTLDEC) {
   1529        1.13   mycroft 		icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0);
   1530         1.1       cgd 		return;
   1531         1.1       cgd 	}
   1532         1.1       cgd 	ip->ip_ttl -= IPTTLDEC;
   1533         1.1       cgd 
   1534        1.19   mycroft 	sin = satosin(&ipforward_rt.ro_dst);
   1535         1.1       cgd 	if ((rt = ipforward_rt.ro_rt) == 0 ||
   1536        1.35   mycroft 	    !in_hosteq(ip->ip_dst, sin->sin_addr)) {
   1537         1.1       cgd 		if (ipforward_rt.ro_rt) {
   1538         1.1       cgd 			RTFREE(ipforward_rt.ro_rt);
   1539         1.1       cgd 			ipforward_rt.ro_rt = 0;
   1540         1.1       cgd 		}
   1541         1.1       cgd 		sin->sin_family = AF_INET;
   1542        1.35   mycroft 		sin->sin_len = sizeof(struct sockaddr_in);
   1543         1.1       cgd 		sin->sin_addr = ip->ip_dst;
   1544         1.1       cgd 
   1545         1.1       cgd 		rtalloc(&ipforward_rt);
   1546         1.1       cgd 		if (ipforward_rt.ro_rt == 0) {
   1547        1.13   mycroft 			icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
   1548         1.1       cgd 			return;
   1549         1.1       cgd 		}
   1550         1.1       cgd 		rt = ipforward_rt.ro_rt;
   1551         1.1       cgd 	}
   1552         1.1       cgd 
   1553         1.1       cgd 	/*
   1554        1.34   mycroft 	 * Save at most 68 bytes of the packet in case
   1555         1.1       cgd 	 * we need to generate an ICMP message to the src.
   1556       1.119    itojun 	 * Pullup to avoid sharing mbuf cluster between m and mcopy.
   1557         1.1       cgd 	 */
   1558  1.130.2.12   nathanw 	mcopy = m_copym(m, 0, imin(ntohs(ip->ip_len), 68), M_DONTWAIT);
   1559       1.119    itojun 	if (mcopy)
   1560       1.119    itojun 		mcopy = m_pullup(mcopy, ip->ip_hl << 2);
   1561         1.1       cgd 
   1562         1.1       cgd 	/*
   1563         1.1       cgd 	 * If forwarding packet using same interface that it came in on,
   1564         1.1       cgd 	 * perhaps should send a redirect to sender to shortcut a hop.
   1565         1.1       cgd 	 * Only send redirect if source is sending directly to us,
   1566         1.1       cgd 	 * and if packet was not source routed (or has any options).
   1567         1.1       cgd 	 * Also, don't send redirect if forwarding using a default route
   1568         1.1       cgd 	 * or a route modified by a redirect.
   1569         1.1       cgd 	 */
   1570         1.1       cgd 	if (rt->rt_ifp == m->m_pkthdr.rcvif &&
   1571         1.1       cgd 	    (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
   1572        1.35   mycroft 	    !in_nullhost(satosin(rt_key(rt))->sin_addr) &&
   1573         1.1       cgd 	    ipsendredirects && !srcrt) {
   1574        1.19   mycroft 		if (rt->rt_ifa &&
   1575        1.19   mycroft 		    (ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_subnetmask) ==
   1576        1.19   mycroft 		    ifatoia(rt->rt_ifa)->ia_subnet) {
   1577        1.77   thorpej 			if (rt->rt_flags & RTF_GATEWAY)
   1578        1.77   thorpej 				dest = satosin(rt->rt_gateway)->sin_addr.s_addr;
   1579        1.77   thorpej 			else
   1580        1.77   thorpej 				dest = ip->ip_dst.s_addr;
   1581        1.77   thorpej 			/*
   1582        1.77   thorpej 			 * Router requirements says to only send host
   1583        1.77   thorpej 			 * redirects.
   1584        1.77   thorpej 			 */
   1585        1.77   thorpej 			type = ICMP_REDIRECT;
   1586        1.77   thorpej 			code = ICMP_REDIRECT_HOST;
   1587         1.1       cgd #ifdef DIAGNOSTIC
   1588        1.77   thorpej 			if (ipprintfs)
   1589        1.77   thorpej 				printf("redirect (%d) to %x\n", code,
   1590        1.77   thorpej 				    (u_int32_t)dest);
   1591         1.1       cgd #endif
   1592         1.1       cgd 		}
   1593         1.1       cgd 	}
   1594         1.1       cgd 
   1595        1.89    itojun #ifdef IPSEC
   1596   1.130.2.2   nathanw 	/* Don't lookup socket in forwarding case */
   1597       1.127    itojun 	(void)ipsec_setsocket(m, NULL);
   1598       1.103    itojun #endif
   1599        1.27   thorpej 	error = ip_output(m, (struct mbuf *)0, &ipforward_rt,
   1600        1.27   thorpej 	    (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), 0);
   1601         1.1       cgd 	if (error)
   1602         1.1       cgd 		ipstat.ips_cantforward++;
   1603         1.1       cgd 	else {
   1604         1.1       cgd 		ipstat.ips_forward++;
   1605         1.1       cgd 		if (type)
   1606         1.1       cgd 			ipstat.ips_redirectsent++;
   1607         1.1       cgd 		else {
   1608        1.63      matt 			if (mcopy) {
   1609        1.63      matt #ifdef GATEWAY
   1610        1.64   thorpej 				if (mcopy->m_flags & M_CANFASTFWD)
   1611        1.64   thorpej 					ipflow_create(&ipforward_rt, mcopy);
   1612        1.63      matt #endif
   1613         1.1       cgd 				m_freem(mcopy);
   1614        1.63      matt 			}
   1615         1.1       cgd 			return;
   1616         1.1       cgd 		}
   1617         1.1       cgd 	}
   1618         1.1       cgd 	if (mcopy == NULL)
   1619         1.1       cgd 		return;
   1620        1.13   mycroft 	destifp = NULL;
   1621        1.13   mycroft 
   1622         1.1       cgd 	switch (error) {
   1623         1.1       cgd 
   1624         1.1       cgd 	case 0:				/* forwarded, but need redirect */
   1625         1.1       cgd 		/* type, code set above */
   1626         1.1       cgd 		break;
   1627         1.1       cgd 
   1628         1.1       cgd 	case ENETUNREACH:		/* shouldn't happen, checked above */
   1629         1.1       cgd 	case EHOSTUNREACH:
   1630         1.1       cgd 	case ENETDOWN:
   1631         1.1       cgd 	case EHOSTDOWN:
   1632         1.1       cgd 	default:
   1633         1.1       cgd 		type = ICMP_UNREACH;
   1634         1.1       cgd 		code = ICMP_UNREACH_HOST;
   1635         1.1       cgd 		break;
   1636         1.1       cgd 
   1637         1.1       cgd 	case EMSGSIZE:
   1638         1.1       cgd 		type = ICMP_UNREACH;
   1639         1.1       cgd 		code = ICMP_UNREACH_NEEDFRAG;
   1640        1.89    itojun #ifndef IPSEC
   1641        1.13   mycroft 		if (ipforward_rt.ro_rt)
   1642        1.13   mycroft 			destifp = ipforward_rt.ro_rt->rt_ifp;
   1643        1.89    itojun #else
   1644        1.89    itojun 		/*
   1645        1.89    itojun 		 * If the packet is routed over IPsec tunnel, tell the
   1646        1.89    itojun 		 * originator the tunnel MTU.
   1647        1.89    itojun 		 *	tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz
   1648        1.89    itojun 		 * XXX quickhack!!!
   1649        1.89    itojun 		 */
   1650        1.89    itojun 		if (ipforward_rt.ro_rt) {
   1651        1.89    itojun 			struct secpolicy *sp;
   1652        1.89    itojun 			int ipsecerror;
   1653        1.95    itojun 			size_t ipsechdr;
   1654        1.89    itojun 			struct route *ro;
   1655        1.89    itojun 
   1656        1.89    itojun 			sp = ipsec4_getpolicybyaddr(mcopy,
   1657        1.95    itojun 			                            IPSEC_DIR_OUTBOUND,
   1658        1.95    itojun 			                            IP_FORWARDING,
   1659        1.95    itojun 			                            &ipsecerror);
   1660        1.89    itojun 
   1661        1.89    itojun 			if (sp == NULL)
   1662        1.89    itojun 				destifp = ipforward_rt.ro_rt->rt_ifp;
   1663        1.89    itojun 			else {
   1664        1.89    itojun 				/* count IPsec header size */
   1665        1.95    itojun 				ipsechdr = ipsec4_hdrsiz(mcopy,
   1666        1.95    itojun 				                         IPSEC_DIR_OUTBOUND,
   1667        1.95    itojun 				                         NULL);
   1668        1.89    itojun 
   1669        1.89    itojun 				/*
   1670        1.89    itojun 				 * find the correct route for outer IPv4
   1671        1.89    itojun 				 * header, compute tunnel MTU.
   1672        1.89    itojun 				 *
   1673        1.89    itojun 				 * XXX BUG ALERT
   1674        1.89    itojun 				 * The "dummyifp" code relies upon the fact
   1675        1.89    itojun 				 * that icmp_error() touches only ifp->if_mtu.
   1676        1.89    itojun 				 */
   1677        1.89    itojun 				/*XXX*/
   1678        1.89    itojun 				destifp = NULL;
   1679        1.89    itojun 				if (sp->req != NULL
   1680        1.95    itojun 				 && sp->req->sav != NULL
   1681        1.95    itojun 				 && sp->req->sav->sah != NULL) {
   1682        1.95    itojun 					ro = &sp->req->sav->sah->sa_route;
   1683        1.89    itojun 					if (ro->ro_rt && ro->ro_rt->rt_ifp) {
   1684        1.89    itojun 						dummyifp.if_mtu =
   1685  1.130.2.10   nathanw 						    ro->ro_rt->rt_rmx.rmx_mtu ?
   1686  1.130.2.10   nathanw 						    ro->ro_rt->rt_rmx.rmx_mtu :
   1687        1.89    itojun 						    ro->ro_rt->rt_ifp->if_mtu;
   1688        1.89    itojun 						dummyifp.if_mtu -= ipsechdr;
   1689        1.89    itojun 						destifp = &dummyifp;
   1690        1.89    itojun 					}
   1691        1.89    itojun 				}
   1692        1.89    itojun 
   1693        1.89    itojun 				key_freesp(sp);
   1694        1.89    itojun 			}
   1695        1.89    itojun 		}
   1696        1.89    itojun #endif /*IPSEC*/
   1697         1.1       cgd 		ipstat.ips_cantfrag++;
   1698         1.1       cgd 		break;
   1699         1.1       cgd 
   1700         1.1       cgd 	case ENOBUFS:
   1701   1.130.2.7   nathanw #if 1
   1702   1.130.2.7   nathanw 		/*
   1703   1.130.2.7   nathanw 		 * a router should not generate ICMP_SOURCEQUENCH as
   1704   1.130.2.7   nathanw 		 * required in RFC1812 Requirements for IP Version 4 Routers.
   1705   1.130.2.7   nathanw 		 * source quench could be a big problem under DoS attacks,
   1706  1.130.2.10   nathanw 		 * or if the underlying interface is rate-limited.
   1707   1.130.2.7   nathanw 		 */
   1708   1.130.2.7   nathanw 		if (mcopy)
   1709   1.130.2.7   nathanw 			m_freem(mcopy);
   1710   1.130.2.7   nathanw 		return;
   1711   1.130.2.7   nathanw #else
   1712         1.1       cgd 		type = ICMP_SOURCEQUENCH;
   1713         1.1       cgd 		code = 0;
   1714         1.1       cgd 		break;
   1715   1.130.2.7   nathanw #endif
   1716         1.1       cgd 	}
   1717        1.13   mycroft 	icmp_error(mcopy, type, code, dest, destifp);
   1718        1.44   thorpej }
   1719        1.44   thorpej 
   1720        1.44   thorpej void
   1721        1.44   thorpej ip_savecontrol(inp, mp, ip, m)
   1722       1.109  augustss 	struct inpcb *inp;
   1723       1.109  augustss 	struct mbuf **mp;
   1724       1.109  augustss 	struct ip *ip;
   1725       1.109  augustss 	struct mbuf *m;
   1726        1.44   thorpej {
   1727        1.44   thorpej 
   1728        1.44   thorpej 	if (inp->inp_socket->so_options & SO_TIMESTAMP) {
   1729        1.44   thorpej 		struct timeval tv;
   1730        1.44   thorpej 
   1731        1.44   thorpej 		microtime(&tv);
   1732        1.44   thorpej 		*mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
   1733        1.44   thorpej 		    SCM_TIMESTAMP, SOL_SOCKET);
   1734        1.44   thorpej 		if (*mp)
   1735        1.44   thorpej 			mp = &(*mp)->m_next;
   1736        1.44   thorpej 	}
   1737        1.44   thorpej 	if (inp->inp_flags & INP_RECVDSTADDR) {
   1738        1.44   thorpej 		*mp = sbcreatecontrol((caddr_t) &ip->ip_dst,
   1739        1.44   thorpej 		    sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
   1740        1.44   thorpej 		if (*mp)
   1741        1.44   thorpej 			mp = &(*mp)->m_next;
   1742        1.44   thorpej 	}
   1743        1.44   thorpej #ifdef notyet
   1744        1.44   thorpej 	/*
   1745        1.44   thorpej 	 * XXX
   1746        1.44   thorpej 	 * Moving these out of udp_input() made them even more broken
   1747        1.44   thorpej 	 * than they already were.
   1748        1.44   thorpej 	 *	- fenner (at) parc.xerox.com
   1749        1.44   thorpej 	 */
   1750        1.44   thorpej 	/* options were tossed already */
   1751        1.44   thorpej 	if (inp->inp_flags & INP_RECVOPTS) {
   1752        1.44   thorpej 		*mp = sbcreatecontrol((caddr_t) opts_deleted_above,
   1753        1.44   thorpej 		    sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP);
   1754        1.44   thorpej 		if (*mp)
   1755        1.44   thorpej 			mp = &(*mp)->m_next;
   1756        1.44   thorpej 	}
   1757        1.44   thorpej 	/* ip_srcroute doesn't do what we want here, need to fix */
   1758        1.44   thorpej 	if (inp->inp_flags & INP_RECVRETOPTS) {
   1759        1.44   thorpej 		*mp = sbcreatecontrol((caddr_t) ip_srcroute(),
   1760        1.44   thorpej 		    sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP);
   1761        1.44   thorpej 		if (*mp)
   1762        1.44   thorpej 			mp = &(*mp)->m_next;
   1763        1.44   thorpej 	}
   1764        1.44   thorpej #endif
   1765        1.44   thorpej 	if (inp->inp_flags & INP_RECVIF) {
   1766        1.44   thorpej 		struct sockaddr_dl sdl;
   1767        1.44   thorpej 
   1768        1.44   thorpej 		sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data[0]);
   1769        1.44   thorpej 		sdl.sdl_family = AF_LINK;
   1770        1.44   thorpej 		sdl.sdl_index = m->m_pkthdr.rcvif ?
   1771        1.44   thorpej 		    m->m_pkthdr.rcvif->if_index : 0;
   1772        1.44   thorpej 		sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0;
   1773        1.44   thorpej 		*mp = sbcreatecontrol((caddr_t) &sdl, sdl.sdl_len,
   1774        1.44   thorpej 		    IP_RECVIF, IPPROTO_IP);
   1775        1.44   thorpej 		if (*mp)
   1776        1.44   thorpej 			mp = &(*mp)->m_next;
   1777        1.44   thorpej 	}
   1778        1.13   mycroft }
   1779        1.13   mycroft 
   1780        1.13   mycroft int
   1781        1.13   mycroft ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
   1782        1.13   mycroft 	int *name;
   1783        1.13   mycroft 	u_int namelen;
   1784        1.13   mycroft 	void *oldp;
   1785        1.13   mycroft 	size_t *oldlenp;
   1786        1.13   mycroft 	void *newp;
   1787        1.13   mycroft 	size_t newlen;
   1788        1.13   mycroft {
   1789        1.88  sommerfe 	extern int subnetsarelocal, hostzeroisbroadcast;
   1790        1.52   thorpej 
   1791        1.54     lukem 	int error, old;
   1792        1.54     lukem 
   1793        1.13   mycroft 	/* All sysctl names at this level are terminal. */
   1794        1.13   mycroft 	if (namelen != 1)
   1795        1.13   mycroft 		return (ENOTDIR);
   1796        1.13   mycroft 
   1797        1.13   mycroft 	switch (name[0]) {
   1798        1.13   mycroft 	case IPCTL_FORWARDING:
   1799        1.13   mycroft 		return (sysctl_int(oldp, oldlenp, newp, newlen, &ipforwarding));
   1800        1.13   mycroft 	case IPCTL_SENDREDIRECTS:
   1801        1.13   mycroft 		return (sysctl_int(oldp, oldlenp, newp, newlen,
   1802        1.13   mycroft 			&ipsendredirects));
   1803        1.13   mycroft 	case IPCTL_DEFTTL:
   1804        1.13   mycroft 		return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_defttl));
   1805        1.13   mycroft #ifdef notyet
   1806        1.13   mycroft 	case IPCTL_DEFMTU:
   1807        1.13   mycroft 		return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));
   1808        1.13   mycroft #endif
   1809        1.26   thorpej 	case IPCTL_FORWSRCRT:
   1810        1.47       cjs 		/* Don't allow this to change in a secure environment.  */
   1811        1.26   thorpej 		if (securelevel > 0)
   1812        1.46       cjs 			return (sysctl_rdint(oldp, oldlenp, newp,
   1813        1.46       cjs 			    ip_forwsrcrt));
   1814        1.46       cjs 		else
   1815        1.46       cjs 			return (sysctl_int(oldp, oldlenp, newp, newlen,
   1816        1.46       cjs 			    &ip_forwsrcrt));
   1817        1.27   thorpej 	case IPCTL_DIRECTEDBCAST:
   1818        1.27   thorpej 		return (sysctl_int(oldp, oldlenp, newp, newlen,
   1819        1.27   thorpej 		    &ip_directedbcast));
   1820        1.47       cjs 	case IPCTL_ALLOWSRCRT:
   1821        1.47       cjs 		return (sysctl_int(oldp, oldlenp, newp, newlen,
   1822        1.47       cjs 		    &ip_allowsrcrt));
   1823        1.52   thorpej 	case IPCTL_SUBNETSARELOCAL:
   1824        1.52   thorpej 		return (sysctl_int(oldp, oldlenp, newp, newlen,
   1825        1.52   thorpej 		    &subnetsarelocal));
   1826        1.53       kml 	case IPCTL_MTUDISC:
   1827        1.60       kml 		error = sysctl_int(oldp, oldlenp, newp, newlen,
   1828        1.60       kml 		    &ip_mtudisc);
   1829        1.60       kml 		if (ip_mtudisc != 0 && ip_mtudisc_timeout_q == NULL) {
   1830  1.130.2.10   nathanw 			ip_mtudisc_timeout_q =
   1831        1.60       kml 			    rt_timer_queue_create(ip_mtudisc_timeout);
   1832        1.60       kml 		} else if (ip_mtudisc == 0 && ip_mtudisc_timeout_q != NULL) {
   1833        1.60       kml 			rt_timer_queue_destroy(ip_mtudisc_timeout_q, TRUE);
   1834        1.60       kml 			ip_mtudisc_timeout_q = NULL;
   1835        1.60       kml 		}
   1836        1.60       kml 		return error;
   1837        1.54     lukem 	case IPCTL_ANONPORTMIN:
   1838        1.54     lukem 		old = anonportmin;
   1839        1.54     lukem 		error = sysctl_int(oldp, oldlenp, newp, newlen, &anonportmin);
   1840       1.118    itojun 		if (anonportmin >= anonportmax || anonportmin < 0
   1841       1.118    itojun 		    || anonportmin > 65535
   1842        1.54     lukem #ifndef IPNOPRIVPORTS
   1843        1.54     lukem 		    || anonportmin < IPPORT_RESERVED
   1844        1.54     lukem #endif
   1845        1.54     lukem 		    ) {
   1846        1.54     lukem 			anonportmin = old;
   1847        1.54     lukem 			return (EINVAL);
   1848        1.54     lukem 		}
   1849        1.54     lukem 		return (error);
   1850        1.54     lukem 	case IPCTL_ANONPORTMAX:
   1851        1.54     lukem 		old = anonportmax;
   1852        1.54     lukem 		error = sysctl_int(oldp, oldlenp, newp, newlen, &anonportmax);
   1853       1.118    itojun 		if (anonportmin >= anonportmax || anonportmax < 0
   1854       1.118    itojun 		    || anonportmax > 65535
   1855        1.54     lukem #ifndef IPNOPRIVPORTS
   1856        1.54     lukem 		    || anonportmax < IPPORT_RESERVED
   1857        1.54     lukem #endif
   1858        1.54     lukem 		    ) {
   1859        1.54     lukem 			anonportmax = old;
   1860        1.54     lukem 			return (EINVAL);
   1861        1.54     lukem 		}
   1862        1.60       kml 		return (error);
   1863        1.60       kml 	case IPCTL_MTUDISCTIMEOUT:
   1864  1.130.2.14   nathanw 		old = ip_mtudisc_timeout;
   1865        1.60       kml 		error = sysctl_int(oldp, oldlenp, newp, newlen,
   1866        1.60       kml 		   &ip_mtudisc_timeout);
   1867  1.130.2.14   nathanw 		if (ip_mtudisc_timeout < 0) {
   1868  1.130.2.14   nathanw 			ip_mtudisc_timeout = old;
   1869  1.130.2.13   nathanw 			return (EINVAL);
   1870  1.130.2.14   nathanw 		}
   1871        1.60       kml 		if (ip_mtudisc_timeout_q != NULL)
   1872  1.130.2.10   nathanw 			rt_timer_queue_change(ip_mtudisc_timeout_q,
   1873        1.60       kml 					      ip_mtudisc_timeout);
   1874        1.54     lukem 		return (error);
   1875        1.65      matt #ifdef GATEWAY
   1876        1.65      matt 	case IPCTL_MAXFLOWS:
   1877        1.67   thorpej 	    {
   1878        1.67   thorpej 		int s;
   1879        1.67   thorpej 
   1880        1.65      matt 		error = sysctl_int(oldp, oldlenp, newp, newlen,
   1881        1.65      matt 		   &ip_maxflows);
   1882        1.67   thorpej 		s = splsoftnet();
   1883        1.65      matt 		ipflow_reap(0);
   1884        1.67   thorpej 		splx(s);
   1885        1.65      matt 		return (error);
   1886        1.67   thorpej 	    }
   1887        1.89    itojun #endif
   1888        1.90    itojun 	case IPCTL_HOSTZEROBROADCAST:
   1889        1.90    itojun 		return (sysctl_int(oldp, oldlenp, newp, newlen,
   1890        1.90    itojun 		    &hostzeroisbroadcast));
   1891        1.89    itojun #if NGIF > 0
   1892        1.89    itojun 	case IPCTL_GIF_TTL:
   1893  1.130.2.13   nathanw 		return (sysctl_int(oldp, oldlenp, newp, newlen,
   1894        1.90    itojun 				  &ip_gif_ttl));
   1895   1.130.2.7   nathanw #endif
   1896   1.130.2.7   nathanw 
   1897   1.130.2.7   nathanw #if NGRE > 0
   1898   1.130.2.7   nathanw 	case IPCTL_GRE_TTL:
   1899  1.130.2.13   nathanw 		return (sysctl_int(oldp, oldlenp, newp, newlen,
   1900   1.130.2.7   nathanw 				  &ip_gre_ttl));
   1901       1.117      tron #endif
   1902       1.117      tron 
   1903       1.117      tron #ifndef IPNOPRIVPORTS
   1904       1.117      tron 	case IPCTL_LOWPORTMIN:
   1905       1.117      tron 		old = lowportmin;
   1906       1.117      tron 		error = sysctl_int(oldp, oldlenp, newp, newlen, &lowportmin);
   1907       1.117      tron 		if (lowportmin >= lowportmax
   1908       1.117      tron 		    || lowportmin > IPPORT_RESERVEDMAX
   1909       1.117      tron 		    || lowportmin < IPPORT_RESERVEDMIN
   1910       1.117      tron 		    ) {
   1911       1.117      tron 			lowportmin = old;
   1912       1.117      tron 			return (EINVAL);
   1913       1.117      tron 		}
   1914       1.117      tron 		return (error);
   1915       1.117      tron 	case IPCTL_LOWPORTMAX:
   1916       1.117      tron 		old = lowportmax;
   1917       1.117      tron 		error = sysctl_int(oldp, oldlenp, newp, newlen, &lowportmax);
   1918       1.117      tron 		if (lowportmin >= lowportmax
   1919       1.117      tron 		    || lowportmax > IPPORT_RESERVEDMAX
   1920       1.117      tron 		    || lowportmax < IPPORT_RESERVEDMIN
   1921       1.117      tron 		    ) {
   1922       1.117      tron 			lowportmax = old;
   1923       1.117      tron 			return (EINVAL);
   1924       1.117      tron 		}
   1925       1.117      tron 		return (error);
   1926        1.65      matt #endif
   1927   1.130.2.1   nathanw 
   1928   1.130.2.1   nathanw 	case IPCTL_MAXFRAGPACKETS:
   1929   1.130.2.1   nathanw 		return (sysctl_int(oldp, oldlenp, newp, newlen,
   1930   1.130.2.1   nathanw 		    &ip_maxfragpackets));
   1931        1.88  sommerfe 
   1932        1.13   mycroft 	default:
   1933        1.13   mycroft 		return (EOPNOTSUPP);
   1934        1.13   mycroft 	}
   1935        1.13   mycroft 	/* NOTREACHED */
   1936         1.1       cgd }
   1937