Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Aug 2014 18:09:37 +0000 (UTC)
From:      Alexander V. Chernikov <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r269823 - in projects/ipfw: sbin/ipfw sys/netinet sys/netpfil/ipfw
Message-ID:  <53e906e2.2564.1de9f0da@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Mon Aug 11 18:09:37 2014
New Revision: 269823
URL: http://svnweb.freebsd.org/changeset/base/269823

Log:
  * Add the abilify to lock/unlock given table from changes.
  
  Example:
  
  # ipfw table si lock
  # ipfw table si info
  +++ table(si), set(0) +++
   kindex: 0, type: cidr, locked
   valtype: number, references: 0
   algorithm: cidr:radix
   items: 0, size: 288
  # ipfw table si add 4.5.6.7
  ignored: 4.5.6.7/32 0
  ipfw: Adding record failed: table is locked
  # ipfw table si unlock
  # ipfw table si add 4.5.6.7
  added: 4.5.6.7/32 0
  # ipfw table si lock
  # ipfw table si delete 4.5.6.7
  ignored: 4.5.6.7/32 0
  ipfw: Deleting record failed: table is locked
  # ipfw table si unlock
  # ipfw table si delete 4.5.6.7
  deleted: 4.5.6.7/32 0

Modified:
  projects/ipfw/sbin/ipfw/ipfw2.h
  projects/ipfw/sbin/ipfw/tables.c
  projects/ipfw/sys/netinet/ip_fw.h
  projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c

