socsvn commit: r272257 - soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw

dpl at FreeBSD.org dpl at FreeBSD.org
Tue Aug 12 08:49:59 UTC 2014


Author: dpl
Date: Tue Aug 12 08:49:58 2014
New Revision: 272257
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=272257

Log:
  Moved all the packet matching part into a function to be used as compiled bitcode. As a side effect, we now have taken out PULLUP_TO/PULLUP_LEN out of ip_fw2.c
  

Modified:
  soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/ip_fw_rules.h
  soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc

Modified: soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/ip_fw_rules.h
==============================================================================
--- soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/ip_fw_rules.h	Tue Aug 12 08:41:15 2014	(r272256)
+++ soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/ip_fw_rules.h	Tue Aug 12 08:49:58 2014	(r272257)
@@ -13,10 +13,16 @@
 #include <sys/mbuf.h>
 #include <sys/kernel.h>
 
+#include <net/ethernet.h>
+#include <netinet/icmp6.h>
 #include <netinet/ip.h>
 #include <netinet/ip_icmp.h>
 #include <netinet/ip_fw.h>
+#include <netinet/ip_carp.h>
+#include <netinet/pim.h>
+#include <netinet/sctp.h>
 #include <netinet/tcp_var.h>
+#include <netinet/udp.h>
 
 #include <netinet/ip6.h>
 #ifdef INET6
@@ -80,6 +86,8 @@
  * then it sets p to point at the offset "len" in the mbuf. WARNING: the
  * pointer might become stale after other pullups (but we never use it
  * this way).
+ * 
+ * This is a modified version, since returns 1, insteaf of goto pullup_failed.
  */
 #define PULLUP_TO(_len, p, T)	PULLUP_LEN(_len, p, sizeof(T))
 #define PULLUP_LEN(_len, p, T)					\
@@ -88,7 +96,7 @@
 	if ((m)->m_len < x) {					\
 		args->m = m = m_pullup(m, x);			\
 		if (m == NULL)					\
-			goto pullup_failed;			\
+			return (1);			\
 	}							\
 	p = (mtod(m, char *) + (_len));				\
 } while (0)
@@ -96,6 +104,249 @@
 /* Needed vars defined at ip_fw2.c */
 VNET_DECLARE(int, V_ipfw_vnet_ready);
 
