From owner-svn-soc-all@FreeBSD.ORG Tue Aug 12 08:49:59 2014 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id A244EB2C for ; Tue, 12 Aug 2014 08:49:59 +0000 (UTC) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 848672B74 for ; Tue, 12 Aug 2014 08:49:59 +0000 (UTC) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.14.9/8.14.9) with ESMTP id s7C8nxiG065285 for ; Tue, 12 Aug 2014 08:49:59 GMT (envelope-from dpl@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.14.9/8.14.9/Submit) id s7C8nwgD065281 for svn-soc-all@FreeBSD.org; Tue, 12 Aug 2014 08:49:58 GMT (envelope-from dpl@FreeBSD.org) Date: Tue, 12 Aug 2014 08:49:58 GMT Message-Id: <201408120849.s7C8nwgD065281@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to dpl@FreeBSD.org using -f From: dpl@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r272257 - soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Aug 2014 08:49:59 -0000 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 #include +#include +#include #include #include #include +#include +#include +#include #include +#include #include #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); }