svn commit: r234108 - projects/pf/head/sys/contrib/pf/net

Gleb Smirnoff glebius at FreeBSD.org
Tue Apr 10 19:11:10 UTC 2012


Author: glebius
Date: Tue Apr 10 19:11:09 2012
New Revision: 234108
URL: http://svn.freebsd.org/changeset/base/234108

Log:
  Get rid of copyin/copyout under locks in the pf table ioctls.
  This is done by allocation enough memory before entering the
  locked code.
  
  Ioctls fixed:
  DIOCRADDTABLES  +
  DIOCRDELTABLES  +
  DIOCRGETTABLES  +
  DIOCRGETTSTATS  +
  DIOCRCLRTSTATS  +
  DIOCRSETTFLAGS
  DIOCRADDADDRS   +
  DIOCRDELADDRS   +
  DIOCRSETADDRS   +
  DIOCRGETADDRS   +
  DIOCRCLRASTATS
  DIOCRTSTADDRS   +
  DIOCRINADEFINE  +
  
  Lack of + means that the ioctl wasn't tested, due to absence
  of it in the pfctl. However, code is quite similar, so I think
  these couple is also okay.
  
  While here, clean up some more code:
  - Don't pretend that we can use M_WAITOK in ioctl path. We can't.
    We need to acquire lock quite prior to allocating memory, and
    to fix that quite a lot needs to be redesigned.
  - Remove spl(9)

Modified:
  projects/pf/head/sys/contrib/pf/net/pf.c
  projects/pf/head/sys/contrib/pf/net/pf_if.c
  projects/pf/head/sys/contrib/pf/net/pf_ioctl.c
  projects/pf/head/sys/contrib/pf/net/pf_table.c
  projects/pf/head/sys/contrib/pf/net/pfvar.h

Modified: projects/pf/head/sys/contrib/pf/net/pf.c
==============================================================================
--- projects/pf/head/sys/contrib/pf/net/pf.c	Tue Apr 10 17:37:24 2012	(r234107)
+++ projects/pf/head/sys/contrib/pf/net/pf.c	Tue Apr 10 19:11:09 2012	(r234108)
@@ -1425,7 +1425,7 @@ pf_tbladdr_setup(struct pf_ruleset *rs, 
 {
 	if (aw->type != PF_ADDR_TABLE)
 		return (0);
-	if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname, 1)) == NULL)
+	if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname)) == NULL)
 		return (1);
 	return (0);
 }

Modified: projects/pf/head/sys/contrib/pf/net/pf_if.c
==============================================================================
--- projects/pf/head/sys/contrib/pf/net/pf_if.c	Tue Apr 10 17:37:24 2012	(r234107)
+++ projects/pf/head/sys/contrib/pf/net/pf_if.c	Tue Apr 10 19:11:09 2012	(r234108)
@@ -429,7 +429,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *a
 		goto _bad;
 	}
 
-	if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname, 1)) == NULL) {
+	if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname)) == NULL) {
 		rv = 1;
 		goto _bad;
 	}

Modified: projects/pf/head/sys/contrib/pf/net/pf_ioctl.c
==============================================================================
--- projects/pf/head/sys/contrib/pf/net/pf_ioctl.c	Tue Apr 10 17:37:24 2012	(r234107)
+++ projects/pf/head/sys/contrib/pf/net/pf_ioctl.c	Tue Apr 10 19:11:09 2012	(r234108)
@@ -1304,7 +1304,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca
 
 		if (rule->overload_tblname[0]) {
 			if ((rule->overload_tbl = pfr_attach_table(ruleset,
-			    rule->overload_tblname, 0)) == NULL)
+			    rule->overload_tblname)) == NULL)
 				error = EINVAL;
 			else
 				rule->overload_tbl->pfrkt_flags |=
@@ -1573,7 +1573,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca
 
 			if (newrule->overload_tblname[0]) {
 				if ((newrule->overload_tbl = pfr_attach_table(
-				    ruleset, newrule->overload_tblname, 0)) ==
+				    ruleset, newrule->overload_tblname)) ==
 				    NULL)
 					error = EINVAL;
 				else
@@ -1847,7 +1847,7 @@ DIOCGETSTATES_full:
 		    sizeof(struct pfsync_state) * nr);
 		if (error) {
 			free(pstore, M_TEMP);
-			goto fail;
+			break;
 		}
 		ps->ps_len = sizeof(struct pfsync_state) * nr;
 		free(pstore, M_TEMP);
@@ -1943,7 +1943,7 @@ DIOCGETSTATES_full:
 		if (pt->timeout < 0 || pt->timeout >= PFTM_MAX ||
 		    pt->seconds < 0) {
 			error = EINVAL;
-			goto fail;
+			break;
 		}
 		PF_LOCK();
 		old = V_pf_default_rule.timeout[pt->timeout];
@@ -1962,7 +1962,7 @@ DIOCGETSTATES_full:
 
 		if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) {
 			error = EINVAL;
-			goto fail;
+			break;
 		}
 		pt->seconds = V_pf_default_rule.timeout[pt->timeout];
 		break;
@@ -1973,7 +1973,7 @@ DIOCGETSTATES_full:
 
 		if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
 			error = EINVAL;
-			goto fail;
+			break;
 		}
 		pl->limit = V_pf_pool_limits[pl->index].limit;
 		break;
