Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 27 May 2009 19:13:36 GMT
From:      Tatsiana Elavaya <tsel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 162900 for review
Message-ID:  <200905271913.n4RJDa8r070024@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=162900

Change 162900 by tsel@tsel_mz on 2009/05/27 19:12:53

	Implement rule aliases.
	
	Usage:
	# ./ipfw add 200 alias alias2 allow all from any to any
	00200 alias alias2 allow ip from any to any
	# ./ipfw add 100 alias alias1 skipto alias2 all from any to any
	00100 alias alias1 skipto alias2 ip from any to any
	# ./ipfw show    
	00100  18   1152 alias alias1 skipto alias2 ip from any to any
	00200 585 117328 alias alias2 allow ip from any to any
	65535 109  27557 deny ip from any to any

Affected files ...

.. //depot/projects/soc2009/tsel_ipfw/sbin/ipfw/ipfw2.c#2 edit
.. //depot/projects/soc2009/tsel_ipfw/sbin/ipfw/ipfw2.h#2 edit
.. //depot/projects/soc2009/tsel_ipfw/sbin/ipfw/main.c#2 edit
.. //depot/projects/soc2009/tsel_ipfw/sys/netinet/ip_fw.h#2 edit

Differences ...

==== //depot/projects/soc2009/tsel_ipfw/sbin/ipfw/ipfw2.c#2 (text+ko) ====

@@ -449,6 +449,69 @@
 	return 0;
 }
 
+static void*
+ipfw_get_all(int ocmd, int *nbytes)
+{
+	void *data = NULL;
+	int nalloc = 1024;	/* start somewhere... */
+
+	/* get rules or pipes from kernel, resizing array as necessary */
+	*nbytes = nalloc;
+
+	while (*nbytes >= nalloc) {
+		nalloc = nalloc * 2 + 200;
+		*nbytes = nalloc;
+		data = safe_realloc(data, *nbytes);
+		if (do_cmd(ocmd, data, (uintptr_t)nbytes) < 0)
+			err(EX_OSERR, "getsockopt(IP_%s_GET)",
+				co.do_pipe ? "DUMMYNET" : "FW");
+	}
+	return data;
+}
+
+static struct ip_fw*
+get_rule_cache(int *len)
+{
+	static struct ip_fw *rules = NULL;
+	static int rules_len = 0;
+
+	if (rules == NULL) {
+		rules = (struct ip_fw*) ipfw_get_all(IP_FW_GET, &rules_len);
+		rules_len = rules_len / sizeof(struct ip_fw);
+	}
+
+	*len = rules_len;
+	return rules;
+}
+
+static int
+alias_lookup_rulenum(const char *alias)
+{
+	struct ip_fw *rules;
+	int len, i;
+
+	rules = get_rule_cache(&len);
+	for (i = 0; i < len; i++) {
+		if (!strcmp(rules[i].alias, alias))
+			return rules[i].rulenum;
+	}
+	return -1;
+}
+
+static char* 
+alias_lookup(int rulenum)
+{
+	struct ip_fw *rules;
+	int len, i;
+
+	rules = get_rule_cache(&len);
+	for (i = 0; i < len; i++) {
+		if (rules[i].rulenum == rulenum)
+			return rules[i].alias[0] ? rules[i].alias : NULL;
+	}
+	return NULL;
+}
+
 /*
  * prints one port, symbolic or numeric
  */
@@ -973,6 +1036,9 @@
 		}
 	}
 
+	if (rule->alias[0])
+		printf("alias %s ", rule->alias);
+
 	if (co.show_sets)
 		printf("set %d ", rule->set);
 
@@ -1029,9 +1095,14 @@
 				print_unreach6_code(cmd->arg1);
 			break;
 
-		case O_SKIPTO:
-			PRINT_UINT_ARG("skipto ", cmd->arg1);
+		case O_SKIPTO: {
+			char *alias = alias_lookup(cmd->arg1);
+			if (alias == NULL)
+				PRINT_UINT_ARG("skipto ", cmd->arg1);
+			else
+				printf("skipto %s", alias);
 			break;
+	       }
 
 		case O_PIPE:
 			PRINT_UINT_ARG("pipe ", cmd->arg1);
@@ -1715,6 +1786,20 @@
 	}
 }
 
