Subject: Patches for using ipfilter with IPv6
To: None <tech-net@netbsd.org>
From: Darren Reed <darrenr@reed.wattle.id.au>
List: tech-net
Date: 12/19/1999 01:10:20
Hi,
   Below I've attached some patches which I've put together which provide
support for per-protocol filtering.  Whilst there were some criticisms
about putting things in header files, I stuck with the changes I made
because it seemed wrong that these networking files had an abitrary list
of externs.

   To summarise, the patches do as follows:

- change pfil to work on per-protocol lists rather than global ones for
  all protocols - this required adding passing 'struct protosw *' as a
  part of the external interface to pfil;

- add an extern for ip_protox[] to <netinet/in.h> and remove explicit
  extern for ip_protox[] from various .c files;

- add an extern for inetsw[] to <sys/protosw.h> and remove explicit
  extern for inetsw[] from various .c files;
(did both of these, again, for ip6_protox[] into <netinet6/in6.h> and
 inet6sw[] into <netinet6/ip6protosw.h>)

- move ip_protox[] to /sys/netinet/in_proto.c;

- change ip_fil.c to use new pfil interface;

- change ip_input() and ip_output() to use new pfil interface;

- add pfil processing to ip6_output.c (did someone for IPV6FIREWALL ? :)
  and ip6_input.c, including addition of include for opt_pfil_hooks.h;

- add a new field, "struct pfil_head pr_pfh" to both 'struct protosw'
  and 'struct ip6protosw', with includes for <net/pfil.h> in each .h file.

I'd like at least one other person to test these patches before I commit
them.  If you want to test these patches with actual filtering of IPv6
packets, you can download the latest code from:
http://coombs.anu.edu.au/~avalon/ip-filter.html

Cheers,
Darren

Index: net/pfil.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/pfil.c,v
retrieving revision 1.9
diff -c -r1.9 pfil.c
*** pfil.c	1999/10/10 09:07:32	1.9
--- pfil.c	1999/12/18 13:45:21
***************
*** 35,63 ****
  #include <sys/socketvar.h>
  #include <sys/systm.h>
  #include <sys/proc.h>
  #include <sys/queue.h>
  
  #include <net/if.h>
  #include <net/pfil.h>
  
- typedef TAILQ_HEAD(, packet_filter_hook) pfil_list_t;
- pfil_list_t pfil_in_list;
- pfil_list_t pfil_out_list;
- static int done_pfil_init;
  
! static void pfil_init __P((void));
  static void pfil_list_add(pfil_list_t *,
      int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)), int);
  static void pfil_list_remove(pfil_list_t *,
      int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)));
  
  static void
! pfil_init()
  {
  
! 	TAILQ_INIT(&pfil_in_list);
! 	TAILQ_INIT(&pfil_out_list);
! 	done_pfil_init = 1;
  }
  
  /*
--- 35,61 ----
  #include <sys/socketvar.h>
  #include <sys/systm.h>
  #include <sys/proc.h>
+ #include <sys/protosw.h>
  #include <sys/queue.h>
  
  #include <net/if.h>
  #include <net/pfil.h>
  
  
! static void pfil_init __P((struct pfil_head *));
  static void pfil_list_add(pfil_list_t *,
      int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)), int);
  static void pfil_list_remove(pfil_list_t *,
      int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)));
  
  static void
! pfil_init(ph)
! 	struct pfil_head *ph;
  {
  
! 	TAILQ_INIT(&ph->ph_in);
! 	TAILQ_INIT(&ph->ph_out);
! 	ph->ph_init = 1;
  }
  
  /*
***************
*** 69,89 ****
   *	PFIL_WAITOK	OK to call malloc with M_WAITOK.
   */
  void