@@ -1988,7 +1988,7 @@ DIOCGETSTATES_full:
 		    V_pf_pool_limits[pl->index].pp == NULL) {
 			PF_UNLOCK();
 			error = EINVAL;
-			goto fail;
+			break;
 		}
 		uma_zone_set_max(V_pf_pool_limits[pl->index].pp, pl->limit);
 		old_limit = V_pf_pool_limits[pl->index].limit;
@@ -2544,86 +2544,140 @@ DIOCGETSTATES_full:
 
 	case DIOCRADDTABLES: {
 		struct pfioc_table *io = (struct pfioc_table *)addr;
+		struct pfr_table *pfrts;
+		size_t totlen;
 
 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
 			error = ENODEV;
 			break;
 		}
+		totlen = io->pfrio_size * sizeof(struct pfr_table);
+		pfrts = malloc(totlen, M_TEMP, M_WAITOK);
+		error = copyin(io->pfrio_buffer, pfrts, totlen);
+		if (error) {
+			free(pfrts, M_TEMP);
+			break;
+		}
 		PF_LOCK();
-		error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size,
+		error = pfr_add_tables(pfrts, io->pfrio_size,
 		    &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL);
 		PF_UNLOCK();
+		free(pfrts, M_TEMP);
 		break;
 	}
 
 	case DIOCRDELTABLES: {
 		struct pfioc_table *io = (struct pfioc_table *)addr;
+		struct pfr_table *pfrts;
+		size_t totlen;
 
 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
 			error = ENODEV;
 			break;
 		}
+		totlen = io->pfrio_size * sizeof(struct pfr_table);
+		pfrts = malloc(totlen, M_TEMP, M_WAITOK);
+		error = copyin(io->pfrio_buffer, pfrts, totlen);
+		if (error) {
+			free(pfrts, M_TEMP);
+			break;
+		}
 		PF_LOCK();
-		error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size,
+		error = pfr_del_tables(pfrts, io->pfrio_size,
 		    &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
 		PF_UNLOCK();
+		free(pfrts, M_TEMP);
 		break;
 	}
 
 	case DIOCRGETTABLES: {
 		struct pfioc_table *io = (struct pfioc_table *)addr;
+		struct pfr_table *pfrts;
+		size_t totlen;
 
 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
 			error = ENODEV;
 			break;
 		}
+		totlen = io->pfrio_size * sizeof(struct pfr_table);
+		pfrts = malloc(totlen, M_TEMP, M_WAITOK);
 		PF_LOCK();
-		error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer,
+		error = pfr_get_tables(&io->pfrio_table, pfrts,
 		    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
 		PF_UNLOCK();
+		if (error == 0)
+			error = copyout(pfrts, io->pfrio_buffer, totlen);
+		free(pfrts, M_TEMP);
 		break;
 	}
 
 	case DIOCRGETTSTATS: {
 		struct pfioc_table *io = (struct pfioc_table *)addr;
+		struct pfr_tstats *pfrtstats;
+		size_t totlen;
 
 		if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
 			error = ENODEV;
 			break;
 		}
+		totlen = io->pfrio_size * sizeof(struct pfr_tstats);
+		pfrtstats = malloc(totlen, M_TEMP, M_WAITOK);
 		PF_LOCK();
-		error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer,
+		error = pfr_get_tstats(&io->pfrio_table, pfrtstats,
 		    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
 		PF_UNLOCK();
+		if (error == 0)
+			error = copyout(pfrtstats, io->pfrio_buffer, totlen);
+		free(pfrtstats, M_TEMP);
 		break;
 	}
 
 	case DIOCRCLRTSTATS: {
 		struct pfioc_table *io = (struct pfioc_table *)addr;
+		struct pfr_table *pfrts;
+		size_t totlen;
 
 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
 			error = ENODEV;
 			break;
 		}
+		totlen = io->pfrio_size * sizeof(struct pfr_table);
+		pfrts = malloc(totlen, M_TEMP, M_WAITOK);
+		error = copyin(io->pfrio_buffer, pfrts, totlen);
+		if (error) {
+			free(pfrts, M_TEMP);
+			break;
+		}
 		PF_LOCK();
-		error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size,
+		error = pfr_clr_tstats(pfrts, io->pfrio_size,
 		    &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
 		PF_UNLOCK();
+		free(pfrts, M_TEMP);
 		break;
 	}
 
 	case DIOCRSETTFLAGS: {
 		struct pfioc_table *io = (struct pfioc_table *)addr;
+		struct pfr_table *pfrts;
+		size_t totlen;
 
 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
 			error = ENODEV;
 			break;
 		}
+		totlen = io->pfrio_size * sizeof(struct pfr_table);
+		pfrts = malloc(totlen, M_TEMP, M_WAITOK);
+		error = copyin(io->pfrio_buffer, pfrts, totlen);
+		if (error) {
+			free(pfrts, M_TEMP);
+			break;
+		}
 		PF_LOCK();
-		error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size,
+		error = pfr_set_tflags(pfrts, io->pfrio_size,
 		    io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
 		    &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
 		PF_UNLOCK();
+		free(pfrts, M_TEMP);
 		break;
 	}
 