+static void
+ipfw_list_aliases(void *data, uint nbytes, int ac, char *av[])
+{
+	struct ip_fw *rules;
+	int len, i;
+
+	rules = (struct ip_fw*) data;
+	len = nbytes / sizeof(struct ip_fw);
+	for (i = 0; i < len; i++) {
+		if (rules[i].alias[0] != '\0')
+			printf("%-5d %s\n", rules[i].rulenum, rules[i].alias);
+	}
+}
+
 void
 ipfw_list(int ac, char *av[], int show_counters)
 {
@@ -1723,19 +1808,16 @@
 
 #define NEXT(r)	((struct ip_fw *)((char *)r + RULESIZE(r)))
 	char *lim;
-	void *data = NULL;
 	int bcwidth, n, nbytes, nstat, ndyn, pcwidth, width;
 	int exitval = EX_OK;
 	int lac;
 	char **lav;
+	void *data;
 	u_long rnum, last;
 	char *endptr;
 	int seen = 0;
 	uint8_t set;
 
-	const int ocmd = co.do_pipe ? IP_DUMMYNET_GET : IP_FW_GET;
-	int nalloc = 1024;	/* start somewhere... */
-
 	last = 0;
 
 	if (co.test_only) {
@@ -1746,20 +1828,16 @@
 	ac--;
 	av++;
 
-	/* get rules or pipes from kernel, resizing array as necessary */
-	nbytes = nalloc;
+	data = ipfw_get_all(co.do_pipe ? IP_DUMMYNET_GET : IP_FW_GET, &nbytes);
 
-	while (nbytes >= nalloc) {
-		nalloc = nalloc * 2 + 200;
-		nbytes = nalloc;
-		data = safe_realloc(data, nbytes);
-		if (do_cmd(ocmd, data, (uintptr_t)&nbytes) < 0)
-			err(EX_OSERR, "getsockopt(IP_%s_GET)",
-				co.do_pipe ? "DUMMYNET" : "FW");
+	if (co.do_pipe) {
+		ipfw_list_pipes(data, nbytes, ac, av);
+		goto done;
 	}
 
-	if (co.do_pipe) {
-		ipfw_list_pipes(data, nbytes, ac, av);
+	if (ac && !strcmp(*av, "alias")) {
+		ipfw_list_aliases(data, nbytes, ac, av);
+		ac--; av++;
 		goto done;
 	}
 
@@ -2610,6 +2688,18 @@
 		ac--;
 	}
 
+	/* [alias ALIAS] */
+	if (ac > 1 && _substrcmp(*av, "alias") == 0) {
+		int alias_rule;
+
+		NEED1("missing alias name");
+		alias_rule = alias_lookup_rulenum(av[1]);
+		if (alias_rule > 0)
+			errx(EX_DATAERR, "rule %d already has alias %s", alias_rule, av[1]);
+		strlcpy(rule->alias, av[1], IPFW_ALIAS_NAME_SIZE);
+		av += 2; ac -= 2;
+	}
+
 	/* [set N]	-- set number (0..RESVD_SET), optional */
 	if (ac > 1 && _substrcmp(*av, "set") == 0) {
 		int set = strtoul(av[1], NULL, 10);
@@ -2724,6 +2814,11 @@
 				action->arg1 = ntohs(s->s_port);
 			else
 				errx(EX_DATAERR, "illegal divert/tee port");
+		} else if (i == TOK_SKIPTO) {
+			action->arg1 = alias_lookup_rulenum(*av);
+			if (action->arg1 <= 0 || action->arg1 >= IPFW_DEFAULT_RULE)
+				errx(EX_DATAERR, "illegal argument for %s",
+				    *(av - 1));
 		} else
 			errx(EX_DATAERR, "illegal argument for %s", *(av - 1));
 		ac--; av++;

==== //depot/projects/soc2009/tsel_ipfw/sbin/ipfw/ipfw2.h#2 (text+ko) ====


==== //depot/projects/soc2009/tsel_ipfw/sbin/ipfw/main.c#2 (text+ko) ====

@@ -40,7 +40,7 @@
 "ipfw syntax summary (but please do read the ipfw(8) manpage):\n\n"
 "\tipfw [-abcdefhnNqStTv] <command>\n\n"
 "where <command> is one of the following:\n\n"
-"add [num] [set N] [prob x] RULE-BODY\n"
+"add [num] [alias ALIAS] [set N] [prob x] RULE-BODY\n"
 "{pipe|queue} N config PIPE-BODY\n"
 "[pipe|queue] {zero|delete|show} [N{,N}]\n"
 "nat N config {ip IPADDR|if IFNAME|log|deny_in|same_ports|unreg_only|reset|\n"

==== //depot/projects/soc2009/tsel_ipfw/sys/netinet/ip_fw.h#2 (text+ko) ====

@@ -421,6 +421,8 @@
                        */
 } ipfw_insn_icmp6;
 
+#define IPFW_ALIAS_NAME_SIZE 	32
+
 /*
  * Here we have the structure representing an ipfw rule.
  *
@@ -464,6 +466,7 @@
 	u_int64_t	pcnt;		/* Packet counter		*/
 	u_int64_t	bcnt;		/* Byte counter			*/
 	u_int32_t	timestamp;	/* tv_sec of last match		*/
+	char		alias[IPFW_ALIAS_NAME_SIZE];
 
 	ipfw_insn	cmd[1];		/* storage for commands		*/
 };



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905271913.n4RJDa8r070024>