! pfil_add_hook(func, flags)
  	int	(*func) __P((void *, int, struct ifnet *, int,
  			     struct mbuf **));
  	int	flags;
  {
  
! 	if (done_pfil_init == 0)
! 		pfil_init();
  
  	if (flags & PFIL_IN)
! 		pfil_list_add(&pfil_in_list, func, PFIL_IN |
! 		    (flags & PFIL_WAITOK));
  	if (flags & PFIL_OUT)
! 		pfil_list_add(&pfil_out_list, func, PFIL_OUT |
! 		    (flags & PFIL_WAITOK));
  }
  
  static void
--- 67,87 ----
   *	PFIL_WAITOK	OK to call malloc with M_WAITOK.
   */
  void
! pfil_add_hook(func, flags, psw)
  	int	(*func) __P((void *, int, struct ifnet *, int,
  			     struct mbuf **));
  	int	flags;
+ 	struct	protosw	*psw;
  {
+ 	struct	pfil_head	*ph = &psw->pr_pfh;
  
! 	if (ph->ph_init == 0)
! 		pfil_init(ph);
  
  	if (flags & PFIL_IN)
! 		pfil_list_add(&ph->ph_in, func, flags);
  	if (flags & PFIL_OUT)
! 		pfil_list_add(&ph->ph_out, func, flags);
  }
  
  static void
***************
*** 91,97 ****
  	pfil_list_t *list;
  	int	(*func) __P((void *, int, struct ifnet *, int,
  			     struct mbuf **));
! 	int	flags;
  {
  	struct packet_filter_hook *pfh;
  
--- 89,95 ----
  	pfil_list_t *list;
  	int	(*func) __P((void *, int, struct ifnet *, int,
  			     struct mbuf **));
! 	int flags;
  {
  	struct packet_filter_hook *pfh;
  
***************
*** 99,114 ****
  	    flags & PFIL_WAITOK ? M_WAITOK : M_NOWAIT);
  	if (pfh == NULL)
  		panic("no memory for packet filter hook");
- 
  	pfh->pfil_func = func;
  	/*
  	 * insert the input list in reverse order of the output list
  	 * so that the same path is followed in or out of the kernel.
  	 */
! 	if (flags & PFIL_IN)
! 		TAILQ_INSERT_HEAD(list, pfh, pfil_link);
! 	else
! 		TAILQ_INSERT_TAIL(list, pfh, pfil_link);
  }
  
  /*
--- 97,108 ----
  	    flags & PFIL_WAITOK ? M_WAITOK : M_NOWAIT);
  	if (pfh == NULL)
  		panic("no memory for packet filter hook");
  	pfh->pfil_func = func;
  	/*
  	 * insert the input list in reverse order of the output list
  	 * so that the same path is followed in or out of the kernel.
  	 */
! 	TAILQ_INSERT_TAIL(list, pfh, pfil_link);
  }
  
  /*
***************
*** 116,134 ****
   * hook list.
   */
  void
! pfil_remove_hook(func, flags)
  	int	(*func) __P((void *, int, struct ifnet *, int,
  			     struct mbuf **));
  	int	flags;
  {
  
! 	if (done_pfil_init == 0)
! 		pfil_init();
  
  	if (flags & PFIL_IN)
! 		pfil_list_remove(&pfil_in_list, func);
  	if (flags & PFIL_OUT)
! 		pfil_list_remove(&pfil_out_list, func);
  }
  
  /*
--- 110,130 ----
   * hook list.
   */
  void
! pfil_remove_hook(func, flags, psw)
  	int	(*func) __P((void *, int, struct ifnet *, int,
  			     struct mbuf **));
  	int	flags;