@@ -2643,61 +2697,105 @@ DIOCGETSTATES_full:
 
 	case DIOCRADDADDRS: {
 		struct pfioc_table *io = (struct pfioc_table *)addr;
+		struct pfr_addr *pfras;
+		size_t totlen;
 
 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
 			error = ENODEV;
 			break;
 		}
+		totlen = io->pfrio_size * sizeof(struct pfr_addr);
+		pfras = malloc(totlen, M_TEMP, M_WAITOK);
+		error = copyin(io->pfrio_buffer, pfras, totlen);
+		if (error) {
+			free(pfras, M_TEMP);
+			break;
+		}
 		PF_LOCK();
-		error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer,
+		error = pfr_add_addrs(&io->pfrio_table, pfras,
 		    io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
 		    PFR_FLAG_USERIOCTL);
 		PF_UNLOCK();
+		if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
+			error = copyout(pfras, io->pfrio_buffer, totlen);
+		free(pfras, M_TEMP);
 		break;
 	}
 
 	case DIOCRDELADDRS: {
 		struct pfioc_table *io = (struct pfioc_table *)addr;
+		struct pfr_addr *pfras;
+		size_t totlen;
 
 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
 			error = ENODEV;
 			break;
 		}
+		totlen = io->pfrio_size * sizeof(struct pfr_addr);
+		pfras = malloc(totlen, M_TEMP, M_WAITOK);
+		error = copyin(io->pfrio_buffer, pfras, totlen);
+		if (error) {
+			free(pfras, M_TEMP);
+			break;
+		}
 		PF_LOCK();
-		error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer,
+		error = pfr_del_addrs(&io->pfrio_table, pfras,
 		    io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
 		    PFR_FLAG_USERIOCTL);
 		PF_UNLOCK();
+		if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
+			error = copyout(pfras, io->pfrio_buffer, totlen);
+		free(pfras, M_TEMP);
 		break;
 	}
 
 	case DIOCRSETADDRS: {
 		struct pfioc_table *io = (struct pfioc_table *)addr;
+		struct pfr_addr *pfras;
+		size_t totlen;
 
 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
 			error = ENODEV;
 			break;
 		}
+		totlen = (io->pfrio_size + io->pfrio_size2) *
+		    sizeof(struct pfr_addr);
+		pfras = malloc(totlen, M_TEMP, M_WAITOK);
+		error = copyin(io->pfrio_buffer, pfras, totlen);
+		if (error) {
+			free(pfras, M_TEMP);
+			break;
+		}
 		PF_LOCK();
-		error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer,
+		error = pfr_set_addrs(&io->pfrio_table, pfras,
 		    io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
 		    &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
 		    PFR_FLAG_USERIOCTL, 0);
 		PF_UNLOCK();
+		if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
+			error = copyout(pfras, io->pfrio_buffer, totlen);
+		free(pfras, M_TEMP);
 		break;
 	}
 
 	case DIOCRGETADDRS: {
 		struct pfioc_table *io = (struct pfioc_table *)addr;
+		struct pfr_addr *pfras;
+		size_t totlen;
 
 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
 			error = ENODEV;
 			break;
 		}
+		totlen = io->pfrio_size * sizeof(struct pfr_addr);
+		pfras = malloc(totlen, M_TEMP, M_WAITOK);
 		PF_LOCK();
-		error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer,
+		error = pfr_get_addrs(&io->pfrio_table, pfras,
 		    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
 		PF_UNLOCK();
+		if (error == 0)
+			error = copyout(pfras, io->pfrio_buffer, totlen);
+		free(pfras, M_TEMP);
 		break;
 	}
 
@@ -2717,46 +2815,80 @@ DIOCGETSTATES_full:
 
 	case DIOCRCLRASTATS: {
 		struct pfioc_table *io = (struct pfioc_table *)addr;
+		struct pfr_addr *pfras;
+		size_t totlen;
 
 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
 			error = ENODEV;
 			break;
 		}
+		totlen = io->pfrio_size * sizeof(struct pfr_addr);
+		pfras = malloc(totlen, M_TEMP, M_WAITOK);
+		error = copyin(io->pfrio_buffer, pfras, totlen);
+		if (error) {
+			free(pfras, M_TEMP);
+			break;
+		}
 		PF_LOCK();
-		error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer,
+		error = pfr_clr_astats(&io->pfrio_table, pfras,
 		    io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags |
 		    PFR_FLAG_USERIOCTL);
 		PF_UNLOCK();
+		if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
+			error = copyout(pfras, io->pfrio_buffer, totlen);
+		free(pfras, M_TEMP);
 		break;
 	}
 
 	case DIOCRTSTADDRS: {
 		struct pfioc_table *io = (struct pfioc_table *)addr;
+		struct pfr_addr *pfras;
+		size_t totlen;
 
 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
 			error = ENODEV;
 			break;
 		}
+		totlen = io->pfrio_size * sizeof(struct pfr_addr);
+		pfras = malloc(totlen, M_TEMP, M_WAITOK);
+		error = copyin(io->pfrio_buffer, pfras, totlen);
+		if (error) {
+			free(pfras, M_TEMP);
+			break;
+		}
 		PF_LOCK();
-		error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer,
+		error = pfr_tst_addrs(&io->pfrio_table, pfras,
 		    io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags |
 		    PFR_FLAG_USERIOCTL);
 		PF_UNLOCK();
