[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

pf match on route labels



finally got around to find the right tree... this diff actually works.
Let pf match on route labels.
everybody can create labeled routes:
  route add -label foo 10.1.1.1 127.0.0.1
everybody can filter on 'em with that diff:
  pass to route foo keep state
everybody can test and report back
and maybe somebody wants to help with the manpage even?

Index: sys/net/pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.471
diff -u -r1.471 pf.c
--- sys/net/pf.c	7 Dec 2004 18:02:03 -0000	1.471
+++ sys/net/pf.c	8 Dec 2004 16:55:07 -0000
@@ -5118,6 +5118,49 @@
 	return (0);
 }
 
+int
+pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw)
+{
+	struct sockaddr_in	*dst;
+#ifdef INET6
+	struct sockaddr_in6	*dst6;
+	struct route_in6	 ro;
+#else
+	struct route		 ro;
+#endif
+	int			 ret = 0;
+
+	bzero(&ro, sizeof(ro));
+	switch (af) {
+	case AF_INET:
+		dst = satosin(&ro.ro_dst);
+		dst->sin_family = AF_INET;
+		dst->sin_len = sizeof(*dst);
+		dst->sin_addr = addr->v4;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
+		dst6->sin6_family = AF_INET6;
+		dst6->sin6_len = sizeof(*dst6);
+		dst6->sin6_addr = addr->v6;
+		break;
+#endif /* INET6 */
+	default:
+		return (0);
+	}
+
+	rtalloc_noclone((struct route *)&ro, NO_CLONING);
+
+	if (ro.ro_rt != NULL) {
+		if (ro.ro_rt->rt_labelid == aw->v.rtlabel)
+			ret = 1;
+		RTFREE(ro.ro_rt);
+	}
+
+	return (ret);
+}
+
 #ifdef INET
 void
 pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
Index: sys/net/pf_ioctl.c
===================================================================
RCS file: /cvs/src/sys/net/pf_ioctl.c,v
retrieving revision 1.135
diff -u -r1.135 pf_ioctl.c
--- sys/net/pf_ioctl.c	7 Dec 2004 18:02:04 -0000	1.135
+++ sys/net/pf_ioctl.c	8 Dec 2004 16:55:08 -0000
@@ -121,6 +121,9 @@
 static u_int16_t	 tagname2tag(struct pf_tags *, char *);
 static void		 tag2tagname(struct pf_tags *, u_int16_t, char *);
 static void		 tag_unref(struct pf_tags *, u_int16_t);
+int			 pf_rtlabel_add(struct pf_addr_wrap *);
+void			 pf_rtlabel_remove(struct pf_addr_wrap *);
+void			 pf_rtlabel_copyout(struct pf_addr_wrap *);
 
 #define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
 
@@ -593,6 +596,8 @@
 		pf_qid_unref(rule->pqid);
 	pf_qid_unref(rule->qid);
 #endif
+	pf_rtlabel_remove(&rule->src.addr);
+	pf_rtlabel_remove(&rule->dst.addr);
 	pfi_dynaddr_remove(&rule->src.addr);
 	pfi_dynaddr_remove(&rule->dst.addr);
 	if (rulequeue == NULL) {
@@ -702,6 +707,37 @@
 	return (tag_unref(&pf_tags, tag));
 }
 
+int
+pf_rtlabel_add(struct pf_addr_wrap *a)
+{
+	if (a->type == PF_ADDR_RTLABEL &&
+	    (a->v.rtlabel = rtlabel_name2id(a->v.rtlabelname)) == 0)
+		return (-1);
+	return (0);
+}
+
+void
+pf_rtlabel_remove(struct pf_addr_wrap *a)
+{
+	if (a->type == PF_ADDR_RTLABEL)
+		rtlabel_unref(a->v.rtlabel);
+}
+
+void
+pf_rtlabel_copyout(struct pf_addr_wrap *a)
+{
+	const char	*name;
+
+	if (a->type == PF_ADDR_RTLABEL && a->v.rtlabel) {
+		if ((name = rtlabel_id2name(a->v.rtlabel)) == NULL)
+			strlcpy(a->v.rtlabelname, "?",
+			    sizeof(a->v.rtlabelname));
+		else
+			strlcpy(a->v.rtlabelname, name,
+			    sizeof(a->v.rtlabelname));
+	}
+}
+
 #ifdef ALTQ
 u_int32_t
 pf_qname2qid(char *qname)
@@ -1168,6 +1204,9 @@
 				error = EBUSY;
 		if (rule->rt && !rule->direction)
 			error = EINVAL;
+		if (pf_rtlabel_add(&rule->src.addr) ||
+		    pf_rtlabel_add(&rule->dst.addr))
+			error = EBUSY;
 		if (pfi_dynaddr_setup(&rule->src.addr, rule->af))
 			error = EINVAL;
 		if (pfi_dynaddr_setup(&rule->dst.addr, rule->af))
@@ -1273,6 +1312,8 @@
 		pfi_dynaddr_copyout(&pr->rule.dst.addr);
 		pf_tbladdr_copyout(&pr->rule.src.addr);
 		pf_tbladdr_copyout(&pr->rule.dst.addr);
+		pf_rtlabel_copyout(&pr->rule.src.addr);
+		pf_rtlabel_copyout(&pr->rule.dst.addr);
 		for (i = 0; i < PF_SKIP_COUNT; ++i)
 			if (rule->skip[i].ptr == NULL)
 				pr->rule.skip[i].nr = -1;
@@ -1384,9 +1425,11 @@
 				if ((newrule->match_tag = pf_tagname2tag(
 				    newrule->match_tagname)) == 0)
 					error = EBUSY;
-
 			if (newrule->rt && !newrule->direction)
 				error = EINVAL;