+ 	struct protosw *psw;
  {
+ 	struct	pfil_head	*ph = &psw->pr_pfh;	
  
! 	if (ph->ph_init == 0)
! 		pfil_init(ph);
  
  	if (flags & PFIL_IN)
! 		pfil_list_remove(&ph->ph_in, func);
  	if (flags & PFIL_OUT)
! 		pfil_list_remove(&ph->ph_out, func);
  }
  
  /*
***************
*** 156,171 ****
  }
  
  struct packet_filter_hook *
! pfil_hook_get(flag)
  	int flag;
  {
  
! 	if (done_pfil_init)
  		switch (flag) {
  		case PFIL_IN:
! 			return (pfil_in_list.tqh_first);
  		case PFIL_OUT:
! 			return (pfil_out_list.tqh_first);
  		}
  	return NULL;
  }
--- 152,169 ----
  }
  
  struct packet_filter_hook *
! pfil_hook_get(flag, psw)
  	int flag;
+ 	struct protosw *psw;
  {
+ 	struct	pfil_head	*ph = &psw->pr_pfh;	
  
! 	if (ph->ph_init != 0)
  		switch (flag) {
  		case PFIL_IN:
! 			return (ph->ph_in.tqh_first);
  		case PFIL_OUT:
! 			return (ph->ph_out.tqh_first);
  		}
  	return NULL;
  }
Index: net/pfil.h
===================================================================
RCS file: /cvsroot/syssrc/sys/net/pfil.h,v
retrieving revision 1.9
diff -c -r1.9 pfil.h
*** pfil.h	1998/03/19 15:45:30	1.9
--- pfil.h	1999/12/18 00:43:59
***************
*** 31,41 ****
  #ifndef _NET_PFIL_H_
  #define _NET_PFIL_H_
  
- /* note: this file needs <net/if.h> and <sys/mbuf.h> */
- 
- #ifdef _KERNEL
  #include <sys/queue.h>
  
  /*
   * The packet filter hooks are designed for anything to call them to
   * possibly intercept the packet.
--- 31,42 ----
  #ifndef _NET_PFIL_H_
  #define _NET_PFIL_H_
  
  #include <sys/queue.h>
  
+ struct protosw;
+ struct mbuf;
+ struct ifnet;
+ 
  /*
   * The packet filter hooks are designed for anything to call them to
   * possibly intercept the packet.
***************
*** 49,63 ****
  
  #define PFIL_IN		0x00000001
  #define PFIL_OUT	0x00000002
! #define PFIL_WAITOK	0x00000008
  #define PFIL_ALL	(PFIL_IN|PFIL_OUT)
  
! struct packet_filter_hook *pfil_hook_get __P((int));
  void	pfil_add_hook __P((int (*func) __P((void *, int,
! 	    struct ifnet *, int, struct mbuf **)), int));
  void	pfil_remove_hook __P((int (*func) __P((void *, int,
! 	    struct ifnet *, int, struct mbuf **)), int));
! #endif /* _KERNEL */
  
  /* XXX */
  #if defined(_KERNEL) && !defined(_LKM)
--- 50,71 ----
  
  #define PFIL_IN		0x00000001
  #define PFIL_OUT	0x00000002
! #define PFIL_WAITOK	0x00000004
  #define PFIL_ALL	(PFIL_IN|PFIL_OUT)
+ 
+ typedef	TAILQ_HEAD(pfil_list, packet_filter_hook) pfil_list_t;
+ 
+ struct pfil_head {
+ 	pfil_list_t	ph_in;
+ 	pfil_list_t	ph_out;
+ 	int		ph_init;
+ } pfil_head_t;
  
! struct packet_filter_hook *pfil_hook_get __P((int, struct protosw *));
  void	pfil_add_hook __P((int (*func) __P((void *, int,
! 	    struct ifnet *, int, struct mbuf **)), int, struct protosw *));
  void	pfil_remove_hook __P((int (*func) __P((void *, int,
! 	    struct ifnet *, int, struct mbuf **)), int, struct protosw *));
  
  /* XXX */
  #if defined(_KERNEL) && !defined(_LKM)
Index: netinet/in.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/in.h,v
retrieving revision 1.44
diff -c -r1.44 in.h
*** in.h	1999/12/13 15:17:19	1.44
--- in.h	1999/12/18 13:15:08
***************
*** 372,377 ****
--- 372,378 ----
  
  #ifdef _KERNEL
  extern	struct in_addr zeroin_addr;
+ extern	u_char	ip_protox[];
  
  int	in_broadcast __P((struct in_addr, struct ifnet *));
  int	in_canforward __P((struct in_addr));