Modified: projects/ipfw/sbin/ipfw/ipfw2.h
==============================================================================
--- projects/ipfw/sbin/ipfw/ipfw2.h	Mon Aug 11 17:45:41 2014	(r269822)
+++ projects/ipfw/sbin/ipfw/ipfw2.h	Mon Aug 11 18:09:37 2014	(r269823)
@@ -225,6 +225,8 @@ enum tokens {
 	TOK_TALIST,
 	TOK_FTYPE,
 	TOK_ATOMIC,
+	TOK_LOCK,
+	TOK_UNLOCK,
 };
 /*
  * the following macro returns an error message if we run out of

Modified: projects/ipfw/sbin/ipfw/tables.c
==============================================================================
--- projects/ipfw/sbin/ipfw/tables.c	Mon Aug 11 17:45:41 2014	(r269822)
+++ projects/ipfw/sbin/ipfw/tables.c	Mon Aug 11 18:09:37 2014	(r269823)
@@ -59,6 +59,7 @@ static int table_do_swap(ipfw_obj_header
 static void table_create(ipfw_obj_header *oh, int ac, char *av[]);
 static void table_modify(ipfw_obj_header *oh, int ac, char *av[]);
 static void table_lookup(ipfw_obj_header *oh, int ac, char *av[]);
+static void table_lock(ipfw_obj_header *oh, int lock);
 static int table_swap(ipfw_obj_header *oh, char *second);
 static int table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i);
 static int table_show_info(ipfw_xtable_info *i, void *arg);
@@ -115,6 +116,8 @@ static struct _s_x tablecmds[] = {
       { "list",		TOK_LIST },
       { "lookup",	TOK_LOOKUP },
       { "atomic",	TOK_ATOMIC },
+      { "lock",		TOK_LOCK },
+      { "unlock",	TOK_UNLOCK },
       { NULL, 0 }
 };
 
@@ -240,6 +243,10 @@ ipfw_table_handler(int ac, char *av[])
 		NEED1("second table name required");
 		table_swap(&oh, *av);
 		break;
+	case TOK_LOCK:
+	case TOK_UNLOCK:
+		table_lock(&oh, (tcmd == TOK_LOCK));
+		break;
 	case TOK_DETAIL:
 	case TOK_INFO:
 		arg = (tcmd == TOK_DETAIL) ? (void *)1 : NULL;
@@ -297,6 +304,7 @@ static struct _s_x tablenewcmds[] = {
       { "valtype",	TOK_VALTYPE },
       { "algo",		TOK_ALGO },
       { "limit",	TOK_LIMIT },
+      { "locked",	TOK_LOCK },
       { NULL, 0 }
 };
 
@@ -440,6 +448,9 @@ table_create(ipfw_obj_header *oh, int ac
 			strlcpy(xi.algoname, *av, sizeof(xi.algoname));
 			ac--; av++;
 			break;
+		case TOK_LOCK:
+			xi.flags |= IPFW_TGFLAGS_LOCKED;
+			break;
 		}
 	}
 
@@ -485,10 +496,6 @@ table_modify(ipfw_obj_header *oh, int ac
 	sz = sizeof(tbuf);
 	memset(&xi, 0, sizeof(xi));
 
-	/* Set some defaults to preserve compability */
-	xi.type = IPFW_TABLE_CIDR;
-	xi.vtype = IPFW_VTYPE_U32;
-
 	while (ac > 0) {
 		if ((tcmd = match_token(tablenewcmds, *av)) == -1)
 			errx(EX_USAGE, "unknown option: %s", *av);
@@ -542,6 +549,25 @@ table_do_modify(ipfw_obj_header *oh, ipf
 
 	return (error);
 }
+
+/*
+ * Locks or unlocks given table
+ */
+static void
+table_lock(ipfw_obj_header *oh, int lock)
+{
+	ipfw_xtable_info xi;
+	int error;
+
+	memset(&xi, 0, sizeof(xi));
+
+	xi.mflags |= IPFW_TMFLAGS_LOCK;
+	xi.flags |= (lock != 0) ? IPFW_TGFLAGS_LOCKED : 0;
+
+	if ((error = table_do_modify(oh, &xi)) != 0)
+		err(EX_OSERR, "Table %s failed", lock != 0 ? "lock" : "unlock");
+}
+
 /*
  * Destroys given table specified by @oh->ntlv.
  * Returns 0 on success.
@@ -713,7 +739,10 @@ table_show_info(ipfw_xtable_info *i, voi
 		snprintf(tvtype, sizeof(tvtype), "%s", vtype);
 
 	printf("--- table(%s), set(%u) ---\n", i->tablename, i->set);
-	printf(" kindex: %d, type: %s\n", i->kidx, ttype);
+	if ((i->flags & IPFW_TGFLAGS_LOCKED) != 0)
+		printf(" kindex: %d, type: %s, locked\n", i->kidx, ttype);
+	else
+		printf(" kindex: %d, type: %s\n", i->kidx, ttype);
 	printf(" valtype: %s, references: %u\n", tvtype, i->refcnt);
 	printf(" algorithm: %s\n", i->algoname);
 	printf(" items: %u, size: %u\n", i->count, i->size);
@@ -1007,6 +1036,9 @@ table_modify_record(ipfw_obj_header *oh,
 	case ENOENT:
 		etxt = "record not found";
 		break;
+	case EACCES:
+		etxt = "table is locked";
+		break;
 	default:
 		etxt = strerror(error);
 	}

Modified: projects/ipfw/sys/netinet/ip_fw.h
==============================================================================
--- projects/ipfw/sys/netinet/ip_fw.h	Mon Aug 11 17:45:41 2014	(r269822)
+++ projects/ipfw/sys/netinet/ip_fw.h	Mon Aug 11 18:09:37 2014	(r269823)
@@ -866,7 +866,7 @@ typedef struct _ipfw_xtable_info {
 	uint8_t		vtype;		/* value type (u32)		*/
 	uint8_t		vftype;		/* value format type (ip,number)*/
 	uint16_t	mflags;		/* modification flags		*/
-	uint16_t	spare;
+	uint16_t	flags;		/* generic table flags		*/
 	uint32_t	set;		/* set table is in		*/
 	uint32_t	kidx;		/* kernel index			*/
 	uint32_t	refcnt;		/* number of references		*/
@@ -877,13 +877,18 @@ typedef struct _ipfw_xtable_info {
 	char		algoname[64];	/* algorithm name		*/
 	ipfw_ta_tinfo	ta_info;	/* additional algo stats	*/
 } ipfw_xtable_info;
+/* Generic table flags */
+#define	IPFW_TGFLAGS_LOCKED	0x01	/* Tables is locked from changes*/
+/* Table type-specific flags */
 #define	IPFW_TFFLAG_SRCIP	0x01
 #define	IPFW_TFFLAG_DSTIP	0x02
 #define	IPFW_TFFLAG_SRCPORT	0x04
 #define	IPFW_TFFLAG_DSTPORT	0x08
 #define	IPFW_TFFLAG_PROTO	0x10
-#define	IPFW_TMFLAGS_FTYPE	0x01	/* Change ftype field		*/
-#define	IPFW_TMFLAGS_LIMIT	0x02	/* Change limit value		*/
+/* Table modification flags */
+#define	IPFW_TMFLAGS_FTYPE	0x0001	/* Change ftype field		*/
+#define	IPFW_TMFLAGS_LIMIT	0x0002	/* Change limit value		*/
+#define	IPFW_TMFLAGS_LOCK	0x0004	/* Change table lock state	*/
 
 typedef struct _ipfw_iface_info {
 	char		ifname[64];	/* interface name		*/

Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c	Mon Aug 11 17:45:41 2014	(r269822)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c	Mon Aug 11 18:09:37 2014	(r269823)
@@ -76,7 +76,7 @@ struct table_config {
 	uint8_t		vtype;		/* value type */
 	uint8_t		vftype;		/* value format type */
 	uint8_t		tflags;		/* type flags */
-	uint8_t		spare0;	
+	uint8_t		locked;		/* 1 if locked from changes */
 	uint32_t	count;		/* Number of records */
 	uint32_t	limit;		/* Max number of records */
 	uint8_t		linked;		/* 1 if already linked */
@@ -210,6 +210,11 @@ add_table_entry(struct ip_fw_chain *ch, 
 			return (EINVAL);
 		}
 
+		if (tc->locked != 0) {
+			IPFW_UH_WUNLOCK(ch);
+			return (EACCES);
+		}
+
 		/* Try to exit early on limit hit */
 		if ((error = check_table_limit(tc, tei)) != 0 && count == 1) {
 				IPFW_UH_WUNLOCK(ch);
@@ -439,6 +444,11 @@ del_table_entry(struct ip_fw_chain *ch, 
 		return (ESRCH);
 	}
 
+	if (tc->locked != 0) {
+		IPFW_UH_WUNLOCK(ch);
+		return (EACCES);
+	}
+
 	if (tc->no.type != ti->type) {
 		IPFW_UH_WUNLOCK(ch);
 		return (EINVAL);
@@ -1616,6 +1626,8 @@ ipfw_modify_table(struct ip_fw_chain *ch
 		tc->vftype = i->vftype;
 	if ((i->mflags & IPFW_TMFLAGS_LIMIT) != 0)
 		tc->limit = i->limit;
+	if ((i->mflags & IPFW_TMFLAGS_LOCK) != 0)
+		tc->locked = ((i->flags & IPFW_TGFLAGS_LOCKED) != 0);
 	IPFW_UH_WUNLOCK(ch);
 
 	return (0);
@@ -1704,6 +1716,7 @@ create_table_internal(struct ip_fw_chain
 
 	tc->vftype = i->vftype;
 	tc->limit = i->limit;
+	tc->locked = (i->flags & IPFW_TGFLAGS_LOCKED) != 0;
 
 	IPFW_UH_WLOCK(ch);
 
@@ -1792,6 +1805,7 @@ export_table_info(struct ip_fw_chain *ch
 	i->refcnt = tc->no.refcnt;
 	i->count = tc->count;
 	i->limit = tc->limit;
+	i->flags |= (tc->locked != 0) ? IPFW_TGFLAGS_LOCKED : 0;
 	i->size = tc->count * sizeof(ipfw_obj_tentry);
 	i->size += sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info);
 	strlcpy(i->tablename, tc->tablename, sizeof(i->tablename));



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?53e906e2.2564.1de9f0da>