PERFORCE change 143248 for review

Gleb Kurtsou gk at FreeBSD.org
Tue Jun 10 18:03:32 UTC 2008


http://perforce.freebsd.org/chv.cgi?CH=143248

Change 143248 by gk at gk_h1 on 2008/06/10 18:03:17

	support filtering by mac in ipfw lookup tables
	example:
	~ # ipfw add allow ip from 'table(1)' to any in recv if_home 
	~ # ipfw table 1 add 192.168.1.1 ether 00:a0:c9:dd:23:47

Affected files ...

.. //depot/projects/soc2008/gk_l2filter/sbin-ipfw/ipfw2.c#3 edit
.. //depot/projects/soc2008/gk_l2filter/sys-netinet/ip_fw.h#4 edit
.. //depot/projects/soc2008/gk_l2filter/sys-netinet/ip_fw2.c#5 edit

Differences ...

==== //depot/projects/soc2008/gk_l2filter/sbin-ipfw/ipfw2.c#3 (text+ko) ====

@@ -5966,6 +5966,12 @@
 		if (lookup_host(*av, (struct in_addr *)&ent.addr) != 0)
 			errx(EX_NOHOST, "hostname ``%s'' unknown", *av);
 		ac--; av++;
+		ent.mac_addr = 0;
+		if (do_add && ac >= 2 && strcmp(*av, "mac") == 0) {
+			uint8_t mask[8];
+			get_mac_addr_mask(av[1], (uint8_t*)&ent.mac_addr, mask);
+			ac-=2; av+=2;
+		}
 		if (do_add && ac) {
 			unsigned int tval;
 			/* isdigit is a bit of a hack here.. */
@@ -6014,20 +6020,28 @@
 			err(EX_OSERR, "getsockopt(IP_FW_TABLE_LIST)");
 		for (a = 0; a < tbl->cnt; a++) {
 			unsigned int tval;
+			char tval_buf[128];
+			char tmac_buf[128];
 			tval = tbl->ent[a].value;
 			if (do_value_as_ip) {
-			    char tbuf[128];
-			    strncpy(tbuf, inet_ntoa(*(struct in_addr *)
-				&tbl->ent[a].addr), 127);
 			    /* inet_ntoa expects network order */
 			    tval = htonl(tval);
-			    printf("%s/%u %s\n", tbuf, tbl->ent[a].masklen,
-			        inet_ntoa(*(struct in_addr *)&tval));
+			    strlcpy(tval_buf, inet_ntoa(*(struct in_addr *)
+				&tval), sizeof(tval_buf));
+			} else {
+			    snprintf(tval_buf, sizeof(tval_buf), "%u", tval);
+			}
+			if (tbl->ent[a].mac_addr) {
+			    uint8_t *x = (uint8_t *)&tbl->ent[a].mac_addr;
+		            snprintf(tmac_buf, sizeof(tmac_buf), "mac %02x:%02x:%02x:%02x:%02x:%02x ",
+		                 x[0], x[1], x[2], x[3], x[4], x[5]);
 			} else {
-			    printf("%s/%u %u\n",
-			        inet_ntoa(*(struct in_addr *)&tbl->ent[a].addr),
-			        tbl->ent[a].masklen, tval);
+			    tmac_buf[0] = 0;
 			}
+
+			printf("%s/%u %s%s\n",
+			    inet_ntoa(*(struct in_addr *)&tbl->ent[a].addr),
+			    tbl->ent[a].masklen, tmac_buf, tval_buf);
 		}
 	} else
 		errx(EX_USAGE, "invalid table command %s", *av);

==== //depot/projects/soc2008/gk_l2filter/sys-netinet/ip_fw.h#4 (text+ko) ====

@@ -533,6 +533,7 @@
  */
 typedef struct	_ipfw_table_entry {
 	in_addr_t	addr;		/* network address		*/
+	u_int64_t	mac_addr;	/* mac address			*/
 	u_int32_t	value;		/* value			*/
 	u_int16_t	tbl;		/* table number			*/
 	u_int8_t	masklen;	/* mask length			*/

==== //depot/projects/soc2008/gk_l2filter/sys-netinet/ip_fw2.c#5 (text+ko) ====

@@ -153,6 +153,7 @@
 struct table_entry {
 	struct radix_node	rn[2];
 	struct sockaddr_in	addr, mask;
+	u_int64_t		mac_addr;
 	u_int32_t		value;
 };
 
@@ -1752,7 +1753,7 @@
 
 static int
 add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
-    uint8_t mlen, uint32_t value)
+    uint8_t mlen, u_int64_t mac_addr, uint32_t value)
 {
 	struct radix_node_head *rnh;
 	struct table_entry *ent;
@@ -1767,6 +1768,7 @@
 	ent->addr.sin_len = ent->mask.sin_len = 8;
 	ent->mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
 	ent->addr.sin_addr.s_addr = addr & ent->mask.sin_addr.s_addr;
+	ent->mac_addr = mac_addr;
 	IPFW_WLOCK(&layer3_chain);
 	if (rnh->rnh_addaddr(&ent->addr, &ent->mask, rnh, (void *)ent) ==
 	    NULL) {
@@ -1861,7 +1863,7 @@
 
 static int
 lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
-    uint32_t *val)
+    struct ether_addr *ea, uint32_t *val)
 {
 	struct radix_node_head *rnh;
 	struct table_entry *ent;
@@ -1874,6 +1876,10 @@
 	sa.sin_addr.s_addr = addr;
 	ent = (struct table_entry *)(rnh->rnh_lookup(&sa, NULL, rnh));
 	if (ent != NULL) {
+		if (ea && ent->mac_addr) {
+			if (ent->mac_addr != ((*(u_int64_t*)ea)))
+				return (0);
+		}
 		*val = ent->value;
 		return (1);
 	}
@@ -1918,6 +1924,7 @@
 	else
 		ent->masklen = 33 - ffs(ntohl(n->mask.sin_addr.s_addr));
 	ent->addr = n->addr.sin_addr.s_addr;
+	ent->mac_addr = n->mac_addr;
 	ent->value = n->value;
 	tbl->cnt++;
 	return (0);
@@ -2649,13 +2656,19 @@
 			case O_IP_SRC_LOOKUP:
 			case O_IP_DST_LOOKUP:
 				if (is_ipv4) {
+				    struct ether_addr *ea = NULL;
 				    uint32_t a =
 					(cmd->opcode == O_IP_DST_LOOKUP) ?
 					    dst_ip.s_addr : src_ip.s_addr;
 				    uint32_t v;
 
+				    if (args->eh) {
+					    ea = (struct ether_addr*)((cmd->opcode == O_IP_DST_LOOKUP) ?
+						    args->eh->ether_dhost :
+						    args->eh->ether_shost);
+				    }
 				    match = lookup_table(chain, cmd->arg1, a,
-					&v);
+					ea, &v);
 				    if (!match)
 					break;
 				    if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
@@ -4267,7 +4280,7 @@
 			if (error)
 				break;
 			error = add_table_entry(&layer3_chain, ent.tbl,
-			    ent.addr, ent.masklen, ent.value);
+			    ent.addr, ent.masklen, ent.mac_addr, ent.value);
 		}
 		break;
 


More information about the p4-projects mailing list