Index: netinet/in_proto.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/in_proto.c,v
retrieving revision 1.34
diff -c -r1.34 in_proto.c
*** in_proto.c	1999/12/13 15:17:20	1.34
--- in_proto.c	1999/12/11 02:13:47
***************
*** 266,271 ****
--- 266,273 ----
      { PF_INET, "internet", 0, 0, 0, 
        inetsw, &inetsw[sizeof(inetsw)/sizeof(inetsw[0])], 0,
        rn_inithead, 32, sizeof(struct sockaddr_in) };
+ 
+ u_char	ip_protox[IPPROTO_MAX];
  
  #define	TCP_SYN_HASH_SIZE	293
  #define	TCP_SYN_BUCKET_SIZE	35
Index: netinet/ip_fil.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_fil.c,v
retrieving revision 1.38
diff -c -r1.38 ip_fil.c
*** ip_fil.c	1999/12/12 11:11:16	1.38
--- ip_fil.c	1999/12/18 13:11:59
***************
*** 264,270 ****
  		return -1;
  
  # ifdef NETBSD_PF
! 	pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
  # endif
  
  # ifdef __sgi
--- 264,271 ----
  		return -1;
  
  # ifdef NETBSD_PF
! 	pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
! 		       &inetsw[ip_protox[IPPROTO_IP]]);
  # endif
  
  # ifdef __sgi
Index: netinet/ip_icmp.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_icmp.c,v
retrieving revision 1.38
diff -c -r1.38 ip_icmp.c
*** ip_icmp.c	1999/07/09 22:57:18	1.38
--- ip_icmp.c	1999/12/18 12:34:39
***************
*** 152,159 ****
  /*static*/ int	ip_next_mtu __P((int, int));
  #endif
  
- extern	struct protosw inetsw[];
- 
  static void icmp_mtudisc __P((struct icmp *));
  static void icmp_mtudisc_timeout __P((struct rtentry *, struct rttimer *));
  
--- 152,157 ----
***************
*** 279,285 ****
  	struct in_ifaddr *ia;
  	void *(*ctlfunc) __P((int, struct sockaddr *, void *));
  	int code;
- 	extern u_char ip_protox[];
  	int hlen;
  	va_list ap;
  
--- 277,282 ----
Index: netinet/ip_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_input.c,v
retrieving revision 1.94
diff -c -r1.94 ip_input.c
*** ip_input.c	1999/10/26 09:53:17	1.94
--- ip_input.c	1999/12/18 12:27:54
***************
*** 194,201 ****
  struct rttimer_queue *ip_mtudisc_timeout_q = NULL;
  
  extern	struct domain inetdomain;
- extern	struct protosw inetsw[];
- u_char	ip_protox[IPPROTO_MAX];
  int	ipqmaxlen = IFQ_MAXLEN;
  struct	in_ifaddrhead in_ifaddr;
  struct	in_ifaddrhashhead *in_ifaddrhashtbl;
--- 194,199 ----
***************
*** 443,458 ****
  			m_adj(m, len - m->m_pkthdr.len);
  	}
  
- #ifdef IPSEC
- 	/* ipflow (IP fast fowarding) is not compatible with IPsec. */
- 	m->m_flags &= ~M_CANFASTFWD;
- #else
  	/*
  	 * Assume that we can create a fast-forward IP flow entry
  	 * based on this packet.
  	 */
  	m->m_flags |= M_CANFASTFWD;
- #endif
  
  #ifdef PFIL_HOOKS
  	/*
--- 441,451 ----
***************
*** 463,471 ****
  	 * in the list may have previously cleared it.
  	 */
  	m0 = m;