+
+int
+inspect_pkt(struct ip_fw_args *args, struct ip *ip, struct mbuf *m, struct in_addr *src_ip, struct in_addr *dst_ip, uint16_t *src_port, uint16_t *dst_port, uint16_t *etype, uint16_t *ext_hd, uint16_t *iplen, int *pktlen, int *is_ipv4, int *is_ipv6, u_int *hlen, uint8_t *proto, uint8_t *icmp6_type, u_short *ip6f_mf, u_short *offset, void *ulp)
+{
+	/*
+	 * if we have an ether header,
+	 */
+	if (args->eh)
+		*etype = ntohs(args->eh->ether_type);
+
+	/* Identify IP packets and fill up variables. */
+	if ((*pktlen) >= sizeof(struct ip6_hdr) &&
+	    (args->eh == NULL || (*etype) == ETHERTYPE_IPV6) && ip->ip_v == 6) {
+		struct ip6_hdr *ip6 = (struct ip6_hdr *)ip;
+		*is_ipv6 = 1;
+		args->f_id.addr_type = 6;
+		(*hlen) = sizeof(struct ip6_hdr);
+		*proto = ip6->ip6_nxt;
+
+		/* Search extension headers to find upper layer protocols */
+		while (ulp == NULL && (*offset) == 0) {
+			switch (*proto) {
+			case IPPROTO_ICMPV6:
+				PULLUP_TO((*hlen), ulp, struct icmp6_hdr);
+				*icmp6_type = ICMP6(ulp)->icmp6_type;
+				break;
+
+			case IPPROTO_TCP:
+				PULLUP_TO((*hlen), ulp, struct tcphdr);
+				*dst_port = TCP(ulp)->th_dport;
+				*src_port = TCP(ulp)->th_sport;
+				/* save flags for dynamic rules */
+				args->f_id._flags = TCP(ulp)->th_flags;
+				break;
+
+			case IPPROTO_SCTP:
+				PULLUP_TO((*hlen), ulp, struct sctphdr);
+				*src_port = SCTP(ulp)->src_port;
+				*dst_port = SCTP(ulp)->dest_port;
+				break;
+
+			case IPPROTO_UDP:
+				PULLUP_TO((*hlen), ulp, struct udphdr);
+				*dst_port = UDP(ulp)->uh_dport;
+				*src_port = UDP(ulp)->uh_sport;
+				break;
+
+			case IPPROTO_HOPOPTS:	/* RFC 2460 */
+				PULLUP_TO((*hlen), ulp, struct ip6_hbh);
+				*ext_hd |= EXT_HOPOPTS;
+				(*hlen) += (((struct ip6_hbh *)ulp)->ip6h_len + 1) << 3;
+				*proto = ((struct ip6_hbh *)ulp)->ip6h_nxt;
+				ulp = NULL;
+				break;
+
+			case IPPROTO_ROUTING:	/* RFC 2460 */
+				PULLUP_TO((*hlen), ulp, struct ip6_rthdr);
+				switch (((struct ip6_rthdr *)ulp)->ip6r_type) {
+				case 0:
+					*ext_hd |= EXT_RTHDR0;
+					break;
+				case 2:
+					*ext_hd |= EXT_RTHDR2;
+					break;
+				default:
+					if (V_fw_verbose)
+						printf("IPFW2: IPV6 - Unknown "
+						    "Routing Header type(%d)\n",
+						    ((struct ip6_rthdr *)
+						    ulp)->ip6r_type);
+					if (V_fw_deny_unknown_exthdrs)
+					    return (IP_FW_DENY);
+					break;
+				}
+				*ext_hd |= EXT_ROUTING;
+				(*hlen) += (((struct ip6_rthdr *)ulp)->ip6r_len + 1) << 3;
+				*proto = ((struct ip6_rthdr *)ulp)->ip6r_nxt;
+				ulp = NULL;
+				break;
+
+			case IPPROTO_FRAGMENT:	/* RFC 2460 */
+				PULLUP_TO((*hlen), ulp, struct ip6_frag);
+				*ext_hd |= EXT_FRAGMENT;
+				(*hlen) += sizeof (struct ip6_frag);
+				*proto = ((struct ip6_frag *)ulp)->ip6f_nxt;
+				*offset = ((struct ip6_frag *)ulp)->ip6f_offlg &
+					IP6F_OFF_MASK;
+				*ip6f_mf = ((struct ip6_frag *)ulp)->ip6f_offlg &
+					IP6F_MORE_FRAG;
+				if (V_fw_permit_single_frag6 == 0 &&
+				    *offset == 0 && *ip6f_mf == 0) {
+					if (V_fw_verbose)
+						printf("IPFW2: IPV6 - Invalid "
+						    "Fragment Header\n");
+					if (V_fw_deny_unknown_exthdrs)
+					    return (IP_FW_DENY);
+					break;
+				}
+				args->f_id.extra =
+				    ntohl(((struct ip6_frag *)ulp)->ip6f_ident);
+				ulp = NULL;
+				break;
+
+			case IPPROTO_DSTOPTS:	/* RFC 2460 */
+				PULLUP_TO((*hlen), ulp, struct ip6_hbh);
+				*ext_hd |= EXT_DSTOPTS;
+				(*hlen) += (((struct ip6_hbh *)ulp)->ip6h_len + 1) << 3;
+				*proto = ((struct ip6_hbh *)ulp)->ip6h_nxt;
+				ulp = NULL;
+				break;
+
+			case IPPROTO_AH:	/* RFC 2402 */
+				PULLUP_TO((*hlen), ulp, struct ip6_ext);
+				*ext_hd |= EXT_AH;
+				(*hlen) += (((struct ip6_ext *)ulp)->ip6e_len + 2) << 2;
+				*proto = ((struct ip6_ext *)ulp)->ip6e_nxt;
+				ulp = NULL;
+				break;
+
+			case IPPROTO_ESP:	/* RFC 2406 */
+				PULLUP_TO((*hlen), ulp, uint32_t);	/* SPI, Seq# */
+				/* Anything past Seq# is variable length and
+				 * data past this ext. header is encrypted. */
+				*ext_hd |= EXT_ESP;
+				break;
+
+			case IPPROTO_NONE:	/* RFC 2460 */
+				/*
+				 * Packet ends here, and IPv6 header has
+				 * already been pulled up. If ip6e_len!=0
+				 * then octets must be ignored.
+				 */
+				ulp = ip; /* non-NULL to get out of loop. */
+				break;
+
+			case IPPROTO_OSPFIGP:
+				/* XXX OSPF header check? */
+				PULLUP_TO((*hlen), ulp, struct ip6_ext);
+				break;
+
+			case IPPROTO_PIM:
+				/* XXX PIM header check? */
+				PULLUP_TO((*hlen), ulp, struct pim);
+				break;
+
+			case IPPROTO_CARP:
+				PULLUP_TO((*hlen), ulp, struct carp_header);
+				if (((struct carp_header *)ulp)->carp_version !=
+				    CARP_VERSION) 
+					return (IP_FW_DENY);
+				if (((struct carp_header *)ulp)->carp_type !=
+				    CARP_ADVERTISEMENT) 
+					return (IP_FW_DENY);
+				break;
+
+			case IPPROTO_IPV6:	/* RFC 2893 */
+				PULLUP_TO((*hlen), ulp, struct ip6_hdr);
+				break;
+
+			case IPPROTO_IPV4:	/* RFC 2893 */
+				PULLUP_TO((*hlen), ulp, struct ip);
+				break;
+
+			default:
+				if (V_fw_verbose)
+					printf("IPFW2: IPV6 - Unknown "
+					    "Extension Header(%d), ext_hd=%x\n",
+					     *proto, *ext_hd);
+				if (V_fw_deny_unknown_exthdrs)
+				    return (IP_FW_DENY);
+				PULLUP_TO((*hlen), ulp, struct ip6_ext);
+				break;
+			} /*switch */
+		}
+		ip = mtod(m, struct ip *);
+		ip6 = (struct ip6_hdr *)ip;
+		args->f_id.src_ip6 = ip6->ip6_src;
+		args->f_id.dst_ip6 = ip6->ip6_dst;
+		args->f_id.src_ip = 0;
+		args->f_id.dst_ip = 0;
+		args->f_id.flow_id6 = ntohl(ip6->ip6_flow);
+	} else if ((*pktlen) >= sizeof(struct ip) &&
+	    (args->eh == NULL || (*etype) == ETHERTYPE_IP) && ip->ip_v == 4) {
+	    	*is_ipv4 = 1;
+		(*hlen) = ip->ip_hl << 2;
+		args->f_id.addr_type = 4;
+
+		/*
+		 * Collect parameters into local variables for faster matching.
+		 */
+		*proto = ip->ip_p;
+		*src_ip = ip->ip_src;
+		*dst_ip = ip->ip_dst;
+		*offset = ntohs(ip->ip_off) & IP_OFFMASK;
+		*iplen = ntohs(ip->ip_len);
+		*pktlen = *iplen < (*pktlen) ? *iplen : (*pktlen);
+
+		if (*offset == 0) {
+			switch (*proto) {
+			case IPPROTO_TCP:
+				PULLUP_TO((*hlen), ulp, struct tcphdr);
+				*dst_port = TCP(ulp)->th_dport;
+				*src_port = TCP(ulp)->th_sport;
+				/* save flags for dynamic rules */
+				args->f_id._flags = TCP(ulp)->th_flags;
+				break;
+
+			case IPPROTO_SCTP:
+				PULLUP_TO((*hlen), ulp, struct sctphdr);
+				*src_port = SCTP(ulp)->src_port;
+				*dst_port = SCTP(ulp)->dest_port;
+				break;
+
+			case IPPROTO_UDP:
+				PULLUP_TO((*hlen), ulp, struct udphdr);
+				*dst_port = UDP(ulp)->uh_dport;
+				*src_port = UDP(ulp)->uh_sport;
+				break;
+
+			case IPPROTO_ICMP:
+				PULLUP_TO((*hlen), ulp, struct icmphdr);
+				//args->f_id.flags = ICMP(ulp)->icmp_type;
+				break;
+
+			default:
+				break;
+			}
+		}
+
+		ip = mtod(m, struct ip *);
+		args->f_id.src_ip = ntohl((*src_ip).s_addr);
+		args->f_id.dst_ip = ntohl((*dst_ip).s_addr);
+	}
+
+	if (*proto) { /* we may have port numbers, store them */
+		args->f_id.proto = *proto;
+		args->f_id.src_port = *src_port = ntohs(*src_port);
+		args->f_id.dst_port = *dst_port = ntohs(*dst_port);
+	}
+	
+	return (0);
+}
+
 /*
  * Auxiliar functions.
  */
