summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormlaier <mlaier@FreeBSD.org>2004-09-29 04:54:33 +0000
committermlaier <mlaier@FreeBSD.org>2004-09-29 04:54:33 +0000
commitb65eae4c193f1c3c9580e5ac2bad5585034743f2 (patch)
treeb760834c7691b17430788d5a6041455045da8ac1
parente455dd69f84961133d47cca1588021dfafac9e28 (diff)
downloadFreeBSD-src-b65eae4c193f1c3c9580e5ac2bad5585034743f2.zip
FreeBSD-src-b65eae4c193f1c3c9580e5ac2bad5585034743f2.tar.gz
Add an additional struct inpcb * argument to pfil(9) in order to enable
passing along socket information. This is required to work around a LOR with the socket code which results in an easy reproducible hard lockup with debug.mpsafenet=1. This commit does *not* fix the LOR, but enables us to do so later. The missing piece is to turn the filter locking into a leaf lock and will follow in a seperate (later) commit. This will hopefully be MT5'ed in order to fix the problem for RELENG_5 in forseeable future. Suggested by: rwatson A lot of work by: csjp (he'd be even more helpful w/o mentor-reviews ;) Reviewed by: rwatson, csjp Tested by: -pf, -ipfw, LINT, csjp and myself MFC after: 3 days LOR IDs: 14 - 17 (not fixed yet)
-rw-r--r--UPDATING5
-rw-r--r--share/man/man9/pfil.96
-rw-r--r--sys/contrib/ipfilter/netinet/ip_fil.c27
-rw-r--r--sys/contrib/pf/net/pf.c87
-rw-r--r--sys/contrib/pf/net/pf_ioctl.c28
-rw-r--r--sys/contrib/pf/net/pfvar.h11
-rw-r--r--sys/net/bridge.c2
-rw-r--r--sys/net/pfil.c12
-rw-r--r--sys/net/pfil.h9
-rw-r--r--sys/netinet/ip_fastfwd.c4
-rw-r--r--sys/netinet/ip_fw.h5
-rw-r--r--sys/netinet/ip_fw2.c43
-rw-r--r--sys/netinet/ip_fw_pfil.c8
-rw-r--r--sys/netinet/ip_input.c2
-rw-r--r--sys/netinet/ip_output.c2
-rw-r--r--sys/netinet6/ip6_forward.c2
-rw-r--r--sys/netinet6/ip6_input.c2
-rw-r--r--sys/netinet6/ip6_output.c2
-rw-r--r--sys/sys/param.h2
19 files changed, 206 insertions, 53 deletions
diff --git a/UPDATING b/UPDATING
index ed87094..c42ae04 100644
--- a/UPDATING
+++ b/UPDATING
@@ -23,6 +23,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 6.x IS SLOW:
developers choose to disable these features on build machines
to maximize performance.
+20040929:
+ The pfil API has gained an additional argument to pass an inpcb.
+ You should rebuild all pfil consuming modules: ipfw, ipfilter
+ and pf.
+
20040928:
If enabled, the default is now to run named in a chroot
"sandbox." For users with existing configurations in
diff --git a/share/man/man9/pfil.9 b/share/man/man9/pfil.9
index c0da628..293e605 100644
--- a/share/man/man9/pfil.9
+++ b/share/man/man9/pfil.9
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 8, 2003
+.Dd September 29, 2004
.Dt PFIL 9
.Os
.Sh NAME
@@ -59,9 +59,9 @@
.Ft void
.Fn pfil_remove_hook "int (*func)()" "void *arg" "int flags" "struct pfil_head *"
.Ft int
-.Fn (*func) "void *arg" "struct mbuf **mp" "struct ifnet *" "int dir"
+.Fn (*func) "void *arg" "struct mbuf **mp" "struct ifnet *" "int dir" "struct inpcb *"
.Ft int
-.Fn pfil_run_hooks "struct pfil_head *head" "struct mbuf **mp" "struct ifnet *" "int dir"
+.Fn pfil_run_hooks "struct pfil_head *head" "struct mbuf **mp" "struct ifnet *" "int dir" "struct inpcb *"
.Sh DESCRIPTION
The
.Nm
diff --git a/sys/contrib/ipfilter/netinet/ip_fil.c b/sys/contrib/ipfilter/netinet/ip_fil.c
index 9ac3fb2..954f540 100644
--- a/sys/contrib/ipfilter/netinet/ip_fil.c
+++ b/sys/contrib/ipfilter/netinet/ip_fil.c
@@ -312,7 +312,8 @@ int dir;
}
# endif
#endif /* __NetBSD_Version >= 105110000 && _KERNEL */
-#if (__FreeBSD_version >= 501108) && defined(_KERNEL)
+#if (__FreeBSD_version >= 501108) && (__FreeBSD_version < 600004) && \
+ defined(_KERNEL)
static int
fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
@@ -331,7 +332,29 @@ fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
ifp, (dir == PFIL_OUT), mp));
}
# endif
-#endif /* __FreeBSD_version >= 501108 */
+
+#elif (__FreeBSD_version >= 600004) && defined(_KERNEL)
+
+static int
+fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
+{
+ struct ip *ip = mtod(*mp, struct ip *);
+ return fr_check(ip, ip->ip_hl << 2, ifp, (dir == PFIL_OUT), mp);
+}
+
+# ifdef USE_INET6
+# include <netinet/ip6.h>
+
+static int
+fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
+{
+ return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
+ ifp, (dir == PFIL_OUT), mp));
+}
+# endif
+#endif /* __FreeBSD_version >= 600004 && _KERNEL */
#ifdef _KERNEL
# if defined(IPFILTER_LKM) && !defined(__sgi)
int iplidentify(s)
diff --git a/sys/contrib/pf/net/pf.c b/sys/contrib/pf/net/pf.c
index 9e2bfee..2a5b627 100644
--- a/sys/contrib/pf/net/pf.c
+++ b/sys/contrib/pf/net/pf.c
@@ -185,11 +185,19 @@ struct pf_rule *pf_get_translation(struct pf_pdesc *, struct mbuf *,
int pf_test_tcp(struct pf_rule **, struct pf_state **,
int, struct pfi_kif *, struct mbuf *, int,
void *, struct pf_pdesc *, struct pf_rule **,
+#ifdef __FreeBSD__
+ struct pf_ruleset **, struct inpcb *);
+#else
struct pf_ruleset **);
+#endif
int pf_test_udp(struct pf_rule **, struct pf_state **,
int, struct pfi_kif *, struct mbuf *, int,
void *, struct pf_pdesc *, struct pf_rule **,
+#ifdef __FreeBSD__
+ struct pf_ruleset **, struct inpcb *);
+#else
struct pf_ruleset **);
+#endif
int pf_test_icmp(struct pf_rule **, struct pf_state **,
int, struct pfi_kif *, struct mbuf *, int,
void *, struct pf_pdesc *, struct pf_rule **,
@@ -229,8 +237,13 @@ void pf_route(struct mbuf **, struct pf_rule *, int,
struct ifnet *, struct pf_state *);
void pf_route6(struct mbuf **, struct pf_rule *, int,
struct ifnet *, struct pf_state *);
+#ifdef __FreeBSD__
+int pf_socket_lookup(uid_t *, gid_t *,
+ int, struct pf_pdesc *, struct inpcb *);
+#else
int pf_socket_lookup(uid_t *, gid_t *,
int, struct pf_pdesc *);
+#endif
u_int8_t pf_get_wscale(struct mbuf *, int, u_int16_t,
sa_family_t);
u_int16_t pf_get_mss(struct mbuf *, int, u_int16_t,
@@ -2376,7 +2389,12 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
}
int
+#ifdef __FreeBSD__
+pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, struct pf_pdesc *pd,
+ struct inpcb *inp_arg)
+#else
pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, struct pf_pdesc *pd)
+#endif
{
struct pf_addr *saddr, *daddr;
u_int16_t sport, dport;
@@ -2389,6 +2407,17 @@ pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, struct pf_pdesc *pd)
*uid = UID_MAX;
*gid = GID_MAX;
+#ifdef __FreeBSD__
+ if (inp_arg != NULL) {
+ INP_LOCK_ASSERT(inp_arg);
+ if (inp_arg->inp_socket) {
+ *uid = inp_arg->inp_socket->so_cred->cr_uid;
+ *gid = inp_arg->inp_socket->so_cred->cr_groups[0];
+ return (1);
+ } else
+ return (0);
+ }
+#endif
switch (pd->proto) {
case IPPROTO_TCP:
sport = pd->hdr.tcp->th_sport;
@@ -2663,7 +2692,12 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
int
pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
struct pfi_kif *kif, struct mbuf *m, int off, void *h,
+#ifdef __FreeBSD__
+ struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
+ struct inpcb *inp)
+#else
struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)
+#endif
{
struct pf_rule *nr = NULL;
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
@@ -2742,12 +2776,20 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
else if ((r->flagset & th->th_flags) != r->flags)
r = TAILQ_NEXT(r, entries);
else if (r->uid.op && (lookup != -1 || (lookup =
+#ifdef __FreeBSD__
+ pf_socket_lookup(&uid, &gid, direction, pd, inp), 1)) &&
+#else
pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
+#endif
!pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
uid))
r = TAILQ_NEXT(r, entries);
else if (r->gid.op && (lookup != -1 || (lookup =
+#ifdef __FreeBSD__
+ pf_socket_lookup(&uid, &gid, direction, pd, inp), 1)) &&
+#else
pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
+#endif
!pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
gid))
r = TAILQ_NEXT(r, entries);
@@ -3023,7 +3065,12 @@ cleanup:
int
pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
struct pfi_kif *kif, struct mbuf *m, int off, void *h,
+#ifdef __FreeBSD__
+ struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
+ struct inpcb *inp)
+#else
struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)
+#endif
{
struct pf_rule *nr = NULL;
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
@@ -3099,12 +3146,20 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
else if (r->rule_flag & PFRULE_FRAGMENT)
r = TAILQ_NEXT(r, entries);
else if (r->uid.op && (lookup != -1 || (lookup =
+#ifdef __FreeBSD__
+ pf_socket_lookup(&uid, &gid, direction, pd, inp), 1)) &&
+#else
pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
+#endif
!pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
uid))
r = TAILQ_NEXT(r, entries);
else if (r->gid.op && (lookup != -1 || (lookup =
+#ifdef __FreeBSD__
+ pf_socket_lookup(&uid, &gid, direction, pd, inp), 1)) &&
+#else
pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
+#endif
!pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
gid))
r = TAILQ_NEXT(r, entries);
@@ -5229,7 +5284,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
if (oifp != ifp) {
#ifdef __FreeBSD__
PF_UNLOCK();
- if (pf_test(PF_OUT, ifp, &m0) != PF_PASS) {
+ if (pf_test(PF_OUT, ifp, &m0, NULL) != PF_PASS) {
PF_LOCK();
goto bad;
} else if (m0 == NULL) {
@@ -5519,7 +5574,7 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
if (oifp != ifp) {
#ifdef __FreeBSD__
PF_UNLOCK();
- if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS) {
+ if (pf_test6(PF_OUT, ifp, &m0, NULL) != PF_PASS) {
PF_LOCK();
goto bad;
} else if (m0 == NULL) {
@@ -5811,7 +5866,11 @@ pf_add_mbuf_tag(struct mbuf *m, u_int tag)
#ifdef INET
int
+#ifdef __FreeBSD__
+pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
+#else
pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
+#endif
{
struct pfi_kif *kif;
u_short action, reason = 0, log = 0;
@@ -5925,8 +5984,13 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_tcp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, inp);
+#else
action = pf_test_tcp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
+#endif
break;
}
@@ -5959,8 +6023,13 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_udp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, inp);
+#else
action = pf_test_udp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
+#endif
break;
}
@@ -6137,7 +6206,11 @@ done:
#ifdef INET6
int
+#ifdef __FreeBSD__
+pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
+#else
pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
+#endif
{
struct pfi_kif *kif;
u_short action, reason = 0, log = 0;
@@ -6274,8 +6347,13 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_tcp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, inp);
+#else
action = pf_test_tcp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
+#endif
break;
}
@@ -6308,8 +6386,13 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_udp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, inp);
+#else
action = pf_test_udp(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset);
+#endif
break;
}
diff --git a/sys/contrib/pf/net/pf_ioctl.c b/sys/contrib/pf/net/pf_ioctl.c
index 9e173ba..4767dee 100644
--- a/sys/contrib/pf/net/pf_ioctl.c
+++ b/sys/contrib/pf/net/pf_ioctl.c
@@ -182,14 +182,14 @@ static void pf_clear_srcnodes(void);
* Wrapper functions for pfil(9) hooks
*/
static int pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp,
- int dir);
+ int dir, struct inpcb *inp);
static int pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp,
- int dir);
+ int dir, struct inpcb *inp);
#ifdef INET6
static int pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp,
- int dir);
+ int dir, struct inpcb *inp);
static int pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp,
- int dir);
+ int dir, struct inpcb *inp);
#endif
static int hook_pf(void);
@@ -3203,7 +3203,8 @@ shutdown_pf(void)
}
static int
-pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
+pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
{
/*
* XXX Wed Jul 9 22:03:16 2003 UTC
@@ -3222,7 +3223,7 @@ pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
HTONS(h->ip_len);
HTONS(h->ip_off);
}
- chk = pf_test(PF_IN, ifp, m);
+ chk = pf_test(PF_IN, ifp, m, inp);
if (chk && *m) {
m_freem(*m);
*m = NULL;
@@ -3237,7 +3238,8 @@ pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
}
static int
-pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
+pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
{
/*
* XXX Wed Jul 9 22:03:16 2003 UTC
@@ -3261,7 +3263,7 @@ pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
HTONS(h->ip_len);
HTONS(h->ip_off);
}
- chk = pf_test(PF_OUT, ifp, m);
+ chk = pf_test(PF_OUT, ifp, m, inp);
if (chk && *m) {
m_freem(*m);
*m = NULL;
@@ -3277,14 +3279,15 @@ pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
#ifdef INET6
static int
-pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
+pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
{
/*
* IPv6 does not affected ip_len/ip_off byte order changes.
*/
int chk;
- chk = pf_test6(PF_IN, ifp, m);
+ chk = pf_test6(PF_IN, ifp, m, inp);
if (chk && *m) {
m_freem(*m);
*m = NULL;
@@ -3293,7 +3296,8 @@ pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
}
static int
-pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
+pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
{
/*
* IPv6 does not affected ip_len/ip_off byte order changes.
@@ -3305,7 +3309,7 @@ pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
in_delayed_cksum(*m);
(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
}
- chk = pf_test6(PF_OUT, ifp, m);
+ chk = pf_test6(PF_OUT, ifp, m, inp);
if (chk && *m) {
m_freem(*m);
*m = NULL;
diff --git a/sys/contrib/pf/net/pfvar.h b/sys/contrib/pf/net/pfvar.h
index 11446f8..ab21c59 100644
--- a/sys/contrib/pf/net/pfvar.h
+++ b/sys/contrib/pf/net/pfvar.h
@@ -54,6 +54,9 @@
#include <netinet/tcp_fsm.h>
struct ip;
+#ifdef __FreeBSD__
+struct inpcb;
+#endif
#define PF_TCPS_PROXY_SRC ((TCP_NSTATES)+0)
#define PF_TCPS_PROXY_DST ((TCP_NSTATES)+1)
@@ -1453,11 +1456,19 @@ void pf_rm_rule(struct pf_rulequeue *,
struct pf_rule *);
#ifdef INET
+#ifdef __FreeBSD__
+int pf_test(int, struct ifnet *, struct mbuf **, struct inpcb *);
+#else
int pf_test(int, struct ifnet *, struct mbuf **);
+#endif
#endif /* INET */
#ifdef INET6
+#ifdef __FreeBSD__
+int pf_test6(int, struct ifnet *, struct mbuf **, struct inpcb *);
+#else
int pf_test6(int, struct ifnet *, struct mbuf **);
+#endif
void pf_poolmask(struct pf_addr *, struct pf_addr*,
struct pf_addr *, struct pf_addr *, u_int8_t);
void pf_addr_inc(struct pf_addr *, sa_family_t);
diff --git a/sys/net/bridge.c b/sys/net/bridge.c
index 1d4472e..75f7c30 100644
--- a/sys/net/bridge.c
+++ b/sys/net/bridge.c
@@ -1009,7 +1009,7 @@ bdg_forward(struct mbuf *m0, struct ifnet *dst)
ip->ip_len = ntohs(ip->ip_len);
ip->ip_off = ntohs(ip->ip_off);
- if (pfil_run_hooks(&inet_pfil_hook, &m0, src, PFIL_IN) != 0) {
+ if (pfil_run_hooks(&inet_pfil_hook, &m0, src, PFIL_IN, NULL) != 0) {
/* NB: hook should consume packet */
return NULL;
}
diff --git a/sys/net/pfil.c b/sys/net/pfil.c
index 942607c..f5fff2a 100644
--- a/sys/net/pfil.c
+++ b/sys/net/pfil.c
@@ -52,7 +52,7 @@ MTX_SYSINIT(pfil_heads_lock, &pfil_global_lock, "pfil_head_list lock", MTX_DEF);
static int pfil_list_add(pfil_list_t *, struct packet_filter_hook *, int);
static int pfil_list_remove(pfil_list_t *,
- int (*)(void *, struct mbuf **, struct ifnet *, int), void *);
+ int (*)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *), void *);
LIST_HEAD(, pfil_head) pfil_head_list =
LIST_HEAD_INITIALIZER(&pfil_head_list);
@@ -113,7 +113,7 @@ PFIL_WUNLOCK(struct pfil_head *ph)
*/
int
pfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp,
- int dir)
+ int dir, struct inpcb *inp)
{
struct packet_filter_hook *pfh;
struct mbuf *m = *mp;
@@ -126,7 +126,7 @@ pfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp,
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);
+ rv = (*pfh->pfil_func)(pfh->pfil_arg, &m, ifp, dir, inp);
if (rv != 0 || m == NULL)
break;
}
@@ -233,7 +233,7 @@ pfil_head_get(int type, u_long val)
* PFIL_WAITOK OK to call malloc with M_WAITOK.
*/
int
-pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int),
+pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *),
void *arg, int flags, struct pfil_head *ph)
{
struct packet_filter_hook *pfh1 = NULL;
@@ -305,7 +305,7 @@ error:
* hook list.
*/
int
-pfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int),
+pfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *),
void *arg, int flags, struct pfil_head *ph)
{
int err = 0;
@@ -361,7 +361,7 @@ pfil_list_add(pfil_list_t *list, struct packet_filter_hook *pfh1, int flags)
*/
static int
pfil_list_remove(pfil_list_t *list,
- int (*func)(void *, struct mbuf **, struct ifnet *, int), void *arg)
+ int (*func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *), void *arg)
{
struct packet_filter_hook *pfh;
diff --git a/sys/net/pfil.h b/sys/net/pfil.h
index 5400a72..ed5a3d0 100644
--- a/sys/net/pfil.h
+++ b/sys/net/pfil.h
@@ -40,6 +40,7 @@
struct mbuf;
struct ifnet;
+struct inpcb;
/*
* The packet filter hooks are designed for anything to call them to
@@ -47,7 +48,7 @@ struct ifnet;
*/
struct packet_filter_hook {
TAILQ_ENTRY(packet_filter_hook) pfil_link;
- int (*pfil_func)(void *, struct mbuf **, struct ifnet *, int);
+ int (*pfil_func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *);
void *pfil_arg;
int pfil_flags;
};
@@ -84,12 +85,12 @@ struct pfil_head {
};
int pfil_run_hooks(struct pfil_head *, struct mbuf **, struct ifnet *,
- int);
+ int, struct inpcb *inp);
int pfil_add_hook(int (*func)(void *, struct mbuf **,
- struct ifnet *, int), void *, int, struct pfil_head *);
+ struct ifnet *, int, struct inpcb *), void *, int, struct pfil_head *);
int pfil_remove_hook(int (*func)(void *, struct mbuf **,
- struct ifnet *, int), void *, int, struct pfil_head *);
+ struct ifnet *, int, struct inpcb *), void *, int, struct pfil_head *);
int pfil_head_register(struct pfil_head *);
int pfil_head_unregister(struct pfil_head *);
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
index 8d78c0e..9095756 100644
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -359,7 +359,7 @@ ip_fastforward(struct mbuf *m)
if (inet_pfil_hook.ph_busy_count == -1)
goto passin;
- if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN) ||
+ if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL) ||
m == NULL)
return 1;
@@ -437,7 +437,7 @@ passin:
if (inet_pfil_hook.ph_busy_count == -1)
goto passout;
- if (pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT) || m == NULL) {
+ if (pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT, NULL) || m == NULL) {
goto consumed;
}
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index 0229a22..ac903f5 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -425,6 +425,7 @@ struct ip_fw_args {
struct ipfw_flow_id f_id; /* grabbed from IP header */
u_int32_t retval;
+ struct inpcb *inp;
};
/*
@@ -435,8 +436,8 @@ struct ip_fw_args {
struct sockopt;
struct dn_flow_set;
-int ipfw_check_in(void *, struct mbuf **, struct ifnet *, int);
-int ipfw_check_out(void *, struct mbuf **, struct ifnet *, int);
+int ipfw_check_in(void *, struct mbuf **, struct ifnet *, int, struct inpcb *inp);
+int ipfw_check_out(void *, struct mbuf **, struct ifnet *, int, struct inpcb *inp);
int ipfw_chk(struct ip_fw_args *);
diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c
index a33b361..a8bcede 100644
--- a/sys/netinet/ip_fw2.c
+++ b/sys/netinet/ip_fw2.c
@@ -1532,21 +1532,48 @@ dump_table(ipfw_table *tbl)
return (0);
}
+static void
+fill_ugid_cache(struct inpcb *inp, struct ip_fw_ugid *ugp)
+{
+ struct ucred *cr;
+
+ if (inp->inp_socket != NULL) {
+ cr = inp->inp_socket->so_cred;
+ ugp->fw_prid = jailed(cr) ?
+ cr->cr_prison->pr_id : -1;
+ ugp->fw_uid = cr->cr_uid;
+ ugp->fw_ngroups = cr->cr_ngroups;
+ bcopy(cr->cr_groups, ugp->fw_groups,
+ sizeof(ugp->fw_groups));
+ }
+}
+
static int
check_uidgid(ipfw_insn_u32 *insn,
int proto, struct ifnet *oif,
struct in_addr dst_ip, u_int16_t dst_port,
struct in_addr src_ip, u_int16_t src_port,
- struct ip_fw_ugid *ugp, int *lookup)
+ struct ip_fw_ugid *ugp, int *lookup, struct inpcb *inp)
{
struct inpcbinfo *pi;
int wildcard;
struct inpcb *pcb;
int match;
- struct ucred *cr;
gid_t *gp;
/*
+ * Check to see if the UDP or TCP stack supplied us with
+ * the PCB. If so, rather then holding a lock and looking
+ * up the PCB, we can use the one that was supplied.
+ */
+ if (inp && *lookup == 0) {
+ INP_LOCK_ASSERT(inp);
+ if (inp->inp_socket != NULL) {
+ fill_ugid_cache(inp, ugp);
+ *lookup = 1;
+ }
+ }
+ /*
* If we have already been here and the packet has no
* PCB entry associated with it, then we can safely
* assume that this is a no match.
@@ -1563,7 +1590,7 @@ check_uidgid(ipfw_insn_u32 *insn,
return 0;
match = 0;
if (*lookup == 0) {
- INP_INFO_RLOCK(pi); /* XXX LOR with IPFW */
+ INP_INFO_RLOCK(pi);
pcb = (oif) ?
in_pcblookup_hash(pi,
dst_ip, htons(dst_port),
@@ -1576,13 +1603,7 @@ check_uidgid(ipfw_insn_u32 *insn,
if (pcb != NULL) {
INP_LOCK(pcb);
if (pcb->inp_socket != NULL) {
- cr = pcb->inp_socket->so_cred;
- ugp->fw_prid = jailed(cr) ?
- cr->cr_prison->pr_id : -1;
- ugp->fw_uid = cr->cr_uid;
- ugp->fw_ngroups = cr->cr_ngroups;
- bcopy(cr->cr_groups, ugp->fw_groups,
- sizeof(ugp->fw_groups));
+ fill_ugid_cache(pcb, ugp);
*lookup = 1;
}
INP_UNLOCK(pcb);
@@ -1938,7 +1959,7 @@ check_body:
proto, oif,
dst_ip, dst_port,
src_ip, src_port, &fw_ugid_cache,
- &ugid_lookup);
+ &ugid_lookup, args->inp);
break;
case O_RECV:
diff --git a/sys/netinet/ip_fw_pfil.c b/sys/netinet/ip_fw_pfil.c
index 69e0188..3b08f69 100644
--- a/sys/netinet/ip_fw_pfil.c
+++ b/sys/netinet/ip_fw_pfil.c
@@ -73,7 +73,8 @@ ip_dn_ruledel_t *ip_dn_ruledel_ptr = NULL;
static int ipfw_divert(struct mbuf **, int, int);
int
-ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
+ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
{
struct ip_fw_args args;
struct m_tag *dn_tag;
@@ -102,6 +103,7 @@ ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
again:
args.m = *m0;
+ args.inp = inp;
ipfw = ipfw_chk(&args);
*m0 = args.m;
@@ -156,7 +158,8 @@ pass:
}
int
-ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
+ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
{
struct ip_fw_args args;
struct m_tag *dn_tag;
@@ -186,6 +189,7 @@ ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir)
again:
args.m = *m0;
args.oif = ifp;
+ args.inp = inp;
ipfw = ipfw_chk(&args);
*m0 = args.m;
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 223866f..37fbfd6 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -437,7 +437,7 @@ tooshort:
odst = ip->ip_dst;
if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif,
- PFIL_IN) != 0)
+ PFIL_IN, NULL) != 0)
return;
if (m == NULL) /* consumed by filter */
return;
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index d50beef..dfc939b 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -662,7 +662,7 @@ spd_done:
/* Run through list of hooks for output packets. */
odst.s_addr = ip->ip_dst.s_addr;
- error = pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT);
+ error = pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT, inp);
if (error != 0 || m == NULL)
goto done;
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index 94206ab..c85e5e5 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -580,7 +580,7 @@ ip6_forward(m, srcrt)
goto pass;
/* Run through list of hooks for output packets. */
- error = pfil_run_hooks(&inet6_pfil_hook, &m, rt->rt_ifp, PFIL_OUT);
+ error = pfil_run_hooks(&inet6_pfil_hook, &m, rt->rt_ifp, PFIL_OUT, NULL);
if (error != 0)
goto senderr;
if (m == NULL)
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index e5bb0c3..dc3b318 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -424,7 +424,7 @@ ip6_input(m)
if (inet6_pfil_hook.ph_busy_count == -1)
goto passin;
- if (pfil_run_hooks(&inet6_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN))
+ if (pfil_run_hooks(&inet6_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL))
return;
if (m == NULL) /* consumed by filter */
return;
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index bdee8fe..03ef3bc 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -938,7 +938,7 @@ skip_ipsec2:;
goto passout;
/* Run through list of hooks for output packets. */
- error = pfil_run_hooks(&inet6_pfil_hook, &m, ifp, PFIL_OUT);
+ error = pfil_run_hooks(&inet6_pfil_hook, &m, ifp, PFIL_OUT, inp);
if (error != 0 || m == NULL)
goto done;
ip6 = mtod(m, struct ip6_hdr *);
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 8b062df..b0d5864 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -57,7 +57,7 @@
* is created, otherwise 1.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 600003 /* Master, propagated to newvers */
+#define __FreeBSD_version 600004 /* Master, propagated to newvers */
#ifndef LOCORE
#include <sys/types.h>
OpenPOWER on IntegriCloud