Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/ipfw/nptv6/nptv6.c
| Show First 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | |||||
| #include <netinet/ip6.h> | #include <netinet/ip6.h> | ||||
| #include <netinet/icmp6.h> | #include <netinet/icmp6.h> | ||||
| #include <netinet6/in6_var.h> | #include <netinet6/in6_var.h> | ||||
| #include <netinet6/ip6_var.h> | #include <netinet6/ip6_var.h> | ||||
| #include <netpfil/ipfw/ip_fw_private.h> | #include <netpfil/ipfw/ip_fw_private.h> | ||||
| #include <netpfil/ipfw/nptv6/nptv6.h> | #include <netpfil/ipfw/nptv6/nptv6.h> | ||||
| VNET_DEFINE_STATIC(uint16_t, nptv6_eid) = 0; | VNET_DEFINE_STATIC(uint32_t, nptv6_eid) = 0; | ||||
| #define V_nptv6_eid VNET(nptv6_eid) | #define V_nptv6_eid VNET(nptv6_eid) | ||||
| #define IPFW_TLV_NPTV6_NAME IPFW_TLV_EACTION_NAME(V_nptv6_eid) | #define IPFW_TLV_NPTV6_NAME IPFW_TLV_EACTION_NAME(V_nptv6_eid) | ||||
| static eventhandler_tag nptv6_ifaddr_event; | static eventhandler_tag nptv6_ifaddr_event; | ||||
| static struct nptv6_cfg *nptv6_alloc_config(const char *name, uint8_t set); | static struct nptv6_cfg *nptv6_alloc_config(const char *name, uint8_t set); | ||||
| static void nptv6_free_config(struct nptv6_cfg *cfg); | static void nptv6_free_config(struct nptv6_cfg *cfg); | ||||
| static struct nptv6_cfg *nptv6_find(struct namedobj_instance *ni, | static struct nptv6_cfg *nptv6_find(struct namedobj_instance *ni, | ||||
| const char *name, uint8_t set); | const char *name, uint8_t set); | ||||
| static int nptv6_rewrite_internal(struct nptv6_cfg *cfg, struct mbuf **mp, | static int nptv6_rewrite_internal(struct nptv6_cfg *cfg, struct mbuf **mp, | ||||
| int offset); | int offset); | ||||
| static int nptv6_rewrite_external(struct nptv6_cfg *cfg, struct mbuf **mp, | static int nptv6_rewrite_external(struct nptv6_cfg *cfg, struct mbuf **mp, | ||||
| int offset); | int offset); | ||||
| #define NPTV6_LOOKUP(chain, cmd) \ | #define NPTV6_LOOKUP(chain, cmd) \ | ||||
| (struct nptv6_cfg *)SRV_OBJECT((chain), (cmd)->arg1) | (struct nptv6_cfg *)SRV_OBJECT((chain), insntod(cmd, kidx)->kidx) | ||||
| #ifndef IN6_MASK_ADDR | #ifndef IN6_MASK_ADDR | ||||
| #define IN6_MASK_ADDR(a, m) do { \ | #define IN6_MASK_ADDR(a, m) do { \ | ||||
| (a)->s6_addr32[0] &= (m)->s6_addr32[0]; \ | (a)->s6_addr32[0] &= (m)->s6_addr32[0]; \ | ||||
| (a)->s6_addr32[1] &= (m)->s6_addr32[1]; \ | (a)->s6_addr32[1] &= (m)->s6_addr32[1]; \ | ||||
| (a)->s6_addr32[2] &= (m)->s6_addr32[2]; \ | (a)->s6_addr32[2] &= (m)->s6_addr32[2]; \ | ||||
| (a)->s6_addr32[3] &= (m)->s6_addr32[3]; \ | (a)->s6_addr32[3] &= (m)->s6_addr32[3]; \ | ||||
| } while (0) | } while (0) | ||||
| ▲ Show 20 Lines • Show All 261 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
| struct nptv6_cfg *cfg; | struct nptv6_cfg *cfg; | ||||
| ipfw_insn *icmd; | ipfw_insn *icmd; | ||||
| int ret; | int ret; | ||||
| *done = 0; /* try next rule if not matched */ | *done = 0; /* try next rule if not matched */ | ||||
| ret = IP_FW_DENY; | ret = IP_FW_DENY; | ||||
| icmd = cmd + 1; | icmd = cmd + F_LEN(cmd); | ||||
| if (cmd->opcode != O_EXTERNAL_ACTION || | if (cmd->opcode != O_EXTERNAL_ACTION || | ||||
| cmd->arg1 != V_nptv6_eid || | insntod(cmd, kidx)->kidx != V_nptv6_eid || | ||||
| icmd->opcode != O_EXTERNAL_INSTANCE || | icmd->opcode != O_EXTERNAL_INSTANCE || | ||||
| (cfg = NPTV6_LOOKUP(chain, icmd)) == NULL || | (cfg = NPTV6_LOOKUP(chain, icmd)) == NULL || | ||||
| (cfg->flags & NPTV6_READY) == 0) | (cfg->flags & NPTV6_READY) == 0) | ||||
| return (ret); | return (ret); | ||||
| /* | /* | ||||
| * We need act as router, so when forwarding is disabled - | * We need act as router, so when forwarding is disabled - | ||||
| * do nothing. | * do nothing. | ||||
| */ | */ | ||||
| if (V_ip6_forwarding == 0 || args->f_id.addr_type != 6) | if (V_ip6_forwarding == 0 || args->f_id.addr_type != 6) | ||||
| return (ret); | return (ret); | ||||
| /* | /* | ||||
| * NOTE: we expect ipfw_chk() did m_pullup() up to upper level | * NOTE: we expect ipfw_chk() did m_pullup() up to upper level | ||||
| * protocol's headers. Also we skip some checks, that ip6_input(), | * protocol's headers. Also we skip some checks, that ip6_input(), | ||||
| * ip6_forward(), ip6_fastfwd() and ipfw_chk() already did. | * ip6_forward(), ip6_fastfwd() and ipfw_chk() already did. | ||||
| */ | */ | ||||
| ip6 = mtod(args->m, struct ip6_hdr *); | ip6 = mtod(args->m, struct ip6_hdr *); | ||||
| NPTV6_IPDEBUG("eid %u, oid %u, %s -> %s %d", | NPTV6_IPDEBUG("eid %u, oid %u, %s -> %s %d", | ||||
| cmd->arg1, icmd->arg1, | insntod(cmd, kidx)->kidx, insntod(icmd, kidx)->kidx, | ||||
| inet_ntop(AF_INET6, &ip6->ip6_src, _s, sizeof(_s)), | inet_ntop(AF_INET6, &ip6->ip6_src, _s, sizeof(_s)), | ||||
| inet_ntop(AF_INET6, &ip6->ip6_dst, _d, sizeof(_d)), | inet_ntop(AF_INET6, &ip6->ip6_dst, _d, sizeof(_d)), | ||||
| ip6->ip6_nxt); | ip6->ip6_nxt); | ||||
| if (IN6_ARE_MASKED_ADDR_EQUAL(&ip6->ip6_src, | if (IN6_ARE_MASKED_ADDR_EQUAL(&ip6->ip6_src, | ||||
| &cfg->internal, &cfg->mask)) { | &cfg->internal, &cfg->mask)) { | ||||
| /* | /* | ||||
| * XXX: Do not translate packets when both src and dst | * XXX: Do not translate packets when both src and dst | ||||
| * are from internal prefix. | * are from internal prefix. | ||||
| ▲ Show 20 Lines • Show All 513 Lines • ▼ Show 20 Lines | if (cfg == NULL) { | ||||
| return (ESRCH); | return (ESRCH); | ||||
| } | } | ||||
| COUNTER_ARRAY_ZERO(cfg->stats, NPTV6STATS); | COUNTER_ARRAY_ZERO(cfg->stats, NPTV6STATS); | ||||
| IPFW_UH_WUNLOCK(ch); | IPFW_UH_WUNLOCK(ch); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static struct ipfw_sopt_handler scodes[] = { | static struct ipfw_sopt_handler scodes[] = { | ||||
| { IP_FW_NPTV6_CREATE, 0, HDIR_SET, nptv6_create }, | { IP_FW_NPTV6_CREATE, IP_FW3_OPVER, HDIR_SET, nptv6_create }, | ||||
| { IP_FW_NPTV6_DESTROY,0, HDIR_SET, nptv6_destroy }, | { IP_FW_NPTV6_DESTROY, IP_FW3_OPVER, HDIR_SET, nptv6_destroy }, | ||||
| { IP_FW_NPTV6_CONFIG, 0, HDIR_BOTH, nptv6_config }, | { IP_FW_NPTV6_CONFIG, IP_FW3_OPVER, HDIR_BOTH,nptv6_config }, | ||||
| { IP_FW_NPTV6_LIST, 0, HDIR_GET, nptv6_list }, | { IP_FW_NPTV6_LIST, IP_FW3_OPVER, HDIR_GET, nptv6_list }, | ||||
| { IP_FW_NPTV6_STATS, 0, HDIR_GET, nptv6_stats }, | { IP_FW_NPTV6_STATS, IP_FW3_OPVER, HDIR_GET, nptv6_stats }, | ||||
| { IP_FW_NPTV6_RESET_STATS,0, HDIR_SET, nptv6_reset_stats }, | { IP_FW_NPTV6_RESET_STATS, IP_FW3_OPVER, HDIR_SET, nptv6_reset_stats }, | ||||
| }; | }; | ||||
| static int | static int | ||||
| nptv6_classify(ipfw_insn *cmd, uint16_t *puidx, uint8_t *ptype) | nptv6_classify(ipfw_insn *cmd0, uint32_t *puidx, uint8_t *ptype) | ||||
| { | { | ||||
| ipfw_insn *icmd; | ipfw_insn *icmd; | ||||
| icmd = cmd - 1; | icmd = cmd0 - F_LEN(cmd0); | ||||
| NPTV6_DEBUG("opcode %d, arg1 %d, opcode0 %d, arg1 %d", | NPTV6_DEBUG("opcode %u, kidx %u, opcode0 %u, kidx %u", | ||||
| cmd->opcode, cmd->arg1, icmd->opcode, icmd->arg1); | cmd->opcode, insntod(cmd, kidx)->kidx, | ||||
| icmd->opcode, insntod(icmd, kidx)->kidx); | |||||
| if (icmd->opcode != O_EXTERNAL_ACTION || | if (icmd->opcode != O_EXTERNAL_ACTION || | ||||
| icmd->arg1 != V_nptv6_eid) | insntod(icmd, kidx)->kidx != V_nptv6_eid) | ||||
| return (1); | return (1); | ||||
| *puidx = cmd->arg1; | *puidx = insntod(cmd0, kidx)->kidx; | ||||
| *ptype = 0; | *ptype = 0; | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static void | static void | ||||
| nptv6_update_arg1(ipfw_insn *cmd, uint16_t idx) | nptv6_update_kidx(ipfw_insn *cmd0, uint32_t idx) | ||||
| { | { | ||||
| cmd->arg1 = idx; | insntod(cmd0, kidx)->kidx = idx; | ||||
| NPTV6_DEBUG("opcode %d, arg1 -> %d", cmd->opcode, cmd->arg1); | NPTV6_DEBUG("opcode %u, kidx -> %u", cmd->opcode, idx); | ||||
| } | } | ||||
| static int | static int | ||||
| nptv6_findbyname(struct ip_fw_chain *ch, struct tid_info *ti, | nptv6_findbyname(struct ip_fw_chain *ch, struct tid_info *ti, | ||||
| struct named_object **pno) | struct named_object **pno) | ||||
| { | { | ||||
| int err; | int err; | ||||
| err = ipfw_objhash_find_type(CHAIN_TO_SRV(ch), ti, | err = ipfw_objhash_find_type(CHAIN_TO_SRV(ch), ti, | ||||
| IPFW_TLV_NPTV6_NAME, pno); | IPFW_TLV_NPTV6_NAME, pno); | ||||
| NPTV6_DEBUG("uidx %u, type %u, err %d", ti->uidx, ti->type, err); | NPTV6_DEBUG("uidx %u, type %u, err %d", ti->uidx, ti->type, err); | ||||
| return (err); | return (err); | ||||
| } | } | ||||
| static struct named_object * | static struct named_object * | ||||
| nptv6_findbykidx(struct ip_fw_chain *ch, uint16_t idx) | nptv6_findbykidx(struct ip_fw_chain *ch, uint32_t idx) | ||||
| { | { | ||||
| struct namedobj_instance *ni; | struct namedobj_instance *ni; | ||||
| struct named_object *no; | struct named_object *no; | ||||
| IPFW_UH_WLOCK_ASSERT(ch); | IPFW_UH_WLOCK_ASSERT(ch); | ||||
| ni = CHAIN_TO_SRV(ch); | ni = CHAIN_TO_SRV(ch); | ||||
| no = ipfw_objhash_lookup_kidx(ni, idx); | no = ipfw_objhash_lookup_kidx(ni, idx); | ||||
| KASSERT(no != NULL, ("NPT with index %d not found", idx)); | KASSERT(no != NULL, ("NPT with index %u not found", idx)); | ||||
| NPTV6_DEBUG("kidx %u -> %s", idx, no->name); | NPTV6_DEBUG("kidx %u -> %s", idx, no->name); | ||||
| return (no); | return (no); | ||||
| } | } | ||||
| static int | static int | ||||
| nptv6_manage_sets(struct ip_fw_chain *ch, uint16_t set, uint8_t new_set, | nptv6_manage_sets(struct ip_fw_chain *ch, uint32_t set, uint8_t new_set, | ||||
| enum ipfw_sets_cmd cmd) | enum ipfw_sets_cmd cmd) | ||||
| { | { | ||||
| return (ipfw_obj_manage_sets(CHAIN_TO_SRV(ch), IPFW_TLV_NPTV6_NAME, | return (ipfw_obj_manage_sets(CHAIN_TO_SRV(ch), IPFW_TLV_NPTV6_NAME, | ||||
| set, new_set, cmd)); | set, new_set, cmd)); | ||||
| } | } | ||||
| static struct opcode_obj_rewrite opcodes[] = { | static struct opcode_obj_rewrite opcodes[] = { | ||||
| { | { | ||||
| .opcode = O_EXTERNAL_INSTANCE, | .opcode = O_EXTERNAL_INSTANCE, | ||||
| .etlv = IPFW_TLV_EACTION /* just show it isn't table */, | .etlv = IPFW_TLV_EACTION /* just show it isn't table */, | ||||
| .classifier = nptv6_classify, | .classifier = nptv6_classify, | ||||
| .update = nptv6_update_arg1, | .update = nptv6_update_kidx, | ||||
| .find_byname = nptv6_findbyname, | .find_byname = nptv6_findbyname, | ||||
| .find_bykidx = nptv6_findbykidx, | .find_bykidx = nptv6_findbykidx, | ||||
| .manage_sets = nptv6_manage_sets, | .manage_sets = nptv6_manage_sets, | ||||
| }, | }, | ||||
| }; | }; | ||||
| static int | static int | ||||
| destroy_config_cb(struct namedobj_instance *ni, struct named_object *no, | destroy_config_cb(struct namedobj_instance *ni, struct named_object *no, | ||||
| ▲ Show 20 Lines • Show All 50 Lines • Show Last 20 Lines | |||||