@@ -1167,16 +1418,7 @@
 static IPFW_RULES_INLINE int
 rule_tcpopts(int *match, u_int hlen, void *ulp, uint8_t proto, u_short offset, ipfw_insn *cmd, struct mbuf *m, struct ip_fw_args *args)
 {
-	/* Modified PULLUP_TO, returns 1 if error */
-	do {
-		int x = (hlen) + (TCP(ulp)->th_off << 2);
-		if ((m)->m_len < x) {
-			args->m = m = m_pullup(m, x);
-			if (m == NULL)
-				return (1);
-		}
-		ulp = (mtod(m, char *) + (hlen));
-	} while (0);
+	PULLUP_TO(hlen, ulp , (TCP(ulp)->th_off << 2));
 
 	*match = (proto == IPPROTO_TCP && offset == 0 &&
 	    tcpopts_match(TCP(ulp), cmd));

Modified: soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc
==============================================================================
--- soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc	Tue Aug 12 08:41:15 2014	(r272256)
+++ soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc	Tue Aug 12 08:49:58 2014	(r272257)
@@ -86,7 +86,7 @@
 	Value *ext_hd; //unsigned
 
 	// This sets up some vars, at star time.
-	Function *look_pkt;
+	Function *inspect_pkt;
 
 	// Auxiliary functions used by our JITed code.
 	Function *is_icmp_query;
@@ -240,7 +240,7 @@
 
 		// Get Function defs from bitcode.
 		// All of them are auxiliary functions.
-		look_pkt = mod->getFunction("look_pkt");
+		inspect_pkt = mod->getFunction("inspect_pkt");
 		is_icmp_query = mod->getFunction("is_icmp_query");
 		flags_match = mod->getFunction("flags_match");
 		ipopts_match = mod->getFunction("ipopts_match");
@@ -296,12 +296,12 @@
 		return ((funcptr)NULL);
 	}
 
-	// Emits all the code necessary to fill in some vars.
-	// XXX Should we emit that? Or should we create a function call instead?
+	// Call the function that fills in some vars.
 	int
 	emit_lookpkt()
 	{
-		//irb.CreateCall();
+		// If it returns zero, we have to goto pullup_failed.
+		irb.CreateCall(inspect_pkt);
 		return (0);
 	}
 


More information about the svn-soc-all mailing list