+			if (pf_rtlabel_add(&newrule->src.addr) ||
+			    pf_rtlabel_add(&newrule->dst.addr))
+				error = EBUSY;
 			if (pfi_dynaddr_setup(&newrule->src.addr, newrule->af))
 				error = EINVAL;
 			if (pfi_dynaddr_setup(&newrule->dst.addr, newrule->af))
@@ -2058,6 +2101,7 @@
 		bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr));
 		pfi_dynaddr_copyout(&pp->addr.addr);
 		pf_tbladdr_copyout(&pp->addr.addr);
+		pf_rtlabel_copyout(&pp->addr.addr);
 		break;
 	}
 
Index: sys/net/pfvar.h
===================================================================
RCS file: /cvs/src/sys/net/pfvar.h,v
retrieving revision 1.208
diff -u -r1.208 pfvar.h
--- sys/net/pfvar.h	7 Dec 2004 10:33:41 -0000	1.208
+++ sys/net/pfvar.h	8 Dec 2004 16:55:09 -0000
@@ -39,6 +39,7 @@
 #include <sys/tree.h>
 
 #include <net/radix.h>
+#include <net/route.h>
 #include <netinet/ip_ipsp.h>
 #include <netinet/tcp_fsm.h>
 
@@ -77,7 +78,7 @@
 enum	{ PF_POOL_NONE, PF_POOL_BITMASK, PF_POOL_RANDOM,
 	  PF_POOL_SRCHASH, PF_POOL_ROUNDROBIN };
 enum	{ PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL,
-	  PF_ADDR_TABLE };
+	  PF_ADDR_TABLE, PF_ADDR_RTLABEL };
 #define PF_POOL_TYPEMASK	0x0f
 #define PF_POOL_STICKYADDR	0x20
 #define	PF_WSCALE_FLAG		0x80
@@ -114,6 +115,8 @@
 		}			 a;
 		char			 ifname[IFNAMSIZ];
 		char			 tblname[PF_TABLE_NAME_SIZE];
+		char			 rtlabelname[RTLABEL_LEN];
+		u_int32_t		 rtlabel;
 	}			 v;
 	union {
 		struct pfi_dynaddr	*dyn;
@@ -279,6 +282,8 @@
 	(							\
 		(((aw)->type == PF_ADDR_NOROUTE &&		\
 		    pf_routable((x), (af))) ||			\
+		((aw)->type == PF_ADDR_RTLABEL &&		\
+		    !pf_rtlabel_match((x), (af), (aw))) ||	\
 		((aw)->type == PF_ADDR_TABLE &&			\
 		    !pfr_match_addr((aw)->p.tbl, (x), (af))) ||	\
 		((aw)->type == PF_ADDR_DYNIFTL &&		\
@@ -1428,6 +1433,7 @@
 	pf_state_expires(const struct pf_state *);
 void	pf_purge_expired_fragments(void);
 int	pf_routable(struct pf_addr *addr, sa_family_t af);
+int	pf_rtlabel_match(struct pf_addr *, sa_family_t, struct pf_addr_wrap *);
 void	pfr_initialize(void);
 int	pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t);
 void	pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t,
Index: sbin/pfctl/parse.y
===================================================================
RCS file: /cvs/src/sbin/pfctl/parse.y,v
retrieving revision 1.467
diff -u -r1.467 parse.y
--- sbin/pfctl/parse.y	7 Dec 2004 10:33:41 -0000	1.467
+++ sbin/pfctl/parse.y	8 Dec 2004 16:55:11 -0000
@@ -406,7 +406,7 @@
 %token	LOAD
 %token	STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
 %token	MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH
-%token	TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY
+%token	TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY ROUTE
 %token	<v.string>		STRING
 %token	<v.i>			PORTBINARY
 %type	<v.interface>		interface if_list if_item_not if_item
@@ -2255,6 +2255,21 @@
 			$$->next = NULL;
 			$$->tail = $$;
 		}
+		| ROUTE	STRING		{
+			$$ = calloc(1, sizeof(struct node_host));
+			if ($$ == NULL)
+				err(1, "host: calloc");
+			$$->addr.type = PF_ADDR_RTLABEL;
+			if (strlcpy($$->addr.v.rtlabelname, $2,
+			    sizeof($$->addr.v.rtlabelname)) >=
+			    sizeof($$->addr.v.rtlabelname)) {
+				yyerror("route label too long, max %u chars",
+				    sizeof($$->addr.v.rtlabelname) - 1);
+				YYERROR;
+			}
+			$$->next = NULL;
+			$$->tail = $$;
+		}
 		;
 
 number		: STRING			{
@@ -4539,6 +4554,7 @@
 		{ "return-icmp6",	RETURNICMP6},
 		{ "return-rst",		RETURNRST},
 		{ "round-robin",	ROUNDROBIN},
+		{ "route",		ROUTE},
 		{ "route-to",		ROUTETO},
 		{ "rule",		RULE},
 		{ "scrub",		SCRUB},
Index: sbin/pfctl/pf_print_state.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pf_print_state.c,v
retrieving revision 1.39
diff -u -r1.39 pf_print_state.c
--- sbin/pfctl/pf_print_state.c	10 Feb 2004 17:48:08 -0000	1.39
+++ sbin/pfctl/pf_print_state.c	8 Dec 2004 16:55:11 -0000
@@ -96,6 +96,9 @@
 	case PF_ADDR_NOROUTE:
 		printf("no-route");
 		return;
+	case PF_ADDR_RTLABEL:
+		printf("route \"%s\"", addr->v.rtlabelname);
+		return;
 	default:
 		printf("?");
 		return;



Visit your host, monkey.org