Date: Thu, 12 Jun 2014 09:57:33 GMT From: dpl@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r269435 - soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw Message-ID: <201406120957.s5C9vXDx093065@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dpl Date: Thu Jun 12 09:57:33 2014 New Revision: 269435 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=269435 Log: Finished second uops. Let's clear that XXX now. Modified: soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw/ip_fw2.c soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw/ip_rules.h Modified: soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw/ip_fw2.c ============================================================================== --- soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw/ip_fw2.c Thu Jun 12 09:24:17 2014 (r269434) +++ soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw/ip_fw2.c Thu Jun 12 09:57:33 2014 (r269435) @@ -1713,119 +1713,15 @@ case O_SKIPTO: rule_skipto(&match, &l, &cmd, &skip_or, &f_pos, f, pktlen, chain, cmd, tablearg); continue; - break; /* not reached */ + break; /* NOTREACHED */ - case O_CALLRETURN: { - /* - * Implementation of `subroutine' call/return, - * in the stack carried in an mbuf tag. This - * is different from `skipto' in that any call - * address is possible (`skipto' must prevent - * backward jumps to avoid endless loops). - * We have `return' action when F_NOT flag is - * present. The `m_tag_id' field is used as - * stack pointer. - */ - struct m_tag *mtag; - uint16_t jmpto, *stack; - -#define IS_CALL ((cmd->len & F_NOT) == 0) -#define IS_RETURN ((cmd->len & F_NOT) != 0) - /* - * Hand-rolled version of m_tag_locate() with - * wildcard `type'. - * If not already tagged, allocate new tag. - */ - mtag = m_tag_first(m); - while (mtag != NULL) { - if (mtag->m_tag_cookie == - MTAG_IPFW_CALL) - break; - mtag = m_tag_next(m, mtag); - } - if (mtag == NULL && IS_CALL) { - mtag = m_tag_alloc(MTAG_IPFW_CALL, 0, - IPFW_CALLSTACK_SIZE * - sizeof(uint16_t), M_NOWAIT); - if (mtag != NULL) - m_tag_prepend(m, mtag); - } - - /* - * On error both `call' and `return' just - * continue with next rule. - */ - if (IS_RETURN && (mtag == NULL || - mtag->m_tag_id == 0)) { - l = 0; /* exit inner loop */ - break; - } - if (IS_CALL && (mtag == NULL || - mtag->m_tag_id >= IPFW_CALLSTACK_SIZE)) { - printf("ipfw: call stack error, " - "go to next rule\n"); - l = 0; /* exit inner loop */ - break; - } - - IPFW_INC_RULE_COUNTER(f, pktlen); - stack = (uint16_t *)(mtag + 1); - - /* - * The `call' action may use cached f_pos - * (in f->next_rule), whose version is written - * in f->next_rule. - * The `return' action, however, doesn't have - * fixed jump address in cmd->arg1 and can't use - * cache. - */ - if (IS_CALL) { - stack[mtag->m_tag_id] = f->rulenum; - mtag->m_tag_id++; - f_pos = jump_fast(chain, f, cmd->arg1, - tablearg, 1); - } else { /* `return' action */ - mtag->m_tag_id--; - jmpto = stack[mtag->m_tag_id] + 1; - f_pos = ipfw_find_rule(chain, jmpto, 0); - } - - /* - * Skip disabled rules, and re-enter - * the inner loop with the correct - * f_pos, f, l and cmd. - * Also clear cmdlen and skip_or - */ - for (; f_pos < chain->n_rules - 1 && - (V_set_disable & - (1 << chain->map[f_pos]->set)); f_pos++) - ; - /* Re-enter the inner loop at the dest rule. */ - f = chain->map[f_pos]; - l = f->cmd_len; - cmd = f->cmd; - cmdlen = 0; - skip_or = 0; + case O_CALLRETURN: + rule_callreturn(cmd, m, f, chain, tablearg, pktlen, &skip_or, &cmdlen, &f_pos, &l); continue; break; /* NOTREACHED */ - } -#undef IS_CALL -#undef IS_RETURN case O_REJECT: - /* - * Drop the packet and send a reject notice - * if the packet is not ICMP (or is an ICMP - * query), and it is not multicast/broadcast. - */ - if (hlen > 0 && is_ipv4 && offset == 0 && - (proto != IPPROTO_ICMP || - is_icmp_query(ICMP(ulp))) && - !(m->m_flags & (M_BCAST|M_MCAST)) && - !IN_MULTICAST(ntohl(dst_ip.s_addr))) { - send_reject(args, cmd->arg1, iplen, ip); - m = args->m; - } + rule_reject(hlen, is_ipv4, offset, proto, ulp, m, dst_ip, args, cmd, iplen, ip); /* FALLTHROUGH */ #ifdef INET6 case O_UNREACH6: @@ -1861,111 +1757,21 @@ rule_ngtee(args, f_pos, chain, cmd, &retval, &l, &done); break; - case O_SETFIB: { - uint32_t fib; - - IPFW_INC_RULE_COUNTER(f, pktlen); - fib = IP_FW_ARG_TABLEARG(cmd->arg1); - if (fib >= rt_numfibs) - fib = 0; - M_SETFIB(m, fib); - args->f_id.fib = fib; - l = 0; /* exit inner loop */ + case O_SETFIB: + rule_setfib(f, pkglen, cmd, rt_numfibs, m, args, &l); break; - } - - case O_SETDSCP: { - uint16_t code; - - code = IP_FW_ARG_TABLEARG(cmd->arg1) & 0x3F; - l = 0; /* exit inner loop */ - if (is_ipv4) { - uint16_t a; - - a = ip->ip_tos; - ip->ip_tos = (code << 2) | (ip->ip_tos & 0x03); - a += ntohs(ip->ip_sum) - ip->ip_tos; - ip->ip_sum = htons(a); - } else if (is_ipv6) { - uint8_t *v; - - v = &((struct ip6_hdr *)ip)->ip6_vfc; - *v = (*v & 0xF0) | (code >> 2); - v++; - *v = (*v & 0x3F) | ((code & 0x03) << 6); - } else - break; - IPFW_INC_RULE_COUNTER(f, pktlen); + case O_SETDSCP: + rule_setdscp(cmd,); break; - } case O_NAT: - l = 0; /* exit inner loop */ - done = 1; /* exit outer loop */ - if (!IPFW_NAT_LOADED) { - retval = IP_FW_DENY; - break; - } - - struct cfg_nat *t; - int nat_id; - - set_match(args, f_pos, chain); - /* Check if this is 'global' nat rule */ - if (cmd->arg1 == 0) { - retval = ipfw_nat_ptr(args, NULL, m); - break; - } - t = ((ipfw_insn_nat *)cmd)->nat; - if (t == NULL) { - nat_id = IP_FW_ARG_TABLEARG(cmd->arg1); - t = (*lookup_nat_ptr)(&chain->nat, nat_id); - - if (t == NULL) { - retval = IP_FW_DENY; - break; - } - if (cmd->arg1 != IP_FW_TABLEARG) - ((ipfw_insn_nat *)cmd)->nat = t; - } - retval = ipfw_nat_ptr(args, t, m); + rule_nat(args, f_pos, chain, cmd, &retval, &done, &l); break; - case O_REASS: { - int ip_off; - - IPFW_INC_RULE_COUNTER(f, pktlen); - l = 0; /* in any case exit inner loop */ - ip_off = ntohs(ip->ip_off); - - /* if not fragmented, go to next rule */ - if ((ip_off & (IP_MF | IP_OFFMASK)) == 0) - break; - - args->m = m = ip_reass(m); - - /* - * do IP header checksum fixup. - */ - if (m == NULL) { /* fragment got swallowed */ - retval = IP_FW_DENY; - } else { /* good, packet complete */ - int hlen; - - ip = mtod(m, struct ip *); - hlen = ip->ip_hl << 2; - ip->ip_sum = 0; - if (hlen == sizeof(struct ip)) - ip->ip_sum = in_cksum_hdr(ip); - else - ip->ip_sum = in_cksum(m, hlen); - retval = IP_FW_REASS; - set_match(args, f_pos, chain); - } - done = 1; /* exit outer loop */ + case O_REASS: + rule_reass(f, pktlen, ip, args, m, &retval, &done, &l); break; - } default: panic("-- unknown opcode %d\n", cmd->opcode); Modified: soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw/ip_rules.h ============================================================================== --- soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw/ip_rules.h Thu Jun 12 09:24:17 2014 (r269434) +++ soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw/ip_rules.h Thu Jun 12 09:57:33 2014 (r269435) @@ -26,7 +26,7 @@ * packet with the ports info. */ if (offset != 0) - break; + return; if (proto == IPPROTO_TCP || proto == IPPROTO_UDP) *match = check_uidgid( @@ -164,10 +164,10 @@ else if (v == 6) /* dscp */ key = (ip->ip_tos >> 2) & 0x3f; else if (offset != 0) - break; + return; else if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) - break; + return; else if (v == 2) key = htonl(dst_port); else if (v == 3) @@ -193,12 +193,12 @@ key = htonl(key); } else #endif /* !USERSPACE */ - break; + return; } *match = ipfw_lookup_table(chain, cmd->arg1, key, &v); if (!(*match)) - break; + return; if (cmdlen == F_INSN_SIZE(ipfw_insn_u32)) *match = ((ipfw_insn_u32 *)cmd)->d[0] == v; @@ -265,7 +265,7 @@ args->f_id.src_ip; if (addr < d[0]) - break; + return; addr -= d[0]; /* subtract base */ *match = (addr < cmd->arg1) && ( d[ 1 + (addr>>5)] & @@ -413,7 +413,7 @@ v++; x |= *v >> 6; } else - break; + return; /* DSCP bitmask is stored as low_u32 high_u32 */ if (x > 32) @@ -524,7 +524,7 @@ *match = 1; at = pf_find_mtag(m); if (at != NULL && at->qid != 0) - break; + return; mtag = m_tag_get(PACKET_TAG_PF, sizeof(struct pf_mtag), M_NOWAIT | M_ZERO); if (mtag == NULL) { @@ -733,14 +733,14 @@ struct inpcbinfo *pi; if (is_ipv6) /* XXX can we remove this ? */ - break; + return; if (proto == IPPROTO_TCP) pi = &V_tcbinfo; else if (proto == IPPROTO_UDP) pi = &V_udbinfo; else - break; + return; /* * XXXRW: so_user_cookie should almost @@ -781,7 +781,7 @@ if (cmdlen == 1) { *match = m_tag_locate(m, MTAG_IPFW, tag, NULL) != NULL; - break; + return; } /* we have ranges */ @@ -939,19 +939,135 @@ } inline void -rule_callreturn(ipfw_insn *cmd, int *cmdlen, struct mbuf *m, int *l, struct ip_fw *f, int pktlen, uint32_t *tablearg, jmpto, f_pos, struct ip_fw_chain *chain, int *skip_or) +rule_callreturn(ipfw_insn *cmd, struct mbuf *m, struct ip_fw *f, struct ip_fw_chain *chain, uint32_t tablearg, int pktlen, int *skip_or, int *cmdlen, int *f_pos, int *l) { + /* + * Implementation of `subroutine' call/return, + * in the stack carried in an mbuf tag. This + * is different from `skipto' in that any call + * address is possible (`skipto' must prevent + * backward jumps to avoid endless loops). + * We have `return' action when F_NOT flag is + * present. The `m_tag_id' field is used as + * stack pointer. + */ + struct m_tag *mtag; + uint16_t jmpto, *stack; + +#define IS_CALL ((cmd->len & F_NOT) == 0) +#define IS_RETURN ((cmd->len & F_NOT) != 0) + /* + * Hand-rolled version of m_tag_locate() with + * wildcard `type'. + * If not already tagged, allocate new tag. + */ + mtag = m_tag_first(m); + while (mtag != NULL) { + if (mtag->m_tag_cookie == + MTAG_IPFW_CALL) + break; + mtag = m_tag_next(m, mtag); + } + if (mtag == NULL && IS_CALL) { + mtag = m_tag_alloc(MTAG_IPFW_CALL, 0, + IPFW_CALLSTACK_SIZE * + sizeof(uint16_t), M_NOWAIT); + if (mtag != NULL) + m_tag_prepend(m, mtag); + } + + /* + * On error both `call' and `return' just + * continue with next rule. + */ + if (IS_RETURN && (mtag == NULL || + mtag->m_tag_id == 0)) { + l = 0; /* exit inner loop */ + break; + } + if (IS_CALL && (mtag == NULL || + mtag->m_tag_id >= IPFW_CALLSTACK_SIZE)) { + printf("ipfw: call stack error, " + "go to next rule\n"); + l = 0; /* exit inner loop */ + break; + } + + IPFW_INC_RULE_COUNTER(f, pktlen); + stack = (uint16_t *)(mtag + 1); + + /* + * The `call' action may use cached f_pos + * (in f->next_rule), whose version is written + * in f->next_rule. + * The `return' action, however, doesn't have + * fixed jump address in cmd->arg1 and can't use + * cache. + */ + if (IS_CALL) { + stack[mtag->m_tag_id] = f->rulenum; + mtag->m_tag_id++; + (*f_pos) = jump_fast(chain, f, cmd->arg1, + tablearg, 1); + } else { /* `return' action */ + mtag->m_tag_id--; + jmpto = stack[mtag->m_tag_id] + 1; + (*f_pos) = ipfw_find_rule(chain, jmpto, 0); + } + + /* + * Skip disabled rules, and re-enter + * the inner loop with the correct + * f_pos, f, l and cmd. + * Also clear cmdlen and skip_or + */ + for (; (*f_pos) < chain->n_rules - 1 && + (V_set_disable & + (1 << chain->map[(*f_pos)]->set)); (*f_pos)++) + ; + /* Re-enter the inner loop at the dest rule. */ + f = chain->map[(*f_pos)]; + *l = f->cmd_len; + cmd = f->cmd; + *cmdlen = 0; + *skip_or = 0; +#undef IS_CALL +#undef IS_RETURN } inline void -rule_reject(u_int hlen, int is_ipv4 u_short offset, uint8_t proto, void *void *ulp, struct mbuf *m, struct in_addr *dst_ip, struct ip_fw_args *args, ipfw_insn *cmd, uint16_t iplen struct ip *ip) +rule_reject(u_int hlen, int is_ipv4 u_short offset, uint8_t proto, void *ulp, struct mbuf *m, struct in_addr *dst_ip, struct ip_fw_args *args, ipfw_insn *cmd, uint16_t iplen struct ip *ip) { + /* + * Drop the packet and send a reject notice + * if the packet is not ICMP (or is an ICMP + * query), and it is not multicast/broadcast. + */ + if (hlen > 0 && is_ipv4 && offset == 0 && + (proto != IPPROTO_ICMP || + is_icmp_query(ICMP(ulp))) && + !(m->m_flags & (M_BCAST|M_MCAST)) && + !IN_MULTICAST(ntohl(dst_ip.s_addr))) { + send_reject(args, cmd->arg1, iplen, ip); + m = args->m; + } } #ifdef INET6 inline void -rule_unreach6(u_int hlen, int is_ipv4 u_short offset, uint8_t proto, icmp6_type, struct mbuf *m, struct ip_fw_args *args, ipfw_insn *cmd, struct ip *ip) +rule_unreach6(u_int hlen, int is_ipv4 u_short offset, uint8_t proto, uint8_t icmp6_type, struct mbuf *m, struct ip_fw_args *args, ipfw_insn *cmd, struct ip *ip) { + if (hlen > 0 && is_ipv6 && + ((offset & IP6F_OFF_MASK) == 0) && + (proto != IPPROTO_ICMPV6 || + (is_icmp6_query(icmp6_type) == 1)) && + !(m->m_flags & (M_BCAST|M_MCAST)) && + !IN6_IS_ADDR_MULTICAST(&args->f_id.dst_ip6)) { + send_reject6( + args, cmd->arg1, hlen, + (struct ip6_hdr *)ip); + m = args->m; + } } #endif /* INET6 */ @@ -1021,21 +1137,112 @@ *done = 1; /* exit outer loop */ } +/* XXX typeof rt_numfibs? */ inline void rule_setfib(struct ip_fw *f, int pktlen, ipfw_insn *cmd, rt_numfibs, struct mbuf *m, struct ip_fw_args *args, int *l) { + uint32_t fib; + + IPFW_INC_RULE_COUNTER(f, pktlen); + fib = IP_FW_ARG_TABLEARG(cmd->arg1); + if (fib >= rt_numfibs) + fib = 0; + M_SETFIB(m, fib); + args->f_id.fib = fib; + *l = 0; /* exit inner loop */ } inline void -rule_setdscp(ipfw_insn *cmd, int *l, int is_ipv4 a, int is_ipv6 f, int pktlen) +rule_setdscp(ipfw_insn *cmd, int is_ipv4, int is_ipv6, struct ip_fw *f, int pktlen, int *l) { -} + uint16_t code; + + code = IP_FW_ARG_TABLEARG(cmd->arg1) & 0x3F; + l = 0; /* exit inner loop */ + if (is_ipv4) { + uint16_t a; + + a = ip->ip_tos; + ip->ip_tos = (code << 2) | (ip->ip_tos & 0x03); + a += ntohs(ip->ip_sum) - ip->ip_tos; + ip->ip_sum = htons(a); + } else if (is_ipv6) { + uint8_t *v; + + v = &((struct ip6_hdr *)ip)->ip6_vfc; + *v = (*v & 0xF0) | (code >> 2); + v++; + *v = (*v & 0x3F) | ((code & 0x03) << 6); + } else + return; + IPFW_INC_RULE_COUNTER(f, pktlen); +} inline void -rule_nat(int *l, int *done, int *retval, struct ip_fw_args *args, int f_pos, struct ip_fw_chain *chain, ipfw_insn *cmd, struct ip_fw_chain *chain) +rule_nat(struct ip_fw_args *args, int f_pos, struct ip_fw_chain *chain, ipfw_insn *cmd, int *retval, int *done, int *l) { + *l = 0; /* exit inner loop */ + *done = 1; /* exit outer loop */ + if (!IPFW_NAT_LOADED) { + retval = IP_FW_DENY; + return; + } + + struct cfg_nat *t; + int nat_id; + + set_match(args, f_pos, chain); + /* Check if this is 'global' nat rule */ + if (cmd->arg1 == 0) { + retval = ipfw_nat_ptr(args, NULL, m); + return; + } + t = ((ipfw_insn_nat *)cmd)->nat; + if (t == NULL) { + nat_id = IP_FW_ARG_TABLEARG(cmd->arg1); + t = (*lookup_nat_ptr)(&chain->nat, nat_id); + + if (t == NULL) { + *retval = IP_FW_DENY; + return; + } + if (cmd->arg1 != IP_FW_TABLEARG) + ((ipfw_insn_nat *)cmd)->nat = t; + } + *retval = ipfw_nat_ptr(args, t, m); } -inlinue void rule_reass(struct ip_fw *f, int pktlen, int *l, ip_off, struct ip *ip, struct ip_fw_args *args, struct mbuf *m, int *retval, int *done) +inlinue void rule_reass(struct ip_fw *f, int pktlen, struct ip *ip, struct ip_fw_args *args, struct mbuf *m, int *retval, int *done, int *l) { + int ip_off; + + IPFW_INC_RULE_COUNTER(f, pktlen); + *l = 0; /* in any case exit inner loop */ + ip_off = ntohs(ip->ip_off); + + /* if not fragmented, go to next rule */ + if ((ip_off & (IP_MF | IP_OFFMASK)) == 0) + return; + + args->m = m = ip_reass(m); + + /* + * do IP header checksum fixup. + */ + if (m == NULL) { /* fragment got swallowed */ + *retval = IP_FW_DENY; + } else { /* good, packet complete */ + int hlen; + + ip = mtod(m, struct ip *); + hlen = ip->ip_hl << 2; + ip->ip_sum = 0; + if (hlen == sizeof(struct ip)) + ip->ip_sum = in_cksum_hdr(ip); + else + ip->ip_sum = in_cksum(m, hlen); + *retval = IP_FW_REASS; + set_match(args, f_pos, chain); + } + *done = 1; /* exit outer loop */ }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406120957.s5C9vXDx093065>
