Index: sbin/ipfw/ipfw.8 =================================================================== --- sbin/ipfw/ipfw.8 +++ sbin/ipfw/ipfw.8 @@ -3456,6 +3456,17 @@ Turn off private address handling in .Nm nat64 instance. +.It Cm swap_conf +Allow the exchanging of runtime configurations between two instances with +the same name in different sets during the sets swapping. +The runtime configuration keeps all states, that were created by the +.cm nat64lsn +instance. +Both instances must allow exchanging. +Initial configuration of both instances must be similar, i.e. +the instance name and IPv4 and IPv6 prefixes must be the same. +.It Cm -swap_conf +Turn off the ability of runtime configuration exchanging. .El .Pp To inspect a states table of stateful NAT64 the following command can be used: Index: sbin/ipfw/ipfw2.h =================================================================== --- sbin/ipfw/ipfw2.h +++ sbin/ipfw/ipfw2.h @@ -293,6 +293,8 @@ TOK_LOGOFF, TOK_PRIVATE, TOK_PRIVATEOFF, + TOK_SWAPCONF, + TOK_SWAPCONFOFF, /* NAT64 CLAT tokens */ TOK_NAT64CLAT, Index: sbin/ipfw/nat64lsn.c =================================================================== --- sbin/ipfw/nat64lsn.c +++ sbin/ipfw/nat64lsn.c @@ -380,6 +380,8 @@ { "-log", TOK_LOGOFF }, { "allow_private", TOK_PRIVATE }, { "-allow_private", TOK_PRIVATEOFF }, + { "swap_conf", TOK_SWAPCONF }, + { "-swap_conf", TOK_SWAPCONFOFF }, /* for compatibility with old configurations */ { "max_ports", TOK_MAX_PORTS }, /* unused */ { NULL, 0 } @@ -514,6 +516,12 @@ case TOK_PRIVATEOFF: cfg->flags &= ~NAT64_ALLOW_PRIVATE; break; + case TOK_SWAPCONF: + cfg->flags |= NAT64LSN_ALLOW_SWAPCONF; + break; + case TOK_SWAPCONFOFF: + cfg->flags &= ~NAT64LSN_ALLOW_SWAPCONF; + break; } } @@ -631,6 +639,12 @@ case TOK_PRIVATEOFF: cfg->flags &= ~NAT64_ALLOW_PRIVATE; break; + case TOK_SWAPCONF: + cfg->flags |= NAT64LSN_ALLOW_SWAPCONF; + break; + case TOK_SWAPCONFOFF: + cfg->flags &= ~NAT64LSN_ALLOW_SWAPCONF; + break; default: errx(EX_USAGE, "Can't change %s option", opt); } @@ -796,10 +810,12 @@ printf(" icmp_age %u", cfg->st_icmp_ttl); if (co.verbose || cfg->jmaxlen != NAT64LSN_JMAXLEN) printf(" jmaxlen %u", cfg->jmaxlen); - if (cfg->flags & NAT64_LOG) - printf(" log"); if (cfg->flags & NAT64_ALLOW_PRIVATE) printf(" allow_private"); + if (cfg->flags & NAT64LSN_ALLOW_SWAPCONF) + printf(" swap_conf"); + if (cfg->flags & NAT64_LOG) + printf(" log"); printf("\n"); return (0); } Index: sys/netinet6/ip_fw_nat64.h =================================================================== --- sys/netinet6/ip_fw_nat64.h +++ sys/netinet6/ip_fw_nat64.h @@ -97,6 +97,11 @@ #define NAT64_ALLOW_PRIVATE 0x0002 /* Allow private IPv4 address * translation */ +#define NAT64LSN_ALLOW_SWAPCONF 0x0004 /* Allow configuration exchange + * between NAT64LSN instances + * during the sets swapping. + */ + typedef struct _ipfw_nat64stl_cfg { char name[64]; /* NAT name */ ipfw_obj_ntlv ntlv6; /* object name tlv */ Index: sys/netpfil/ipfw/nat64/nat64lsn.h =================================================================== --- sys/netpfil/ipfw/nat64/nat64lsn.h +++ sys/netpfil/ipfw/nat64/nat64lsn.h @@ -191,8 +191,6 @@ STAILQ_HEAD(nat64lsn_job_head, nat64lsn_job_item); struct nat64lsn_cfg { - struct named_object no; - struct nat64lsn_hosts_slist *hosts_hash; struct nat64lsn_alias *aliases; /* array of aliases */ @@ -218,7 +216,8 @@ uint16_t st_icmp_ttl; /* ICMP expire */ struct nat64_config base; -#define NAT64LSN_FLAGSMASK (NAT64_LOG | NAT64_ALLOW_PRIVATE) +#define NAT64LSN_FLAGSMASK (NAT64_LOG | NAT64_ALLOW_PRIVATE |\ + NAT64LSN_ALLOW_SWAPCONF) #define NAT64LSN_ANYPREFIX 0x00000100 struct mtx periodic_lock; @@ -227,6 +226,11 @@ struct vnet *vp; struct nat64lsn_job_head jhead; int jlen; +}; + +struct nat64lsn_instance { + struct named_object no; + struct nat64lsn_cfg *cfg; char name[64]; /* Nat instance name */ }; @@ -243,9 +247,11 @@ #define CALLOUT_LOCK(p) mtx_lock(&(p)->periodic_lock) #define CALLOUT_UNLOCK(p) mtx_unlock(&(p)->periodic_lock) -struct nat64lsn_cfg *nat64lsn_init_instance(struct ip_fw_chain *ch, +MALLOC_DECLARE(M_NAT64LSN); + +struct nat64lsn_cfg *nat64lsn_init_config(struct ip_fw_chain *ch, in_addr_t prefix, int plen); -void nat64lsn_destroy_instance(struct nat64lsn_cfg *cfg); +void nat64lsn_destroy_config(struct nat64lsn_cfg *cfg); void nat64lsn_start_instance(struct nat64lsn_cfg *cfg); void nat64lsn_init_internal(void); void nat64lsn_uninit_internal(void); Index: sys/netpfil/ipfw/nat64/nat64lsn.c =================================================================== --- sys/netpfil/ipfw/nat64/nat64lsn.c +++ sys/netpfil/ipfw/nat64/nat64lsn.c @@ -87,7 +87,7 @@ static void nat64lsn_periodic(void *data); #define PERIODIC_DELAY 4 #define NAT64_LOOKUP(chain, cmd) \ - (struct nat64lsn_cfg *)SRV_OBJECT((chain), (cmd)->arg1) + (struct nat64lsn_instance *)SRV_OBJECT((chain), (cmd)->arg1) /* * Delayed job queue, used to create new hosts * and new portgroups @@ -1514,7 +1514,7 @@ ipfw_nat64lsn(struct ip_fw_chain *ch, struct ip_fw_args *args, ipfw_insn *cmd, int *done) { - struct nat64lsn_cfg *cfg; + struct nat64lsn_instance *i; ipfw_insn *icmd; int ret; @@ -1525,29 +1525,29 @@ if (cmd->opcode != O_EXTERNAL_ACTION || cmd->arg1 != V_nat64lsn_eid || icmd->opcode != O_EXTERNAL_INSTANCE || - (cfg = NAT64_LOOKUP(ch, icmd)) == NULL) + (i = NAT64_LOOKUP(ch, icmd)) == NULL) return (IP_FW_DENY); *done = 1; /* terminate the search */ switch (args->f_id.addr_type) { case 4: - ret = nat64lsn_translate4(cfg, &args->f_id, &args->m); + ret = nat64lsn_translate4(i->cfg, &args->f_id, &args->m); break; case 6: /* * Check that destination IPv6 address matches our prefix6. */ - if ((cfg->base.flags & NAT64LSN_ANYPREFIX) == 0 && - memcmp(&args->f_id.dst_ip6, &cfg->base.plat_prefix, - cfg->base.plat_plen / 8) != 0) { - ret = cfg->nomatch_verdict; + if ((i->cfg->base.flags & NAT64LSN_ANYPREFIX) == 0 && + memcmp(&args->f_id.dst_ip6, &i->cfg->base.plat_prefix, + i->cfg->base.plat_plen / 8) != 0) { + ret = i->cfg->nomatch_verdict; break; } - ret = nat64lsn_translate6(cfg, &args->f_id, &args->m); + ret = nat64lsn_translate6(i->cfg, &args->f_id, &args->m); break; default: - ret = cfg->nomatch_verdict; + ret = i->cfg->nomatch_verdict; } if (ret != IP_FW_PASS && args->m != NULL) { @@ -1619,7 +1619,7 @@ } struct nat64lsn_cfg * -nat64lsn_init_instance(struct ip_fw_chain *ch, in_addr_t prefix, int plen) +nat64lsn_init_config(struct ip_fw_chain *ch, in_addr_t prefix, int plen) { struct nat64lsn_cfg *cfg; struct nat64lsn_alias *alias; @@ -1722,7 +1722,7 @@ } void -nat64lsn_destroy_instance(struct nat64lsn_cfg *cfg) +nat64lsn_destroy_config(struct nat64lsn_cfg *cfg) { struct nat64lsn_host *host; int i; Index: sys/netpfil/ipfw/nat64/nat64lsn_control.c =================================================================== --- sys/netpfil/ipfw/nat64/nat64lsn_control.c +++ sys/netpfil/ipfw/nat64/nat64lsn_control.c @@ -60,15 +60,16 @@ VNET_DEFINE(uint16_t, nat64lsn_eid) = 0; -static struct nat64lsn_cfg * +static struct nat64lsn_instance * nat64lsn_find(struct namedobj_instance *ni, const char *name, uint8_t set) { - struct nat64lsn_cfg *cfg; + struct named_object *no; - cfg = (struct nat64lsn_cfg *)ipfw_objhash_lookup_name_type(ni, set, + no = ipfw_objhash_lookup_name_type(ni, set, IPFW_TLV_NAT64LSN_NAME, name); - - return (cfg); + if (no == NULL) + return (NULL); + return (__containerof(no, struct nat64lsn_instance, no)); } static void @@ -115,6 +116,7 @@ { ipfw_obj_lheader *olh; ipfw_nat64lsn_cfg *uc; + struct nat64lsn_instance *i; struct nat64lsn_cfg *cfg; struct namedobj_instance *ni; uint32_t addr4, mask4; @@ -160,12 +162,14 @@ } IPFW_UH_RUNLOCK(ch); - cfg = nat64lsn_init_instance(ch, addr4, uc->plen4); - strlcpy(cfg->name, uc->name, sizeof(cfg->name)); - cfg->no.name = cfg->name; - cfg->no.etlv = IPFW_TLV_NAT64LSN_NAME; - cfg->no.set = uc->set; + i = malloc(sizeof(struct nat64lsn_instance), M_NAT64LSN, + M_WAITOK | M_ZERO); + strlcpy(i->name, uc->name, sizeof(i->name)); + i->no.name = i->name; + i->no.etlv = IPFW_TLV_NAT64LSN_NAME; + i->no.set = uc->set; + cfg = nat64lsn_init_config(ch, addr4, uc->plen4); cfg->base.plat_prefix = uc->prefix6; cfg->base.plat_plen = uc->plen6; cfg->base.flags = (uc->flags & NAT64LSN_FLAGSMASK) | NAT64_PLATPFX; @@ -183,26 +187,28 @@ cfg->st_estab_ttl = uc->st_estab_ttl; cfg->st_udp_ttl = uc->st_udp_ttl; cfg->st_icmp_ttl = uc->st_icmp_ttl; - cfg->nomatch_verdict = IP_FW_DENY; IPFW_UH_WLOCK(ch); if (nat64lsn_find(ni, uc->name, uc->set) != NULL) { IPFW_UH_WUNLOCK(ch); - nat64lsn_destroy_instance(cfg); + nat64lsn_destroy_config(cfg); + free(i, M_NAT64LSN); return (EEXIST); } - if (ipfw_objhash_alloc_idx(CHAIN_TO_SRV(ch), &cfg->no.kidx) != 0) { + if (ipfw_objhash_alloc_idx(ni, &i->no.kidx) != 0) { IPFW_UH_WUNLOCK(ch); - nat64lsn_destroy_instance(cfg); + nat64lsn_destroy_config(cfg); + free(i, M_NAT64LSN); return (ENOSPC); } - ipfw_objhash_add(CHAIN_TO_SRV(ch), &cfg->no); + ipfw_objhash_add(ni, &i->no); /* Okay, let's link data */ - SRV_OBJECT(ch, cfg->no.kidx) = cfg; + i->cfg = cfg; + SRV_OBJECT(ch, i->no.kidx) = i; nat64lsn_start_instance(cfg); IPFW_UH_WUNLOCK(ch); @@ -210,13 +216,14 @@ } static void -nat64lsn_detach_config(struct ip_fw_chain *ch, struct nat64lsn_cfg *cfg) +nat64lsn_detach_instance(struct ip_fw_chain *ch, + struct nat64lsn_instance *i) { IPFW_UH_WLOCK_ASSERT(ch); - - ipfw_objhash_del(CHAIN_TO_SRV(ch), &cfg->no); - ipfw_objhash_free_idx(CHAIN_TO_SRV(ch), cfg->no.kidx); + SRV_OBJECT(ch, i->no.kidx) = NULL; + ipfw_objhash_del(CHAIN_TO_SRV(ch), &i->no); + ipfw_objhash_free_idx(CHAIN_TO_SRV(ch), i->no.kidx); } /* @@ -230,7 +237,7 @@ nat64lsn_destroy(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd) { - struct nat64lsn_cfg *cfg; + struct nat64lsn_instance *i; ipfw_obj_header *oh; if (sd->valsize != sizeof(*oh)) @@ -239,23 +246,23 @@ oh = (ipfw_obj_header *)op3; IPFW_UH_WLOCK(ch); - cfg = nat64lsn_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set); - if (cfg == NULL) { + i = nat64lsn_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set); + if (i == NULL) { IPFW_UH_WUNLOCK(ch); return (ENOENT); } - if (cfg->no.refcnt > 0) { + if (i->no.refcnt > 0) { IPFW_UH_WUNLOCK(ch); return (EBUSY); } - ipfw_reset_eaction_instance(ch, V_nat64lsn_eid, cfg->no.kidx); - SRV_OBJECT(ch, cfg->no.kidx) = NULL; - nat64lsn_detach_config(ch, cfg); + ipfw_reset_eaction_instance(ch, V_nat64lsn_eid, i->no.kidx); + nat64lsn_detach_instance(ch, i); IPFW_UH_WUNLOCK(ch); - nat64lsn_destroy_instance(cfg); + nat64lsn_destroy_config(i->cfg); + free(i, M_NAT64LSN); return (0); } @@ -308,9 +315,14 @@ #undef __COPY_STAT_FIELD static void -nat64lsn_export_config(struct ip_fw_chain *ch, struct nat64lsn_cfg *cfg, +nat64lsn_export_config(struct ip_fw_chain *ch, struct nat64lsn_instance *i, ipfw_nat64lsn_cfg *uc) { + struct nat64lsn_cfg *cfg; + + strlcpy(uc->name, i->no.name, sizeof(uc->name)); + uc->set = i->no.set; + cfg = i->cfg; uc->flags = cfg->base.flags & NAT64LSN_FLAGSMASK; uc->states_chunks = cfg->states_chunks; @@ -326,8 +338,6 @@ uc->prefix6 = cfg->base.plat_prefix; uc->plen4 = cfg->plen4; uc->plen6 = cfg->base.plat_plen; - uc->set = cfg->no.set; - strlcpy(uc->name, cfg->no.name, sizeof(uc->name)); } struct nat64_dump_arg { @@ -339,12 +349,14 @@ export_config_cb(struct namedobj_instance *ni, struct named_object *no, void *arg) { - struct nat64_dump_arg *da = (struct nat64_dump_arg *)arg; + struct nat64_dump_arg *da; ipfw_nat64lsn_cfg *uc; + da = (struct nat64_dump_arg *)arg; uc = (struct _ipfw_nat64lsn_cfg *)ipfw_get_sopt_space(da->sd, sizeof(*uc)); - nat64lsn_export_config(da->ch, (struct nat64lsn_cfg *)no, uc); + nat64lsn_export_config(da->ch, + __containerof(no, struct nat64lsn_instance, no), uc); return (0); } @@ -403,6 +415,7 @@ { ipfw_obj_header *oh; ipfw_nat64lsn_cfg *uc; + struct nat64lsn_instance *i; struct nat64lsn_cfg *cfg; struct namedobj_instance *ni; @@ -420,12 +433,12 @@ ni = CHAIN_TO_SRV(ch); if (sd->sopt->sopt_dir == SOPT_GET) { IPFW_UH_RLOCK(ch); - cfg = nat64lsn_find(ni, oh->ntlv.name, oh->ntlv.set); - if (cfg == NULL) { + i = nat64lsn_find(ni, oh->ntlv.name, oh->ntlv.set); + if (i == NULL) { IPFW_UH_RUNLOCK(ch); return (ENOENT); } - nat64lsn_export_config(ch, cfg, uc); + nat64lsn_export_config(ch, i, uc); IPFW_UH_RUNLOCK(ch); return (0); } @@ -433,8 +446,8 @@ nat64lsn_default_config(uc); IPFW_UH_WLOCK(ch); - cfg = nat64lsn_find(ni, oh->ntlv.name, oh->ntlv.set); - if (cfg == NULL) { + i = nat64lsn_find(ni, oh->ntlv.name, oh->ntlv.set); + if (i == NULL) { IPFW_UH_WUNLOCK(ch); return (ENOENT); } @@ -444,7 +457,7 @@ * jmaxlen, nh_del_age, pg_del_age, tcp_syn_age, tcp_close_age, * tcp_est_age, udp_age, icmp_age, flags, states_chunks. */ - + cfg = i->cfg; cfg->states_chunks = uc->states_chunks; cfg->jmaxlen = uc->jmaxlen; cfg->host_delete_delay = uc->nh_delete_delay; @@ -475,7 +488,7 @@ struct sockopt_data *sd) { struct ipfw_nat64lsn_stats stats; - struct nat64lsn_cfg *cfg; + struct nat64lsn_instance *i; ipfw_obj_header *oh; ipfw_obj_ctlv *ctlv; size_t sz; @@ -491,13 +504,13 @@ memset(&stats, 0, sizeof(stats)); IPFW_UH_RLOCK(ch); - cfg = nat64lsn_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set); - if (cfg == NULL) { + i = nat64lsn_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set); + if (i == NULL) { IPFW_UH_RUNLOCK(ch); return (ENOENT); } - export_stats(ch, cfg, &stats); + export_stats(ch, i->cfg, &stats); IPFW_UH_RUNLOCK(ch); ctlv = (ipfw_obj_ctlv *)(oh + 1); @@ -522,7 +535,7 @@ nat64lsn_reset_stats(struct ip_fw_chain *ch, ip_fw3_opheader *op, struct sockopt_data *sd) { - struct nat64lsn_cfg *cfg; + struct nat64lsn_instance *i; ipfw_obj_header *oh; if (sd->valsize != sizeof(*oh)) @@ -533,12 +546,12 @@ return (EINVAL); IPFW_UH_WLOCK(ch); - cfg = nat64lsn_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set); - if (cfg == NULL) { + i = nat64lsn_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set); + if (i == NULL) { IPFW_UH_WUNLOCK(ch); return (ENOENT); } - COUNTER_ARRAY_ZERO(cfg->base.stats.cnt, NAT64STATS); + COUNTER_ARRAY_ZERO(i->cfg->base.stats.cnt, NAT64STATS); IPFW_UH_WUNLOCK(ch); return (0); } @@ -700,6 +713,7 @@ ipfw_obj_header *oh; ipfw_obj_data *od; ipfw_nat64lsn_stg_v1 *stg; + struct nat64lsn_instance *i; struct nat64lsn_cfg *cfg; struct nat64lsn_pg *pg; union nat64lsn_pgidx idx; @@ -727,11 +741,12 @@ return (EINVAL); IPFW_UH_RLOCK(ch); - cfg = nat64lsn_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set); - if (cfg == NULL) { + i = nat64lsn_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set); + if (i == NULL) { IPFW_UH_RUNLOCK(ch); return (ENOENT); } + cfg = i->cfg; if (idx.index == 0) { /* Fill in starting point */ idx.addr = cfg->prefix4; idx.proto = IPPROTO_ICMP; @@ -869,11 +884,89 @@ return (no); } +#define NAT64LSN_ARE_EQUAL(v) (cfg0->v == cfg1->v) +static int +nat64lsn_cmp_configs(struct nat64lsn_cfg *cfg0, struct nat64lsn_cfg *cfg1) +{ + + if ((cfg0->base.flags & cfg1->base.flags & NAT64LSN_ALLOW_SWAPCONF) && + NAT64LSN_ARE_EQUAL(prefix4) && + NAT64LSN_ARE_EQUAL(pmask4) && + NAT64LSN_ARE_EQUAL(plen4) && + NAT64LSN_ARE_EQUAL(base.plat_plen) && + IN6_ARE_ADDR_EQUAL(&cfg0->base.plat_prefix, + &cfg1->base.plat_prefix)) + return (0); + return (1); +} +#undef NAT64LSN_ARE_EQUAL + +static void +nat64lsn_swap_configs(struct nat64lsn_instance *i0, + struct nat64lsn_instance *i1) +{ + struct nat64lsn_cfg *cfg; + + cfg = i0->cfg; + i0->cfg = i1->cfg; + i1->cfg = cfg; +} + +/* + * NAT64LSN sets swap handler. + * + * When two sets have NAT64LSN instance with the same name, we check + * most important configuration parameters, and if there are no difference, + * and both instances have NAT64LSN_ALLOW_SWAPCONF flag, we will exchange + * configs between instances. This allows to keep NAT64 states when ipfw's + * rules are reloaded using new set. + * + * XXX: since manage_sets caller doesn't hold IPFW_WLOCK(), it is possible + * that some states will be created during switching, because set of rules + * is changed a bit earley than named objects. + */ +static int +nat64lsn_swap_sets_cb(struct namedobj_instance *ni, struct named_object *no, + void *arg) +{ + struct nat64lsn_instance *i0, *i1; + uint8_t *sets; + + sets = arg; + if (no->set == sets[0]) { + /* + * Check if we have instance in new set with the same + * config that is sets aware and ready to swap configs. + */ + i1 = nat64lsn_find(ni, no->name, sets[1]); + if (i1 != NULL) { + i0 = __containerof(no, struct nat64lsn_instance, no); + /* Compare configs */ + if (nat64lsn_cmp_configs(i0->cfg, i1->cfg) == 0) { + IPFW_UH_WLOCK_ASSERT(&V_layer3_chain); + IPFW_WLOCK(&V_layer3_chain); + nat64lsn_swap_configs(i0, i1); + IPFW_WUNLOCK(&V_layer3_chain); + } + } + no->set = sets[1]; + } else if (no->set == sets[1]) + no->set = sets[0]; + return (0); +} + static int nat64lsn_manage_sets(struct ip_fw_chain *ch, uint16_t set, uint8_t new_set, enum ipfw_sets_cmd cmd) { + uint8_t sets[2]; + if (cmd == SWAP_ALL) { + sets[0] = (uint8_t)set; + sets[1] = new_set; + return (ipfw_objhash_foreach_type(CHAIN_TO_SRV(ch), + nat64lsn_swap_sets_cb, &sets, IPFW_TLV_NAT64LSN_NAME)); + } return (ipfw_obj_manage_sets(CHAIN_TO_SRV(ch), IPFW_TLV_NAT64LSN_NAME, set, new_set, cmd)); } @@ -894,14 +987,14 @@ destroy_config_cb(struct namedobj_instance *ni, struct named_object *no, void *arg) { - struct nat64lsn_cfg *cfg; + struct nat64lsn_instance *i; struct ip_fw_chain *ch; ch = (struct ip_fw_chain *)arg; - cfg = (struct nat64lsn_cfg *)SRV_OBJECT(ch, no->kidx); - SRV_OBJECT(ch, no->kidx) = NULL; - nat64lsn_detach_config(ch, cfg); - nat64lsn_destroy_instance(cfg); + i = (struct nat64lsn_instance *)SRV_OBJECT(ch, no->kidx); + nat64lsn_detach_instance(ch, i); + nat64lsn_destroy_config(i->cfg); + free(i, M_NAT64LSN); return (0); } Index: sys/sys/counter.h =================================================================== --- sys/sys/counter.h +++ sys/sys/counter.h @@ -43,23 +43,23 @@ uint64_t counter_u64_fetch(counter_u64_t); #define COUNTER_ARRAY_ALLOC(a, n, wait) do { \ - for (int i = 0; i < (n); i++) \ - (a)[i] = counter_u64_alloc(wait); \ + for (int _i = 0; _i < (n); _i++) \ + (a)[_i] = counter_u64_alloc(wait); \ } while (0) #define COUNTER_ARRAY_FREE(a, n) do { \ - for (int i = 0; i < (n); i++) \ - counter_u64_free((a)[i]); \ + for (int _i = 0; _i < (n); _i++) \ + counter_u64_free((a)[_i]); \ } while (0) #define COUNTER_ARRAY_COPY(a, dstp, n) do { \ - for (int i = 0; i < (n); i++) \ - ((uint64_t *)(dstp))[i] = counter_u64_fetch((a)[i]);\ + for (int _i = 0; _i < (n); _i++) \ + ((uint64_t *)(dstp))[_i] = counter_u64_fetch((a)[_i]);\ } while (0) #define COUNTER_ARRAY_ZERO(a, n) do { \ - for (int i = 0; i < (n); i++) \ - counter_u64_zero((a)[i]); \ + for (int _i = 0; _i < (n); _i++) \ + counter_u64_zero((a)[_i]); \ } while (0) /*