Subject: Full story on PFIL_HOOKS rearrangement
To: None <tech-net@netbsd.org>
From: Jason R Thorpe <thorpej@zembu.com>
List: tech-net
Date: 11/09/2000 23:55:36
The diff below includes some things I previously talked about -- the
placement of the PFIL_HOOKS calls. Here is also changes to make the
mechanism more generic -- you can have multiple hook heads -- they're
registered with a "key" and "dlt" pair.
Key is a void * (so it could be e.g. a network interface structure; this
gets into my classification engine, which I'll describe in more detail
later). DLT is a BPF DLT constant that indicates what kind of link
level header is present.
For INET and INET6, the keys are ((void *) AF_INET) and ((void *) AF_INET6),
and the DLT is DLT_RAW (since there is no link level header present when
the packets are handed off to the filter).
The interface to the pfil_* functions have changed, as has the interface
to the hooks themselves. I have compsenated with wrappers for IP Filter.
Below is my proposed patch.
Feedback ASAP appreciated.
--
-- Jason R. Thorpe <thorpej@zembu.com>
Index: net/bpf.h
===================================================================
RCS file: /cvsroot/syssrc/sys/net/bpf.h,v
retrieving revision 1.26
diff -c -r1.26 bpf.h
*** net/bpf.h 2000/11/02 16:14:05 1.26
--- net/bpf.h 2000/11/10 07:45:08
***************
*** 44,49 ****
--- 44,51 ----
#ifndef _NET_BPF_H_
#define _NET_BPF_H_
+ #include <sys/time.h>
+
/* BSD style release date */
#define BPF_RELEASE 199606
Index: net/pfil.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/pfil.c,v
retrieving revision 1.15
diff -c -r1.15 pfil.c
*** net/pfil.c 2000/02/23 02:35:42 1.15
--- net/pfil.c 2000/11/10 07:45:10
***************
*** 40,62 ****
#include <net/if.h>
#include <net/pfil.h>
- static void pfil_init __P((struct pfil_head *));
static int pfil_list_add(pfil_list_t *,
! int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)), int);
static int 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;
}
/*
* pfil_add_hook() adds a function to the packet filter hook. the
* flags are:
* PFIL_IN call me on incoming packets
--- 40,132 ----
#include <net/if.h>
#include <net/pfil.h>
static int pfil_list_add(pfil_list_t *,
! int (*)(void *, struct mbuf **, struct ifnet *, int), void *, int);
!
static int pfil_list_remove(pfil_list_t *,
! int (*)(void *, struct mbuf **, struct ifnet *, int), void *);
!
! LIST_HEAD(, pfil_head) pfil_head_list =
! LIST_HEAD_INITIALIZER(&pfil_head_list);
!
! /*
! * pfil_run_hooks() runs the specified packet filter hooks.
! */
! int
! pfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp,
! int dir)
! {
! struct packet_filter_hook *pfh;
! struct mbuf *m = *mp;
! int rv = 0;
!
! for (pfh = pfil_hook_get(dir, ph); pfh != NULL;
! pfh = TAILQ_NEXT(pfh, pfil_link)) {
! if (pfh->pfil_func != NULL) {
! rv = (*pfh->pfil_func)(pfh->pfil_arg, &m, ifp, dir);
! if (rv != 0 || m == NULL)
! break;
! }
! }
!
! *mp = m;
! return (rv);
! }
! /*
! * pfil_head_register() registers a pfil_head with the packet filter
! * hook mechanism.
! */
! int
! pfil_head_register(struct pfil_head *ph)
{
+ struct pfil_head *lph;
! for (lph = LIST_FIRST(&pfil_head_list); lph != NULL;
! lph = LIST_NEXT(lph, ph_list)) {
! if (lph->ph_key == ph->ph_key &&
! lph->ph_dlt == ph->ph_dlt)
! return EEXIST;
! }
!
! TAILQ_INIT(&ph->ph_in);
TAILQ_INIT(&ph->ph_out);
!
! LIST_INSERT_HEAD(&pfil_head_list, ph, ph_list);
!
! return (0);
}
/*
+ * pfil_head_unregister() removes a pfil_head from the packet filter
+ * hook mechanism.
+ */
+ int
+ pfil_head_unregister(struct pfil_head *pfh)
+ {
+
+ LIST_REMOVE(pfh, ph_list);
+ return (0);
+ }
+
+ /*
+ * pfil_head_get() returns the pfil_head for a given key/dlt.
+ */
+ struct pfil_head *
+ pfil_head_get(void *key, int dlt)
+ {
+ struct pfil_head *ph;
+
+ for (ph = LIST_FIRST(&pfil_head_list); ph != NULL;
+ ph = LIST_NEXT(ph, ph_list)) {
+ if (ph->ph_key == key && ph->ph_dlt == dlt)
+ break;
+ }
+
+ return (ph);
+ }
+
+ /*
* pfil_add_hook() adds a function to the packet filter hook. the
* flags are:
* PFIL_IN call me on incoming packets
***************
*** 65,118 ****
* PFIL_WAITOK OK to call malloc with M_WAITOK.
*/
int
! pfil_add_hook(func, flags, ph)
! int (*func) __P((void *, int, struct ifnet *, int,
! struct mbuf **));
! int flags;
! struct pfil_head *ph;
{
int err = 0;
-
- if (ph->ph_init == 0)
- pfil_init(ph);
! if (flags & PFIL_IN)
! err = pfil_list_add(&ph->ph_in, func, flags & ~PFIL_OUT);
! if (err)
! return err;
! if (flags & PFIL_OUT)
! err = pfil_list_add(&ph->ph_out, func, flags & ~PFIL_IN);
! if (err) {
! if (flags & PFIL_IN)
! pfil_list_remove(&ph->ph_in, func);
! return err;
}
return 0;
}
static int
! pfil_list_add(list, func, flags)
! pfil_list_t *list;
! int (*func) __P((void *, int, struct ifnet *, int,
! struct mbuf **));
! int flags;
{
struct packet_filter_hook *pfh;
pfh = (struct packet_filter_hook *)malloc(sizeof(*pfh), M_IFADDR,
! flags & PFIL_WAITOK ? M_WAITOK : M_NOWAIT);
if (pfh == NULL)
return ENOMEM;
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);
return 0;
}
--- 135,195 ----
* PFIL_WAITOK OK to call malloc with M_WAITOK.
*/
int
! pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int),
! void *arg, int flags, struct pfil_head *ph)
{
int err = 0;
! if (flags & PFIL_IN) {
! err = pfil_list_add(&ph->ph_in, func, arg, flags & ~PFIL_OUT);
! if (err)
! return err;
! }
! if (flags & PFIL_OUT) {
! err = pfil_list_add(&ph->ph_out, func, arg, flags & ~PFIL_IN);
! if (err) {
! if (flags & PFIL_IN)
! pfil_list_remove(&ph->ph_in, func, arg);
! return err;
! }
}
return 0;
}
static int
! pfil_list_add(pfil_list_t *list,
! int (*func)(void *, struct mbuf **, struct ifnet *, int), void *arg,
! int flags)
{
struct packet_filter_hook *pfh;
+ /*
+ * First make sure the hook is not already there.
+ */
+ for (pfh = TAILQ_FIRST(list); pfh != NULL;
+ pfh = TAILQ_NEXT(pfh, pfil_link)) {
+ if (pfh->pfil_func == func &&
+ pfh->pfil_arg == arg)
+ return EEXIST;
+ }
+
pfh = (struct packet_filter_hook *)malloc(sizeof(*pfh), M_IFADDR,
! (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT);
if (pfh == NULL)
return ENOMEM;
+
pfh->pfil_func = func;
+ pfh->pfil_arg = arg;
+
/*
* 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);
+
return 0;
}
***************
*** 121,141 ****
* hook list.
*/
int
! pfil_remove_hook(func, flags, ph)
! int (*func) __P((void *, int, struct ifnet *, int,
! struct mbuf **));
! int flags;
! struct pfil_head *ph;
{
int err = 0;
- if (ph->ph_init == 0)
- pfil_init(ph);
-
if (flags & PFIL_IN)
! err = pfil_list_remove(&ph->ph_in, func);
if ((err == 0) && (flags & PFIL_OUT))
! err = pfil_list_remove(&ph->ph_out, func);
return err;
}
--- 198,212 ----
* hook list.
*/
int
! pfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int),
! void *arg, int flags, struct pfil_head *ph)
{
int err = 0;
if (flags & PFIL_IN)
! err = pfil_list_remove(&ph->ph_in, func, arg);
if ((err == 0) && (flags & PFIL_OUT))
! err = pfil_list_remove(&ph->ph_out, func, arg);
return err;
}
***************
*** 144,176 ****
* specified list.
*/
static int
! pfil_list_remove(list, func)
! pfil_list_t *list;
! int (*func) __P((void *, int, struct ifnet *, int,
! struct mbuf **));
{
struct packet_filter_hook *pfh;
! for (pfh = list->tqh_first; pfh; pfh = pfh->pfil_link.tqe_next)
! if (pfh->pfil_func == func) {
TAILQ_REMOVE(list, pfh, pfil_link);
free(pfh, M_IFADDR);
return 0;
}
return ENOENT;
- }
-
- struct packet_filter_hook *
- pfil_hook_get(flag, ph)
- int flag;
- struct pfil_head *ph;
- {
- 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;
}
--- 215,232 ----
* specified list.
*/
static int
! pfil_list_remove(pfil_list_t *list,
! int (*func)(void *, struct mbuf **, struct ifnet *, int), void *arg)
{
struct packet_filter_hook *pfh;
! for (pfh = TAILQ_FIRST(list); pfh != NULL;
! pfh = TAILQ_NEXT(pfh, pfil_link)) {
! if (pfh->pfil_func == func && pfh->pfil_arg == arg) {
TAILQ_REMOVE(list, pfh, pfil_link);
free(pfh, M_IFADDR);
return 0;
}
+ }
return ENOENT;
}
Index: net/pfil.h
===================================================================
RCS file: /cvsroot/syssrc/sys/net/pfil.h,v
retrieving revision 1.13
diff -c -r1.13 pfil.h
*** net/pfil.h 2000/04/19 04:46:23 1.13
--- net/pfil.h 2000/11/10 07:45:10
***************
*** 32,37 ****
--- 32,38 ----
#define _NET_PFIL_H_
#include <sys/queue.h>
+ #include <net/bpf.h>
struct mbuf;
struct ifnet;
***************
*** 42,49 ****
*/
struct packet_filter_hook {
TAILQ_ENTRY(packet_filter_hook) pfil_link;
! int (*pfil_func) __P((void *, int, struct ifnet *, int,
! struct mbuf **));
int pfil_flags;
};
--- 43,50 ----
*/
struct packet_filter_hook {
TAILQ_ENTRY(packet_filter_hook) pfil_link;
! int (*pfil_func)(void *, struct mbuf **, struct ifnet *, int);
! void *pfil_arg;
int pfil_flags;
};
***************
*** 57,71 ****
struct pfil_head {
pfil_list_t ph_in;
pfil_list_t ph_out;
! int ph_init;
};
typedef struct pfil_head pfil_head_t;
! struct packet_filter_hook *pfil_hook_get __P((int, struct pfil_head *));
! int pfil_add_hook __P((int (*func) __P((void *, int,
! struct ifnet *, int, struct mbuf **)), int, struct pfil_head *));
! int pfil_remove_hook __P((int (*func) __P((void *, int,
! struct ifnet *, int, struct mbuf **)), int, struct pfil_head *));
/* XXX */
#if defined(_KERNEL) && !defined(_LKM)
--- 58,93 ----
struct pfil_head {
pfil_list_t ph_in;
pfil_list_t ph_out;
! void *ph_key;
! int ph_dlt;
! LIST_ENTRY(pfil_head) ph_list;
};
typedef struct pfil_head pfil_head_t;
! int pfil_run_hooks(struct pfil_head *, struct mbuf **, struct ifnet *,
! int);
!
! int pfil_add_hook(int (*func)(void *, struct mbuf **,
! struct ifnet *, int), void *, int, struct pfil_head *);
! int pfil_remove_hook(int (*func)(void *, struct mbuf **,
! struct ifnet *, int), void *, int, struct pfil_head *);
!
! int pfil_head_register(struct pfil_head *);
! int pfil_head_unregister(struct pfil_head *);
!
! struct pfil_head *pfil_head_get(void *, int);
!
! static __inline struct packet_filter_hook *
! pfil_hook_get(int dir, struct pfil_head *ph)
! {
!
! if (dir == PFIL_IN)
! return (TAILQ_FIRST(&ph->ph_in));
! else if (dir == PFIL_OUT)
! return (TAILQ_FIRST(&ph->ph_out));
! else
! return (NULL);
! }
/* XXX */
#if defined(_KERNEL) && !defined(_LKM)
Index: netinet/fil.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/fil.c,v
retrieving revision 1.40
diff -c -r1.40 fil.c
*** netinet/fil.c 2000/10/08 13:01:30 1.40
--- netinet/fil.c 2000/11/10 07:45:11
***************
*** 713,718 ****
--- 713,760 ----
return pass;
}
+ #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) && \
+ defined(_KERNEL)
+ #include <net/pfil.h>
+
+ int
+ fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
+ {
+ struct ip *ip = mtod(*mp, struct ip *);
+ int rv, hlen = ip->ip_hl << 2;
+
+ /*
+ * We get the packet with all fields in network byte
+ * order. We expect ip_len and ip_off to be in host
+ * order. We frob them, call the filter, then frob
+ * them back.
+ *
+ * Note, we don't need to update the checksum, because
+ * it has already been verified.
+ */
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
+
+ rv = fr_check(ip, hlen, ifp, (dir == PFIL_OUT), mp);
+
+ HTONS(ip->ip_len);
+ HTONS(ip->ip_off);
+
+ return (rv);
+ }
+
+ #ifdef USE_INET6
+ #include <netinet/ip6.h>
+
+ int
+ fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
+ {
+
+ return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
+ ifp, (dir == PFIL_OUT), mp));
+ }
+ #endif
+ #endif /* __NetBSD_Version >= 105110000 && _KERNEL */
/*
* frcheck - filter check
Index: netinet/ip_fil.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_fil.c,v
retrieving revision 1.59
diff -c -r1.59 ip_fil.c
*** netinet/ip_fil.c 2000/08/22 16:02:16 1.59
--- netinet/ip_fil.c 2000/11/10 07:45:13
***************
*** 245,250 ****
--- 245,256 ----
# if defined(__sgi) || (defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000))
int error = 0;
# endif
+ #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)
+ struct pfil_head *ph_inet;
+ #ifdef USE_INET6
+ struct pfil_head *ph_inet6;
+ #endif
+ #endif
SPL_NET(s);
if (fr_running || (fr_checkp == fr_check)) {
***************
*** 264,272 ****
return EIO;
# ifdef NETBSD_PF
# if __NetBSD_Version__ >= 104200000
! error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
if (error) {
# ifdef USE_INET6
goto pfil_error;
--- 270,298 ----
return EIO;
# ifdef NETBSD_PF
+ # if __NetBSD_Version__ >= 105110000
+ ph_inet = pfil_head_get((void *)(u_long) AF_INET, DLT_RAW);
+ #ifdef USE_INET6
+ ph_inet6 = pfil_head_get((void *)(u_long) AF_INET6, DLT_RAW);
+ #endif
+ if (ph_inet == NULL
+ #ifdef USE_INET6
+ && ph_inet6 == NULL
+ #endif
+ )
+ return ENODEV;
+ # endif
# if __NetBSD_Version__ >= 104200000
! # if __NetBSD_Version__ >= 105110000
! if (ph_inet != NULL)
! error = pfil_add_hook((void *)fr_check_wrapper, NULL,
! PFIL_IN|PFIL_OUT, ph_inet);
! else
! error = 0;
! # else
! error = pfil_add_hook((void *)fr_check_wrapper, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+ # endif
if (error) {
# ifdef USE_INET6
goto pfil_error;
***************
*** 281,291 ****
pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
# endif
# ifdef USE_INET6
! error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
if (error) {
! pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
pfil_error:
appr_unload();
ip_natunload();
--- 307,330 ----
pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
# endif
# ifdef USE_INET6
! # if __NetBSD_Version__ >= 105110000
! if (ph_inet6 != NULL)
! error = pfil_add_hook((void *)fr_check_wrapper6, NULL,
! PFIL_IN|PFIL_OUT, ph_inet6);
! else
! error = 0;
! # else
! error = pfil_add_hook((void *)fr_check_wrapper6, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
+ # endif
if (error) {
! # if __NetBSD_Version__ >= 105110000
! pfil_remove_hook((void *)fr_check_wrapper, NULL,
! PFIL_IN|PFIL_OUT, ph_inet);
! # else
! pfil_remove_hook((void *)fr_check_wrapper, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+ # endif
pfil_error:
appr_unload();
ip_natunload();
***************
*** 354,359 ****
--- 393,406 ----
{
int s, i = FR_INQUE|FR_OUTQUE;
#if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)
+ # if __NetBSD_Version__ >= 105110000
+ struct pfil_head *ph_inet = pfil_head_get((void *)(u_long) AF_INET,
+ DLT_RAW);
+ #ifdef USE_INET6
+ struct pfil_head *ph_inet6 = pfil_head_get((void *)(u_long) AF_INET6,
+ DLT_RAW);
+ #endif
+ # endif
int error = 0;
#endif
***************
*** 388,403 ****
# ifdef NETBSD_PF
# if __NetBSD_Version__ >= 104200000
! error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
if (error)
return error;
# else
pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
# endif
# ifdef USE_INET6
! error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
if (error)
return error;
# endif
--- 435,466 ----
# ifdef NETBSD_PF
# if __NetBSD_Version__ >= 104200000
! # if __NetBSD_Version__ >= 105110000
! if (ph_inet != NULL)
! error = pfil_remove_hook((void *)fr_check_wrapper, NULL,
! PFIL_IN|PFIL_OUT, ph_inet);
! else
! error = 0;
! # else
! error = pfil_remove_hook((void *)fr_check_wrapper, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+ # endif
if (error)
return error;
# else
pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
# endif
# ifdef USE_INET6
! # if __NetBSD_Version__ >= 105110000
! if (ph_inet6 != NULL)
! error = pfil_remove_hook((void *)fr_check_wrapper6, NULL,
! PFIL_IN|PFIL_OUT, ph_inet6);
! else
! error = 0;
! # else
! error = pfil_remove_hook((void *)fr_check_wrapper6, PFIL_IN|PFIL_OUT,
&inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
+ # endif
if (error)
return error;
# endif
Index: netinet/ip_fil.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_fil.h,v
retrieving revision 1.37
diff -c -r1.37 ip_fil.h
*** netinet/ip_fil.h 2000/06/12 10:28:21 1.37
--- netinet/ip_fil.h 2000/11/10 07:45:13
***************
*** 531,536 ****
--- 531,542 ----
extern int fr_qout __P((queue_t *, mblk_t *));
extern int iplread __P((dev_t, struct uio *, cred_t *));
# else /* SOLARIS */
+ #if defined(__NetBSD__)
+ extern int fr_check_wrapper __P((void *, struct mbuf **,
+ struct ifnet *, int));
+ extern int fr_check_wrapper6 __P((void *, struct mbuf **,
+ struct ifnet *, int));
+ #endif
extern int fr_check __P((ip_t *, int, void *, int, mb_t **));
extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **));
extern int ipfr_fastroute __P((mb_t *, fr_info_t *, frdest_t *));
Index: netinet/ip_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_input.c,v
retrieving revision 1.120
diff -c -r1.120 ip_input.c
*** netinet/ip_input.c 2000/11/08 14:28:15 1.120
--- netinet/ip_input.c 2000/11/10 07:45:14
***************
*** 205,210 ****
--- 205,214 ----
struct ipstat ipstat;
u_int16_t ip_id;
+ #ifdef PFIL_HOOKS
+ struct pfil_head inet_pfil_hook;
+ #endif
+
struct ipqhead ipq;
int ipq_locked;
***************
*** 312,317 ****
--- 316,331 ----
#ifdef GATEWAY
ipflow_init();
#endif
+
+ #ifdef PFIL_HOOKS
+ /* Register our Packet Filter hook. */
+ inet_pfil_hook.ph_key = (void *)(u_long) AF_INET;
+ inet_pfil_hook.ph_dlt = DLT_RAW;
+ i = pfil_head_register(&inet_pfil_hook);
+ if (i != 0)
+ printf("ip_init: WARNING: unable to register pfil hook, "
+ "error %d\n", i);
+ #endif /* PFIL_HOOKS */
}
struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET };
***************
*** 350,360 ****
struct ipqent *ipqe;
int hlen = 0, mff, len;
int downmatch;
- #ifdef PFIL_HOOKS
- struct packet_filter_hook *pfh;
- struct mbuf *m0;
- int rv;
- #endif /* PFIL_HOOKS */
#ifdef DIAGNOSTIC
if ((m->m_flags & M_PKTHDR) == 0)
--- 364,369 ----
***************
*** 414,425 ****
goto bad;
}
! /*
! * Convert fields to host representation.
! */
! NTOHS(ip->ip_len);
! NTOHS(ip->ip_off);
! len = ip->ip_len;
/*
* Check for additional length bogosity
--- 423,430 ----
goto bad;
}
! /* Retrieve the packet length. */
! len = ntohs(ip->ip_len);
/*
* Check for additional length bogosity
***************
*** 466,485 ****
* 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_IP]].pr_pfh);
! 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;
! if (m == NULL)
! return;
! ip = mtod(m, struct ip *);
! }
#endif /* PFIL_HOOKS */
/*
* Process options and, if not destined for us,
--- 471,489 ----
* Note that filters must _never_ set this flag, as another filter
* in the list may have previously cleared it.
*/
! if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif,
! PFIL_IN) != 0)
! return;
! if (m == NULL)
! return;
! ip = mtod(m, struct ip *);
#endif /* PFIL_HOOKS */
+
+ /*
+ * Convert fields to host representation.
+ */
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
/*
* Process options and, if not destined for us,
Index: netinet/ip_output.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_output.c,v
retrieving revision 1.77
diff -c -r1.77 ip_output.c
*** netinet/ip_output.c 2000/10/23 03:42:18 1.77
--- netinet/ip_output.c 2000/11/10 07:45:16
***************
*** 146,151 ****
--- 146,155 ----
static void ip_mloopback
__P((struct ifnet *, struct mbuf *, struct sockaddr_in *));
+ #ifdef PFIL_HOOKS
+ extern struct pfil_head inet_pfil_hook; /* XXX */
+ #endif
+
/*
* IP output. The packet in mbuf chain m contains a skeletal IP
* header (with len, off, ttl, proto, tos, src, dst).
***************
*** 176,190 ****
int mtu;
struct ip_moptions *imo;
va_list ap;
- #ifdef PFIL_HOOKS
- struct packet_filter_hook *pfh;
- struct mbuf *m1;
- int rv;
- #endif /* PFIL_HOOKS */
#ifdef IPSEC
struct socket *so;
struct secpolicy *sp = NULL;
#endif /*IPSEC*/
va_start(ap, m0);
opt = va_arg(ap, struct mbuf *);
--- 180,190 ----
int mtu;
struct ip_moptions *imo;
va_list ap;
#ifdef IPSEC
struct socket *so;
struct secpolicy *sp = NULL;
#endif /*IPSEC*/
+ u_int16_t ip_len, ip_off;
va_start(ap, m0);
opt = va_arg(ap, struct mbuf *);
***************
*** 420,443 ****
(ro->ro_rt->rt_rmx.rmx_locks & RTV_MTU) == 0)
ip->ip_off |= IP_DF;
#ifdef PFIL_HOOKS
/*
* Run through list of hooks for output packets.
*/
! m1 = m;
! pfh = pfil_hook_get(PFIL_OUT, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
! for (; pfh; pfh = pfh->pfil_link.tqe_next)
! if (pfh->pfil_func) {
! rv = pfh->pfil_func(ip, hlen, ifp, 1, &m1);
! if (rv) {
! error = EHOSTUNREACH;
! goto done;
! }
! m = m1;
! if (m == NULL)
! goto done;
! ip = mtod(m, struct ip *);
! }
#endif /* PFIL_HOOKS */
#ifdef IPSEC
--- 420,446 ----
(ro->ro_rt->rt_rmx.rmx_locks & RTV_MTU) == 0)
ip->ip_off |= IP_DF;
+ /*
+ * Remember the current ip_len and ip_off, and swap them into
+ * network order.
+ */
+ ip_len = ip->ip_len;
+ ip_off = ip->ip_off;
+
+ HTONS(ip->ip_len);
+ HTONS(ip->ip_off);
+
#ifdef PFIL_HOOKS
/*
* Run through list of hooks for output packets.
*/
! if ((error = pfil_run_hooks(&inet_pfil_hook, &m, ifp,
! PFIL_OUT)) != 0)
! goto done;
! if (m == NULL)
! goto done;
!
! ip = mtod(m, struct ip *);
#endif /* PFIL_HOOKS */
#ifdef IPSEC
***************
*** 482,490 ****
printf("ip_output: Invalid policy found. %d\n", sp->policy);
}
! ip->ip_len = htons((u_short)ip->ip_len);
! ip->ip_off = htons((u_short)ip->ip_off);
! ip->ip_sum = 0;
{
struct ipsec_output_state state;
--- 485,494 ----
printf("ip_output: Invalid policy found. %d\n", sp->policy);
}
! /*
! * ipsec4_output() expects ip_len and ip_off in network
! * order. They have been set to network order above.
! */
{
struct ipsec_output_state state;
***************
*** 541,546 ****
--- 545,553 ----
#else
hlen = ip->ip_hl << 2;
#endif
+ ip_len = ntohs(ip->ip_len);
+ ip_off = ntohs(ip->ip_off);
+
if (ro->ro_rt == NULL) {
if ((flags & IP_ROUTETOIF) == 0) {
printf("ip_output: "
***************
*** 553,568 ****
ifp = ro->ro_rt->rt_ifp;
}
- /* make it flipped, again. */
- ip->ip_len = ntohs((u_short)ip->ip_len);
- ip->ip_off = ntohs((u_short)ip->ip_off);
skip_ipsec:
#endif /*IPSEC*/
/*
* If small enough for mtu of path, can just send directly.
*/
! if ((u_int16_t)ip->ip_len <= mtu) {
#if IFA_STATS
/*
* search for the source address structure to
--- 560,572 ----
ifp = ro->ro_rt->rt_ifp;
}
skip_ipsec:
#endif /*IPSEC*/
/*
* If small enough for mtu of path, can just send directly.
*/
! if (ip_len <= mtu) {
#if IFA_STATS
/*
* search for the source address structure to
***************
*** 570,579 ****
*/
INADDR_TO_IA(ip->ip_src, ia);
if (ia)
! ia->ia_ifa.ifa_data.ifad_outbytes += ip->ip_len;
#endif
- HTONS(ip->ip_len);
- HTONS(ip->ip_off);
ip->ip_sum = 0;
ip->ip_sum = in_cksum(m, hlen);
error = (*ifp->if_output)(ifp, m, sintosa(dst), ro->ro_rt);
--- 574,581 ----
*/
INADDR_TO_IA(ip->ip_src, ia);
if (ia)
! ia->ia_ifa.ifa_data.ifad_outbytes += ip_len;
#endif
ip->ip_sum = 0;
ip->ip_sum = in_cksum(m, hlen);
error = (*ifp->if_output)(ifp, m, sintosa(dst), ro->ro_rt);
***************
*** 583,589 ****
--- 585,598 ----
/*
* Too large for interface; fragment if possible.
* Must be able to put at least 8 bytes per fragment.
+ *
+ * Note we swap ip_len and ip_off into host order to make
+ * the logic below a little simpler.
*/
+
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
+
#if 0
/*
* If IPsec packet is too big for the interface, try fragment it.
Index: netinet6/ip6_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ip6_input.c,v
retrieving revision 1.28
diff -c -r1.28 ip6_input.c
*** netinet6/ip6_input.c 2000/10/23 03:45:25 1.28
--- netinet6/ip6_input.c 2000/11/10 07:45:17
***************
*** 140,145 ****
--- 140,149 ----
ip6_fw_ctl_t *ip6_fw_ctl_ptr;
#endif
+ #ifdef PFIL_HOOKS
+ struct pfil_head inet6_pfil_hook;
+ #endif
+
struct ip6stat ip6stat;
static void ip6_init2 __P((void *));
***************
*** 181,186 ****
--- 185,200 ----
ip6_flow_seq = random() ^ tv.tv_usec;
ip6_init2((void *)0);
+
+ #ifdef PFIL_HOOKS
+ /* Register our Packet Filter hook. */
+ inet6_pfil_hook.ph_key = (void *)(u_long) AF_INET6;
+ inet6_pfil_hook.ph_dlt = DLT_RAW;
+ i = pfil_head_register(&inet6_pfil_hook);
+ if (i != 0)
+ printf("ip6_init: WARNING: unable to register pfil hook, "
+ "error %d\n", i);
+ #endif /* PFIL_HOOKS */
}
static void
***************
*** 232,242 ****
u_int32_t rtalert = ~0;
int nxt, ours = 0;
struct ifnet *deliverifp = NULL;
- #ifdef PFIL_HOOKS
- struct packet_filter_hook *pfh;
- struct mbuf *m0;
- int rv;
- #endif /* PFIL_HOOKS */
#ifdef IPSEC
/*
--- 246,251 ----
***************
*** 303,321 ****
* 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]].pr_pfh);
! 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 */
--- 312,323 ----
* Note that filters must _never_ set this flag, as another filter
* in the list may have previously cleared it.
*/
! if (pfil_run_hooks(&inet6_pfil_hook, &m, m->m_pkthdr.rcvif,
! PFIL_IN) != 0)
! return;
! if (m == NULL)
! return;
! ip6 = mtod(m, struct ip6_hdr *);
#endif /* PFIL_HOOKS */
Index: netinet6/ip6_output.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ip6_output.c,v
retrieving revision 1.26
diff -c -r1.26 ip6_output.c
*** netinet6/ip6_output.c 2000/10/23 03:45:25 1.26
--- netinet6/ip6_output.c 2000/11/10 07:45:18
***************
*** 106,111 ****
--- 106,115 ----
#include <netinet6/ip6_fw.h>
#endif
+ #ifdef PFIL_HOOKS
+ extern struct pfil_head inet6_pfil_hook; /* XXX */
+ #endif
+
struct ip6_exthdrs {
struct mbuf *ip6e_ip6;
struct mbuf *ip6e_hbh;
***************
*** 157,167 ****
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;
--- 161,166 ----
***************
*** 826,845 ****
/*
* Run through list of hooks for output packets.
*/
! m1 = m;
! pfh = pfil_hook_get(PFIL_OUT, &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
! for (; pfh; pfh = pfh->pfil_link.tqe_next)
! if (pfh->pfil_func) {
! rv = pfh->pfil_func(ip6, sizeof(*ip6), ifp, 1, &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.
--- 825,836 ----
/*
* Run through list of hooks for output packets.
*/
! if ((error = pfil_run_hooks(&inet6_pfil_hook, &m, ifp,
! PFIL_OUT)) != 0)
! goto done;
! if (m == NULL)
! goto done;
! ip6 = mtod(m, struct ip6_hdr *);
#endif /* PFIL_HOOKS */
/*
* Send the packet to the outgoing interface.
Index: netinet6/ip6protosw.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ip6protosw.h,v
retrieving revision 1.7
diff -c -r1.7 ip6protosw.h
*** netinet6/ip6protosw.h 2000/10/18 21:14:16 1.7
--- netinet6/ip6protosw.h 2000/11/10 07:45:18
***************
*** 75,81 ****
* Protocol switch table for IPv6.
* All other definitions should refer to sys/protosw.h
*/
- #include <net/pfil.h>
struct mbuf;
struct sockaddr;
--- 75,80 ----
***************
*** 141,147 ****
__P((void));
int (*pr_sysctl) /* sysctl for protocol */
__P((int *, u_int, void *, size_t *, void *, size_t));
- struct pfil_head pr_pfh;
};
extern struct ip6protosw inet6sw[];
--- 140,145 ----
Index: sys/param.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/param.h,v
retrieving revision 1.110
diff -c -r1.110 param.h
*** sys/param.h 2000/11/08 14:53:23 1.110
--- sys/param.h 2000/11/10 07:45:18
***************
*** 65,71 ****
*
*/
! #define __NetBSD_Version__ 105100000 /* NetBSD 1.5J */
/*
* Historical NetBSD #define
--- 65,71 ----
*
*/
! #define __NetBSD_Version__ 105110000 /* NetBSD 1.5K */
/*
* Historical NetBSD #define
Index: sys/protosw.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/protosw.h,v
retrieving revision 1.22
diff -c -r1.22 protosw.h
*** sys/protosw.h 2000/02/17 10:59:41 1.22
--- sys/protosw.h 2000/11/10 07:45:19
***************
*** 61,71 ****
* described below.
*/
- /*
- * For pfil_head structure.
- */
- #include <net/pfil.h>
-
struct mbuf;
struct sockaddr;
struct socket;
--- 61,66 ----
***************
*** 105,111 ****
__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 */
--- 100,105 ----