! 	for (pfh = pfil_hook_get(PFIL_IN); pfh; pfh = pfh->pfil_link.tqe_next)
  		if (pfh->pfil_func) {
! 			rv = pfh->pfil_func(ip, hlen, m->m_pkthdr.rcvif, 0, &m0);
  			if (rv)
  				return;
  			m = m0;
--- 456,466 ----
  	 * in the list may have previously cleared it.
  	 */
  	m0 = m;
! 	pfh = pfil_hook_get(PFIL_IN, &inetsw[ip_protox[IPPROTO_IP]]);
! 	for (; pfh; pfh = pfh->pfil_link.tqe_next)
  		if (pfh->pfil_func) {
! 			rv = pfh->pfil_func(ip, hlen,
! 					    m->m_pkthdr.rcvif, 0, &m0);
  			if (rv)
  				return;
  			m = m0;
Index: netinet/ip_output.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_output.c,v
retrieving revision 1.64
diff -c -r1.64 ip_output.c
*** ip_output.c	1999/12/13 17:04:11	1.64
--- ip_output.c	1999/12/11 01:58:55
***************
*** 417,423 ****
  	 * Run through list of hooks for output packets.
  	 */
  	m1 = m;
! 	for (pfh = pfil_hook_get(PFIL_OUT); pfh; pfh = pfh->pfil_link.tqe_next)
  		if (pfh->pfil_func) {
  		    	rv = pfh->pfil_func(ip, hlen, ifp, 1, &m1);
  			if (rv) {
--- 412,419 ----
  	 * Run through list of hooks for output packets.
  	 */
  	m1 = m;
! 	pfh = pfil_hook_get(PFIL_OUT, &inetsw[ip_protox[IPPROTO_IP]]);
! 	for (; pfh; pfh = pfh->pfil_link.tqe_next)
  		if (pfh->pfil_func) {
  		    	rv = pfh->pfil_func(ip, hlen, ifp, 1, &m1);
  			if (rv) {
Index: netinet/raw_ip.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/raw_ip.c,v
retrieving revision 1.47
diff -c -r1.47 raw_ip.c
*** raw_ip.c	1999/12/13 15:17:20	1.47
--- raw_ip.c	1999/12/18 12:34:20
***************
*** 95,102 ****
  #include <netinet6/ipsec.h>
  #endif /*IPSEC*/
  
- extern u_char ip_protox[];
- extern struct  protosw inetsw[];
  struct inpcbtable rawcbtable;
  
  int	 rip_bind __P((struct inpcb *, struct mbuf *));
--- 95,100 ----
Index: netinet6/ah_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ah_input.c,v
retrieving revision 1.5
diff -c -r1.5 ah_input.c
*** ah_input.c	1999/07/30 10:35:35	1.5
--- ah_input.c	1999/12/18 12:35:02
***************
*** 83,92 ****
  #endif
  
  #ifdef INET
- extern struct protosw inetsw[];
- #if defined(__bsdi__) || defined(__NetBSD__)
- extern u_char ip_protox[];
- #endif
  
  void
  #if __STDC__
--- 83,88 ----
Index: netinet6/icmp6.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/icmp6.c,v
retrieving revision 1.13
diff -c -r1.13 icmp6.c
*** icmp6.c	1999/12/15 06:28:44	1.13
--- icmp6.c	1999/12/18 13:27:53
***************
*** 104,109 ****
--- 104,110 ----
  #include <netinet/in_pcb.h>
  #endif
  #include <netinet6/nd6.h>
+ #include <netinet6/in6.h>
  #include <netinet6/in6_ifattach.h>
  #include <netinet6/ip6protosw.h>
  
***************
*** 122,129 ****
  #include <net/net_osdep.h>
  
  extern struct domain inet6domain;
- extern struct ip6protosw inet6sw[];
- extern u_char ip6_protox[];
  
  struct icmp6stat icmp6stat;
  
--- 123,128 ----
Index: netinet6/ip6_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ip6_input.c,v
retrieving revision 1.9
diff -c -r1.9 ip6_input.c
*** ip6_input.c	1999/12/13 15:17:22	1.9
--- ip6_input.c	1999/12/18 13:38:21
***************
*** 71,76 ****
--- 71,77 ----
  #include "opt_inet.h"
  #ifdef __NetBSD__	/*XXX*/
  #include "opt_ipsec.h"
+ #include "opt_pfil_hooks.h"
  #endif
  #endif
  
***************
*** 95,100 ****
--- 96,104 ----
  #include <net/if_dl.h>
  #include <net/route.h>
  #include <net/netisr.h>
+ #ifdef PFIL_HOOKS
+ #include <net/pfil.h>
+ #endif
  
  #include <netinet/in.h>
  #include <netinet/in_systm.h>
***************
*** 138,144 ****
  #endif
  
  extern struct domain inet6domain;
- extern struct ip6protosw inet6sw[];
  #ifdef __bsdi__
  #if _BSDI_VERSION < 199802
  extern struct ifnet loif;
--- 142,147 ----
***************
*** 284,289 ****
--- 287,297 ----
  	u_int32_t plen;
  	u_int32_t rtalert = ~0;
  	int nxt, ours = 0;
+ #ifdef PFIL_HOOKS
+ 	struct packet_filter_hook *pfh;
+ 	struct mbuf *m0;
+ 	int rv;
+ #endif /* PFIL_HOOKS */
  	struct ifnet *deliverifp = NULL;
  #if defined(__bsdi__) && _BSDI_VERSION < 199802
  	struct ifnet *loifp = &loif;
***************
*** 353,358 ****
--- 361,388 ----
  
  	ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
  
+ #ifdef PFIL_HOOKS
+ 	/*
+ 	 * Run through list of hooks for input packets.  If there are any
+ 	 * filters which require that additional packets in the flow are
+ 	 * not fast-forwarded, they must clear the M_CANFASTFWD flag.
+ 	 * Note that filters must _never_ set this flag, as another filter
+ 	 * in the list may have previously cleared it.
+ 	 */
+ 	m0 = m;
+ 	pfh = pfil_hook_get(PFIL_IN, &inetsw[ip_protox[IPPROTO_IPV6]]);
+ 	for (; pfh; pfh = pfh->pfil_link.tqe_next)
+ 		if (pfh->pfil_func) {
+ 			rv = pfh->pfil_func(ip6, sizeof(*ip6),
+ 					    m->m_pkthdr.rcvif, 0, &m0);
+ 			if (rv)
+ 				return;
+ 			m = m0;
+ 			if (m == NULL)
+ 				return;
+ 			ip6 = mtod(m, struct ip6_hdr *);
+ 		}
+ #endif /* PFIL_HOOKS */
  #ifdef IPV6FIREWALL
  	/*
  	 * Check with the firewall...
Index: netinet6/ip6_output.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ip6_output.c,v
retrieving revision 1.9
diff -c -r1.9 ip6_output.c
*** ip6_output.c	1999/12/13 15:17:23	1.9
--- ip6_output.c	1999/12/18 13:39:30
***************
*** 71,76 ****
--- 71,77 ----
  #include "opt_inet.h"
  #ifdef __NetBSD__	/*XXX*/
  #include "opt_ipsec.h"
+ #include "opt_pfil_hooks.h"
  #endif
  #endif
  
***************
*** 92,97 ****
--- 93,101 ----
  
  #include <net/if.h>
  #include <net/route.h>
+ #ifdef PFIL_HOOKS
+ #include <net/pfil.h>
+ #endif
  
  #include <netinet/in.h>
  #include <netinet/in_var.h>
***************
*** 194,199 ****
--- 198,208 ----
  	struct route_in6 *ro_pmtu = NULL;
  	int hdrsplit = 0;
  	int needipsec = 0;
+ #ifdef PFIL_HOOKS
+ 	struct packet_filter_hook *pfh;
+ 	struct mbuf *m1;
+ 	int rv;
+ #endif /* PFIL_HOOKS */
  #ifdef IPSEC
  	int needipsectun = 0;
  	struct socket *so;
***************
*** 845,850 ****
--- 854,883 ----
  		m->m_pkthdr.rcvif = NULL;
  	}
  
+ #ifdef PFIL_HOOKS
+ 	/*
+ 	 * Run through list of hooks for input packets.  If there are any
+ 	 * filters which require that additional packets in the flow are
+ 	 * not fast-forwarded, they must clear the M_CANFASTFWD flag.
+ 	 * Note that filters must _never_ set this flag, as another filter
+ 	 * in the list may have previously cleared it.
+ 	 */
+ 	m1 = m;
+ 	pfh = pfil_hook_get(PFIL_OUT, &inetsw[ip_protox[IPPROTO_IP]]);
+ 	for (; pfh; pfh = pfh->pfil_link.tqe_next)
+ 		if (pfh->pfil_func) {
+ 			rv = pfh->pfil_func(ip6, sizeof(*ip6),
+ 					    m->m_pkthdr.rcvif, 0, &m1);
+ 			if (rv) {
+ 				error = EHOSTUNREACH;
+ 				goto done;
+ 			}
+ 			m = m1;
+ 			if (m == NULL)
+ 				goto done;
+ 			ip6 = mtod(m, struct ip6_hdr *);
+ 		}
+ #endif /* PFIL_HOOKS */
  	/*
  	 * Send the packet to the outgoing interface.
  	 * If necessary, do IPv6 fragmentation before sending. 
Index: netinet6/ip6protosw.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ip6protosw.h,v
retrieving revision 1.4
diff -c -r1.4 ip6protosw.h
*** ip6protosw.h	1999/12/13 15:17:23	1.4
--- ip6protosw.h	1999/12/18 13:26:33
***************
*** 74,79 ****
--- 74,82 ----
   * Protocol switch table for IPv6.
   * All other definitions should refer to sys/protosw.h
   */
+ #ifdef __NetBSD__
+ #include <net/pfil.h>
+ #endif
  
  struct mbuf;
  struct sockaddr;
***************
*** 146,151 ****
--- 149,159 ----
  	int	(*pr_sysctl)		/* sysctl for protocol */
  			__P((int *, u_int, void *, size_t *, void *, size_t));
  #endif
+ #ifdef __NetBSD__
+ 	struct	pfil_head pr_pfh;
+ #endif
  };
+ 
+ extern struct ip6protosw inet6sw[];
  
  #endif /* !_NETINET6_IP6PROTOSW_H_ */
Index: netinet6/ipcomp_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ipcomp_input.c,v
retrieving revision 1.6
diff -c -r1.6 ipcomp_input.c
*** ipcomp_input.c	1999/11/05 14:57:00	1.6
--- ipcomp_input.c	1999/12/18 12:35:17
***************
*** 85,94 ****
  #endif
  
  #ifdef INET
- extern struct protosw inetsw[];
- #if defined(__bsdi__) || defined(__NetBSD__)
- extern u_char ip_protox[];
- #endif
  
  void
  #if __STDC__
--- 85,90 ----
Index: sys/protosw.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/protosw.h,v
retrieving revision 1.18
diff -c -r1.18 protosw.h
*** protosw.h	1999/07/01 05:56:53	1.18
--- protosw.h	1999/12/18 12:29:28
***************
*** 38,43 ****
--- 38,45 ----
  #ifndef _SYS_PROTOSW_H_
  #define _SYS_PROTOSW_H_
  
+ #include <net/pfil.h>			/* XXX - pickup pfil_head type */
+ 
  /*
   * Protocol switch table.
   *
***************
*** 100,105 ****
--- 102,108 ----
  			__P((void));
  	int	(*pr_sysctl)		/* sysctl for protocol */
  			__P((int *, u_int, void *, size_t *, void *, size_t));
+ 	struct	pfil_head	pr_pfh;
  };
  
  #define	PR_SLOWHZ	2		/* 2 slow timeouts per second */
***************
*** 257,262 ****
--- 260,266 ----
  struct protosw *pffindproto __P((int, int, int));
  struct protosw *pffindtype __P((int, int));
  void pfctlinput __P((int, struct sockaddr *));
+ extern struct protosw inetsw[];
  #endif /* _KERNEL */
  
  #endif /* !_SYS_PROTOSW_H_ */