Date: Thu, 12 Jun 2014 08:40:39 GMT From: dpl@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r269431 - soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw Message-ID: <201406120840.s5C8edED014071@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dpl Date: Thu Jun 12 08:40:37 2014 New Revision: 269431 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=269431 Log: Added up to rule_skipto(). 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 04:47:14 2014 (r269430) +++ soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw/ip_fw2.c Thu Jun 12 08:40:37 2014 (r269431) @@ -780,7 +780,7 @@ */ static inline void set_match(struct ip_fw_args *args, int slot, - struct ip_fw_chain *chain) + struct ip_fw_chain *chain) { args->rule.chain_id = chain->id; args->rule.slot = slot + 1; /* we use 0 as a marker */ @@ -1625,116 +1625,21 @@ rule_ip4(&match, is_ipv4); break; - case O_TAG: { - struct m_tag *mtag; - uint32_t tag = IP_FW_ARG_TABLEARG(cmd->arg1); - - /* Packet is already tagged with this tag? */ - mtag = m_tag_locate(m, MTAG_IPFW, tag, NULL); - - /* We have `untag' action when F_NOT flag is - * present. And we must remove this mtag from - * mbuf and reset `match' to zero (`match' will - * be inversed later). - * Otherwise we should allocate new mtag and - * push it into mbuf. - */ - if (cmd->len & F_NOT) { /* `untag' action */ - if (mtag != NULL) - m_tag_delete(m, mtag); - match = 0; - } else { - if (mtag == NULL) { - mtag = m_tag_alloc( MTAG_IPFW, - tag, 0, M_NOWAIT); - if (mtag != NULL) - m_tag_prepend(m, mtag); - } - match = 1; - } + case O_TAG: + rule_tag(&match, cmd, m); break; - } case O_FIB: /* try match the specified fib */ - if (args->f_id.fib == cmd->arg1) - match = 1; + rule_fib(&match, args, cmd); break; - case O_SOCKARG: { -#ifndef USERSPACE /* not supported in userspace */ - struct inpcb *inp = args->inp; - struct inpcbinfo *pi; - - if (is_ipv6) /* XXX can we remove this ? */ - break; - - if (proto == IPPROTO_TCP) - pi = &V_tcbinfo; - else if (proto == IPPROTO_UDP) - pi = &V_udbinfo; - else - break; - - /* - * XXXRW: so_user_cookie should almost - * certainly be inp_user_cookie? - */ - - /* For incomming packet, lookup up the - inpcb using the src/dest ip/port tuple */ - if (inp == NULL) { - inp = in_pcblookup(pi, - src_ip, htons(src_port), - dst_ip, htons(dst_port), - INPLOOKUP_RLOCKPCB, NULL); - if (inp != NULL) { - tablearg = - inp->inp_socket->so_user_cookie; - if (tablearg) - match = 1; - INP_RUNLOCK(inp); - } - } else { - if (inp->inp_socket) { - tablearg = - inp->inp_socket->so_user_cookie; - if (tablearg) - match = 1; - } - } -#endif /* !USERSPACE */ + case O_SOCKARG: + rule_sockarg(); break; - } - - case O_TAGGED: { - struct m_tag *mtag; - uint32_t tag = IP_FW_ARG_TABLEARG(cmd->arg1); - - if (cmdlen == 1) { - match = m_tag_locate(m, MTAG_IPFW, - tag, NULL) != NULL; - break; - } - /* we have ranges */ - for (mtag = m_tag_first(m); - mtag != NULL && !match; - mtag = m_tag_next(m, mtag)) { - uint16_t *p; - int i; - - if (mtag->m_tag_cookie != MTAG_IPFW) - continue; - - p = ((ipfw_insn_u16 *)cmd)->ports; - i = cmdlen - 1; - for(; !match && i > 0; i--, p += 2) - match = - mtag->m_tag_id >= p[0] && - mtag->m_tag_id <= p[1]; - } + case O_TAGGED: + rule_tagged(&match, cmd, cmdlen, m); break; - } /* * The second set of opcodes represents 'actions', @@ -1779,99 +1684,30 @@ */ case O_LIMIT: case O_KEEP_STATE: - if (ipfw_install_state(f, - (ipfw_insn_limit *)cmd, args, tablearg)) { - /* error or limit violation */ - retval = IP_FW_DENY; - l = 0; /* exit inner loop */ - done = 1; /* exit outer loop */ - } - match = 1; + rule_keep_state(&match, f, cmd, args, tablearg, &retval, &l, &done); break; case O_PROBE_STATE: case O_CHECK_STATE: - /* - * dynamic rules are checked at the first - * keep-state or check-state occurrence, - * with the result being stored in dyn_dir. - * The compiler introduces a PROBE_STATE - * instruction for us when we have a - * KEEP_STATE (because PROBE_STATE needs - * to be run first). - */ - if (dyn_dir == MATCH_UNKNOWN && - (q = ipfw_lookup_dyn_rule(&args->f_id, - &dyn_dir, proto == IPPROTO_TCP ? - TCP(ulp) : NULL)) - != NULL) { - /* - * Found dynamic entry, update stats - * and jump to the 'action' part of - * the parent rule by setting - * f, cmd, l and clearing cmdlen. - */ - IPFW_INC_DYN_COUNTER(q, pktlen); - /* XXX we would like to have f_pos - * readily accessible in the dynamic - * rule, instead of having to - * lookup q->rule. - */ - f = q->rule; - f_pos = ipfw_find_rule(chain, - f->rulenum, f->id); - cmd = ACTION_PTR(f); - l = f->cmd_len - f->act_ofs; - ipfw_dyn_unlock(q); - cmdlen = 0; - match = 1; - break; - } - /* - * Dynamic entry not found. If CHECK_STATE, - * skip to next rule, if PROBE_STATE just - * ignore and continue with next opcode. - */ - if (cmd->opcode == O_CHECK_STATE) - l = 0; /* exit inner loop */ - match = 1; + rule_check_state(&match); break; case O_ACCEPT: - retval = 0; /* accept */ - l = 0; /* exit inner loop */ - done = 1; /* exit outer loop */ + rule_accept(&retval, &l, &done); break; case O_PIPE: case O_QUEUE: - set_match(args, f_pos, chain); - args->rule.info = IP_FW_ARG_TABLEARG(cmd->arg1); - if (cmd->opcode == O_PIPE) - args->rule.info |= IPFW_IS_PIPE; - if (V_fw_one_pass) - args->rule.info |= IPFW_ONEPASS; - retval = IP_FW_DUMMYNET; - l = 0; /* exit inner loop */ - done = 1; /* exit outer loop */ + rule_queue(args, f_pos, chain, cmd, &retval, &l, &done); break; case O_DIVERT: case O_TEE: - if (args->eh) /* not on layer 2 */ - break; - /* otherwise this is terminal */ - l = 0; /* exit inner loop */ - done = 1; /* exit outer loop */ - retval = (cmd->opcode == O_DIVERT) ? - IP_FW_DIVERT : IP_FW_TEE; - set_match(args, f_pos, chain); - args->rule.info = IP_FW_ARG_TABLEARG(cmd->arg1); + rule_tee(&l, &done, &retval, cmd, args, f_pos, chain); break; case O_COUNT: - IPFW_INC_RULE_COUNTER(f, pktlen); - l = 0; /* exit inner loop */ + rule_count(&l, f, pktlen); break; case O_SKIPTO: Modified: soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw/ip_rules.h ============================================================================== --- soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw/ip_rules.h Thu Jun 12 04:47:14 2014 (r269430) +++ soc2014/dpl/netmap-ipfw/sys/netpfil/ipfw/ip_rules.h Thu Jun 12 08:40:37 2014 (r269431) @@ -219,7 +219,6 @@ } -//XXX Speak with mentor about passing both dst_ip and src_ip. inline void rule_ip_dst_mask(int *match, int is_ipv4, ipfw_insn *cmd, int cmdlen, struct in_addr *dst_ip, struct in_addr *src_ip) { @@ -585,9 +584,8 @@ verify_path(src_ip, NULL, args->f_id.fib))); } -// XXX typeof(m)? inline void -rule_antispoof(int *match, struct ifnet *oif, u_int hlen, int is_ipv4, int is_ipv6, struct in_addr *src_ip, struct ip_fw_args *args, m) +rule_antispoof(int *match, struct ifnet *oif, u_int hlen, int is_ipv4, int is_ipv6, struct in_addr *src_ip, struct ip_fw_args *args, struct mbuf *m) { /* Outgoing packets automatically pass/match */ if (oif == NULL && hlen > 0 && @@ -809,42 +807,139 @@ * The second sets of opcodes. They represent the actions of a rule. */ inline void -rule_keep_state(int *match, f, ipfw_insn *cmd, struct ip_fw_args *args, uint32_t *tablearg, retval, l, done) +rule_keep_state(int *match, struct ip_fw *f, ipfw_insn *cmd, struct ip_fw_args *args, uint32_t *tablearg, int *retval, int *l, int *done) { + if (ipfw_install_state(f, + (ipfw_insn_limit *)cmd, args, tablearg)) { + /* error or limit violation */ + *retval = IP_FW_DENY; + *l = 0; /* exit inner loop */ + *done = 1; /* exit outer loop */ + } + *match = 1; } +/* XXX typeof dyn_dir? */ +/* XXX typeof q? */ inline void -rule_check_state(int *match, dyn_dir, q, struct ip_fw_args *args, uint8_t proto, void *void *ulp, pktlen, f, f_pos, struct ip_fw_chain *chain, ipfw_insn *cmd, int *cmdlen, l) +rule_check_state(int *match, dyn_dir, q, struct ip_fw_args *args, uint8_t proto, void *ulp, int pktlen, struct ip_fw *f, int *f_pos, struct ip_fw_chain *chain, ipfw_insn *cmd, int *cmdlen, int *l) { + /* + * dynamic rules are checked at the first + * keep-state or check-state occurrence, + * with the result being stored in dyn_dir. + * The compiler introduces a PROBE_STATE + * instruction for us when we have a + * KEEP_STATE (because PROBE_STATE needs + * to be run first). + */ + if (dyn_dir == MATCH_UNKNOWN && + (q = ipfw_lookup_dyn_rule(&args->f_id, + &dyn_dir, proto == IPPROTO_TCP ? + TCP(ulp) : NULL)) + != NULL) { + /* + * Found dynamic entry, update stats + * and jump to the 'action' part of + * the parent rule by setting + * f, cmd, l and clearing cmdlen. + */ + IPFW_INC_DYN_COUNTER(q, pktlen); + /* XXX we would like to have f_pos + * readily accessible in the dynamic + * rule, instead of having to + * lookup q->rule. + */ + f = q->rule; + *f_pos = ipfw_find_rule(chain, + f->rulenum, f->id); + cmd = ACTION_PTR(f); + *l = f->cmd_len - f->act_ofs; + ipfw_dyn_unlock(q); + *cmdlen = 0; + *match = 1; + return; + } + /* + * Dynamic entry not found. If CHECK_STATE, + * skip to next rule, if PROBE_STATE just + * ignore and continue with next opcode. + */ + if (cmd->opcode == O_CHECK_STATE) + *l = 0; /* exit inner loop */ + *match = 1; } inline void -rule_accept(retval, l, done) +rule_accept(int *retval, int *l, int *done) { + *retval = 0; /* accept */ + *l = 0; /* exit inner loop */ + *done = 1; /* exit outer loop */ } inline void -rule_queue(args, f_pos, struct ip_fw_chain *chain, ipfw_insn *cmd, retval, l, done) +rule_queue(struct ip_fw_args *args, int f_pos, struct ip_fw_chain *chain, ipfw_insn *cmd, int *retval, int *l, int *done) { + set_match(args, f_pos, chain); + args->rule.info = IP_FW_ARG_TABLEARG(cmd->arg1); + if (cmd->opcode == O_PIPE) + args->rule.info |= IPFW_IS_PIPE; + if (V_fw_one_pass) + args->rule.info |= IPFW_ONEPASS; + *retval = IP_FW_DUMMYNET; + *l = 0; /* exit inner loop */ + *done = 1; /* exit outer loop */ } inline void -rule_tee(args, l, done, retval, ipfw_insn *cmd, struct ip_fw_args *args, f_pos, struct ip_fw_chain *chain) +rule_tee(int *l, int *done, int *retval, ipfw_insn *cmd, struct ip_fw_args *args, int f_pos, struct ip_fw_chain *chain) { + if (args->eh) /* not on layer 2 */ + return; + /* otherwise this is terminal */ + *l = 0; /* exit inner loop */ + *done = 1; /* exit outer loop */ + *retval = (cmd->opcode == O_DIVERT) ? + IP_FW_DIVERT : IP_FW_TEE; + set_match(args, f_pos, chain); + args->rule.info = IP_FW_ARG_TABLEARG(cmd->arg1); } inline void -rule_count(l, f, pktlen) +rule_count(int *l, struct ip_fw *f, int pktlen) { + IPFW_INC_RULE_COUNTER(f, pktlen); + *l = 0; /* exit inner loop */ } inline void -rule_skipto(int *match, f, f_pos, pktlen, struct ip_fw_chain *chain, ipfw_insn *cmd, uint32_t *tablearg, l, ipfw_insn *cmd, int *cmdlen, skip_or) +rule_skipto(int *match, int *l, ipfw_insn *cmd, int *cmdlen, int *skip_or, int *f_pos, struct ip_fw *f, int pktlen, struct ip_fw_chain *chain, ipfw_insn *cmd, uint32_t tablearg) { + IPFW_INC_RULE_COUNTER(f, pktlen); + *f_pos = jump_fast(chain, f, cmd->arg1, tablearg, 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 skipto rule. */ + f = chain->map[f_pos]; + *l = f->cmd_len; + cmd = f->cmd; + *match = 1; + *cmdlen = 0; + *skip_or = 0; } inline void -rule_callreturn(ipfw_insn *cmd, int *cmdlen, struct mbuf *m, l, f, pktlen, uint32_t *tablearg, jmpto, f_pos, struct ip_fw_chain *chain, skip_or) +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) { } @@ -862,42 +957,42 @@ inline void -rule_deny(l, done, retval) +rule_deny(int *l, int *done, int *retval) { } inline void -rule_forward_ip(args, q, dyn_dir, ipfw_insn *cmd, sa, retval, l, done) +rule_forward_ip(args, q, dyn_dir, ipfw_insn *cmd, sa, int *retval, int *l, int *done) { } #ifdef INET6 inline void -rule_forward_ip6(args, q, f, dun_dir, ipfw_insn *cmd, struct ip_fw_args *args, retval, l, done) +rule_forward_ip6(args, q, struct ip_fw *f, dun_dir, ipfw_insn *cmd, struct ip_fw_args *args, int *retval, int *l, int *done) { } #endif /* INET6 */ inline void -rule_ngtee(args, f_pos, struct ip_fw_chain *chain, ipfw_insn *cmd, V_fw_one_pass, retval, l, done) +rule_ngtee(args, f_pos, struct ip_fw_chain *chain, ipfw_insn *cmd, V_fw_one_pass, int *retval, int *l, int *done) { } inline void -rule_setfib(f, pktlen, ipfw_insn *cmd, rt_numfibs, struct mbuf *m, struct ip_fw_args *args, l) +rule_setfib(struct ip_fw *f, int pktlen, ipfw_insn *cmd, rt_numfibs, struct mbuf *m, struct ip_fw_args *args, int *l) { } inline void -rule_setdscp(ipfw_insn *cmd, l, int is_ipv4 a, int is_ipv6 f, pktlen) +rule_setdscp(ipfw_insn *cmd, int *l, int is_ipv4 a, int is_ipv6 f, int pktlen) { } inline void -rule_nat(l, done, retval, struct ip_fw_args *args, f_pos, struct ip_fw_chain *chain, ipfw_insn *cmd, struct ip_fw_chain *chain) +rule_nat(int *l, int *done, int *retval, struct ip_fw_args *args, f_pos, struct ip_fw_chain *chain, ipfw_insn *cmd, struct ip_fw_chain *chain) { } -inlinue void rule_reass(f, pktlen, l, ip_off, struct ip *ip, struct ip_fw_args *args, struct mbuf *m, retval, done) +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) { }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406120840.s5C8edED014071>