add packet filter interface code. see pfil(9) for more details. you

need the PACKET_FILTER option to enable this code.  currently, ipfilter
version 3.1.1-beta has been converted to use this new interface.
This commit is contained in:
mrg 1996-09-06 05:07:43 +00:00
parent 94bfaac456
commit ae47956db0
4 changed files with 210 additions and 7 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: in.c,v 1.29 1996/06/23 12:12:44 mycroft Exp $ */
/* $NetBSD: in.c,v 1.30 1996/09/06 05:07:43 mrg Exp $ */
/*
* Copyright (c) 1982, 1986, 1991, 1993
@ -43,12 +43,14 @@
#include <sys/socketvar.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/queue.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/in_var.h>
#include <netinet/if_ether.h>
#include <netinet/ip_mroute.h>
@ -62,6 +64,14 @@
#define SUBNETSARELOCAL 1
#endif
int subnetsarelocal = SUBNETSARELOCAL;
#ifdef PACKET_FILTER
LIST_HEAD(, packet_filter_hook) pfil_in_list;
LIST_HEAD(, packet_filter_hook) pfil_out_list;
LIST_HEAD(, packet_filter_hook) pfil_bad_list;
static int done_pfil_init;
#endif /* PACKET_FILTER */
/*
* Return 1 if an internet address is for a ``local'' host
* (one to which we have a connection). If subnetsarelocal
@ -555,5 +565,118 @@ in_delmulti(inm)
}
splx(s);
}
#endif
#ifdef PACKET_FILTER
void pfil_init __P((void));
int pfil_list_remove(struct packet_filter_hook *,
int (*) __P((void *, int, struct ifnet *, int, struct mbuf **)), int,
int);
void
pfil_init()
{
LIST_INIT(&pfil_in_list);
LIST_INIT(&pfil_out_list);
LIST_INIT(&pfil_bad_list);
done_pfil_init = 1;
}
/*
* pfil_add_hook() adds a function to the packet filter hook. the
* flags are:
* PFIL_IN call me on incoming packets
* PFIL_OUT call me on outgoing packets
* PFIL_BAD call me when rejecting a packet (that was
* not already reject by in/out filters).
* PFIL_ALL call me on all of the above
* 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;
{
struct packet_filter_hook *pfh;
if (done_pfil_init == 0)
pfil_init();
pfh = (struct packet_filter_hook *)malloc(sizeof(*pfh), M_IFADDR,
flags & PFIL_WAITOK ? M_WAITOK : M_NOWAIT);
if (pfh == NULL)
panic("no memory for packet filter hook");
pfh->pfil_flags = flags;
pfh->pfil_func = func;
if (flags & PFIL_IN)
LIST_INSERT_HEAD(&pfil_in_list, pfh, pfil_link);
if (flags & PFIL_OUT)
LIST_INSERT_HEAD(&pfil_out_list, pfh, pfil_link);
if (flags & PFIL_BAD)
LIST_INSERT_HEAD(&pfil_bad_list, pfh, pfil_link);
}
/*
* pfil_remove_hook removes a specific function from the packet filter
* 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.lh_first, func, flags, PFIL_IN))
return;
if (flags & PFIL_OUT &&
pfil_list_remove(pfil_out_list.lh_first, func, flags, PFIL_OUT))
return;
if (flags & PFIL_BAD &&
pfil_list_remove(pfil_bad_list.lh_first, func, flags, PFIL_BAD))
return;
}
int
pfil_list_remove(list, func, flags, flag)
struct packet_filter_hook *list;
int (*func) __P((void *, int, struct ifnet *, int,
struct mbuf **));
int flags, flag;
{
struct packet_filter_hook *pfh;
for (pfh = list; pfh; pfh = pfh->pfil_link.le_next)
if (pfh->pfil_func == func) {
pfh->pfil_flags &= ~flag;
LIST_REMOVE(pfh, pfil_link);
if ((flags & PFIL_ALL) == 0) {
free(pfh, M_IFADDR);
return 1;
}
}
return 0;
}
struct packet_filter_hook *
pfil_hook_get(flag)
int flag;
{
if (done_pfil_init)
switch (flag) {
case PFIL_IN:
return (pfil_in_list.lh_first);
case PFIL_OUT:
return (pfil_out_list.lh_first);
case PFIL_BAD:
return (pfil_bad_list.lh_first);
}
return NULL;
}
#endif /* PACKET_FILTER */

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip.h,v 1.9 1995/05/15 01:22:44 cgd Exp $ */
/* $NetBSD: ip.h,v 1.10 1996/09/06 05:07:43 mrg Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@ -160,6 +160,35 @@ struct ip_timestamp {
#define IPOPT_SECUR_SECRET 0xd788
#define IPOPT_SECUR_TOPSECRET 0x6bc5
/* we need this for the packet filter structure */
#include <sys/queue.h>
struct ifnet;
/*
* The packet filter hooks are designed for anything to call them to
* possibly intercept the packet.
*/
struct packet_filter_hook {
LIST_ENTRY(packet_filter_hook) pfil_link;
int (*pfil_func) __P((void *, int, struct ifnet *, int,
struct mbuf **));
int pfil_flags;
};
#define PFIL_IN 0x00000001
#define PFIL_OUT 0x00000002
#define PFIL_BAD 0x00000004
#define PFIL_WAITOK 0x00000008
#define PFIL_ALL (PFIL_IN|PFIL_OUT|PFIL_BAD)
#ifdef _KERNEL
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 */
/*
* Internet implementation parameters.
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_input.c,v 1.32 1996/08/14 03:46:44 thorpej Exp $ */
/* $NetBSD: ip_input.c,v 1.33 1996/09/06 05:07:44 mrg Exp $ */
/*
* Copyright (c) 1982, 1986, 1988, 1993
@ -153,12 +153,16 @@ struct route ipforward_rt;
void
ipintr()
{
register struct ip *ip;
register struct ip *ip = NULL;
register struct mbuf *m;
register struct ipq *fp;
register struct in_ifaddr *ia;
struct ipqent *ipqe;
int hlen, mff, s;
int hlen = 0, mff, s;
#ifdef PACKET_FILTER
struct packet_filter_hook *pfh;
struct mbuf *m0;
#endif /* PACKET_FILTER */
next:
/*
@ -237,6 +241,19 @@ next:
m_adj(m, ip->ip_len - m->m_pkthdr.len);
}
#ifdef PACKET_FILTER
/*
* Run through list of hooks for input packets.
*/
m0 = m;
for (pfh = pfil_hook_get(PFIL_IN); pfh; pfh = pfh->pfil_link.le_next)
if (pfh->pfil_func) {
if (pfh->pfil_func(ip, hlen, m->m_pkthdr.rcvif, 0, &m0))
goto bad;
ip = mtod(m = m0, struct ip *);
}
#endif /* PACKET_FILTER */
/*
* Process options and, if not destined for us,
* ship it on. ip_dooptions returns 1 when an
@ -418,6 +435,14 @@ found:
(*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
goto next;
bad:
#ifdef PACKET_FILTER
m0 = m;
for (pfh = pfil_hook_get(PFIL_BAD); pfh; pfh = pfh->pfil_link.le_next)
if (pfh->pfil_func) {
(void)pfh->pfil_func(ip, hlen, m->m_pkthdr.rcvif, 2, &m0);
ip = mtod(m = m0, struct ip *);
}
#endif /* PACKET_FILTER */
m_freem(m);
goto next;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_output.c,v 1.29 1996/02/26 23:17:12 mrg Exp $ */
/* $NetBSD: ip_output.c,v 1.30 1996/09/06 05:07:45 mrg Exp $ */
/*
* Copyright (c) 1982, 1986, 1988, 1990, 1993
@ -92,6 +92,10 @@ ip_output(m0, va_alist)
int flags;
struct ip_moptions *imo;
va_list ap;
#ifdef PACKET_FILTER
struct packet_filter_hook *pfh;
struct mbuf *m1;
#endif /* PACKET_FILTER */
va_start(ap, m0);
opt = va_arg(ap, struct mbuf *);
@ -293,6 +297,20 @@ ip_output(m0, va_alist)
} else
m->m_flags &= ~M_BCAST;
#ifdef PACKET_FILTER
/*
* Run through list of hooks for output packets.
*/
m1 = m;
for (pfh = pfil_hook_get(PFIL_OUT); pfh; pfh = pfh->pfil_link.le_next)
if (pfh->pfil_func) {
if (pfh->pfil_func(ip, hlen, m->m_pkthdr.rcvif, 1, &m1)) {
error = EHOSTUNREACH;
goto bad;
}
ip = mtod(m = m1, struct ip *);
}
#endif /* PACKET_FILTER */
sendit:
/*
* If small enough for interface, can just send directly.
@ -398,6 +416,14 @@ done:
RTFREE(ro->ro_rt);
return (error);
bad:
#ifdef PACKET_FILTER
m1 = m;
for (pfh = pfil_hook_get(PFIL_BAD); pfh; pfh = pfh->pfil_link.le_next)
if (pfh->pfil_func) {
(void)pfh->pfil_func(ip, hlen, m->m_pkthdr.rcvif, 2, &m1);
ip = mtod(m = m1, struct ip *);
}
#endif /* PACKET_FILTER */
m_freem(m0);
goto done;
}