aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/ipfilter/netinet/ip_nat.c
diff options
context:
space:
mode:
authorDarren Reed <darrenr@FreeBSD.org>2007-10-30 15:23:27 +0000
committerDarren Reed <darrenr@FreeBSD.org>2007-10-30 15:23:27 +0000
commit782218e85136fb881684d81155c3b1c2b55bf112 (patch)
tree1df015570c1a9b7994c7f033dc2725b6926c0962 /sys/contrib/ipfilter/netinet/ip_nat.c
parent248a0568e7e2d0dc254d31f7a80b5e6397f9516c (diff)
downloadsrc-782218e85136fb881684d81155c3b1c2b55bf112.tar.gz
src-782218e85136fb881684d81155c3b1c2b55bf112.zip
Apply a few changes from ipfilter-current:
* Do not hold any locks over calls to copyin/copyout. * Clean up some #ifdefs * fix a possible mbuf leak when NAT fails on policy routed packets PR: 117216
Notes
Notes: svn path=/head/; revision=173181
Diffstat (limited to 'sys/contrib/ipfilter/netinet/ip_nat.c')
-rw-r--r--sys/contrib/ipfilter/netinet/ip_nat.c70
1 files changed, 44 insertions, 26 deletions
diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c
index 23cb57989b5b..a6963213a0a5 100644
--- a/sys/contrib/ipfilter/netinet/ip_nat.c
+++ b/sys/contrib/ipfilter/netinet/ip_nat.c
@@ -190,8 +190,8 @@ static void nat_addnat __P((struct ipnat *));
static void nat_addrdr __P((struct ipnat *));
static void nat_delrdr __P((struct ipnat *));
static void nat_delnat __P((struct ipnat *));
-static int fr_natgetent __P((caddr_t));
-static int fr_natgetsz __P((caddr_t));
+static int fr_natgetent __P((caddr_t, int));
+static int fr_natgetsz __P((caddr_t, int));
static int fr_natputent __P((caddr_t, int));
static int nat_extraflush __P((int));
static int nat_gettable __P((char *));
@@ -820,20 +820,23 @@ void *ctx;
{
natlookup_t nl;
- if (getlock) {
- READ_ENTER(&ipf_nat);
- }
error = fr_inobj(data, &nl, IPFOBJ_NATLOOKUP);
if (error == 0) {
- if (nat_lookupredir(&nl) != NULL) {
+ void *ptr;
+
+ if (getlock) {
+ READ_ENTER(&ipf_nat);
+ }
+ ptr = nat_lookupredir(&nl);
+ if (getlock) {
+ RWLOCK_EXIT(&ipf_nat);
+ }
+ if (ptr != NULL) {
error = fr_outobj(data, &nl, IPFOBJ_NATLOOKUP);
} else {
error = ESRCH;
}
}
- if (getlock) {
- RWLOCK_EXIT(&ipf_nat);
- }
break;
}
@@ -888,26 +891,14 @@ void *ctx;
case SIOCSTGSZ :
if (fr_nat_lock) {
- if (getlock) {
- READ_ENTER(&ipf_nat);
- }
- error = fr_natgetsz(data);
- if (getlock) {
- RWLOCK_EXIT(&ipf_nat);
- }
+ error = fr_natgetsz(data, getlock);
} else
error = EACCES;
break;
case SIOCSTGET :
if (fr_nat_lock) {
- if (getlock) {
- READ_ENTER(&ipf_nat);
- }
- error = fr_natgetent(data);
- if (getlock) {
- RWLOCK_EXIT(&ipf_nat);
- }
+ error = fr_natgetent(data, getlock);
} else
error = EACCES;
break;
@@ -1202,8 +1193,9 @@ int getlock;
/* The size of the entry is stored in the ng_sz field and the enture natget */
/* structure is copied back to the user. */
/* ------------------------------------------------------------------------ */
-static int fr_natgetsz(data)
+static int fr_natgetsz(data, getlock)
caddr_t data;
+int getlock;
{
ap_session_t *aps;
nat_t *nat, *n;
@@ -1212,6 +1204,10 @@ caddr_t data;
if (BCOPYIN(data, &ng, sizeof(ng)) != 0)
return EFAULT;
+ if (getlock) {
+ READ_ENTER(&ipf_nat);
+ }
+
nat = ng.ng_ptr;
if (!nat) {
nat = nat_instances;
@@ -1220,6 +1216,9 @@ caddr_t data;
* Empty list so the size returned is 0. Simple.
*/
if (nat == NULL) {
+ if (getlock) {
+ RWLOCK_EXIT(&ipf_nat);
+ }
if (BCOPYOUT(&ng, data, sizeof(ng)) != 0)
return EFAULT;
return 0;
@@ -1233,8 +1232,12 @@ caddr_t data;
for (n = nat_instances; n; n = n->nat_next)
if (n == nat)
break;
- if (!n)
+ if (n == NULL) {
+ if (getlock) {
+ RWLOCK_EXIT(&ipf_nat);
+ }
return ESRCH;
+ }
}
/*
@@ -1247,6 +1250,9 @@ caddr_t data;
if (aps->aps_data != 0)
ng.ng_sz += aps->aps_psiz;
}
+ if (getlock) {
+ RWLOCK_EXIT(&ipf_nat);
+ }
if (BCOPYOUT(&ng, data, sizeof(ng)) != 0)
return EFAULT;
@@ -1264,8 +1270,9 @@ caddr_t data;
/* Copies out NAT entry to user space. Any additional data held for a */
/* proxy is also copied, as to is the NAT rule which was responsible for it */
/* ------------------------------------------------------------------------ */
-static int fr_natgetent(data)
+static int fr_natgetent(data, getlock)
caddr_t data;
+int getlock;
{
int error, outsize;
ap_session_t *aps;
@@ -1283,6 +1290,10 @@ caddr_t data;
if (ipn == NULL)
return ENOMEM;
+ if (getlock) {
+ READ_ENTER(&ipf_nat);
+ }
+
ipn->ipn_dsize = ipns.ipn_dsize;
nat = ipns.ipn_next;
if (nat == NULL) {
@@ -1353,10 +1364,17 @@ caddr_t data;
error = ENOBUFS;
}
if (error == 0) {
+ if (getlock) {
+ RWLOCK_EXIT(&ipf_nat);
+ getlock = 0;
+ }
error = fr_outobjsz(data, ipn, IPFOBJ_NATSAVE, ipns.ipn_dsize);
}
finished:
+ if (getlock) {
+ RWLOCK_EXIT(&ipf_nat);
+ }
if (ipn != NULL) {
KFREES(ipn, ipns.ipn_dsize);
}