+		if (error == 0)
+			error = copyout(pfras, io->pfrio_buffer, totlen);
+		free(pfras, M_TEMP);
 		break;
 	}
 
 	case DIOCRINADEFINE: {
 		struct pfioc_table *io = (struct pfioc_table *)addr;
+		struct pfr_addr *pfras;
+		size_t totlen;
 
 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
 			error = ENODEV;
 			break;
 		}
+		totlen = io->pfrio_size * sizeof(struct pfr_addr);
+		pfras = malloc(totlen, M_TEMP, M_WAITOK);
+		error = copyin(io->pfrio_buffer, pfras, totlen);
+		if (error) {
+			free(pfras, M_TEMP);
+			break;
+		}
 		PF_LOCK();
-		error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer,
+		error = pfr_ina_define(&io->pfrio_table, pfras,
 		    io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr,
 		    io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL);
 		PF_UNLOCK();
+		free(pfras, M_TEMP);
 		break;
 	}
 
@@ -2784,14 +2916,14 @@ DIOCGETSTATES_full:
 
 		if (io->esize != sizeof(*ioe)) {
 			error = ENODEV;
-			goto fail;
+			break;
 		}
 		totlen = sizeof(struct pfioc_trans_e) * io->size;
 		ioes = malloc(totlen, M_TEMP, M_WAITOK);
 		error = copyin(io->array, ioes, totlen);
 		if (error) {
 			free(ioes, M_TEMP);
-			goto fail;
+			break;
 		}
 		PF_LOCK();
 		for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
@@ -2850,14 +2982,14 @@ DIOCGETSTATES_full:
 
 		if (io->esize != sizeof(*ioe)) {
 			error = ENODEV;
-			goto fail;
+			break;
 		}
 		totlen = sizeof(struct pfioc_trans_e) * io->size;
 		ioes = malloc(totlen, M_TEMP, M_WAITOK);
 		error = copyin(io->array, ioes, totlen);
 		if (error) {
 			free(ioes, M_TEMP);
-			goto fail;
+			break;
 		}
 		PF_LOCK();
 		for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
@@ -2916,14 +3048,14 @@ DIOCGETSTATES_full:
 
 		if (io->esize != sizeof(*ioe)) {
 			error = ENODEV;
-			goto fail;
+			break;
 		}
 		totlen = sizeof(struct pfioc_trans_e) * io->size;
 		ioes = malloc(totlen, M_TEMP, M_WAITOK);
 		error = copyin(io->array, ioes, totlen);
 		if (error) {
 			free(ioes, M_TEMP);
-			goto fail;
+			break;
 		}
 		PF_LOCK();
 		/* First makes sure everything will succeed. */
@@ -3066,7 +3198,7 @@ DIOCGETSTATES_full:
 		    sizeof(struct pf_src_node) * nr);
 		if (error) {
 			free(pstore, M_TEMP);
-			goto fail;
+			break;
 		}
 		psn->psn_len = sizeof(struct pf_src_node) * nr;
 		free(pstore, M_TEMP);

Modified: projects/pf/head/sys/contrib/pf/net/pf_table.c
==============================================================================
--- projects/pf/head/sys/contrib/pf/net/pf_table.c	Tue Apr 10 17:37:24 2012	(r234107)
+++ projects/pf/head/sys/contrib/pf/net/pf_table.c	Tue Apr 10 19:11:09 2012	(r234108)
@@ -55,41 +55,6 @@ __FBSDID("$FreeBSD$");
 			return (EINVAL);	\
 	} while (0)
 
-static inline int
-_copyin(const void *uaddr, void *kaddr, size_t len)
-{
-	int r;
-
-	PF_UNLOCK();
-	r = copyin(uaddr, kaddr, len);
-	PF_LOCK();
-
-	return (r);
-}
-
-static inline int
-_copyout(const void *uaddr, void *kaddr, size_t len)
-{
-	int r;
-
-	PF_UNLOCK();
-	r = copyout(uaddr, kaddr, len);
-	PF_LOCK();
-
-	return (r);
-}
-
-#define	COPYIN(from, to, size, flags)		\
-	((flags & PFR_FLAG_USERIOCTL) ?		\
-	_copyin((from), (to), (size)) :		\
-	(bcopy((from), (to), (size)), 0))
-
-#define	COPYOUT(from, to, size, flags)		\
-	((flags & PFR_FLAG_USERIOCTL) ?		\
-	_copyout((from), (to), (size)) :	\
-	(bcopy((from), (to), (size)), 0))
-
-
 #define	FILLIN_SIN(sin, addr)			\
 	do {					\
 		(sin).sin_len = sizeof(sin);	\
@@ -143,7 +108,6 @@ struct pfr_walktree {
 		struct pfi_dynaddr	*pfrw1_dyn;
 	}	 pfrw_1;
 	int	 pfrw_free;
-	int	 pfrw_flags;
 };
 #define	pfrw_addr	pfrw_1.pfrw1_addr
 #define	pfrw_astats	pfrw_1.pfrw1_astats
