Home | History | Annotate | Line # | Download | only in netinet
ip_fil_netbsd.c revision 1.11.4.1
      1  1.11.4.1     skrll /*	$NetBSD: ip_fil_netbsd.c,v 1.11.4.1 2016/03/19 11:30:31 skrll Exp $	*/
      2       1.1  christos 
      3       1.1  christos /*
      4       1.1  christos  * Copyright (C) 2012 by Darren Reed.
      5       1.1  christos  *
      6       1.1  christos  * See the IPFILTER.LICENCE file for details on licencing.
      7       1.1  christos  */
      8       1.1  christos #if !defined(lint)
      9       1.2  christos #if defined(__NetBSD__)
     10       1.2  christos #include <sys/cdefs.h>
     11  1.11.4.1     skrll __KERNEL_RCSID(0, "$NetBSD: ip_fil_netbsd.c,v 1.11.4.1 2016/03/19 11:30:31 skrll Exp $");
     12       1.2  christos #else
     13       1.1  christos static const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-2000 Darren Reed";
     14       1.3   darrenr static const char rcsid[] = "@(#)Id: ip_fil_netbsd.c,v 1.1.1.2 2012/07/22 13:45:17 darrenr Exp";
     15       1.2  christos #endif
     16       1.1  christos #endif
     17       1.1  christos 
     18       1.1  christos #if defined(KERNEL) || defined(_KERNEL)
     19       1.1  christos # undef KERNEL
     20       1.1  christos # undef _KERNEL
     21       1.1  christos # define        KERNEL	1
     22       1.1  christos # define        _KERNEL	1
     23       1.1  christos #endif
     24       1.1  christos #include <sys/param.h>
     25       1.1  christos #if (NetBSD >= 199905) && !defined(IPFILTER_LKM)
     26       1.1  christos # include "opt_ipsec.h"
     27       1.1  christos #endif
     28       1.1  christos #include <sys/errno.h>
     29       1.1  christos #include <sys/types.h>
     30       1.1  christos #include <sys/file.h>
     31       1.1  christos #include <sys/ioctl.h>
     32       1.1  christos #include <sys/time.h>
     33       1.1  christos #include <sys/systm.h>
     34       1.1  christos #include <sys/select.h>
     35       1.1  christos #if (NetBSD > 199609)
     36       1.1  christos # include <sys/dirent.h>
     37       1.1  christos #else
     38       1.1  christos # include <sys/dir.h>
     39       1.1  christos #endif
     40       1.1  christos #if (__NetBSD_Version__ >= 599005900)
     41       1.1  christos # include <sys/cprng.h>
     42       1.1  christos #endif
     43       1.1  christos #include <sys/mbuf.h>
     44       1.1  christos #include <sys/protosw.h>
     45       1.1  christos #include <sys/socket.h>
     46       1.1  christos #include <sys/poll.h>
     47       1.1  christos #if (__NetBSD_Version__ >= 399002000)
     48       1.1  christos # include <sys/kauth.h>
     49       1.1  christos #endif
     50       1.1  christos 
     51       1.1  christos #include <net/if.h>
     52       1.1  christos #include <net/route.h>
     53       1.1  christos #include <netinet/in.h>
     54       1.1  christos #include <netinet/in_var.h>
     55       1.1  christos #include <netinet/in_systm.h>
     56       1.1  christos #include <netinet/ip.h>
     57       1.1  christos #include <netinet/ip_var.h>
     58       1.1  christos #include <netinet/tcp.h>
     59       1.1  christos #if __NetBSD_Version__ >= 105190000	/* 1.5T */
     60       1.1  christos # include <netinet/tcp_timer.h>
     61       1.1  christos # include <netinet/tcp_var.h>
     62       1.1  christos #endif
     63       1.1  christos #include <netinet/udp.h>
     64       1.1  christos #include <netinet/tcpip.h>
     65       1.1  christos #include <netinet/ip_icmp.h>
     66       1.1  christos #include "netinet/ip_compat.h"
     67       1.1  christos #ifdef USE_INET6
     68       1.1  christos # include <netinet/icmp6.h>
     69       1.1  christos # if (__NetBSD_Version__ >= 106000000)
     70       1.1  christos #  include <netinet6/nd6.h>
     71       1.1  christos # endif
     72       1.1  christos #endif
     73       1.1  christos #include "netinet/ip_fil.h"
     74       1.1  christos #include "netinet/ip_nat.h"
     75       1.1  christos #include "netinet/ip_frag.h"
     76       1.1  christos #include "netinet/ip_state.h"
     77       1.1  christos #include "netinet/ip_proxy.h"
     78       1.1  christos #include "netinet/ip_auth.h"
     79       1.1  christos #include "netinet/ip_sync.h"
     80       1.1  christos #include "netinet/ip_lookup.h"
     81       1.1  christos #include "netinet/ip_dstlist.h"
     82       1.1  christos #ifdef	IPFILTER_SCAN
     83       1.1  christos #include "netinet/ip_scan.h"
     84       1.1  christos #endif
     85       1.1  christos #include <sys/md5.h>
     86       1.1  christos #include <sys/kernel.h>
     87       1.1  christos #include <sys/conf.h>
     88       1.1  christos #ifdef INET
     89       1.2  christos extern	int	ip_optcopy (struct ip *, struct ip *);
     90       1.1  christos #endif
     91       1.1  christos 
     92       1.1  christos #ifdef IPFILTER_M_IPFILTER
     93       1.1  christos MALLOC_DEFINE(M_IPFILTER, "IP Filter", "IP Filter packet filter data structures");
     94       1.1  christos #endif
     95       1.1  christos 
     96       1.1  christos #if __NetBSD_Version__ >= 105009999
     97       1.1  christos # define	csuminfo	csum_flags
     98       1.1  christos #endif
     99       1.1  christos 
    100       1.1  christos #if __NetBSD_Version__ < 200000000
    101       1.1  christos extern	struct	protosw	inetsw[];
    102       1.1  christos #endif
    103       1.2  christos 
    104       1.2  christos #if (__NetBSD_Version__ >= 599002000)
    105       1.2  christos static kauth_listener_t ipf_listener;
    106       1.2  christos #endif
    107       1.2  christos 
    108       1.2  christos #if (__NetBSD_Version__ < 399001400)
    109       1.2  christos extern int ip6_getpmtu (struct route_in6 *, struct route_in6 *,
    110       1.2  christos 			    struct ifnet *, struct in6_addr *, u_long *,
    111       1.2  christos 			    int *);
    112       1.2  christos #endif
    113       1.1  christos #if (NetBSD >= 199511)
    114       1.1  christos static  int     ipfopen(dev_t dev, int flags, int devtype, PROC_T *p);
    115       1.1  christos static  int     ipfclose(dev_t dev, int flags, int devtype, PROC_T *p);
    116       1.1  christos #else
    117       1.1  christos # if (__NetBSD_Version__ >= 399001400)
    118       1.1  christos static  int     ipfopen(dev_t dev, int flags, struct lwp *);
    119       1.1  christos static  int     ipfclose(dev_t dev, int flags, struct lwp *);
    120       1.1  christos # else
    121       1.1  christos static  int     ipfopen(dev_t dev, int flags);
    122       1.1  christos static  int     ipfclose(dev_t dev, int flags);
    123       1.1  christos # endif /* __NetBSD_Version__ >= 399001400 */
    124       1.1  christos #endif
    125       1.1  christos static  int     ipfread(dev_t, struct uio *, int ioflag);
    126       1.1  christos static  int     ipfwrite(dev_t, struct uio *, int ioflag);
    127       1.1  christos static  int     ipfpoll(dev_t, int events, PROC_T *);
    128       1.2  christos static	void	ipf_timer_func(void *ptr);
    129       1.1  christos 
    130       1.1  christos const struct cdevsw ipl_cdevsw = {
    131       1.8  dholland 	.d_open = ipfopen,
    132       1.8  dholland 	.d_close = ipfclose,
    133       1.8  dholland 	.d_read = ipfread,
    134       1.8  dholland 	.d_write = ipfwrite,
    135       1.8  dholland 	.d_ioctl = ipfioctl,
    136       1.8  dholland 	.d_stop = nostop,
    137       1.8  dholland 	.d_tty = notty,
    138       1.8  dholland 	.d_poll = ipfpoll,
    139       1.8  dholland 	.d_mmap = nommap,
    140       1.1  christos #if  (__NetBSD_Version__ >= 200000000)
    141       1.8  dholland 	.d_kqfilter = nokqfilter,
    142       1.1  christos #endif
    143      1.11  dholland 	.d_discard = nodiscard,
    144       1.1  christos #ifdef D_OTHER
    145       1.8  dholland 	.d_flag = D_OTHER
    146       1.8  dholland #else
    147       1.8  dholland 	.d_flag = 0
    148       1.1  christos #endif
    149       1.1  christos };
    150       1.1  christos 
    151       1.1  christos ipf_main_softc_t ipfmain;
    152       1.1  christos 
    153       1.1  christos static	u_short	ipid = 0;
    154       1.2  christos static	int	(*ipf_savep)(void *, ip_t *, int, void *, int, struct mbuf **);
    155       1.2  christos static	int	ipf_send_ip(fr_info_t *, mb_t *);
    156       1.1  christos #ifdef USE_INET6
    157       1.2  christos static int ipf_fastroute6(struct mbuf *, struct mbuf **,
    158       1.2  christos 			      fr_info_t *, frdest_t *);
    159       1.1  christos #endif
    160       1.1  christos 
    161       1.1  christos #if defined(NETBSD_PF)
    162       1.1  christos # include <net/pfil.h>
    163       1.1  christos /*
    164       1.1  christos  * We provide the ipf_checkp name just to minimize changes later.
    165       1.1  christos  */
    166       1.2  christos int (*ipf_checkp)(void *, ip_t *ip, int hlen, void *ifp, int out, mb_t **mp);
    167       1.1  christos #endif /* NETBSD_PF */
    168       1.1  christos 
    169       1.1  christos #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)
    170       1.1  christos # include <net/pfil.h>
    171       1.1  christos 
    172       1.1  christos static int ipf_check_wrapper(void *, struct mbuf **, struct ifnet *, int );
    173       1.1  christos 
    174       1.1  christos static int
    175       1.2  christos ipf_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
    176       1.1  christos {
    177       1.1  christos 	struct ip *ip;
    178       1.1  christos 	int rv, hlen;
    179       1.1  christos 
    180       1.1  christos #if __NetBSD_Version__ >= 200080000
    181       1.1  christos 	/*
    182       1.1  christos 	 * ensure that mbufs are writable beforehand
    183       1.1  christos 	 * as it's assumed by ipf code.
    184       1.1  christos 	 * XXX inefficient
    185       1.1  christos 	 */
    186       1.1  christos 	int error = m_makewritable(mp, 0, M_COPYALL, M_DONTWAIT);
    187       1.1  christos 
    188       1.1  christos 	if (error) {
    189       1.1  christos 		m_freem(*mp);
    190       1.1  christos 		*mp = NULL;
    191       1.1  christos 		return error;
    192       1.1  christos 	}
    193       1.1  christos #endif
    194       1.1  christos 	ip = mtod(*mp, struct ip *);
    195       1.1  christos 	hlen = ip->ip_hl << 2;
    196       1.1  christos 
    197       1.1  christos #ifdef INET
    198       1.1  christos #if defined(M_CSUM_TCPv4)
    199       1.1  christos 	/*
    200       1.1  christos 	 * If the packet is out-bound, we can't delay checksums
    201       1.1  christos 	 * here.  For in-bound, the checksum has already been
    202       1.1  christos 	 * validated.
    203       1.1  christos 	 */
    204       1.1  christos 	if (dir == PFIL_OUT) {
    205       1.1  christos 		if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
    206       1.1  christos 			in_delayed_cksum(*mp);
    207       1.1  christos 			(*mp)->m_pkthdr.csum_flags &=
    208       1.1  christos 			    ~(M_CSUM_TCPv4|M_CSUM_UDPv4);
    209       1.1  christos 		}
    210       1.1  christos 	}
    211       1.1  christos #endif /* M_CSUM_TCPv4 */
    212       1.1  christos #endif /* INET */
    213       1.1  christos 
    214       1.1  christos 	/*
    215       1.1  christos 	 * Note, we don't need to update the checksum, because
    216       1.1  christos 	 * it has already been verified.
    217       1.1  christos 	 */
    218       1.1  christos 	rv = ipf_check(&ipfmain, ip, hlen, ifp, (dir == PFIL_OUT), mp);
    219       1.1  christos 
    220       1.1  christos 	return (rv);
    221       1.1  christos }
    222       1.1  christos 
    223       1.1  christos # ifdef USE_INET6
    224       1.1  christos #  include <netinet/ip6.h>
    225       1.1  christos 
    226       1.1  christos static int ipf_check_wrapper6(void *, struct mbuf **, struct ifnet *, int );
    227       1.1  christos 
    228       1.1  christos static int
    229       1.2  christos ipf_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
    230       1.1  christos {
    231       1.2  christos #if defined(INET6)
    232       1.1  christos #  if defined(M_CSUM_TCPv6) && (__NetBSD_Version__ > 200000000)
    233       1.1  christos 	/*
    234       1.1  christos 	 * If the packet is out-bound, we can't delay checksums
    235       1.1  christos 	 * here.  For in-bound, the checksum has already been
    236       1.1  christos 	 * validated.
    237       1.1  christos 	 */
    238       1.1  christos 	if (dir == PFIL_OUT) {
    239       1.1  christos 		if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) {
    240       1.1  christos #   if (__NetBSD_Version__ > 399000600)
    241       1.1  christos 			in6_delayed_cksum(*mp);
    242       1.1  christos #   endif
    243       1.1  christos 			(*mp)->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv6|
    244       1.1  christos 							M_CSUM_UDPv6);
    245       1.1  christos 		}
    246       1.1  christos 	}
    247       1.1  christos #  endif
    248       1.2  christos #endif /* INET6 */
    249       1.1  christos 
    250       1.1  christos 	return (ipf_check(&ipfmain, mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
    251       1.1  christos 	    ifp, (dir == PFIL_OUT), mp));
    252       1.1  christos }
    253       1.1  christos # endif
    254       1.1  christos 
    255       1.1  christos 
    256       1.1  christos # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
    257       1.1  christos static int ipf_pfilsync(void *, struct mbuf **, struct ifnet *, int);
    258       1.1  christos 
    259       1.1  christos static int
    260       1.2  christos ipf_pfilsync(void *hdr, struct mbuf **mp, struct ifnet *ifp, int dir)
    261       1.1  christos {
    262       1.1  christos 	/*
    263       1.1  christos 	 * The interface pointer is useless for create (we have nothing to
    264       1.1  christos 	 * compare it to) and at detach, the interface name is still in the
    265       1.1  christos 	 * list of active NICs (albeit, down, but that's not any real
    266       1.1  christos 	 * indicator) and doing ifunit() on the name will still return the
    267       1.1  christos 	 * pointer, so it's not much use then, either.
    268       1.1  christos 	 */
    269       1.1  christos 	ipf_sync(&ipfmain, NULL);
    270       1.1  christos 	return 0;
    271       1.1  christos }
    272       1.1  christos # endif
    273       1.1  christos 
    274       1.1  christos #endif /* __NetBSD_Version__ >= 105110000 */
    275       1.1  christos 
    276       1.1  christos 
    277       1.1  christos #if defined(IPFILTER_LKM)
    278       1.1  christos int
    279       1.1  christos ipf_identify(s)
    280       1.1  christos 	char *s;
    281       1.1  christos {
    282       1.1  christos 	if (strcmp(s, "ipl") == 0)
    283       1.1  christos 		return 1;
    284       1.1  christos 	return 0;
    285       1.1  christos }
    286       1.1  christos #endif /* IPFILTER_LKM */
    287       1.1  christos 
    288       1.2  christos #if (__NetBSD_Version__ >= 599002000)
    289       1.2  christos static int
    290       1.2  christos ipf_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
    291       1.2  christos     void *arg0, void *arg1, void *arg2, void *arg3)
    292       1.2  christos {
    293       1.2  christos 	int result;
    294       1.2  christos 	enum kauth_network_req req;
    295       1.2  christos 
    296       1.2  christos 	result = KAUTH_RESULT_DEFER;
    297       1.2  christos 	req = (enum kauth_network_req)arg0;
    298       1.2  christos 
    299       1.2  christos 	if (action != KAUTH_NETWORK_FIREWALL)
    300       1.2  christos 		return result;
    301       1.2  christos 
    302       1.2  christos 	/* These must have came from device context. */
    303       1.2  christos 	if ((req == KAUTH_REQ_NETWORK_FIREWALL_FW) ||
    304       1.2  christos 	    (req == KAUTH_REQ_NETWORK_FIREWALL_NAT))
    305       1.2  christos 		result = KAUTH_RESULT_ALLOW;
    306       1.2  christos 
    307       1.2  christos 	return result;
    308       1.2  christos }
    309       1.2  christos #endif
    310       1.1  christos 
    311       1.1  christos /*
    312       1.1  christos  * Try to detect the case when compiling for NetBSD with pseudo-device
    313       1.1  christos  */
    314       1.1  christos void
    315       1.2  christos ipfilterattach(int count)
    316       1.1  christos {
    317       1.2  christos 
    318       1.2  christos #if (__NetBSD_Version__ >= 599002000)
    319       1.2  christos 	ipf_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
    320       1.2  christos 	    ipf_listener_cb, NULL);
    321       1.2  christos #endif
    322       1.2  christos 
    323       1.1  christos 	if (ipf_load_all() == 0)
    324       1.1  christos 		(void) ipf_create_all(&ipfmain);
    325       1.1  christos }
    326       1.1  christos 
    327       1.1  christos 
    328       1.1  christos int
    329       1.2  christos ipfattach(ipf_main_softc_t *softc)
    330       1.1  christos {
    331       1.1  christos 	SPL_INT(s);
    332       1.1  christos #if (__NetBSD_Version__ >= 499005500)
    333       1.1  christos 	int i;
    334       1.1  christos #endif
    335       1.1  christos #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)
    336       1.1  christos 	int error = 0;
    337       1.1  christos # if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)
    338       1.5     rmind         pfil_head_t *ph_inet;
    339       1.1  christos #  ifdef USE_INET6
    340       1.5     rmind         pfil_head_t *ph_inet6;
    341       1.1  christos #  endif
    342       1.1  christos #  if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
    343       1.5     rmind         pfil_head_t *ph_ifsync;
    344       1.1  christos #  endif
    345       1.1  christos # endif
    346       1.1  christos #endif
    347       1.1  christos 
    348       1.1  christos 	SPL_NET(s);
    349       1.1  christos 	if ((softc->ipf_running > 0) || (ipf_checkp == ipf_check)) {
    350       1.1  christos 		printf("IP Filter: already initialized\n");
    351       1.1  christos 		SPL_X(s);
    352       1.1  christos 		IPFERROR(130017);
    353       1.1  christos 		return EBUSY;
    354       1.1  christos 	}
    355       1.1  christos 
    356       1.1  christos 	if (ipf_init_all(softc) < 0) {
    357       1.1  christos 		SPL_X(s);
    358       1.1  christos 		IPFERROR(130015);
    359       1.1  christos 		return EIO;
    360       1.1  christos 	}
    361       1.1  christos 
    362       1.1  christos #ifdef NETBSD_PF
    363       1.1  christos # if (__NetBSD_Version__ >= 104200000)
    364       1.1  christos #  if __NetBSD_Version__ >= 105110000
    365       1.5     rmind 	ph_inet = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET);
    366       1.1  christos #   ifdef USE_INET6
    367       1.5     rmind 	ph_inet6 = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET6);
    368       1.1  christos #   endif
    369       1.1  christos #   if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
    370       1.1  christos 	ph_ifsync = pfil_head_get(PFIL_TYPE_IFNET, 0);
    371       1.1  christos #   endif
    372       1.1  christos 
    373       1.1  christos 	if (ph_inet == NULL
    374       1.1  christos #   ifdef USE_INET6
    375       1.1  christos 	    && ph_inet6 == NULL
    376       1.1  christos #   endif
    377       1.1  christos #   if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
    378       1.1  christos 	    && ph_ifsync == NULL
    379       1.1  christos #   endif
    380       1.1  christos 	   ) {
    381       1.1  christos 		SPL_X(s);
    382       1.1  christos 		IPFERROR(130016);
    383       1.1  christos 		return ENODEV;
    384       1.1  christos 	}
    385       1.1  christos 
    386       1.1  christos 	if (ph_inet != NULL)
    387       1.1  christos 		error = pfil_add_hook((void *)ipf_check_wrapper, NULL,
    388       1.1  christos 				      PFIL_IN|PFIL_OUT, ph_inet);
    389       1.1  christos 	else
    390       1.1  christos 		error = 0;
    391       1.1  christos #  else
    392       1.1  christos 	error = pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
    393       1.1  christos 			      &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
    394       1.1  christos #  endif
    395       1.1  christos 	if (error) {
    396       1.1  christos 		IPFERROR(130013);
    397       1.1  christos 		goto pfil_error;
    398       1.1  christos 	}
    399       1.1  christos # else
    400       1.1  christos 	pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT);
    401       1.1  christos # endif
    402       1.1  christos 
    403       1.1  christos # ifdef USE_INET6
    404       1.1  christos #  if __NetBSD_Version__ >= 105110000
    405       1.1  christos 	if (ph_inet6 != NULL)
    406       1.1  christos 		error = pfil_add_hook((void *)ipf_check_wrapper6, NULL,
    407       1.1  christos 				      PFIL_IN|PFIL_OUT, ph_inet6);
    408       1.1  christos 	else
    409       1.1  christos 		error = 0;
    410       1.1  christos 	if (error) {
    411       1.1  christos 		pfil_remove_hook((void *)ipf_check_wrapper6, NULL,
    412       1.1  christos 				 PFIL_IN|PFIL_OUT, ph_inet6);
    413       1.1  christos 		ipfmain.ipf_interror = 130014;
    414       1.1  christos 		goto pfil_error;
    415       1.1  christos 	}
    416       1.1  christos #  else
    417       1.1  christos 	error = pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
    418       1.1  christos 			      &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
    419       1.1  christos 	if (error) {
    420       1.1  christos 		pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
    421       1.1  christos 				 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
    422       1.1  christos 		IPFERROR(130014);
    423       1.1  christos 		goto pfil_error;
    424       1.1  christos 	}
    425       1.1  christos #  endif
    426       1.1  christos # endif
    427       1.1  christos 
    428       1.1  christos # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
    429       1.1  christos 	if (ph_ifsync != NULL)
    430       1.1  christos 		(void) pfil_add_hook((void *)ipf_pfilsync, NULL,
    431       1.1  christos 				     PFIL_IFNET, ph_ifsync);
    432       1.1  christos # endif
    433       1.1  christos #endif
    434       1.1  christos 
    435       1.1  christos #if (__NetBSD_Version__ >= 499005500)
    436       1.1  christos 	for (i = 0; i < IPL_LOGSIZE; i++)
    437       1.1  christos 		selinit(&ipfmain.ipf_selwait[i]);
    438       1.1  christos #else
    439       1.1  christos 	bzero((char *)ipfmain.ipf_selwait, sizeof(ipfmain.ipf_selwait));
    440       1.1  christos #endif
    441       1.1  christos 	ipf_savep = ipf_checkp;
    442       1.1  christos 	ipf_checkp = ipf_check;
    443       1.1  christos 
    444       1.1  christos #ifdef INET
    445       1.1  christos 	if (softc->ipf_control_forwarding & 1)
    446       1.1  christos 		ipforwarding = 1;
    447       1.1  christos #endif
    448       1.1  christos 
    449       1.1  christos 	ipid = 0;
    450       1.1  christos 
    451       1.1  christos 	SPL_X(s);
    452       1.1  christos 
    453       1.1  christos #if (__NetBSD_Version__ >= 104010000)
    454       1.1  christos # if (__NetBSD_Version__ >= 499002000)
    455       1.1  christos 	callout_init(&softc->ipf_slow_ch, 0);
    456       1.1  christos # else
    457       1.1  christos 	callout_init(&softc->ipf_slow_ch);
    458       1.1  christos # endif
    459       1.1  christos 	callout_reset(&softc->ipf_slow_ch, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT,
    460       1.1  christos 		     ipf_timer_func, softc);
    461       1.1  christos #else
    462       1.1  christos 	timeout(ipf_timer_func, softc, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT);
    463       1.1  christos #endif
    464       1.2  christos 
    465       1.1  christos 	return 0;
    466       1.1  christos 
    467       1.1  christos #if __NetBSD_Version__ >= 105110000
    468       1.1  christos pfil_error:
    469       1.1  christos 	SPL_X(s);
    470       1.1  christos 	ipf_fini_all(softc);
    471       1.1  christos 	return error;
    472       1.1  christos #endif
    473       1.1  christos }
    474       1.1  christos 
    475       1.1  christos static void
    476       1.2  christos ipf_timer_func(void *ptr)
    477       1.1  christos {
    478       1.1  christos 	ipf_main_softc_t *softc = ptr;
    479       1.1  christos 	SPL_INT(s);
    480       1.1  christos 
    481       1.1  christos 	SPL_NET(s);
    482       1.1  christos 	READ_ENTER(&softc->ipf_global);
    483       1.1  christos 
    484       1.1  christos 	if (softc->ipf_running > 0)
    485       1.1  christos 		ipf_slowtimer(softc);
    486       1.1  christos 
    487       1.1  christos 	if (softc->ipf_running == -1 || softc->ipf_running == 1) {
    488       1.1  christos #if NETBSD_GE_REV(104240000)
    489       1.1  christos 		callout_reset(&softc->ipf_slow_ch, hz / 2,
    490       1.1  christos 			      ipf_timer_func, softc);
    491       1.1  christos #else
    492       1.1  christos 		timeout(ipf_timer_func, softc,
    493       1.1  christos 			(hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT);
    494       1.1  christos #endif
    495       1.1  christos 	}
    496       1.1  christos 	RWLOCK_EXIT(&softc->ipf_global);
    497       1.1  christos 	SPL_X(s);
    498       1.1  christos }
    499       1.1  christos 
    500       1.1  christos 
    501       1.1  christos /*
    502       1.1  christos  * Disable the filter by removing the hooks from the IP input/output
    503       1.1  christos  * stream.
    504       1.1  christos  */
    505       1.1  christos int
    506       1.2  christos ipfdetach(ipf_main_softc_t *softc)
    507       1.1  christos {
    508       1.1  christos 	SPL_INT(s);
    509       1.1  christos #if (__NetBSD_Version__ >= 499005500)
    510       1.1  christos 	int i;
    511       1.1  christos #endif
    512       1.1  christos #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)
    513       1.1  christos 	int error = 0;
    514       1.1  christos # if __NetBSD_Version__ >= 105150000
    515       1.5     rmind 	pfil_head_t *ph_inet = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET);
    516       1.1  christos #  ifdef USE_INET6
    517       1.5     rmind 	pfil_head_t *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET6);
    518       1.1  christos #  endif
    519       1.1  christos #  if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
    520       1.1  christos 	struct pfil_head *ph_ifsync = pfil_head_get(PFIL_TYPE_IFNET, 0);
    521       1.1  christos #  endif
    522       1.1  christos # endif
    523       1.1  christos #endif
    524       1.1  christos 
    525       1.1  christos 	SPL_NET(s);
    526       1.1  christos 
    527       1.1  christos #if (__NetBSD_Version__ >= 104010000)
    528       1.1  christos 	if (softc->ipf_running > 0)
    529       1.1  christos 		callout_stop(&softc->ipf_slow_ch);
    530       1.1  christos #else
    531       1.1  christos 	untimeout(ipf_slowtimer, NULL);
    532       1.1  christos #endif /* NetBSD */
    533       1.1  christos 
    534       1.1  christos 	ipf_checkp = ipf_savep;
    535       1.1  christos 	(void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE|FR_INACTIVE);
    536       1.1  christos 	(void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE);
    537       1.1  christos 
    538       1.1  christos #ifdef INET
    539       1.1  christos 	if (softc->ipf_control_forwarding & 2)
    540       1.1  christos 		ipforwarding = 0;
    541       1.1  christos #endif
    542       1.1  christos 
    543       1.1  christos #ifdef NETBSD_PF
    544       1.1  christos # if (__NetBSD_Version__ >= 104200000)
    545       1.1  christos #  if __NetBSD_Version__ >= 105110000
    546       1.1  christos #   if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
    547       1.1  christos 	(void) pfil_remove_hook((void *)ipf_pfilsync, NULL,
    548       1.1  christos 				PFIL_IFNET, ph_ifsync);
    549       1.1  christos #   endif
    550       1.1  christos 
    551       1.1  christos 	if (ph_inet != NULL)
    552       1.1  christos 		error = pfil_remove_hook((void *)ipf_check_wrapper, NULL,
    553       1.1  christos 					 PFIL_IN|PFIL_OUT, ph_inet);
    554       1.1  christos 	else
    555       1.1  christos 		error = 0;
    556       1.1  christos #  else
    557       1.1  christos 	error = pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
    558       1.1  christos 				 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
    559       1.1  christos #  endif
    560       1.1  christos 	if (error) {
    561       1.1  christos 		SPL_X(s);
    562       1.1  christos 		IPFERROR(130011);
    563       1.1  christos 		return error;
    564       1.1  christos 	}
    565       1.1  christos # else
    566       1.1  christos 	pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT);
    567       1.1  christos # endif
    568       1.1  christos # ifdef USE_INET6
    569       1.1  christos #  if __NetBSD_Version__ >= 105110000
    570       1.1  christos 	if (ph_inet6 != NULL)
    571       1.1  christos 		error = pfil_remove_hook((void *)ipf_check_wrapper6, NULL,
    572       1.1  christos 					 PFIL_IN|PFIL_OUT, ph_inet6);
    573       1.1  christos 	else
    574       1.1  christos 		error = 0;
    575       1.1  christos #  else
    576       1.1  christos 	error = pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
    577       1.1  christos 				 &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
    578       1.1  christos #  endif
    579       1.1  christos 	if (error) {
    580       1.1  christos 		SPL_X(s);
    581       1.1  christos 		IPFERROR(130012);
    582       1.1  christos 		return error;
    583       1.1  christos 	}
    584       1.1  christos # endif
    585       1.1  christos #endif
    586       1.1  christos 	SPL_X(s);
    587       1.1  christos 
    588       1.1  christos #if (__NetBSD_Version__ >= 499005500)
    589       1.1  christos 	for (i = 0; i < IPL_LOGSIZE; i++)
    590       1.1  christos 		seldestroy(&ipfmain.ipf_selwait[i]);
    591       1.1  christos #endif
    592       1.1  christos 
    593       1.1  christos 	ipf_fini_all(softc);
    594       1.1  christos 
    595       1.1  christos 	return 0;
    596       1.1  christos }
    597       1.1  christos 
    598       1.1  christos 
    599       1.1  christos /*
    600       1.1  christos  * Filter ioctl interface.
    601       1.1  christos  */
    602       1.1  christos int
    603       1.2  christos ipfioctl(dev_t dev, u_long cmd,
    604       1.2  christos #if  (__NetBSD_Version__ >= 499001000)
    605       1.2  christos 	void *data,
    606       1.2  christos #else
    607       1.2  christos 	caddr_t data,
    608       1.2  christos #endif
    609       1.2  christos 	int mode
    610       1.1  christos #if (NetBSD >= 199511)
    611       1.1  christos # if  (__NetBSD_Version__ >= 399001400)
    612       1.2  christos 	, struct lwp *p
    613       1.1  christos #   if (__NetBSD_Version__ >= 399002000)
    614       1.1  christos #     define	UID(l)	kauth_cred_getuid((l)->l_cred)
    615       1.1  christos #  else
    616       1.1  christos #     define	UID(l)	((l)->l_proc->p_cred->p_ruid)
    617       1.1  christos #  endif
    618       1.1  christos # else
    619       1.2  christos 	, struct proc *p
    620       1.1  christos #  define	UID(p)	((p)->p_cred->p_ruid)
    621       1.1  christos # endif
    622       1.2  christos #endif
    623       1.1  christos )
    624       1.1  christos {
    625       1.1  christos 	int error = 0, unit = 0;
    626       1.1  christos 	SPL_INT(s);
    627       1.1  christos 
    628       1.1  christos #if (__NetBSD_Version__ >= 399002000)
    629       1.1  christos 	if ((mode & FWRITE) &&
    630       1.1  christos 	    kauth_authorize_network(p->l_cred, KAUTH_NETWORK_FIREWALL,
    631       1.1  christos 				    KAUTH_REQ_NETWORK_FIREWALL_FW, NULL,
    632       1.1  christos 				    NULL, NULL)) {
    633       1.1  christos 		ipfmain.ipf_interror = 130005;
    634       1.1  christos 		return EPERM;
    635       1.1  christos 	}
    636       1.1  christos #else
    637       1.1  christos 	if ((securelevel >= 2) && (mode & FWRITE)) {
    638       1.1  christos 		ipfmain.ipf_interror = 130001;
    639       1.1  christos 		return EPERM;
    640       1.1  christos 	}
    641       1.1  christos #endif
    642       1.1  christos 
    643       1.1  christos   	unit = GET_MINOR(dev);
    644       1.1  christos   	if ((IPL_LOGMAX < unit) || (unit < 0)) {
    645       1.1  christos 		ipfmain.ipf_interror = 130002;
    646       1.1  christos 		return ENXIO;
    647       1.1  christos 	}
    648       1.1  christos 
    649       1.1  christos 	if (ipfmain.ipf_running <= 0) {
    650       1.2  christos 		if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) {
    651       1.1  christos 			ipfmain.ipf_interror = 130003;
    652       1.1  christos 			return EIO;
    653       1.1  christos 		}
    654       1.1  christos 		if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET &&
    655       1.1  christos 		    cmd != SIOCIPFSET && cmd != SIOCFRENB &&
    656       1.1  christos 		    cmd != SIOCGETFS && cmd != SIOCGETFF &&
    657       1.1  christos 		    cmd != SIOCIPFINTERROR) {
    658       1.1  christos 			ipfmain.ipf_interror = 130004;
    659       1.1  christos 			return EIO;
    660       1.1  christos 		}
    661       1.1  christos 	}
    662       1.1  christos 
    663       1.1  christos 	SPL_NET(s);
    664       1.1  christos 
    665       1.1  christos 	error = ipf_ioctlswitch(&ipfmain, unit, data, cmd, mode, UID(p), p);
    666       1.1  christos 	if (error != -1) {
    667       1.1  christos 		SPL_X(s);
    668       1.1  christos 		return error;
    669       1.1  christos 	}
    670       1.1  christos 
    671       1.1  christos 	SPL_X(s);
    672       1.1  christos 	return error;
    673       1.1  christos }
    674       1.1  christos 
    675       1.1  christos 
    676       1.1  christos /*
    677       1.1  christos  * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that
    678       1.1  christos  * requires a large amount of setting up and isn't any more efficient.
    679       1.1  christos  */
    680       1.1  christos int
    681       1.2  christos ipf_send_reset(fr_info_t *fin)
    682       1.1  christos {
    683       1.1  christos 	struct tcphdr *tcp, *tcp2;
    684       1.1  christos 	int tlen = 0, hlen;
    685       1.1  christos 	struct mbuf *m;
    686       1.1  christos #ifdef USE_INET6
    687       1.1  christos 	ip6_t *ip6;
    688       1.1  christos #endif
    689       1.1  christos 	ip_t *ip;
    690       1.1  christos 
    691       1.1  christos 	tcp = fin->fin_dp;
    692       1.1  christos 	if (tcp->th_flags & TH_RST)
    693       1.1  christos 		return -1;		/* feedback loop */
    694       1.1  christos 
    695       1.1  christos 	if (ipf_checkl4sum(fin) == -1)
    696       1.1  christos 		return -1;
    697       1.1  christos 
    698       1.1  christos 	tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
    699       1.1  christos 			((tcp->th_flags & TH_SYN) ? 1 : 0) +
    700       1.1  christos 			((tcp->th_flags & TH_FIN) ? 1 : 0);
    701       1.1  christos 
    702       1.1  christos #ifdef USE_INET6
    703       1.1  christos 	hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t);
    704       1.1  christos #else
    705       1.1  christos 	hlen = sizeof(ip_t);
    706       1.1  christos #endif
    707       1.1  christos #ifdef MGETHDR
    708       1.1  christos 	MGETHDR(m, M_DONTWAIT, MT_HEADER);
    709       1.1  christos #else
    710       1.1  christos 	MGET(m, M_DONTWAIT, MT_HEADER);
    711       1.1  christos #endif
    712       1.1  christos 	if (m == NULL)
    713       1.1  christos 		return -1;
    714       1.1  christos 	if (sizeof(*tcp2) + hlen > MHLEN) {
    715       1.1  christos 		MCLGET(m, M_DONTWAIT);
    716       1.1  christos 		if (m == NULL)
    717       1.1  christos 			return -1;
    718       1.1  christos 		if ((m->m_flags & M_EXT) == 0) {
    719       1.1  christos 			FREE_MB_T(m);
    720       1.1  christos 			return -1;
    721       1.1  christos 		}
    722       1.1  christos 	}
    723       1.1  christos 
    724       1.1  christos 	m->m_len = sizeof(*tcp2) + hlen;
    725       1.1  christos 	m->m_data += max_linkhdr;
    726       1.1  christos 	m->m_pkthdr.len = m->m_len;
    727       1.1  christos 	m->m_pkthdr.rcvif = (struct ifnet *)0;
    728       1.1  christos 	ip = mtod(m, struct ip *);
    729       1.1  christos 	bzero((char *)ip, hlen);
    730       1.1  christos #ifdef USE_INET6
    731       1.1  christos 	ip6 = (ip6_t *)ip;
    732       1.1  christos #endif
    733       1.1  christos 	bzero((char *)ip, sizeof(*tcp2) + hlen);
    734       1.1  christos 	tcp2 = (struct tcphdr *)((char *)ip + hlen);
    735       1.1  christos 	tcp2->th_sport = tcp->th_dport;
    736       1.1  christos 	tcp2->th_dport = tcp->th_sport;
    737       1.1  christos 
    738       1.1  christos 	if (tcp->th_flags & TH_ACK) {
    739       1.1  christos 		tcp2->th_seq = tcp->th_ack;
    740       1.1  christos 		tcp2->th_flags = TH_RST;
    741       1.1  christos 		tcp2->th_ack = 0;
    742       1.1  christos 	} else {
    743       1.1  christos 		tcp2->th_seq = 0;
    744       1.1  christos 		tcp2->th_ack = ntohl(tcp->th_seq);
    745       1.1  christos 		tcp2->th_ack += tlen;
    746       1.1  christos 		tcp2->th_ack = htonl(tcp2->th_ack);
    747       1.1  christos 		tcp2->th_flags = TH_RST|TH_ACK;
    748       1.1  christos 	}
    749       1.1  christos 	tcp2->th_x2 = 0;
    750       1.1  christos 	TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2);
    751       1.1  christos 	tcp2->th_win = tcp->th_win;
    752       1.1  christos 	tcp2->th_sum = 0;
    753       1.1  christos 	tcp2->th_urp = 0;
    754       1.1  christos 
    755       1.1  christos #ifdef USE_INET6
    756       1.1  christos 	if (fin->fin_v == 6) {
    757       1.1  christos 		ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
    758       1.1  christos 		ip6->ip6_plen = htons(sizeof(struct tcphdr));
    759       1.1  christos 		ip6->ip6_nxt = IPPROTO_TCP;
    760       1.1  christos 		ip6->ip6_hlim = 0;
    761       1.1  christos 		ip6->ip6_src = fin->fin_dst6.in6;
    762       1.1  christos 		ip6->ip6_dst = fin->fin_src6.in6;
    763       1.1  christos 		tcp2->th_sum = in6_cksum(m, IPPROTO_TCP,
    764       1.1  christos 					 sizeof(*ip6), sizeof(*tcp2));
    765       1.1  christos 		return ipf_send_ip(fin, m);
    766       1.1  christos 	}
    767       1.1  christos #endif
    768       1.1  christos #ifdef INET
    769       1.1  christos 	ip->ip_p = IPPROTO_TCP;
    770       1.1  christos 	ip->ip_len = htons(sizeof(struct tcphdr));
    771       1.1  christos 	ip->ip_src.s_addr = fin->fin_daddr;
    772       1.1  christos 	ip->ip_dst.s_addr = fin->fin_saddr;
    773       1.1  christos 	tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2));
    774       1.1  christos 	ip->ip_len = hlen + sizeof(*tcp2);
    775       1.1  christos 	return ipf_send_ip(fin, m);
    776       1.1  christos #else
    777       1.1  christos 	return 0;
    778       1.1  christos #endif
    779       1.1  christos }
    780       1.1  christos 
    781       1.1  christos 
    782       1.1  christos /*
    783       1.1  christos  * Expects ip_len to be in host byte order when called.
    784       1.1  christos  */
    785       1.1  christos static int
    786       1.2  christos ipf_send_ip(fr_info_t *fin, mb_t *m)
    787       1.1  christos {
    788       1.1  christos 	fr_info_t fnew;
    789       1.1  christos #ifdef INET
    790       1.1  christos 	ip_t *oip;
    791       1.1  christos #endif
    792       1.1  christos 	ip_t *ip;
    793       1.1  christos 	int hlen;
    794       1.1  christos 
    795       1.1  christos 	ip = mtod(m, ip_t *);
    796       1.1  christos 	bzero((char *)&fnew, sizeof(fnew));
    797       1.1  christos 	fnew.fin_main_soft = fin->fin_main_soft;
    798       1.1  christos 
    799       1.1  christos 	IP_V_A(ip, fin->fin_v);
    800       1.1  christos 	switch (fin->fin_v)
    801       1.1  christos 	{
    802       1.1  christos #ifdef INET
    803       1.1  christos 	case 4 :
    804       1.1  christos 		oip = fin->fin_ip;
    805       1.1  christos 		hlen = sizeof(*oip);
    806       1.1  christos 		fnew.fin_v = 4;
    807       1.1  christos 		fnew.fin_p = ip->ip_p;
    808       1.1  christos 		fnew.fin_plen = ntohs(ip->ip_len);
    809       1.1  christos 		HTONS(ip->ip_len);
    810       1.1  christos 		IP_HL_A(ip, sizeof(*oip) >> 2);
    811       1.1  christos 		ip->ip_tos = oip->ip_tos;
    812       1.1  christos 		ip->ip_id = ipf_nextipid(fin);
    813       1.1  christos 		ip->ip_off = htons(ip_mtudisc ? IP_DF : 0);
    814       1.1  christos 		ip->ip_ttl = ip_defttl;
    815       1.1  christos 		ip->ip_sum = 0;
    816       1.1  christos 		break;
    817       1.1  christos #endif
    818       1.1  christos #ifdef USE_INET6
    819       1.1  christos 	case 6 :
    820       1.1  christos 	{
    821       1.1  christos 		ip6_t *ip6 = (ip6_t *)ip;
    822       1.1  christos 
    823       1.1  christos 		ip6->ip6_vfc = 0x60;
    824       1.1  christos 		ip6->ip6_hlim = IPDEFTTL;
    825       1.1  christos 
    826       1.1  christos 		hlen = sizeof(*ip6);
    827       1.1  christos 		fnew.fin_p = ip6->ip6_nxt;
    828       1.1  christos 		fnew.fin_v = 6;
    829       1.1  christos 		fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen;
    830       1.1  christos 		break;
    831       1.1  christos 	}
    832       1.1  christos #endif
    833       1.1  christos 	default :
    834       1.1  christos 		return EINVAL;
    835       1.1  christos 	}
    836       1.2  christos #ifdef KAME_IPSEC
    837       1.1  christos 	m->m_pkthdr.rcvif = NULL;
    838       1.1  christos #endif
    839       1.1  christos 
    840       1.1  christos 	fnew.fin_ifp = fin->fin_ifp;
    841       1.1  christos 	fnew.fin_flx = FI_NOCKSUM;
    842       1.1  christos 	fnew.fin_m = m;
    843       1.1  christos 	fnew.fin_ip = ip;
    844       1.1  christos 	fnew.fin_mp = &m;
    845       1.1  christos 	fnew.fin_hlen = hlen;
    846       1.1  christos 	fnew.fin_dp = (char *)ip + hlen;
    847       1.1  christos 	(void) ipf_makefrip(hlen, ip, &fnew);
    848       1.1  christos 
    849       1.1  christos 	return ipf_fastroute(m, &m, &fnew, NULL);
    850       1.1  christos }
    851       1.1  christos 
    852       1.1  christos 
    853       1.1  christos int
    854       1.2  christos ipf_send_icmp_err(int type, fr_info_t *fin, int dst)
    855       1.1  christos {
    856       1.7       mrg 	int err, hlen, xtra, iclen, ohlen, avail;
    857       1.1  christos 	struct in_addr dst4;
    858       1.1  christos 	struct icmp *icmp;
    859       1.1  christos 	struct mbuf *m;
    860       1.1  christos 	i6addr_t dst6;
    861       1.1  christos 	void *ifp;
    862       1.1  christos #ifdef USE_INET6
    863       1.7       mrg 	int code;
    864       1.1  christos 	ip6_t *ip6;
    865       1.1  christos #endif
    866       1.1  christos 	ip_t *ip, *ip2;
    867       1.1  christos 
    868       1.1  christos 	if ((type < 0) || (type > ICMP_MAXTYPE))
    869       1.1  christos 		return -1;
    870       1.1  christos 
    871       1.7       mrg #ifdef USE_INET6
    872       1.1  christos 	code = fin->fin_icode;
    873       1.4   msaitoh 	if ((code < 0) || (code >= sizeof(icmptoicmp6unreach)/sizeof(int)))
    874       1.1  christos 		return -1;
    875       1.1  christos #endif
    876       1.1  christos 
    877       1.1  christos 	if (ipf_checkl4sum(fin) == -1)
    878       1.1  christos 		return -1;
    879       1.1  christos #ifdef MGETHDR
    880       1.1  christos 	MGETHDR(m, M_DONTWAIT, MT_HEADER);
    881       1.1  christos #else
    882       1.1  christos 	MGET(m, M_DONTWAIT, MT_HEADER);
    883       1.1  christos #endif
    884       1.1  christos 	if (m == NULL)
    885       1.1  christos 		return -1;
    886       1.1  christos 	avail = MHLEN;
    887       1.1  christos 
    888       1.1  christos 	xtra = 0;
    889       1.1  christos 	hlen = 0;
    890       1.1  christos 	ohlen = 0;
    891       1.1  christos 	dst4.s_addr = 0;
    892       1.1  christos 	ifp = fin->fin_ifp;
    893       1.1  christos 	if (fin->fin_v == 4) {
    894       1.1  christos 		if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT))
    895       1.1  christos 			switch (ntohs(fin->fin_data[0]) >> 8)
    896       1.1  christos 			{
    897       1.1  christos 			case ICMP_ECHO :
    898       1.1  christos 			case ICMP_TSTAMP :
    899       1.1  christos 			case ICMP_IREQ :
    900       1.1  christos 			case ICMP_MASKREQ :
    901       1.1  christos 				break;
    902       1.1  christos 			default :
    903       1.1  christos 				FREE_MB_T(m);
    904       1.1  christos 				return 0;
    905       1.1  christos 			}
    906       1.1  christos 
    907       1.1  christos 		if (dst == 0) {
    908       1.1  christos 			if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, ifp,
    909       1.1  christos 				       &dst6, NULL) == -1) {
    910       1.1  christos 				FREE_MB_T(m);
    911       1.1  christos 				return -1;
    912       1.1  christos 			}
    913       1.1  christos 			dst4 = dst6.in4;
    914       1.1  christos 		} else
    915       1.1  christos 			dst4.s_addr = fin->fin_daddr;
    916       1.1  christos 
    917       1.1  christos 		hlen = sizeof(ip_t);
    918       1.1  christos 		ohlen = fin->fin_hlen;
    919       1.1  christos 		iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen;
    920       1.1  christos 		if (fin->fin_hlen < fin->fin_plen)
    921       1.1  christos 			xtra = MIN(fin->fin_dlen, 8);
    922       1.1  christos 		else
    923       1.1  christos 			xtra = 0;
    924       1.1  christos 	}
    925       1.1  christos 
    926       1.1  christos #ifdef USE_INET6
    927       1.1  christos 	else if (fin->fin_v == 6) {
    928       1.1  christos 		hlen = sizeof(ip6_t);
    929       1.1  christos 		ohlen = sizeof(ip6_t);
    930       1.1  christos 		iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen;
    931       1.1  christos 		type = icmptoicmp6types[type];
    932       1.1  christos 		if (type == ICMP6_DST_UNREACH)
    933       1.1  christos 			code = icmptoicmp6unreach[code];
    934       1.1  christos 
    935       1.1  christos 		if (iclen + max_linkhdr + fin->fin_plen > avail) {
    936       1.1  christos 			MCLGET(m, M_DONTWAIT);
    937       1.1  christos 			if (m == NULL)
    938       1.1  christos 				return -1;
    939       1.1  christos 			if ((m->m_flags & M_EXT) == 0) {
    940       1.1  christos 				FREE_MB_T(m);
    941       1.1  christos 				return -1;
    942       1.1  christos 			}
    943       1.1  christos 			avail = MCLBYTES;
    944       1.1  christos 		}
    945       1.1  christos 		xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr);
    946       1.1  christos 		xtra = MIN(xtra, IPV6_MMTU - iclen);
    947       1.1  christos 		if (dst == 0) {
    948       1.1  christos 			if (ipf_ifpaddr(&ipfmain, 6, FRI_NORMAL, ifp,
    949       1.1  christos 				       &dst6, NULL) == -1) {
    950       1.1  christos 				FREE_MB_T(m);
    951       1.1  christos 				return -1;
    952       1.1  christos 			}
    953       1.1  christos 		} else
    954       1.1  christos 			dst6 = fin->fin_dst6;
    955       1.1  christos 	}
    956       1.1  christos #endif
    957       1.1  christos 	else {
    958       1.1  christos 		FREE_MB_T(m);
    959       1.1  christos 		return -1;
    960       1.1  christos 	}
    961       1.1  christos 
    962       1.1  christos 	avail -= (max_linkhdr + iclen);
    963       1.1  christos 	if (avail < 0) {
    964       1.1  christos 		FREE_MB_T(m);
    965       1.1  christos 		return -1;
    966       1.1  christos 	}
    967       1.1  christos 	if (xtra > avail)
    968       1.1  christos 		xtra = avail;
    969       1.1  christos 	iclen += xtra;
    970       1.1  christos 	m->m_data += max_linkhdr;
    971       1.1  christos 	m->m_pkthdr.rcvif = (struct ifnet *)0;
    972       1.1  christos 	m->m_pkthdr.len = iclen;
    973       1.1  christos 	m->m_len = iclen;
    974       1.1  christos 	ip = mtod(m, ip_t *);
    975       1.1  christos 	icmp = (struct icmp *)((char *)ip + hlen);
    976       1.1  christos 	ip2 = (ip_t *)&icmp->icmp_ip;
    977       1.1  christos 
    978       1.1  christos 	icmp->icmp_type = type;
    979       1.1  christos 	icmp->icmp_code = fin->fin_icode;
    980       1.1  christos 	icmp->icmp_cksum = 0;
    981       1.1  christos #ifdef icmp_nextmtu
    982       1.1  christos 	if (type == ICMP_UNREACH && fin->fin_icode == ICMP_UNREACH_NEEDFRAG) {
    983       1.1  christos 		if (fin->fin_mtu != 0) {
    984       1.1  christos 			icmp->icmp_nextmtu = htons(fin->fin_mtu);
    985       1.1  christos 
    986       1.1  christos 		} else if (ifp != NULL) {
    987       1.1  christos 			icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp));
    988       1.1  christos 
    989       1.1  christos 		} else {	/* make up a number... */
    990       1.1  christos 			icmp->icmp_nextmtu = htons(fin->fin_plen - 20);
    991       1.1  christos 		}
    992       1.1  christos 	}
    993       1.1  christos #endif
    994       1.1  christos 
    995       1.1  christos 	bcopy((char *)fin->fin_ip, (char *)ip2, ohlen);
    996       1.1  christos 
    997       1.1  christos #if defined(M_CSUM_IPv4)
    998       1.1  christos 	/*
    999       1.1  christos 	 * Clear any in-bound checksum flags for this packet.
   1000       1.1  christos 	 */
   1001       1.1  christos 	m->m_pkthdr.csuminfo = 0;
   1002       1.1  christos #endif /* __NetBSD__ && M_CSUM_IPv4 */
   1003       1.1  christos 
   1004       1.1  christos #ifdef USE_INET6
   1005       1.1  christos 	ip6 = (ip6_t *)ip;
   1006       1.1  christos 	if (fin->fin_v == 6) {
   1007       1.1  christos 		ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
   1008       1.1  christos 		ip6->ip6_plen = htons(iclen - hlen);
   1009       1.1  christos 		ip6->ip6_nxt = IPPROTO_ICMPV6;
   1010       1.1  christos 		ip6->ip6_hlim = 0;
   1011       1.1  christos 		ip6->ip6_src = dst6.in6;
   1012       1.1  christos 		ip6->ip6_dst = fin->fin_src6.in6;
   1013       1.1  christos 		if (xtra > 0)
   1014       1.1  christos 			bcopy((char *)fin->fin_ip + ohlen,
   1015       1.1  christos 			      (char *)&icmp->icmp_ip + ohlen, xtra);
   1016       1.1  christos 		icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6,
   1017       1.1  christos 					     sizeof(*ip6), iclen - hlen);
   1018       1.1  christos 	} else
   1019       1.1  christos #endif
   1020       1.1  christos 	{
   1021       1.1  christos 		ip->ip_p = IPPROTO_ICMP;
   1022       1.1  christos 		ip->ip_src.s_addr = dst4.s_addr;
   1023       1.1  christos 		ip->ip_dst.s_addr = fin->fin_saddr;
   1024       1.1  christos 
   1025       1.1  christos 		if (xtra > 0)
   1026       1.1  christos 			bcopy((char *)fin->fin_ip + ohlen,
   1027       1.1  christos 			      (char *)&icmp->icmp_ip + ohlen, xtra);
   1028       1.1  christos 		icmp->icmp_cksum = ipf_cksum((u_short *)icmp,
   1029       1.1  christos 					     sizeof(*icmp) + 8);
   1030       1.1  christos 		ip->ip_len = iclen;
   1031       1.1  christos 		ip->ip_p = IPPROTO_ICMP;
   1032       1.1  christos 	}
   1033       1.1  christos 	err = ipf_send_ip(fin, m);
   1034       1.1  christos 	return err;
   1035       1.1  christos }
   1036       1.1  christos 
   1037       1.1  christos 
   1038       1.1  christos /*
   1039       1.1  christos  * m0 - pointer to mbuf where the IP packet starts
   1040       1.1  christos  * mpp - pointer to the mbuf pointer that is the start of the mbuf chain
   1041       1.1  christos  */
   1042       1.1  christos int
   1043       1.2  christos ipf_fastroute(mb_t *m0, mb_t **mpp, fr_info_t *fin, frdest_t *fdp)
   1044       1.1  christos {
   1045       1.1  christos 	register struct ip *ip, *mhip;
   1046       1.1  christos 	register struct mbuf *m = *mpp;
   1047       1.1  christos 	register struct route *ro;
   1048       1.1  christos 	int len, off, error = 0, hlen, code;
   1049       1.1  christos 	struct ifnet *ifp, *sifp;
   1050       1.1  christos 	ipf_main_softc_t *softc;
   1051       1.1  christos #if __NetBSD_Version__ >= 499001100
   1052       1.1  christos 	union {
   1053       1.1  christos 		struct sockaddr         dst;
   1054       1.1  christos 		struct sockaddr_in      dst4;
   1055       1.1  christos 	} u;
   1056       1.1  christos #else
   1057       1.1  christos 	struct sockaddr_in *dst4;
   1058       1.1  christos #endif
   1059       1.1  christos 	struct sockaddr *dst;
   1060       1.1  christos 	u_short ip_off, ip_len;
   1061       1.1  christos 	struct route iproute;
   1062       1.1  christos 	struct rtentry *rt;
   1063       1.1  christos 	frdest_t node;
   1064       1.1  christos 	frentry_t *fr;
   1065       1.1  christos 
   1066       1.1  christos 	if (fin->fin_v == 6) {
   1067       1.1  christos #ifdef USE_INET6
   1068       1.1  christos 		error = ipf_fastroute6(m0, mpp, fin, fdp);
   1069       1.1  christos #else
   1070       1.1  christos 		error = EPROTONOSUPPORT;
   1071       1.1  christos #endif
   1072       1.1  christos 		if ((error != 0) && (*mpp != NULL))
   1073       1.1  christos 			FREE_MB_T(*mpp);
   1074       1.1  christos 		return error;
   1075       1.1  christos 	}
   1076       1.1  christos #ifndef INET
   1077       1.1  christos 	FREE_MB_T(*mpp);
   1078       1.1  christos 	return EPROTONOSUPPORT;
   1079       1.1  christos #else
   1080       1.1  christos 
   1081       1.1  christos 	hlen = fin->fin_hlen;
   1082       1.1  christos 	ip = mtod(m0, struct ip *);
   1083       1.1  christos 	softc = fin->fin_main_soft;
   1084       1.1  christos 	rt = NULL;
   1085       1.1  christos 	ifp = NULL;
   1086       1.1  christos 
   1087       1.1  christos # if defined(M_CSUM_IPv4)
   1088       1.1  christos 	/*
   1089       1.1  christos 	 * Clear any in-bound checksum flags for this packet.
   1090       1.1  christos 	 */
   1091       1.1  christos 	m0->m_pkthdr.csuminfo = 0;
   1092       1.1  christos # endif /* __NetBSD__ && M_CSUM_IPv4 */
   1093       1.1  christos 
   1094       1.1  christos 	/*
   1095       1.1  christos 	 * Route packet.
   1096       1.1  christos 	 */
   1097       1.1  christos 	ro = &iproute;
   1098       1.2  christos 	memset(ro, 0, sizeof(*ro));
   1099       1.1  christos 	fr = fin->fin_fr;
   1100       1.1  christos 
   1101       1.1  christos 	if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) &&
   1102       1.1  christos 	    (fdp->fd_type == FRD_DSTLIST)) {
   1103       1.1  christos 		if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0)
   1104       1.1  christos 			fdp = &node;
   1105       1.1  christos 	}
   1106       1.1  christos 	if (fdp != NULL)
   1107       1.1  christos 		ifp = fdp->fd_ptr;
   1108       1.1  christos 	else
   1109       1.1  christos 		ifp = fin->fin_ifp;
   1110       1.1  christos 
   1111       1.1  christos 	if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) {
   1112       1.1  christos 		error = -2;
   1113       1.1  christos 		goto bad;
   1114       1.1  christos 	}
   1115       1.1  christos 
   1116       1.1  christos # if __NetBSD_Version__ >= 499001100
   1117       1.1  christos 	if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0))
   1118       1.1  christos 		sockaddr_in_init(&u.dst4, &fdp->fd_ip, 0);
   1119       1.1  christos 	else
   1120       1.1  christos 		sockaddr_in_init(&u.dst4, &ip->ip_dst, 0);
   1121       1.1  christos 	dst = &u.dst;
   1122       1.1  christos 	rtcache_setdst(ro, dst);
   1123       1.1  christos 	rt = rtcache_init(ro);
   1124       1.1  christos # else
   1125       1.1  christos 	dst4 = (struct sockaddr_in *)&ro->ro_dst;
   1126       1.1  christos 	dst = (struct sockaddr *)dst4;
   1127       1.1  christos 	dst4->sin_family = AF_INET;
   1128       1.1  christos 	dst4->sin_addr = ip->ip_dst;
   1129       1.1  christos 
   1130       1.1  christos 	if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0))
   1131       1.1  christos 		dst4->sin_addr = fdp->fd_ip;
   1132       1.1  christos 
   1133       1.1  christos 	dst4->sin_len = sizeof(*dst);
   1134       1.1  christos 	rtalloc(ro);
   1135       1.1  christos 	rt = ro->ro_rt;
   1136       1.1  christos # endif
   1137       1.1  christos 	if ((ifp == NULL) && (rt != NULL))
   1138       1.1  christos 		ifp = rt->rt_ifp;
   1139       1.1  christos 	if ((rt == NULL) || (ifp == NULL)) {
   1140       1.2  christos #ifdef INET
   1141       1.1  christos 		if (in_localaddr(ip->ip_dst))
   1142       1.1  christos 			error = EHOSTUNREACH;
   1143       1.1  christos 		else
   1144       1.2  christos #endif
   1145       1.1  christos 			error = ENETUNREACH;
   1146       1.1  christos 		goto bad;
   1147       1.1  christos 	}
   1148       1.1  christos 
   1149       1.1  christos 
   1150       1.1  christos 	if (rt->rt_flags & RTF_GATEWAY)
   1151       1.1  christos 		dst = rt->rt_gateway;
   1152       1.1  christos 
   1153       1.1  christos 	rt->rt_use++;
   1154       1.1  christos 
   1155       1.1  christos 	/*
   1156       1.1  christos 	 * For input packets which are being "fastrouted", they won't
   1157       1.1  christos 	 * go back through output filtering and miss their chance to get
   1158       1.1  christos 	 * NAT'd and counted.  Duplicated packets aren't considered to be
   1159       1.1  christos 	 * part of the normal packet stream, so do not NAT them or pass
   1160       1.1  christos 	 * them through stateful checking, etc.
   1161       1.1  christos 	 */
   1162       1.1  christos 	if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) {
   1163       1.1  christos 		sifp = fin->fin_ifp;
   1164       1.1  christos 		fin->fin_ifp = ifp;
   1165       1.1  christos 		fin->fin_out = 1;
   1166       1.1  christos 		(void) ipf_acctpkt(fin, NULL);
   1167       1.1  christos 		fin->fin_fr = NULL;
   1168       1.1  christos 		if (!fr || !(fr->fr_flags & FR_RETMASK)) {
   1169       1.1  christos 			u_32_t pass;
   1170       1.1  christos 
   1171       1.1  christos 			(void) ipf_state_check(fin, &pass);
   1172       1.1  christos 		}
   1173       1.1  christos 
   1174       1.1  christos 		switch (ipf_nat_checkout(fin, NULL))
   1175       1.1  christos 		{
   1176       1.1  christos 		case 0 :
   1177       1.1  christos 			break;
   1178       1.1  christos 		case 1 :
   1179       1.1  christos 			ip->ip_sum = 0;
   1180       1.1  christos 			break;
   1181       1.1  christos 		case -1 :
   1182       1.1  christos 			error = -1;
   1183       1.1  christos 			goto bad;
   1184       1.1  christos 			break;
   1185       1.1  christos 		}
   1186       1.1  christos 
   1187       1.1  christos 		fin->fin_ifp = sifp;
   1188       1.1  christos 		fin->fin_out = 0;
   1189       1.1  christos 	} else
   1190       1.1  christos 		ip->ip_sum = 0;
   1191       1.1  christos 	/*
   1192       1.1  christos 	 * If small enough for interface, can just send directly.
   1193       1.1  christos 	 */
   1194       1.1  christos 	m->m_pkthdr.rcvif = ifp;
   1195       1.1  christos 
   1196       1.1  christos 	ip_len = ntohs(ip->ip_len);
   1197       1.1  christos 	if (ip_len <= ifp->if_mtu) {
   1198       1.1  christos # if defined(M_CSUM_IPv4)
   1199       1.1  christos #  if (__NetBSD_Version__ >= 105009999)
   1200       1.1  christos 		if (ifp->if_csum_flags_tx & M_CSUM_IPv4)
   1201       1.1  christos 			m->m_pkthdr.csuminfo |= M_CSUM_IPv4;
   1202       1.1  christos #  else
   1203       1.1  christos 		if (ifp->if_capabilities & IFCAP_CSUM_IPv4)
   1204       1.1  christos 			m->m_pkthdr.csuminfo |= M_CSUM_IPv4;
   1205       1.1  christos #  endif /* (__NetBSD_Version__ >= 105009999) */
   1206       1.1  christos 		else if (ip->ip_sum == 0)
   1207       1.1  christos 			ip->ip_sum = in_cksum(m, hlen);
   1208       1.1  christos # else
   1209       1.1  christos 		if (!ip->ip_sum)
   1210       1.1  christos 			ip->ip_sum = in_cksum(m, hlen);
   1211       1.1  christos # endif /* M_CSUM_IPv4 */
   1212       1.1  christos 
   1213       1.9    bouyer 		KERNEL_LOCK(1, NULL);
   1214       1.1  christos 		error = (*ifp->if_output)(ifp, m, dst, rt);
   1215       1.9    bouyer 		KERNEL_UNLOCK_ONE(NULL);
   1216       1.1  christos 		goto done;
   1217       1.1  christos 	}
   1218       1.1  christos 
   1219       1.1  christos 	/*
   1220       1.1  christos 	 * Too large for interface; fragment if possible.
   1221       1.1  christos 	 * Must be able to put at least 8 bytes per fragment.
   1222       1.1  christos 	 */
   1223       1.1  christos 	ip_off = ntohs(ip->ip_off);
   1224       1.1  christos 	if (ip_off & IP_DF) {
   1225       1.1  christos 		error = EMSGSIZE;
   1226       1.1  christos 		goto bad;
   1227       1.1  christos 	}
   1228       1.1  christos 	len = (ifp->if_mtu - hlen) &~ 7;
   1229       1.1  christos 	if (len < 8) {
   1230       1.1  christos 		error = EMSGSIZE;
   1231       1.1  christos 		goto bad;
   1232       1.1  christos 	}
   1233       1.1  christos 
   1234       1.1  christos     {
   1235       1.1  christos 	int mhlen, firstlen = len;
   1236       1.1  christos 	struct mbuf **mnext = &m->m_act;
   1237       1.1  christos 
   1238       1.1  christos 	/*
   1239       1.1  christos 	 * Loop through length of segment after first fragment,
   1240       1.1  christos 	 * make new header and copy data of each part and link onto chain.
   1241       1.1  christos 	 */
   1242       1.1  christos 	m0 = m;
   1243       1.1  christos 	mhlen = sizeof (struct ip);
   1244       1.1  christos 	for (off = hlen + len; off < ip_len; off += len) {
   1245       1.1  christos # ifdef MGETHDR
   1246       1.1  christos 		MGETHDR(m, M_DONTWAIT, MT_HEADER);
   1247       1.1  christos # else
   1248       1.1  christos 		MGET(m, M_DONTWAIT, MT_HEADER);
   1249       1.1  christos # endif
   1250       1.1  christos 		if (m == 0) {
   1251       1.1  christos 			m = m0;
   1252       1.1  christos 			error = ENOBUFS;
   1253       1.1  christos 			goto bad;
   1254       1.1  christos 		}
   1255       1.1  christos 		m->m_data += max_linkhdr;
   1256       1.1  christos 		mhip = mtod(m, struct ip *);
   1257       1.1  christos 		bcopy((char *)ip, (char *)mhip, sizeof(*ip));
   1258       1.2  christos #ifdef INET
   1259       1.1  christos 		if (hlen > sizeof (struct ip)) {
   1260       1.1  christos 			mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
   1261       1.1  christos 			IP_HL_A(mhip, mhlen >> 2);
   1262       1.1  christos 		}
   1263       1.2  christos #endif
   1264       1.1  christos 		m->m_len = mhlen;
   1265       1.1  christos 		mhip->ip_off = ((off - hlen) >> 3) + ip_off;
   1266       1.1  christos 		if (off + len >= ip_len)
   1267       1.1  christos 			len = ip_len - off;
   1268       1.1  christos 		else
   1269       1.1  christos 			mhip->ip_off |= IP_MF;
   1270       1.1  christos 		mhip->ip_len = htons((u_short)(len + mhlen));
   1271       1.1  christos 		m->m_next = m_copy(m0, off, len);
   1272       1.1  christos 		if (m->m_next == 0) {
   1273       1.1  christos 			error = ENOBUFS;	/* ??? */
   1274       1.1  christos 			goto sendorfree;
   1275       1.1  christos 		}
   1276       1.1  christos 		m->m_pkthdr.len = mhlen + len;
   1277       1.1  christos 		m->m_pkthdr.rcvif = NULL;
   1278       1.1  christos 		mhip->ip_off = htons((u_short)mhip->ip_off);
   1279       1.1  christos 		mhip->ip_sum = 0;
   1280       1.2  christos #ifdef INET
   1281       1.1  christos 		mhip->ip_sum = in_cksum(m, mhlen);
   1282       1.2  christos #endif
   1283       1.1  christos 		*mnext = m;
   1284       1.1  christos 		mnext = &m->m_act;
   1285       1.1  christos 	}
   1286       1.1  christos 	/*
   1287       1.1  christos 	 * Update first fragment by trimming what's been copied out
   1288       1.1  christos 	 * and updating header, then send each fragment (in order).
   1289       1.1  christos 	 */
   1290       1.1  christos 	m_adj(m0, hlen + firstlen - ip_len);
   1291       1.1  christos 	ip->ip_len = htons((u_short)(hlen + firstlen));
   1292       1.1  christos 	ip->ip_off = htons((u_short)IP_MF);
   1293       1.1  christos 	ip->ip_sum = 0;
   1294       1.2  christos #ifdef INET
   1295       1.1  christos 	ip->ip_sum = in_cksum(m0, hlen);
   1296       1.2  christos #endif
   1297       1.1  christos sendorfree:
   1298       1.1  christos 	for (m = m0; m; m = m0) {
   1299       1.1  christos 		m0 = m->m_act;
   1300       1.1  christos 		m->m_act = 0;
   1301       1.1  christos 		if (error == 0) {
   1302       1.9    bouyer 			KERNEL_LOCK(1, NULL);
   1303       1.1  christos 			error = (*ifp->if_output)(ifp, m, dst, rt);
   1304       1.9    bouyer 			KERNEL_UNLOCK_ONE(NULL);
   1305       1.1  christos 		} else {
   1306       1.1  christos 			FREE_MB_T(m);
   1307       1.1  christos 		}
   1308       1.1  christos 	}
   1309       1.1  christos     }
   1310       1.1  christos done:
   1311       1.1  christos 	if (!error)
   1312       1.1  christos 		softc->ipf_frouteok[0]++;
   1313       1.1  christos 	else
   1314       1.1  christos 		softc->ipf_frouteok[1]++;
   1315       1.1  christos 
   1316       1.1  christos # if __NetBSD_Version__ >= 499001100
   1317       1.1  christos 	rtcache_free(ro);
   1318       1.1  christos # else
   1319       1.1  christos 	if (rt) {
   1320       1.1  christos 		RTFREE(rt);
   1321       1.1  christos 	}
   1322       1.1  christos # endif
   1323       1.1  christos 	return error;
   1324       1.1  christos bad:
   1325       1.1  christos 	if (error == EMSGSIZE) {
   1326       1.1  christos 		sifp = fin->fin_ifp;
   1327       1.1  christos 		code = fin->fin_icode;
   1328       1.1  christos 		fin->fin_icode = ICMP_UNREACH_NEEDFRAG;
   1329       1.1  christos 		fin->fin_ifp = ifp;
   1330       1.1  christos 		(void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1);
   1331       1.1  christos 		fin->fin_ifp = sifp;
   1332       1.1  christos 		fin->fin_icode = code;
   1333       1.1  christos 	}
   1334       1.1  christos 	FREE_MB_T(m);
   1335       1.1  christos 	goto done;
   1336       1.1  christos #endif /* INET */
   1337       1.1  christos }
   1338       1.1  christos 
   1339       1.1  christos 
   1340       1.1  christos #if defined(USE_INET6)
   1341       1.1  christos /*
   1342       1.1  christos  * This is the IPv6 specific fastroute code.  It doesn't clean up the mbuf's
   1343       1.1  christos  * or ensure that it is an IPv6 packet that is being forwarded, those are
   1344       1.1  christos  * expected to be done by the called (ipf_fastroute).
   1345       1.1  christos  */
   1346       1.1  christos static int
   1347       1.2  christos ipf_fastroute6(struct mbuf *m0, struct mbuf **mpp, fr_info_t *fin,
   1348       1.2  christos     frdest_t *fdp)
   1349       1.1  christos {
   1350       1.1  christos # if __NetBSD_Version__ >= 499001100
   1351       1.1  christos 	struct route ip6route;
   1352       1.1  christos 	const struct sockaddr *dst;
   1353       1.1  christos 	union {
   1354       1.1  christos 		struct sockaddr         dst;
   1355       1.1  christos 		struct sockaddr_in6     dst6;
   1356       1.1  christos 	} u;
   1357       1.1  christos 	struct route *ro;
   1358       1.1  christos # else
   1359       1.1  christos 	struct route_in6 ip6route;
   1360       1.1  christos 	struct sockaddr_in6 *dst6;
   1361       1.1  christos 	struct route_in6 *ro;
   1362       1.1  christos # endif
   1363       1.1  christos 	struct rtentry *rt;
   1364       1.1  christos 	struct ifnet *ifp;
   1365       1.1  christos 	u_long mtu;
   1366       1.1  christos 	int error;
   1367       1.1  christos 
   1368       1.1  christos 	error = 0;
   1369       1.1  christos 	ro = &ip6route;
   1370       1.1  christos 
   1371       1.1  christos 	if (fdp != NULL)
   1372       1.1  christos 		ifp = fdp->fd_ptr;
   1373       1.1  christos 	else
   1374       1.1  christos 		ifp = fin->fin_ifp;
   1375       1.2  christos 	memset(ro, 0, sizeof(*ro));
   1376       1.1  christos # if __NetBSD_Version__ >= 499001100
   1377       1.1  christos 	if (fdp != NULL && IP6_NOTZERO(&fdp->fd_ip6))
   1378       1.1  christos 		sockaddr_in6_init(&u.dst6, &fdp->fd_ip6.in6, 0, 0, 0);
   1379       1.1  christos 	else
   1380       1.1  christos 		sockaddr_in6_init(&u.dst6, &fin->fin_fi.fi_dst.in6, 0, 0, 0);
   1381       1.1  christos 	dst = &u.dst;
   1382       1.1  christos 	rtcache_setdst(ro, dst);
   1383       1.1  christos 
   1384       1.1  christos 	rt = rtcache_init(ro);
   1385       1.1  christos 	if ((ifp == NULL) && (rt != NULL))
   1386       1.1  christos 		ifp = rt->rt_ifp;
   1387       1.1  christos # else
   1388       1.1  christos 	dst6 = (struct sockaddr_in6 *)&ro->ro_dst;
   1389       1.1  christos 	dst6->sin6_family = AF_INET6;
   1390       1.1  christos 	dst6->sin6_len = sizeof(struct sockaddr_in6);
   1391       1.1  christos 	dst6->sin6_addr = fin->fin_fi.fi_dst.in6;
   1392       1.1  christos 
   1393       1.1  christos 	if (fdp != NULL) {
   1394       1.1  christos 		if (IP6_NOTZERO(&fdp->fd_ip6))
   1395       1.1  christos 			dst6->sin6_addr = fdp->fd_ip6.in6;
   1396       1.1  christos 	}
   1397       1.1  christos 
   1398       1.1  christos 	rtalloc((struct route *)ro);
   1399       1.1  christos 
   1400       1.1  christos 	if ((ifp == NULL) && (ro->ro_rt != NULL))
   1401       1.1  christos 		ifp = ro->ro_rt->rt_ifp;
   1402       1.1  christos 	rt = ro->ro_rt;
   1403       1.1  christos # endif
   1404       1.1  christos 	if ((rt == NULL) || (ifp == NULL)) {
   1405       1.1  christos 
   1406       1.1  christos 		error = EHOSTUNREACH;
   1407       1.1  christos 		goto bad;
   1408       1.1  christos 	}
   1409       1.1  christos 
   1410       1.1  christos 	/* KAME */
   1411       1.1  christos # if __NetBSD_Version__ >= 499001100
   1412       1.1  christos 	if (IN6_IS_ADDR_LINKLOCAL(&u.dst6.sin6_addr))
   1413       1.1  christos 		u.dst6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
   1414       1.1  christos # else
   1415       1.1  christos 	if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr))
   1416       1.1  christos 		dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
   1417       1.1  christos # endif
   1418       1.1  christos 
   1419       1.1  christos 	{
   1420       1.6    martin # if (__NetBSD_Version__ >= 106010000) && !defined(IN6_LINKMTU)
   1421       1.1  christos 		struct in6_ifextra *ife;
   1422       1.1  christos # endif
   1423       1.1  christos 		if (rt->rt_flags & RTF_GATEWAY)
   1424       1.1  christos # if __NetBSD_Version__ >= 499001100
   1425       1.1  christos 			dst = rt->rt_gateway;
   1426       1.1  christos # else
   1427       1.1  christos 			dst6 = (struct sockaddr_in6 *)rt->rt_gateway;
   1428       1.1  christos # endif
   1429       1.1  christos 		rt->rt_use++;
   1430       1.1  christos 
   1431       1.1  christos 		/* Determine path MTU. */
   1432       1.1  christos # if (__NetBSD_Version__ <= 106009999)
   1433       1.1  christos 		mtu = nd_ifinfo[ifp->if_index].linkmtu;
   1434       1.1  christos # else
   1435       1.1  christos #  ifdef IN6_LINKMTU
   1436       1.1  christos 		mtu = IN6_LINKMTU(ifp);
   1437       1.1  christos #  else
   1438       1.6    martin 		ife = (struct in6_ifextra *)(ifp)->if_afdata[AF_INET6];
   1439       1.1  christos 		mtu = ife->nd_ifinfo[ifp->if_index].linkmtu;
   1440       1.1  christos #  endif
   1441       1.1  christos # endif
   1442       1.1  christos 		if ((error == 0) && (m0->m_pkthdr.len <= mtu)) {
   1443       1.1  christos # if __NetBSD_Version__ >= 499001100
   1444       1.2  christos 			error = nd6_output(ifp, ifp, m0, satocsin6(dst), rt);
   1445       1.1  christos # else
   1446       1.2  christos 			error = nd6_output(ifp, ifp, m0, dst6, rt);
   1447       1.1  christos # endif
   1448       1.1  christos 		} else {
   1449       1.1  christos 			error = EMSGSIZE;
   1450       1.1  christos 		}
   1451       1.1  christos 	}
   1452       1.1  christos bad:
   1453       1.1  christos # if __NetBSD_Version__ >= 499001100
   1454       1.1  christos 	rtcache_free(ro);
   1455       1.1  christos # else
   1456       1.1  christos 	if (ro->ro_rt != NULL) {
   1457       1.1  christos 		RTFREE(((struct route *)ro)->ro_rt);
   1458       1.1  christos 	}
   1459       1.1  christos # endif
   1460       1.1  christos 	return error;
   1461       1.1  christos }
   1462       1.1  christos #endif	/* INET6 */
   1463       1.1  christos 
   1464       1.1  christos 
   1465       1.1  christos int
   1466       1.2  christos ipf_verifysrc(fr_info_t *fin)
   1467       1.1  christos {
   1468       1.1  christos #if __NetBSD_Version__ >= 499001100
   1469       1.1  christos 	union {
   1470       1.1  christos 		struct sockaddr         dst;
   1471       1.1  christos 		struct sockaddr_in      dst4;
   1472       1.1  christos 	} u;
   1473       1.1  christos 	struct rtentry *rt;
   1474       1.1  christos #else
   1475       1.1  christos 	struct sockaddr_in *dst;
   1476       1.1  christos #endif
   1477       1.1  christos 	struct route iproute;
   1478       1.1  christos 	int rc;
   1479       1.1  christos 
   1480       1.1  christos #if __NetBSD_Version__ >= 499001100
   1481       1.1  christos 	sockaddr_in_init(&u.dst4, &fin->fin_src, 0);
   1482       1.1  christos 	rtcache_setdst(&iproute, &u.dst);
   1483       1.1  christos 	rt = rtcache_init(&iproute);
   1484       1.1  christos 	if (rt == NULL)
   1485       1.1  christos 		rc = 0;
   1486       1.1  christos 	else
   1487       1.1  christos 		rc = (fin->fin_ifp == rt->rt_ifp);
   1488       1.1  christos 	rtcache_free(&iproute);
   1489       1.1  christos #else
   1490       1.1  christos 	dst = (struct sockaddr_in *)&iproute.ro_dst;
   1491       1.1  christos 	dst->sin_len = sizeof(*dst);
   1492       1.1  christos 	dst->sin_family = AF_INET;
   1493       1.1  christos 	dst->sin_addr = fin->fin_src;
   1494       1.1  christos 	rtalloc(&iproute);
   1495       1.1  christos 	if (iproute.ro_rt == NULL)
   1496       1.1  christos 		return 0;
   1497       1.1  christos 	rc = (fin->fin_ifp == iproute.ro_rt->rt_ifp);
   1498       1.1  christos 	RTFREE(iproute.ro_rt);
   1499       1.1  christos #endif
   1500       1.1  christos 	return rc;
   1501       1.1  christos }
   1502       1.1  christos 
   1503       1.1  christos 
   1504       1.1  christos /*
   1505       1.1  christos  * return the first IP Address associated with an interface
   1506       1.1  christos  */
   1507       1.1  christos int
   1508       1.2  christos ipf_ifpaddr(ipf_main_softc_t *softc, int v, int atype, void *ifptr,
   1509       1.2  christos     i6addr_t *inp, i6addr_t *inpmask)
   1510       1.1  christos {
   1511       1.1  christos #ifdef USE_INET6
   1512       1.1  christos 	struct in6_addr *inp6 = NULL;
   1513       1.1  christos #endif
   1514       1.1  christos 	struct sockaddr *sock, *mask;
   1515       1.1  christos 	struct sockaddr_in *sin;
   1516       1.1  christos 	struct ifaddr *ifa;
   1517       1.1  christos 	struct ifnet *ifp;
   1518       1.1  christos 
   1519       1.1  christos 	if ((ifptr == NULL) || (ifptr == (void *)-1))
   1520       1.1  christos 		return -1;
   1521       1.1  christos 
   1522       1.1  christos 	ifp = ifptr;
   1523       1.1  christos 	mask = NULL;
   1524       1.1  christos 
   1525       1.1  christos 	if (v == 4)
   1526       1.1  christos 		inp->in4.s_addr = 0;
   1527       1.1  christos #ifdef USE_INET6
   1528       1.1  christos 	else if (v == 6)
   1529       1.1  christos 		bzero((char *)inp, sizeof(*inp));
   1530       1.1  christos #endif
   1531       1.1  christos 
   1532       1.2  christos 	ifa = IFADDR_FIRST(ifp);
   1533       1.2  christos 	sock = ifa ? ifa->ifa_addr : NULL;
   1534       1.1  christos 	while (sock != NULL && ifa != NULL) {
   1535       1.1  christos 		sin = (struct sockaddr_in *)sock;
   1536       1.1  christos 		if ((v == 4) && (sin->sin_family == AF_INET))
   1537       1.1  christos 			break;
   1538       1.1  christos #ifdef USE_INET6
   1539       1.1  christos 		if ((v == 6) && (sin->sin_family == AF_INET6)) {
   1540       1.1  christos 			inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr;
   1541       1.1  christos 			if (!IN6_IS_ADDR_LINKLOCAL(inp6) &&
   1542       1.1  christos 			    !IN6_IS_ADDR_LOOPBACK(inp6))
   1543       1.1  christos 				break;
   1544       1.1  christos 		}
   1545       1.1  christos #endif
   1546       1.2  christos 		ifa = IFADDR_NEXT(ifa);
   1547       1.1  christos 		if (ifa != NULL)
   1548       1.1  christos 			sock = ifa->ifa_addr;
   1549       1.1  christos 	}
   1550       1.1  christos 	if (ifa == NULL || sock == NULL)
   1551       1.1  christos 		return -1;
   1552       1.1  christos 
   1553       1.1  christos 	mask = ifa->ifa_netmask;
   1554       1.1  christos 	if (atype == FRI_BROADCAST)
   1555       1.1  christos 		sock = ifa->ifa_broadaddr;
   1556       1.1  christos 	else if (atype == FRI_PEERADDR)
   1557       1.1  christos 		sock = ifa->ifa_dstaddr;
   1558       1.1  christos 
   1559       1.1  christos #ifdef USE_INET6
   1560       1.1  christos 	if (v == 6)
   1561       1.1  christos 		return ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock,
   1562       1.1  christos 					(struct sockaddr_in6 *)mask,
   1563       1.1  christos 					inp, inpmask);
   1564       1.1  christos #endif
   1565       1.1  christos 	return ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock,
   1566       1.1  christos 				(struct sockaddr_in *)mask,
   1567       1.1  christos 				&inp->in4, &inpmask->in4);
   1568       1.1  christos }
   1569       1.1  christos 
   1570       1.1  christos 
   1571       1.1  christos u_32_t
   1572       1.2  christos ipf_newisn(fr_info_t *fin)
   1573       1.1  christos {
   1574       1.1  christos #if __NetBSD_Version__ >= 105190000	/* 1.5T */
   1575       1.1  christos 	size_t asz;
   1576       1.1  christos 
   1577       1.1  christos 	if (fin->fin_v == 4)
   1578       1.1  christos 		asz = sizeof(struct in_addr);
   1579       1.1  christos 	else if (fin->fin_v == 6)
   1580       1.1  christos 		asz = sizeof(fin->fin_src);
   1581       1.1  christos 	else	/* XXX: no way to return error */
   1582       1.1  christos 		return 0;
   1583       1.2  christos #ifdef INET
   1584       1.1  christos 	return tcp_new_iss1((void *)&fin->fin_src, (void *)&fin->fin_dst,
   1585       1.1  christos 			    fin->fin_sport, fin->fin_dport, asz, 0);
   1586       1.1  christos #else
   1587       1.2  christos 	return ENOSYS;
   1588       1.2  christos #endif
   1589       1.2  christos #else
   1590       1.1  christos 	static int iss_seq_off = 0;
   1591       1.1  christos 	u_char hash[16];
   1592       1.1  christos 	u_32_t newiss;
   1593       1.1  christos 	MD5_CTX ctx;
   1594       1.1  christos 
   1595       1.1  christos 	/*
   1596       1.1  christos 	 * Compute the base value of the ISS.  It is a hash
   1597       1.1  christos 	 * of (saddr, sport, daddr, dport, secret).
   1598       1.1  christos 	 */
   1599       1.1  christos 	MD5Init(&ctx);
   1600       1.1  christos 
   1601       1.1  christos 	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
   1602       1.1  christos 		  sizeof(fin->fin_fi.fi_src));
   1603       1.1  christos 	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
   1604       1.1  christos 		  sizeof(fin->fin_fi.fi_dst));
   1605       1.1  christos 	MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
   1606       1.1  christos 
   1607       1.1  christos 	MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret));
   1608       1.1  christos 
   1609       1.1  christos 	MD5Final(hash, &ctx);
   1610       1.1  christos 
   1611       1.1  christos 	memcpy(&newiss, hash, sizeof(newiss));
   1612       1.1  christos 
   1613       1.1  christos 	/*
   1614       1.1  christos 	 * Now increment our "timer", and add it in to
   1615       1.1  christos 	 * the computed value.
   1616       1.1  christos 	 *
   1617       1.1  christos 	 * XXX Use `addin'?
   1618       1.1  christos 	 * XXX TCP_ISSINCR too large to use?
   1619       1.1  christos 	 */
   1620       1.1  christos 	iss_seq_off += 0x00010000;
   1621       1.1  christos 	newiss += iss_seq_off;
   1622       1.1  christos 	return newiss;
   1623       1.1  christos #endif
   1624       1.1  christos }
   1625       1.1  christos 
   1626       1.1  christos 
   1627       1.1  christos /* ------------------------------------------------------------------------ */
   1628       1.1  christos /* Function:    ipf_nextipid                                                 */
   1629       1.1  christos /* Returns:     int - 0 == success, -1 == error (packet should be droppped) */
   1630       1.1  christos /* Parameters:  fin(I) - pointer to packet information                      */
   1631       1.1  christos /*                                                                          */
   1632       1.1  christos /* Returns the next IPv4 ID to use for this packet.                         */
   1633       1.1  christos /* ------------------------------------------------------------------------ */
   1634       1.1  christos u_short
   1635       1.2  christos ipf_nextipid(fr_info_t *fin)
   1636       1.1  christos {
   1637       1.1  christos #ifdef USE_MUTEXES
   1638       1.1  christos 	ipf_main_softc_t *softc = fin->fin_main_soft;
   1639       1.1  christos #endif
   1640       1.1  christos 	u_short id;
   1641       1.1  christos 
   1642       1.1  christos 	MUTEX_ENTER(&softc->ipf_rw);
   1643       1.1  christos 	id = ipid++;
   1644       1.1  christos 	MUTEX_EXIT(&softc->ipf_rw);
   1645       1.1  christos 
   1646       1.1  christos 	return id;
   1647       1.1  christos }
   1648       1.1  christos 
   1649       1.1  christos 
   1650       1.2  christos EXTERN_INLINE int
   1651       1.2  christos ipf_checkv4sum(fr_info_t *fin)
   1652       1.1  christos {
   1653       1.1  christos #ifdef M_CSUM_TCP_UDP_BAD
   1654       1.1  christos 	int manual, pflag, cflags, active;
   1655       1.1  christos 	mb_t *m;
   1656       1.1  christos 
   1657       1.1  christos 	if ((fin->fin_flx & FI_NOCKSUM) != 0)
   1658       1.1  christos 		return 0;
   1659       1.1  christos 
   1660       1.1  christos 	if ((fin->fin_flx & FI_SHORT) != 0)
   1661       1.1  christos 		return 1;
   1662       1.1  christos 
   1663       1.3   darrenr 	if (fin->fin_cksum != FI_CK_NEEDED)
   1664       1.3   darrenr 		return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1;
   1665       1.1  christos 
   1666       1.1  christos 	manual = 0;
   1667       1.1  christos 	m = fin->fin_m;
   1668       1.1  christos 	if (m == NULL) {
   1669       1.1  christos 		manual = 1;
   1670       1.1  christos 		goto skipauto;
   1671       1.1  christos 	}
   1672       1.1  christos 
   1673       1.1  christos 	switch (fin->fin_p)
   1674       1.1  christos 	{
   1675       1.1  christos 	case IPPROTO_UDP :
   1676       1.1  christos 		pflag = M_CSUM_UDPv4;
   1677       1.1  christos 		break;
   1678       1.1  christos 	case IPPROTO_TCP :
   1679       1.1  christos 		pflag = M_CSUM_TCPv4;
   1680       1.1  christos 		break;
   1681       1.1  christos 	default :
   1682       1.1  christos 		pflag = 0;
   1683       1.1  christos 		manual = 1;
   1684       1.1  christos 		break;
   1685       1.1  christos 	}
   1686       1.1  christos 
   1687       1.1  christos 	active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag;
   1688       1.1  christos 	active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA;
   1689       1.1  christos 	cflags = m->m_pkthdr.csum_flags & active;
   1690       1.1  christos 
   1691       1.1  christos 	if (pflag != 0) {
   1692       1.1  christos 		if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) {
   1693       1.1  christos 			fin->fin_flx |= FI_BAD;
   1694       1.3   darrenr 			fin->fin_cksum = FI_CK_BAD;
   1695       1.1  christos 		} else if (cflags == (pflag | M_CSUM_DATA)) {
   1696       1.1  christos 			if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) {
   1697       1.1  christos 				fin->fin_flx |= FI_BAD;
   1698       1.3   darrenr 				fin->fin_cksum = FI_CK_BAD;
   1699       1.1  christos 			} else {
   1700       1.3   darrenr 				fin->fin_cksum = FI_CK_SUMOK;
   1701       1.1  christos 			}
   1702       1.1  christos 		} else if (cflags == pflag) {
   1703       1.3   darrenr 			fin->fin_cksum = FI_CK_SUMOK;
   1704       1.1  christos 		} else {
   1705       1.1  christos 			manual = 1;
   1706       1.1  christos 		}
   1707       1.1  christos 	}
   1708       1.1  christos skipauto:
   1709       1.1  christos 	if (manual != 0) {
   1710       1.1  christos 		if (ipf_checkl4sum(fin) == -1) {
   1711       1.1  christos 			fin->fin_flx |= FI_BAD;
   1712       1.1  christos 			return -1;
   1713       1.1  christos 		}
   1714       1.1  christos 	}
   1715       1.1  christos #else
   1716       1.1  christos 	if (ipf_checkl4sum(fin) == -1) {
   1717       1.1  christos 		fin->fin_flx |= FI_BAD;
   1718       1.1  christos 		return -1;
   1719       1.1  christos 	}
   1720       1.1  christos #endif
   1721       1.1  christos 	return 0;
   1722       1.1  christos }
   1723       1.1  christos 
   1724       1.1  christos 
   1725       1.1  christos #ifdef USE_INET6
   1726       1.2  christos EXTERN_INLINE int
   1727       1.2  christos ipf_checkv6sum(fr_info_t *fin)
   1728       1.1  christos {
   1729       1.1  christos # ifdef M_CSUM_TCP_UDP_BAD
   1730       1.1  christos 	int manual, pflag, cflags, active;
   1731       1.1  christos 	mb_t *m;
   1732       1.1  christos 
   1733       1.1  christos 	if ((fin->fin_flx & FI_NOCKSUM) != 0)
   1734       1.1  christos 		return 0;
   1735       1.1  christos 
   1736       1.1  christos 	if ((fin->fin_flx & FI_SHORT) != 0)
   1737       1.1  christos 		return 1;
   1738       1.1  christos 
   1739       1.3   darrenr 	if (fin->fin_cksum != FI_CK_SUMOK)
   1740       1.3   darrenr 		return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1;
   1741       1.1  christos 
   1742       1.1  christos 
   1743       1.1  christos 	manual = 0;
   1744       1.1  christos 	m = fin->fin_m;
   1745       1.1  christos 
   1746       1.1  christos 	switch (fin->fin_p)
   1747       1.1  christos 	{
   1748       1.1  christos 	case IPPROTO_UDP :
   1749       1.1  christos 		pflag = M_CSUM_UDPv6;
   1750       1.1  christos 		break;
   1751       1.1  christos 	case IPPROTO_TCP :
   1752       1.1  christos 		pflag = M_CSUM_TCPv6;
   1753       1.1  christos 		break;
   1754       1.1  christos 	default :
   1755       1.1  christos 		pflag = 0;
   1756       1.1  christos 		manual = 1;
   1757       1.1  christos 		break;
   1758       1.1  christos 	}
   1759       1.1  christos 
   1760       1.1  christos 	active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag;
   1761       1.1  christos 	active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA;
   1762       1.1  christos 	cflags = m->m_pkthdr.csum_flags & active;
   1763       1.1  christos 
   1764       1.1  christos 	if (pflag != 0) {
   1765       1.1  christos 		if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) {
   1766       1.1  christos 			fin->fin_flx |= FI_BAD;
   1767       1.1  christos 		} else if (cflags == (pflag | M_CSUM_DATA)) {
   1768       1.1  christos 			if ((m->m_pkthdr.csum_data ^ 0xffff) != 0)
   1769       1.1  christos 				fin->fin_flx |= FI_BAD;
   1770       1.1  christos 		} else if (cflags == pflag) {
   1771       1.1  christos 			;
   1772       1.1  christos 		} else {
   1773       1.1  christos 			manual = 1;
   1774       1.1  christos 		}
   1775       1.1  christos 	}
   1776       1.1  christos 	if (manual != 0) {
   1777       1.1  christos 		if (ipf_checkl4sum(fin) == -1) {
   1778       1.1  christos 			fin->fin_flx |= FI_BAD;
   1779       1.1  christos 			return -1;
   1780       1.1  christos 		}
   1781       1.1  christos 	}
   1782       1.1  christos # else
   1783       1.1  christos 	if (ipf_checkl4sum(fin) == -1) {
   1784       1.1  christos 		fin->fin_flx |= FI_BAD;
   1785       1.1  christos 		return -1;
   1786       1.1  christos 	}
   1787       1.1  christos # endif
   1788       1.1  christos 	return 0;
   1789       1.1  christos }
   1790       1.1  christos #endif /* USE_INET6 */
   1791       1.1  christos 
   1792       1.1  christos 
   1793       1.1  christos size_t
   1794       1.2  christos mbufchainlen(struct mbuf *m0)
   1795       1.1  christos {
   1796       1.1  christos 	size_t len;
   1797       1.1  christos 
   1798       1.1  christos 	if ((m0->m_flags & M_PKTHDR) != 0) {
   1799       1.1  christos 		len = m0->m_pkthdr.len;
   1800       1.1  christos 	} else {
   1801       1.1  christos 		struct mbuf *m;
   1802       1.1  christos 
   1803       1.1  christos 		for (m = m0, len = 0; m != NULL; m = m->m_next)
   1804       1.1  christos 			len += m->m_len;
   1805       1.1  christos 	}
   1806       1.1  christos 	return len;
   1807       1.1  christos }
   1808       1.1  christos 
   1809       1.1  christos 
   1810       1.1  christos /* ------------------------------------------------------------------------ */
   1811       1.1  christos /* Function:    ipf_pullup                                                  */
   1812       1.1  christos /* Returns:     NULL == pullup failed, else pointer to protocol header      */
   1813       1.1  christos /* Parameters:  xmin(I)- pointer to buffer where data packet starts         */
   1814       1.1  christos /*              fin(I) - pointer to packet information                      */
   1815       1.1  christos /*              len(I) - number of bytes to pullup                          */
   1816       1.1  christos /*                                                                          */
   1817       1.1  christos /* Attempt to move at least len bytes (from the start of the buffer) into a */
   1818       1.1  christos /* single buffer for ease of access.  Operating system native functions are */
   1819       1.1  christos /* used to manage buffers - if necessary.  If the entire packet ends up in  */
   1820       1.1  christos /* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */
   1821       1.1  christos /* not been called.  Both fin_ip and fin_dp are updated before exiting _IF_ */
   1822       1.1  christos /* and ONLY if the pullup succeeds.                                         */
   1823       1.1  christos /*                                                                          */
   1824       1.1  christos /* We assume that 'xmin' is a pointer to a buffer that is part of the chain */
   1825       1.1  christos /* of buffers that starts at *fin->fin_mp.                                  */
   1826       1.1  christos /* ------------------------------------------------------------------------ */
   1827       1.1  christos void *
   1828       1.2  christos ipf_pullup(mb_t *xmin, fr_info_t *fin, int len)
   1829       1.1  christos {
   1830       1.1  christos 	int dpoff, ipoff;
   1831       1.1  christos 	mb_t *m = xmin;
   1832       1.1  christos 	char *ip;
   1833       1.1  christos 
   1834       1.1  christos 	if (m == NULL)
   1835       1.1  christos 		return NULL;
   1836       1.1  christos 
   1837       1.1  christos 	ip = (char *)fin->fin_ip;
   1838       1.1  christos 	if ((fin->fin_flx & FI_COALESCE) != 0)
   1839       1.1  christos 		return ip;
   1840       1.1  christos 
   1841       1.1  christos 	ipoff = fin->fin_ipoff;
   1842       1.1  christos 	if (fin->fin_dp != NULL)
   1843       1.1  christos 		dpoff = (char *)fin->fin_dp - (char *)ip;
   1844       1.1  christos 	else
   1845       1.1  christos 		dpoff = 0;
   1846       1.1  christos 
   1847       1.1  christos 	if (M_LEN(m) < len) {
   1848       1.1  christos 		mb_t *n = *fin->fin_mp;
   1849       1.1  christos 		/*
   1850       1.1  christos 		 * Assume that M_PKTHDR is set and just work with what is left
   1851       1.1  christos 		 * rather than check..
   1852       1.1  christos 		 * Should not make any real difference, anyway.
   1853       1.1  christos 		 */
   1854       1.1  christos 		if (m != n) {
   1855       1.1  christos 			/*
   1856       1.1  christos 			 * Record the mbuf that points to the mbuf that we're
   1857       1.1  christos 			 * about to go to work on so that we can update the
   1858       1.1  christos 			 * m_next appropriately later.
   1859       1.1  christos 			 */
   1860       1.1  christos 			for (; n->m_next != m; n = n->m_next)
   1861       1.1  christos 				;
   1862       1.1  christos 		} else {
   1863       1.1  christos 			n = NULL;
   1864       1.1  christos 		}
   1865       1.1  christos 
   1866       1.1  christos #ifdef MHLEN
   1867       1.1  christos 		if (len > MHLEN)
   1868       1.1  christos #else
   1869       1.1  christos 		if (len > MLEN)
   1870       1.1  christos #endif
   1871       1.1  christos 		{
   1872       1.1  christos #ifdef HAVE_M_PULLDOWN
   1873       1.1  christos 			if (m_pulldown(m, 0, len, NULL) == NULL)
   1874       1.1  christos 				m = NULL;
   1875       1.1  christos #else
   1876       1.1  christos 			FREE_MB_T(*fin->fin_mp);
   1877       1.1  christos 			m = NULL;
   1878       1.1  christos 			n = NULL;
   1879       1.1  christos #endif
   1880       1.1  christos 		} else
   1881       1.1  christos 		{
   1882       1.1  christos 			m = m_pullup(m, len);
   1883       1.1  christos 		}
   1884       1.1  christos 		if (n != NULL)
   1885       1.1  christos 			n->m_next = m;
   1886       1.1  christos 		if (m == NULL) {
   1887       1.1  christos 			/*
   1888       1.1  christos 			 * When n is non-NULL, it indicates that m pointed to
   1889       1.1  christos 			 * a sub-chain (tail) of the mbuf and that the head
   1890       1.1  christos 			 * of this chain has not yet been free'd.
   1891       1.1  christos 			 */
   1892       1.1  christos 			if (n != NULL) {
   1893       1.1  christos 				FREE_MB_T(*fin->fin_mp);
   1894       1.1  christos 			}
   1895       1.1  christos 
   1896       1.1  christos 			*fin->fin_mp = NULL;
   1897       1.1  christos 			fin->fin_m = NULL;
   1898       1.1  christos 			return NULL;
   1899       1.1  christos 		}
   1900       1.1  christos 
   1901       1.1  christos 		if (n == NULL)
   1902       1.1  christos 			*fin->fin_mp = m;
   1903       1.1  christos 
   1904       1.1  christos 		while (M_LEN(m) == 0) {
   1905       1.1  christos 			m = m->m_next;
   1906       1.1  christos 		}
   1907       1.1  christos 		fin->fin_m = m;
   1908       1.1  christos 		ip = MTOD(m, char *) + ipoff;
   1909       1.1  christos 
   1910       1.1  christos 		fin->fin_ip = (ip_t *)ip;
   1911       1.1  christos 		if (fin->fin_dp != NULL)
   1912       1.1  christos 			fin->fin_dp = (char *)fin->fin_ip + dpoff;
   1913       1.3   darrenr 		if (fin->fin_fraghdr != NULL)
   1914       1.3   darrenr 			fin->fin_fraghdr = (char *)ip +
   1915       1.3   darrenr 					   ((char *)fin->fin_fraghdr -
   1916       1.3   darrenr 					    (char *)fin->fin_ip);
   1917       1.1  christos 	}
   1918       1.1  christos 
   1919       1.1  christos 	if (len == fin->fin_plen)
   1920       1.1  christos 		fin->fin_flx |= FI_COALESCE;
   1921       1.1  christos 	return ip;
   1922       1.1  christos }
   1923       1.1  christos 
   1924       1.1  christos 
   1925       1.1  christos int
   1926       1.2  christos ipf_inject(fr_info_t *fin, mb_t *m)
   1927       1.1  christos {
   1928       1.1  christos 	int error;
   1929       1.1  christos 
   1930       1.1  christos 	if (fin->fin_out == 0) {
   1931      1.10     rmind 		if (__predict_false(!pktq_enqueue(ip_pktq, m, 0))) {
   1932       1.1  christos 			FREE_MB_T(m);
   1933       1.1  christos 			error = ENOBUFS;
   1934       1.1  christos 		} else {
   1935       1.1  christos 			error = 0;
   1936       1.1  christos 		}
   1937       1.1  christos 	} else {
   1938  1.11.4.1     skrll 		error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
   1939       1.1  christos 	}
   1940       1.1  christos 	return error;
   1941       1.1  christos }
   1942       1.1  christos 
   1943       1.1  christos 
   1944       1.1  christos u_32_t
   1945       1.2  christos ipf_random(void)
   1946       1.1  christos {
   1947       1.1  christos 	int number;
   1948       1.1  christos 
   1949       1.1  christos #ifdef _CPRNG_H
   1950       1.1  christos 	number = cprng_fast32();
   1951       1.1  christos #else
   1952       1.1  christos 	number = arc4random();
   1953       1.1  christos #endif
   1954       1.1  christos 	return number;
   1955       1.1  christos }
   1956       1.1  christos 
   1957       1.1  christos 
   1958       1.1  christos /*
   1959       1.1  christos  * routines below for saving IP headers to buffer
   1960       1.1  christos  */
   1961       1.2  christos static int ipfopen(dev_t dev, int flags
   1962       1.1  christos #if (NetBSD >= 199511)
   1963       1.2  christos     , int devtype, PROC_T *p
   1964       1.2  christos #endif
   1965       1.1  christos )
   1966       1.1  christos {
   1967       1.1  christos 	u_int unit = GET_MINOR(dev);
   1968       1.1  christos 	int error;
   1969       1.1  christos 
   1970       1.1  christos 	if (IPL_LOGMAX < unit) {
   1971       1.1  christos 		error = ENXIO;
   1972       1.1  christos 	} else {
   1973       1.1  christos 		switch (unit)
   1974       1.1  christos 		{
   1975       1.1  christos 		case IPL_LOGIPF :
   1976       1.1  christos 		case IPL_LOGNAT :
   1977       1.1  christos 		case IPL_LOGSTATE :
   1978       1.1  christos 		case IPL_LOGAUTH :
   1979       1.1  christos 		case IPL_LOGLOOKUP :
   1980       1.1  christos 		case IPL_LOGSYNC :
   1981       1.1  christos #ifdef IPFILTER_SCAN
   1982       1.1  christos 		case IPL_LOGSCAN :
   1983       1.1  christos #endif
   1984       1.1  christos 			error = 0;
   1985       1.1  christos 			break;
   1986       1.1  christos 		default :
   1987       1.1  christos 			error = ENXIO;
   1988       1.1  christos 			break;
   1989       1.1  christos 		}
   1990       1.1  christos 	}
   1991       1.1  christos 	return error;
   1992       1.1  christos }
   1993       1.1  christos 
   1994       1.1  christos 
   1995       1.2  christos static int ipfclose(dev_t dev, int flags
   1996       1.1  christos #if (NetBSD >= 199511)
   1997       1.2  christos 	, int devtype, PROC_T *p
   1998       1.2  christos #endif
   1999       1.1  christos )
   2000       1.1  christos {
   2001       1.1  christos 	u_int	unit = GET_MINOR(dev);
   2002       1.1  christos 
   2003       1.1  christos 	if (IPL_LOGMAX < unit)
   2004       1.1  christos 		unit = ENXIO;
   2005       1.1  christos 	else
   2006       1.1  christos 		unit = 0;
   2007       1.1  christos 	return unit;
   2008       1.1  christos }
   2009       1.1  christos 
   2010       1.1  christos /*
   2011       1.1  christos  * ipfread/ipflog
   2012       1.1  christos  * both of these must operate with at least splnet() lest they be
   2013       1.1  christos  * called during packet processing and cause an inconsistancy to appear in
   2014       1.1  christos  * the filter lists.
   2015       1.1  christos  */
   2016       1.2  christos static int ipfread(dev_t dev, struct uio *uio, int ioflag)
   2017       1.1  christos {
   2018       1.1  christos 
   2019       1.1  christos 	if (ipfmain.ipf_running < 1) {
   2020       1.1  christos 		ipfmain.ipf_interror = 130006;
   2021       1.1  christos 		return EIO;
   2022       1.1  christos 	}
   2023       1.1  christos 
   2024       1.1  christos 	if (GET_MINOR(dev) == IPL_LOGSYNC)
   2025       1.1  christos 		return ipf_sync_read(&ipfmain, uio);
   2026       1.1  christos 
   2027       1.1  christos #ifdef IPFILTER_LOG
   2028       1.1  christos 	return ipf_log_read(&ipfmain, GET_MINOR(dev), uio);
   2029       1.1  christos #else
   2030       1.1  christos 	ipfmain.ipf_interror = 130007;
   2031       1.1  christos 	return ENXIO;
   2032       1.1  christos #endif
   2033       1.1  christos }
   2034       1.1  christos 
   2035       1.1  christos 
   2036       1.1  christos /*
   2037       1.1  christos  * ipfwrite
   2038       1.1  christos  * both of these must operate with at least splnet() lest they be
   2039       1.1  christos  * called during packet processing and cause an inconsistancy to appear in
   2040       1.1  christos  * the filter lists.
   2041       1.1  christos  */
   2042       1.2  christos static int ipfwrite(dev_t dev, struct uio *uio, int ioflag)
   2043       1.1  christos {
   2044       1.1  christos 
   2045       1.1  christos 	if (ipfmain.ipf_running < 1) {
   2046       1.1  christos 		ipfmain.ipf_interror = 130008;
   2047       1.1  christos 		return EIO;
   2048       1.1  christos 	}
   2049       1.1  christos 
   2050       1.1  christos 	if (GET_MINOR(dev) == IPL_LOGSYNC)
   2051       1.1  christos 		return ipf_sync_write(&ipfmain, uio);
   2052       1.1  christos 	ipfmain.ipf_interror = 130009;
   2053       1.1  christos 	return ENXIO;
   2054       1.1  christos }
   2055       1.1  christos 
   2056       1.1  christos 
   2057       1.2  christos static int ipfpoll(dev_t dev, int events, PROC_T *p)
   2058       1.1  christos {
   2059       1.1  christos 	u_int unit = GET_MINOR(dev);
   2060       1.1  christos 	int revents = 0;
   2061       1.1  christos 
   2062       1.1  christos 	if (IPL_LOGMAX < unit) {
   2063       1.1  christos 		ipfmain.ipf_interror = 130010;
   2064       1.1  christos 		return ENXIO;
   2065       1.1  christos 	}
   2066       1.1  christos 
   2067       1.1  christos 	switch (unit)
   2068       1.1  christos 	{
   2069       1.1  christos 	case IPL_LOGIPF :
   2070       1.1  christos 	case IPL_LOGNAT :
   2071       1.1  christos 	case IPL_LOGSTATE :
   2072       1.1  christos #ifdef IPFILTER_LOG
   2073       1.1  christos 		if ((events & (POLLIN | POLLRDNORM)) &&
   2074       1.1  christos 		    ipf_log_canread(&ipfmain, unit))
   2075       1.1  christos 			revents |= events & (POLLIN | POLLRDNORM);
   2076       1.1  christos #endif
   2077       1.1  christos 		break;
   2078       1.1  christos 	case IPL_LOGAUTH :
   2079       1.1  christos 		if ((events & (POLLIN | POLLRDNORM)) &&
   2080       1.1  christos 		    ipf_auth_waiting(&ipfmain))
   2081       1.1  christos 			revents |= events & (POLLIN | POLLRDNORM);
   2082       1.1  christos 		break;
   2083       1.1  christos 	case IPL_LOGSYNC :
   2084       1.1  christos 		if ((events & (POLLIN | POLLRDNORM)) &&
   2085       1.1  christos 		    ipf_sync_canread(&ipfmain))
   2086       1.1  christos 			revents |= events & (POLLIN | POLLRDNORM);
   2087       1.1  christos 		if ((events & (POLLOUT | POLLWRNORM)) &&
   2088       1.1  christos 		    ipf_sync_canwrite(&ipfmain))
   2089       1.1  christos 			revents |= events & (POLLOUT | POLLWRNORM);
   2090       1.1  christos 		break;
   2091       1.1  christos 	case IPL_LOGSCAN :
   2092       1.1  christos 	case IPL_LOGLOOKUP :
   2093       1.1  christos 	default :
   2094       1.1  christos 		break;
   2095       1.1  christos 	}
   2096       1.1  christos 
   2097       1.1  christos 	if ((revents == 0) && (((events & (POLLIN|POLLRDNORM)) != 0)))
   2098       1.1  christos 		selrecord(p, &ipfmain.ipf_selwait[unit]);
   2099       1.1  christos 	return revents;
   2100       1.1  christos }
   2101       1.1  christos 
   2102       1.1  christos u_int
   2103       1.2  christos ipf_pcksum(fr_info_t *fin, int hlen, u_int sum)
   2104       1.1  christos {
   2105       1.1  christos 	struct mbuf *m;
   2106       1.1  christos 	u_int sum2;
   2107       1.1  christos 	int off;
   2108       1.1  christos 
   2109       1.1  christos 	m = fin->fin_m;
   2110       1.1  christos 	off = (char *)fin->fin_dp - (char *)fin->fin_ip;
   2111       1.1  christos 	m->m_data += hlen;
   2112       1.1  christos 	m->m_len -= hlen;
   2113       1.1  christos 	sum2 = in_cksum(fin->fin_m, fin->fin_plen - off);
   2114       1.1  christos 	m->m_len += hlen;
   2115       1.1  christos 	m->m_data -= hlen;
   2116       1.1  christos 
   2117       1.1  christos 	/*
   2118       1.1  christos 	 * Both sum and sum2 are partial sums, so combine them together.
   2119       1.1  christos 	 */
   2120       1.1  christos 	sum += ~sum2 & 0xffff;
   2121       1.1  christos 	while (sum > 0xffff)
   2122       1.1  christos 		sum = (sum & 0xffff) + (sum >> 16);
   2123       1.1  christos 	sum2 = ~sum & 0xffff;
   2124       1.1  christos 	return sum2;
   2125       1.1  christos }
   2126