@@ -176,7 +140,7 @@ static void		 pfr_mark_addrs(struct pfr_
 static struct pfr_kentry
 			*pfr_lookup_addr(struct pfr_ktable *,
 			    struct pfr_addr *, int);
-static struct pfr_kentry *pfr_create_kentry(struct pfr_addr *, int);
+static struct pfr_kentry *pfr_create_kentry(struct pfr_addr *);
 static void		 pfr_destroy_kentries(struct pfr_kentryworkq *);
 static void		 pfr_destroy_kentry(struct pfr_kentry *);
 static void		 pfr_insert_kentries(struct pfr_ktable *,
@@ -185,7 +149,7 @@ static void		 pfr_remove_kentries(struct
 			    struct pfr_kentryworkq *);
 static void		 pfr_clstats_kentries(struct pfr_kentryworkq *, long,
 			    int);
-static void		 pfr_reset_feedback(struct pfr_addr *, int, int);
+static void		 pfr_reset_feedback(struct pfr_addr *, int);
 static void		 pfr_prepare_network(union sockaddr_union *, int, int);
 static int		 pfr_route_kentry(struct pfr_ktable *,
 			    struct pfr_kentry *);
@@ -203,7 +167,7 @@ static void		 pfr_clstats_ktables(struct
 			    int);
 static void		 pfr_clstats_ktable(struct pfr_ktable *, long, int);
 static struct pfr_ktable
-			*pfr_create_ktable(struct pfr_table *, long, int, int);
+			*pfr_create_ktable(struct pfr_table *, long, int);
 static void		 pfr_destroy_ktables(struct pfr_ktableworkq *, int);
 static void		 pfr_destroy_ktable(struct pfr_ktable *, int);
 static int		 pfr_ktable_compare(struct pfr_ktable *,
@@ -241,9 +205,8 @@ pfr_clr_addrs(struct pfr_table *tbl, int
 {
 	struct pfr_ktable	*kt;
 	struct pfr_kentryworkq	 workq;
-	int			 s;
 
-	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
+	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
 	if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
 		return (EINVAL);
 	kt = pfr_lookup_table(tbl);
@@ -254,11 +217,7 @@ pfr_clr_addrs(struct pfr_table *tbl, int
 	pfr_enqueue_addrs(kt, &workq, ndel, 0);
 
 	if (!(flags & PFR_FLAG_DUMMY)) {
-		if (flags & PFR_FLAG_ATOMIC)
-			s = splnet();
 		pfr_remove_kentries(kt, &workq);
-		if (flags & PFR_FLAG_ATOMIC)
-			splx(s);
 		if (kt->pfrkt_cnt) {
 			printf("pfr_clr_addrs: corruption detected (%d).\n",
 			    kt->pfrkt_cnt);
@@ -275,12 +234,11 @@ pfr_add_addrs(struct pfr_table *tbl, str
 	struct pfr_ktable	*kt, *tmpkt;
 	struct pfr_kentryworkq	 workq;
 	struct pfr_kentry	*p, *q;
-	struct pfr_addr		 ad;
-	int			 i, rv, s, xadd = 0;
+	struct pfr_addr		*ad;
+	int			 i, rv, xadd = 0;
 	long			 tzero = time_second;
 
-	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
-	    PFR_FLAG_FEEDBACK);
+	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK);
 	if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
 		return (EINVAL);
 	kt = pfr_lookup_table(tbl);
@@ -288,53 +246,42 @@ pfr_add_addrs(struct pfr_table *tbl, str
 		return (ESRCH);
 	if (kt->pfrkt_flags & PFR_TFLAG_CONST)
 		return (EPERM);
-	tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0,
-	    !(flags & PFR_FLAG_USERIOCTL));
+	tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0);
 	if (tmpkt == NULL)
 		return (ENOMEM);
 	SLIST_INIT(&workq);
-	for (i = 0; i < size; i++) {
-		if (COPYIN(addr+i, &ad, sizeof(ad), flags))
-			senderr(EFAULT);
-		if (pfr_validate_addr(&ad))
+	for (i = 0, ad = addr; i < size; i++, ad++) {
+		if (pfr_validate_addr(ad))
 			senderr(EINVAL);
-		p = pfr_lookup_addr(kt, &ad, 1);
-		q = pfr_lookup_addr(tmpkt, &ad, 1);
+		p = pfr_lookup_addr(kt, ad, 1);
+		q = pfr_lookup_addr(tmpkt, ad, 1);
 		if (flags & PFR_FLAG_FEEDBACK) {
 			if (q != NULL)
-				ad.pfra_fback = PFR_FB_DUPLICATE;
+				ad->pfra_fback = PFR_FB_DUPLICATE;
 			else if (p == NULL)
-				ad.pfra_fback = PFR_FB_ADDED;
-			else if (p->pfrke_not != ad.pfra_not)
-				ad.pfra_fback = PFR_FB_CONFLICT;
+				ad->pfra_fback = PFR_FB_ADDED;
+			else if (p->pfrke_not != ad->pfra_not)
+				ad->pfra_fback = PFR_FB_CONFLICT;
 			else
-				ad.pfra_fback = PFR_FB_NONE;
+				ad->pfra_fback = PFR_FB_NONE;
 		}
 		if (p == NULL && q == NULL) {
-			p = pfr_create_kentry(&ad,
-			    !(flags & PFR_FLAG_USERIOCTL));
+			p = pfr_create_kentry(ad);
 			if (p == NULL)
 				senderr(ENOMEM);
 			if (pfr_route_kentry(tmpkt, p)) {
 				pfr_destroy_kentry(p);
-				ad.pfra_fback = PFR_FB_NONE;
+				ad->pfra_fback = PFR_FB_NONE;
 			} else {
 				SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
 				xadd++;
 			}
 		}
-		if (flags & PFR_FLAG_FEEDBACK)
-			if (COPYOUT(&ad, addr+i, sizeof(ad), flags))
-				senderr(EFAULT);
 	}
 	pfr_clean_node_mask(tmpkt, &workq);
-	if (!(flags & PFR_FLAG_DUMMY)) {
-		if (flags & PFR_FLAG_ATOMIC)
-			s = splnet();
+	if (!(flags & PFR_FLAG_DUMMY))
 		pfr_insert_kentries(kt, &workq, tzero);
-		if (flags & PFR_FLAG_ATOMIC)
-			splx(s);
-	} else
+	else
 		pfr_destroy_kentries(&workq);
 	if (nadd != NULL)
 		*nadd = xadd;
@@ -344,7 +291,7 @@ _bad:
 	pfr_clean_node_mask(tmpkt, &workq);
 	pfr_destroy_kentries(&workq);
 	if (flags & PFR_FLAG_FEEDBACK)
-		pfr_reset_feedback(addr, size, flags);
+		pfr_reset_feedback(addr, size);
 	pfr_destroy_ktable(tmpkt, 0);
 	return (rv);
 }
@@ -356,11 +303,10 @@ pfr_del_addrs(struct pfr_table *tbl, str
 	struct pfr_ktable	*kt;
 	struct pfr_kentryworkq	 workq;
 	struct pfr_kentry	*p;
-	struct pfr_addr		 ad;
-	int			 i, rv, s, xdel = 0, log = 1;
+	struct pfr_addr		*ad;
+	int			 i, rv, xdel = 0, log = 1;
 
-	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
-	    PFR_FLAG_FEEDBACK);
+	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK);
 	if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
 		return (EINVAL);
 	kt = pfr_lookup_table(tbl);
@@ -386,56 +332,44 @@ pfr_del_addrs(struct pfr_table *tbl, str
 		pfr_mark_addrs(kt);
 	} else {
 		/* iterate over addresses to delete */
-		for (i = 0; i < size; i++) {
-			if (COPYIN(addr+i, &ad, sizeof(ad), flags))
-				return (EFAULT);
-			if (pfr_validate_addr(&ad))
+		for (i = 0, ad = addr; i < size; i++, ad++) {
+			if (pfr_validate_addr(ad))
 				return (EINVAL);
-			p = pfr_lookup_addr(kt, &ad, 1);
+			p = pfr_lookup_addr(kt, ad, 1);
 			if (p != NULL)
 				p->pfrke_mark = 0;
 		}
 	}
 	SLIST_INIT(&workq);
-	for (i = 0; i < size; i++) {
-		if (COPYIN(addr+i, &ad, sizeof(ad), flags))
-			senderr(EFAULT);
-		if (pfr_validate_addr(&ad))
+	for (i = 0, ad = addr; i < size; i++, ad++) {
+		if (pfr_validate_addr(ad))
 			senderr(EINVAL);
-		p = pfr_lookup_addr(kt, &ad, 1);
+		p = pfr_lookup_addr(kt, ad, 1);
 		if (flags & PFR_FLAG_FEEDBACK) {
 			if (p == NULL)
-				ad.pfra_fback = PFR_FB_NONE;
-			else if (p->pfrke_not != ad.pfra_not)
-				ad.pfra_fback = PFR_FB_CONFLICT;
+				ad->pfra_fback = PFR_FB_NONE;
+			else if (p->pfrke_not != ad->pfra_not)
+				ad->pfra_fback = PFR_FB_CONFLICT;
 			else if (p->pfrke_mark)
-				ad.pfra_fback = PFR_FB_DUPLICATE;
+				ad->pfra_fback = PFR_FB_DUPLICATE;
 			else
-				ad.pfra_fback = PFR_FB_DELETED;
+				ad->pfra_fback = PFR_FB_DELETED;
 		}
-		if (p != NULL && p->pfrke_not == ad.pfra_not &&
+		if (p != NULL && p->pfrke_not == ad->pfra_not &&
 		    !p->pfrke_mark) {
 			p->pfrke_mark = 1;
 			SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
 			xdel++;
 		}
-		if (flags & PFR_FLAG_FEEDBACK)
-			if (COPYOUT(&ad, addr+i, sizeof(ad), flags))
-				senderr(EFAULT);
 	}
-	if (!(flags & PFR_FLAG_DUMMY)) {
-		if (flags & PFR_FLAG_ATOMIC)
-			s = splnet();
+	if (!(flags & PFR_FLAG_DUMMY))
 		pfr_remove_kentries(kt, &workq);
-		if (flags & PFR_FLAG_ATOMIC)
-			splx(s);
-	}
 	if (ndel != NULL)
 		*ndel = xdel;
 	return (0);
 _bad:
 	if (flags & PFR_FLAG_FEEDBACK)
-		pfr_reset_feedback(addr, size, flags);
+		pfr_reset_feedback(addr, size);
 	return (rv);
 }
 
@@ -448,11 +382,10 @@ pfr_set_addrs(struct pfr_table *tbl, str
 	struct pfr_kentryworkq	 addq, delq, changeq;
 	struct pfr_kentry	*p, *q;
 	struct pfr_addr		 ad;
-	int			 i, rv, s, xadd = 0, xdel = 0, xchange = 0;
+	int			 i, rv, xadd = 0, xdel = 0, xchange = 0;
 	long			 tzero = time_second;
 
-	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
-	    PFR_FLAG_FEEDBACK);
+	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK);
 	if (pfr_validate_table(tbl, ignore_pfrt_flags, flags &
 	    PFR_FLAG_USERIOCTL))
 		return (EINVAL);
@@ -461,8 +394,7 @@ pfr_set_addrs(struct pfr_table *tbl, str
 		return (ESRCH);
 	if (kt->pfrkt_flags & PFR_TFLAG_CONST)
 		return (EPERM);
-	tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0,
-	    !(flags & PFR_FLAG_USERIOCTL));
+	tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0);
 	if (tmpkt == NULL)
 		return (ENOMEM);
 	pfr_mark_addrs(kt);
@@ -470,8 +402,11 @@ pfr_set_addrs(struct pfr_table *tbl, str
 	SLIST_INIT(&delq);
 	SLIST_INIT(&changeq);
 	for (i = 0; i < size; i++) {
-		if (COPYIN(addr+i, &ad, sizeof(ad), flags))
-			senderr(EFAULT);
+		/*
+		 * XXXGL: undertand pf_if usage of this function
+		 * and make ad a moving pointer
+		 */
+		bcopy(addr + i, &ad, sizeof(ad));
 		if (pfr_validate_addr(&ad))
 			senderr(EINVAL);
 		ad.pfra_fback = PFR_FB_NONE;
@@ -493,8 +428,7 @@ pfr_set_addrs(struct pfr_table *tbl, str
 				ad.pfra_fback = PFR_FB_DUPLICATE;
 				goto _skip;
 			}
-			p = pfr_create_kentry(&ad,
-			    !(flags & PFR_FLAG_USERIOCTL));
+			p = pfr_create_kentry(&ad);
 			if (p == NULL)
 				senderr(ENOMEM);
 			if (pfr_route_kentry(tmpkt, p)) {
@@ -508,8 +442,7 @@ pfr_set_addrs(struct pfr_table *tbl, str
 		}
 _skip:
 		if (flags & PFR_FLAG_FEEDBACK)
-			if (COPYOUT(&ad, addr+i, sizeof(ad), flags))
-				senderr(EFAULT);
+			bcopy(&ad, addr + i, sizeof(ad));
 	}
 	pfr_enqueue_addrs(kt, &delq, &xdel, ENQUEUE_UNMARKED_ONLY);
 	if ((flags & PFR_FLAG_FEEDBACK) && *size2) {
@@ -521,20 +454,15 @@ _skip:
 		SLIST_FOREACH(p, &delq, pfrke_workq) {
 			pfr_copyout_addr(&ad, p);
 			ad.pfra_fback = PFR_FB_DELETED;
-			if (COPYOUT(&ad, addr+size+i, sizeof(ad), flags))
-				senderr(EFAULT);
+			bcopy(&ad, addr + size + i, sizeof(ad));
 			i++;
 		}
 	}
 	pfr_clean_node_mask(tmpkt, &addq);
 	if (!(flags & PFR_FLAG_DUMMY)) {
-		if (flags & PFR_FLAG_ATOMIC)
-			s = splnet();
 		pfr_insert_kentries(kt, &addq, tzero);
 		pfr_remove_kentries(kt, &delq);
 		pfr_clstats_kentries(&changeq, tzero, INVERT_NEG_FLAG);
-		if (flags & PFR_FLAG_ATOMIC)
-			splx(s);
 	} else
 		pfr_destroy_kentries(&addq);
 	if (nadd != NULL)
@@ -551,7 +479,7 @@ _bad:
 	pfr_clean_node_mask(tmpkt, &addq);
 	pfr_destroy_kentries(&addq);
 	if (flags & PFR_FLAG_FEEDBACK)
-		pfr_reset_feedback(addr, size, flags);
+		pfr_reset_feedback(addr, size);
 	pfr_destroy_ktable(tmpkt, 0);
 	return (rv);
 }
@@ -562,7 +490,7 @@ pfr_tst_addrs(struct pfr_table *tbl, str
 {
 	struct pfr_ktable	*kt;
 	struct pfr_kentry	*p;
-	struct pfr_addr		 ad;
+	struct pfr_addr		*ad;
 	int			 i, xmatch = 0;
 
 	ACCEPT_FLAGS(flags, PFR_FLAG_REPLACE);
@@ -572,22 +500,18 @@ pfr_tst_addrs(struct pfr_table *tbl, str
 	if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
 		return (ESRCH);
 
-	for (i = 0; i < size; i++) {
-		if (COPYIN(addr+i, &ad, sizeof(ad), flags))
-			return (EFAULT);
-		if (pfr_validate_addr(&ad))
+	for (i = 0, ad = addr; i < size; i++, ad++) {
+		if (pfr_validate_addr(ad))
 			return (EINVAL);
-		if (ADDR_NETWORK(&ad))
+		if (ADDR_NETWORK(ad))
 			return (EINVAL);
-		p = pfr_lookup_addr(kt, &ad, 0);
+		p = pfr_lookup_addr(kt, ad, 0);
 		if (flags & PFR_FLAG_REPLACE)
-			pfr_copyout_addr(&ad, p);
-		ad.pfra_fback = (p == NULL) ? PFR_FB_NONE :
+			pfr_copyout_addr(ad, p);
+		ad->pfra_fback = (p == NULL) ? PFR_FB_NONE :
 		    (p->pfrke_not ? PFR_FB_NOTMATCH : PFR_FB_MATCH);
 		if (p != NULL && !p->pfrke_not)
 			xmatch++;
-		if (COPYOUT(&ad, addr+i, sizeof(ad), flags))
-			return (EFAULT);
 	}
 	if (nmatch != NULL)
 		*nmatch = xmatch;
@@ -617,7 +541,6 @@ pfr_get_addrs(struct pfr_table *tbl, str
 	w.pfrw_op = PFRW_GET_ADDRS;
 	w.pfrw_addr = addr;
 	w.pfrw_free = kt->pfrkt_cnt;
-	w.pfrw_flags = flags;
 	rv = kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
 	if (!rv)
 		rv = kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree,
@@ -625,11 +548,9 @@ pfr_get_addrs(struct pfr_table *tbl, str
 	if (rv)
 		return (rv);
 
-	if (w.pfrw_free) {
-		printf("pfr_get_addrs: corruption detected (%d).\n",
-		    w.pfrw_free);
-		return (ENOTTY);
-	}
+	KASSERT(w.pfrw_free == 0, ("%s: corruption detected (%d)", __func__,
+	    w.pfrw_free));
+
 	*size = kt->pfrkt_cnt;
 	return (0);
 }
@@ -641,11 +562,11 @@ pfr_get_astats(struct pfr_table *tbl, st
 	struct pfr_ktable	*kt;
 	struct pfr_walktree	 w;
 	struct pfr_kentryworkq	 workq;
-	int			 rv, s;
+	int			 rv;
 	long			 tzero = time_second;
 
 	/* XXX PFR_FLAG_CLSTATS disabled */
-	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC);
+	ACCEPT_FLAGS(flags, 0);
 	if (pfr_validate_table(tbl, 0, 0))
 		return (EINVAL);
 	kt = pfr_lookup_table(tbl);
@@ -660,9 +581,6 @@ pfr_get_astats(struct pfr_table *tbl, st
 	w.pfrw_op = PFRW_GET_ASTATS;
 	w.pfrw_astats = addr;
 	w.pfrw_free = kt->pfrkt_cnt;
-	w.pfrw_flags = flags;
-	if (flags & PFR_FLAG_ATOMIC)
-		s = splnet();
 	rv = kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
 	if (!rv)
 		rv = kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, 
@@ -671,8 +589,6 @@ pfr_get_astats(struct pfr_table *tbl, st
 		pfr_enqueue_addrs(kt, &workq, NULL, 0);
 		pfr_clstats_kentries(&workq, tzero, 0);
 	}
-	if (flags & PFR_FLAG_ATOMIC)
-		splx(s);
 	if (rv)
 		return (rv);
 
@@ -692,28 +608,23 @@ pfr_clr_astats(struct pfr_table *tbl, st
 	struct pfr_ktable	*kt;
 	struct pfr_kentryworkq	 workq;
 	struct pfr_kentry	*p;
-	struct pfr_addr		 ad;
-	int			 i, rv, s, xzero = 0;
+	struct pfr_addr		*ad;
+	int			 i, rv, xzero = 0;
 
-	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
-	    PFR_FLAG_FEEDBACK);
+	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK);
 	if (pfr_validate_table(tbl, 0, 0))
 		return (EINVAL);
 	kt = pfr_lookup_table(tbl);
 	if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
 		return (ESRCH);
 	SLIST_INIT(&workq);
-	for (i = 0; i < size; i++) {
-		if (COPYIN(addr+i, &ad, sizeof(ad), flags))
-			senderr(EFAULT);
-		if (pfr_validate_addr(&ad))
+	for (i = 0, ad = addr; i < size; i++, ad++) {
+		if (pfr_validate_addr(ad))
 			senderr(EINVAL);
-		p = pfr_lookup_addr(kt, &ad, 1);
+		p = pfr_lookup_addr(kt, ad, 1);
 		if (flags & PFR_FLAG_FEEDBACK) {
-			ad.pfra_fback = (p != NULL) ?
+			ad->pfra_fback = (p != NULL) ?
 			    PFR_FB_CLEARED : PFR_FB_NONE;
-			if (COPYOUT(&ad, addr+i, sizeof(ad), flags))
-				senderr(EFAULT);
 		}
 		if (p != NULL) {
 			SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
@@ -721,19 +632,14 @@ pfr_clr_astats(struct pfr_table *tbl, st
 		}
 	}
 
-	if (!(flags & PFR_FLAG_DUMMY)) {
-		if (flags & PFR_FLAG_ATOMIC)
-			s = splnet();
+	if (!(flags & PFR_FLAG_DUMMY))
 		pfr_clstats_kentries(&workq, 0, 0);
-		if (flags & PFR_FLAG_ATOMIC)
-			splx(s);
-	}

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-projects mailing list