The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netpfil/ipfw/nat64/nat64clat_control.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2019 Yandex LLC
    5  * Copyright (c) 2019 Andrey V. Elsukov <ae@FreeBSD.org>
    6  * Copyright (c) 2019 Boris N. Lytochkin <lytboris@gmail.com>
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  *
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/counter.h>
   36 #include <sys/errno.h>
   37 #include <sys/kernel.h>
   38 #include <sys/lock.h>
   39 #include <sys/malloc.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/module.h>
   42 #include <sys/rmlock.h>
   43 #include <sys/rwlock.h>
   44 #include <sys/socket.h>
   45 #include <sys/sockopt.h>
   46 #include <sys/syslog.h>
   47 #include <sys/sysctl.h>
   48 
   49 #include <net/if.h>
   50 #include <net/if_var.h>
   51 #include <net/route.h>
   52 #include <net/vnet.h>
   53 
   54 #include <netinet/in.h>
   55 #include <netinet/ip_var.h>
   56 #include <netinet/ip_fw.h>
   57 #include <netinet6/in6_var.h>
   58 #include <netinet6/ip6_var.h>
   59 #include <netinet6/ip_fw_nat64.h>
   60 
   61 #include <netpfil/ipfw/ip_fw_private.h>
   62 
   63 #include "nat64clat.h"
   64 
   65 VNET_DEFINE(uint16_t, nat64clat_eid) = 0;
   66 
   67 static struct nat64clat_cfg *nat64clat_alloc_config(const char *name,
   68     uint8_t set);
   69 static void nat64clat_free_config(struct nat64clat_cfg *cfg);
   70 static struct nat64clat_cfg *nat64clat_find(struct namedobj_instance *ni,
   71     const char *name, uint8_t set);
   72 
   73 static struct nat64clat_cfg *
   74 nat64clat_alloc_config(const char *name, uint8_t set)
   75 {
   76         struct nat64clat_cfg *cfg;
   77 
   78         cfg = malloc(sizeof(struct nat64clat_cfg), M_IPFW, M_WAITOK | M_ZERO);
   79         COUNTER_ARRAY_ALLOC(cfg->base.stats.cnt, NAT64STATS, M_WAITOK);
   80         cfg->no.name = cfg->name;
   81         cfg->no.etlv = IPFW_TLV_NAT64CLAT_NAME;
   82         cfg->no.set = set;
   83         strlcpy(cfg->name, name, sizeof(cfg->name));
   84         return (cfg);
   85 }
   86 
   87 static void
   88 nat64clat_free_config(struct nat64clat_cfg *cfg)
   89 {
   90 
   91         COUNTER_ARRAY_FREE(cfg->base.stats.cnt, NAT64STATS);
   92         free(cfg, M_IPFW);
   93 }
   94 
   95 static void
   96 nat64clat_export_config(struct ip_fw_chain *ch, struct nat64clat_cfg *cfg,
   97     ipfw_nat64clat_cfg *uc)
   98 {
   99         uc->plat_prefix = cfg->base.plat_prefix;
  100         uc->plat_plen = cfg->base.plat_plen;
  101         uc->clat_prefix = cfg->base.clat_prefix;
  102         uc->clat_plen = cfg->base.clat_plen;
  103         uc->flags = cfg->base.flags & NAT64CLAT_FLAGSMASK;
  104         uc->set = cfg->no.set;
  105         strlcpy(uc->name, cfg->no.name, sizeof(uc->name));
  106 }
  107 
  108 struct nat64clat_dump_arg {
  109         struct ip_fw_chain *ch;
  110         struct sockopt_data *sd;
  111 };
  112 
  113 static int
  114 export_config_cb(struct namedobj_instance *ni, struct named_object *no,
  115     void *arg)
  116 {
  117         struct nat64clat_dump_arg *da = (struct nat64clat_dump_arg *)arg;
  118         ipfw_nat64clat_cfg *uc;
  119 
  120         uc = (ipfw_nat64clat_cfg *)ipfw_get_sopt_space(da->sd, sizeof(*uc));
  121         nat64clat_export_config(da->ch, (struct nat64clat_cfg *)no, uc);
  122         return (0);
  123 }
  124 
  125 static struct nat64clat_cfg *
  126 nat64clat_find(struct namedobj_instance *ni, const char *name, uint8_t set)
  127 {
  128         struct nat64clat_cfg *cfg;
  129 
  130         cfg = (struct nat64clat_cfg *)ipfw_objhash_lookup_name_type(ni, set,
  131             IPFW_TLV_NAT64CLAT_NAME, name);
  132 
  133         return (cfg);
  134 }
  135 
  136 /*
  137  * Creates new consumer-side nat64 translator instance.
  138  * Data layout (v0)(current):
  139  * Request: [ ipfw_obj_lheader ipfw_nat64clat_cfg ]
  140  *
  141  * Returns 0 on success
  142  */
  143 static int
  144 nat64clat_create(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
  145     struct sockopt_data *sd)
  146 {
  147         ipfw_obj_lheader *olh;
  148         ipfw_nat64clat_cfg *uc;
  149         struct namedobj_instance *ni;
  150         struct nat64clat_cfg *cfg;
  151 
  152         if (sd->valsize != sizeof(*olh) + sizeof(*uc))
  153                 return (EINVAL);
  154 
  155         olh = (ipfw_obj_lheader *)sd->kbuf;
  156         uc = (ipfw_nat64clat_cfg *)(olh + 1);
  157 
  158         if (ipfw_check_object_name_generic(uc->name) != 0)
  159                 return (EINVAL);
  160 
  161         if (uc->set >= IPFW_MAX_SETS ||
  162             nat64_check_prefix6(&uc->plat_prefix, uc->plat_plen) != 0 ||
  163             nat64_check_prefix6(&uc->clat_prefix, uc->clat_plen) != 0)
  164                 return (EINVAL);
  165 
  166         ni = CHAIN_TO_SRV(ch);
  167 
  168         IPFW_UH_RLOCK(ch);
  169         if (nat64clat_find(ni, uc->name, uc->set) != NULL) {
  170                 IPFW_UH_RUNLOCK(ch);
  171                 return (EEXIST);
  172         }
  173         IPFW_UH_RUNLOCK(ch);
  174 
  175         cfg = nat64clat_alloc_config(uc->name, uc->set);
  176         cfg->base.plat_prefix = uc->plat_prefix;
  177         cfg->base.plat_plen = uc->plat_plen;
  178         cfg->base.clat_prefix = uc->clat_prefix;
  179         cfg->base.clat_plen = uc->clat_plen;
  180         cfg->base.flags = (uc->flags & NAT64CLAT_FLAGSMASK) |
  181             NAT64_CLATPFX | NAT64_PLATPFX;
  182         if (IN6_IS_ADDR_WKPFX(&cfg->base.plat_prefix))
  183                 cfg->base.flags |= NAT64_WKPFX;
  184 
  185         IPFW_UH_WLOCK(ch);
  186 
  187         if (nat64clat_find(ni, uc->name, uc->set) != NULL) {
  188                 IPFW_UH_WUNLOCK(ch);
  189                 nat64clat_free_config(cfg);
  190                 return (EEXIST);
  191         }
  192 
  193         if (ipfw_objhash_alloc_idx(ni, &cfg->no.kidx) != 0) {
  194                 IPFW_UH_WUNLOCK(ch);
  195                 nat64clat_free_config(cfg);
  196                 return (ENOSPC);
  197         }
  198         ipfw_objhash_add(CHAIN_TO_SRV(ch), &cfg->no);
  199         /* Okay, let's link data */
  200         SRV_OBJECT(ch, cfg->no.kidx) = cfg;
  201         IPFW_UH_WUNLOCK(ch);
  202 
  203         return (0);
  204 }
  205 
  206 /*
  207  * Change existing nat64clat instance configuration.
  208  * Data layout (v0)(current):
  209  * Request: [ ipfw_obj_header ipfw_nat64clat_cfg ]
  210  * Reply: [ ipfw_obj_header ipfw_nat64clat_cfg ]
  211  *
  212  * Returns 0 on success
  213  */
  214 static int
  215 nat64clat_config(struct ip_fw_chain *ch, ip_fw3_opheader *op,
  216     struct sockopt_data *sd)
  217 {
  218         ipfw_obj_header *oh;
  219         ipfw_nat64clat_cfg *uc;
  220         struct nat64clat_cfg *cfg;
  221         struct namedobj_instance *ni;
  222         uint32_t flags;
  223 
  224         if (sd->valsize != sizeof(*oh) + sizeof(*uc))
  225                 return (EINVAL);
  226 
  227         oh = (ipfw_obj_header *)ipfw_get_sopt_space(sd,
  228             sizeof(*oh) + sizeof(*uc));
  229         uc = (ipfw_nat64clat_cfg *)(oh + 1);
  230 
  231         if (ipfw_check_object_name_generic(oh->ntlv.name) != 0 ||
  232             oh->ntlv.set >= IPFW_MAX_SETS)
  233                 return (EINVAL);
  234 
  235         ni = CHAIN_TO_SRV(ch);
  236         if (sd->sopt->sopt_dir == SOPT_GET) {
  237                 IPFW_UH_RLOCK(ch);
  238                 cfg = nat64clat_find(ni, oh->ntlv.name, oh->ntlv.set);
  239                 if (cfg == NULL) {
  240                         IPFW_UH_RUNLOCK(ch);
  241                         return (ENOENT);
  242                 }
  243                 nat64clat_export_config(ch, cfg, uc);
  244                 IPFW_UH_RUNLOCK(ch);
  245                 return (0);
  246         }
  247 
  248         IPFW_UH_WLOCK(ch);
  249         cfg = nat64clat_find(ni, oh->ntlv.name, oh->ntlv.set);
  250         if (cfg == NULL) {
  251                 IPFW_UH_WUNLOCK(ch);
  252                 return (ENOENT);
  253         }
  254 
  255         /*
  256          * For now allow to change only following values:
  257          *  plat_prefix, plat_plen, clat_prefix, clat_plen, flags.
  258          */
  259         flags = 0;
  260         if (uc->plat_plen != cfg->base.plat_plen ||
  261             !IN6_ARE_ADDR_EQUAL(&uc->plat_prefix, &cfg->base.plat_prefix)) {
  262                 if (nat64_check_prefix6(&uc->plat_prefix, uc->plat_plen) != 0) {
  263                         IPFW_UH_WUNLOCK(ch);
  264                         return (EINVAL);
  265                 }
  266                 flags |= NAT64_PLATPFX;
  267         }
  268 
  269         if (uc->clat_plen != cfg->base.clat_plen ||
  270             !IN6_ARE_ADDR_EQUAL(&uc->clat_prefix, &cfg->base.clat_prefix)) {
  271                 if (nat64_check_prefix6(&uc->clat_prefix, uc->clat_plen) != 0) {
  272                         IPFW_UH_WUNLOCK(ch);
  273                         return (EINVAL);
  274                 }
  275                 flags |= NAT64_CLATPFX;
  276         }
  277 
  278         if (flags != 0) {
  279                 IPFW_WLOCK(ch);
  280                 if (flags & NAT64_PLATPFX) {
  281                         cfg->base.plat_prefix = uc->plat_prefix;
  282                         cfg->base.plat_plen = uc->plat_plen;
  283                 }
  284                 if (flags & NAT64_CLATPFX) {
  285                         cfg->base.clat_prefix = uc->clat_prefix;
  286                         cfg->base.clat_plen = uc->clat_plen;
  287                 }
  288                 IPFW_WUNLOCK(ch);
  289         }
  290 
  291         cfg->base.flags &= ~NAT64CLAT_FLAGSMASK;
  292         cfg->base.flags |= uc->flags & NAT64CLAT_FLAGSMASK;
  293 
  294         IPFW_UH_WUNLOCK(ch);
  295         return (0);
  296 }
  297 
  298 static void
  299 nat64clat_detach_config(struct ip_fw_chain *ch, struct nat64clat_cfg *cfg)
  300 {
  301 
  302         IPFW_UH_WLOCK_ASSERT(ch);
  303 
  304         ipfw_objhash_del(CHAIN_TO_SRV(ch), &cfg->no);
  305         ipfw_objhash_free_idx(CHAIN_TO_SRV(ch), cfg->no.kidx);
  306 }
  307 
  308 /*
  309  * Destroys nat64 instance.
  310  * Data layout (v0)(current):
  311  * Request: [ ipfw_obj_header ]
  312  *
  313  * Returns 0 on success
  314  */
  315 static int
  316 nat64clat_destroy(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
  317     struct sockopt_data *sd)
  318 {
  319         ipfw_obj_header *oh;
  320         struct nat64clat_cfg *cfg;
  321 
  322         if (sd->valsize != sizeof(*oh))
  323                 return (EINVAL);
  324 
  325         oh = (ipfw_obj_header *)sd->kbuf;
  326         if (ipfw_check_object_name_generic(oh->ntlv.name) != 0)
  327                 return (EINVAL);
  328 
  329         IPFW_UH_WLOCK(ch);
  330         cfg = nat64clat_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set);
  331         if (cfg == NULL) {
  332                 IPFW_UH_WUNLOCK(ch);
  333                 return (ENOENT);
  334         }
  335         if (cfg->no.refcnt > 0) {
  336                 IPFW_UH_WUNLOCK(ch);
  337                 return (EBUSY);
  338         }
  339 
  340         ipfw_reset_eaction_instance(ch, V_nat64clat_eid, cfg->no.kidx);
  341         SRV_OBJECT(ch, cfg->no.kidx) = NULL;
  342         nat64clat_detach_config(ch, cfg);
  343         IPFW_UH_WUNLOCK(ch);
  344 
  345         nat64clat_free_config(cfg);
  346         return (0);
  347 }
  348 
  349 /*
  350  * Lists all nat64clat instances currently available in kernel.
  351  * Data layout (v0)(current):
  352  * Request: [ ipfw_obj_lheader ]
  353  * Reply: [ ipfw_obj_lheader ipfw_nat64clat_cfg x N ]
  354  *
  355  * Returns 0 on success
  356  */
  357 static int
  358 nat64clat_list(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
  359     struct sockopt_data *sd)
  360 {
  361         ipfw_obj_lheader *olh;
  362         struct nat64clat_dump_arg da;
  363 
  364         /* Check minimum header size */
  365         if (sd->valsize < sizeof(ipfw_obj_lheader))
  366                 return (EINVAL);
  367 
  368         olh = (ipfw_obj_lheader *)ipfw_get_sopt_header(sd, sizeof(*olh));
  369 
  370         IPFW_UH_RLOCK(ch);
  371         olh->count = ipfw_objhash_count_type(CHAIN_TO_SRV(ch),
  372             IPFW_TLV_NAT64CLAT_NAME);
  373         olh->objsize = sizeof(ipfw_nat64clat_cfg);
  374         olh->size = sizeof(*olh) + olh->count * olh->objsize;
  375 
  376         if (sd->valsize < olh->size) {
  377                 IPFW_UH_RUNLOCK(ch);
  378                 return (ENOMEM);
  379         }
  380         memset(&da, 0, sizeof(da));
  381         da.ch = ch;
  382         da.sd = sd;
  383         ipfw_objhash_foreach_type(CHAIN_TO_SRV(ch), export_config_cb,
  384             &da, IPFW_TLV_NAT64CLAT_NAME);
  385         IPFW_UH_RUNLOCK(ch);
  386 
  387         return (0);
  388 }
  389 
  390 #define __COPY_STAT_FIELD(_cfg, _stats, _field) \
  391         (_stats)->_field = NAT64STAT_FETCH(&(_cfg)->base.stats, _field)
  392 static void
  393 export_stats(struct ip_fw_chain *ch, struct nat64clat_cfg *cfg,
  394     struct ipfw_nat64clat_stats *stats)
  395 {
  396 
  397         __COPY_STAT_FIELD(cfg, stats, opcnt64);
  398         __COPY_STAT_FIELD(cfg, stats, opcnt46);
  399         __COPY_STAT_FIELD(cfg, stats, ofrags);
  400         __COPY_STAT_FIELD(cfg, stats, ifrags);
  401         __COPY_STAT_FIELD(cfg, stats, oerrors);
  402         __COPY_STAT_FIELD(cfg, stats, noroute4);
  403         __COPY_STAT_FIELD(cfg, stats, noroute6);
  404         __COPY_STAT_FIELD(cfg, stats, noproto);
  405         __COPY_STAT_FIELD(cfg, stats, nomem);
  406         __COPY_STAT_FIELD(cfg, stats, dropped);
  407 }
  408 
  409 /*
  410  * Get nat64clat statistics.
  411  * Data layout (v0)(current):
  412  * Request: [ ipfw_obj_header ]
  413  * Reply: [ ipfw_obj_header ipfw_obj_ctlv [ uint64_t x N ]]
  414  *
  415  * Returns 0 on success
  416  */
  417 static int
  418 nat64clat_stats(struct ip_fw_chain *ch, ip_fw3_opheader *op,
  419     struct sockopt_data *sd)
  420 {
  421         struct ipfw_nat64clat_stats stats;
  422         struct nat64clat_cfg *cfg;
  423         ipfw_obj_header *oh;
  424         ipfw_obj_ctlv *ctlv;
  425         size_t sz;
  426 
  427         sz = sizeof(ipfw_obj_header) + sizeof(ipfw_obj_ctlv) + sizeof(stats);
  428         if (sd->valsize % sizeof(uint64_t))
  429                 return (EINVAL);
  430         if (sd->valsize < sz)
  431                 return (ENOMEM);
  432         oh = (ipfw_obj_header *)ipfw_get_sopt_header(sd, sz);
  433         if (oh == NULL)
  434                 return (EINVAL);
  435         memset(&stats, 0, sizeof(stats));
  436 
  437         IPFW_UH_RLOCK(ch);
  438         cfg = nat64clat_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set);
  439         if (cfg == NULL) {
  440                 IPFW_UH_RUNLOCK(ch);
  441                 return (ENOENT);
  442         }
  443         export_stats(ch, cfg, &stats);
  444         IPFW_UH_RUNLOCK(ch);
  445 
  446         ctlv = (ipfw_obj_ctlv *)(oh + 1);
  447         memset(ctlv, 0, sizeof(*ctlv));
  448         ctlv->head.type = IPFW_TLV_COUNTERS;
  449         ctlv->head.length = sz - sizeof(ipfw_obj_header);
  450         ctlv->count = sizeof(stats) / sizeof(uint64_t);
  451         ctlv->objsize = sizeof(uint64_t);
  452         ctlv->version = IPFW_NAT64_VERSION;
  453         memcpy(ctlv + 1, &stats, sizeof(stats));
  454         return (0);
  455 }
  456 
  457 /*
  458  * Reset nat64clat statistics.
  459  * Data layout (v0)(current):
  460  * Request: [ ipfw_obj_header ]
  461  *
  462  * Returns 0 on success
  463  */
  464 static int
  465 nat64clat_reset_stats(struct ip_fw_chain *ch, ip_fw3_opheader *op,
  466     struct sockopt_data *sd)
  467 {
  468         struct nat64clat_cfg *cfg;
  469         ipfw_obj_header *oh;
  470 
  471         if (sd->valsize != sizeof(*oh))
  472                 return (EINVAL);
  473         oh = (ipfw_obj_header *)sd->kbuf;
  474         if (ipfw_check_object_name_generic(oh->ntlv.name) != 0 ||
  475             oh->ntlv.set >= IPFW_MAX_SETS)
  476                 return (EINVAL);
  477 
  478         IPFW_UH_WLOCK(ch);
  479         cfg = nat64clat_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set);
  480         if (cfg == NULL) {
  481                 IPFW_UH_WUNLOCK(ch);
  482                 return (ENOENT);
  483         }
  484         COUNTER_ARRAY_ZERO(cfg->base.stats.cnt, NAT64STATS);
  485         IPFW_UH_WUNLOCK(ch);
  486         return (0);
  487 }
  488 
  489 static struct ipfw_sopt_handler scodes[] = {
  490         { IP_FW_NAT64CLAT_CREATE, 0,    HDIR_SET,       nat64clat_create },
  491         { IP_FW_NAT64CLAT_DESTROY,0,    HDIR_SET,       nat64clat_destroy },
  492         { IP_FW_NAT64CLAT_CONFIG, 0,    HDIR_BOTH,      nat64clat_config },
  493         { IP_FW_NAT64CLAT_LIST,   0,    HDIR_GET,       nat64clat_list },
  494         { IP_FW_NAT64CLAT_STATS,  0,    HDIR_GET,       nat64clat_stats },
  495         { IP_FW_NAT64CLAT_RESET_STATS,0,        HDIR_SET,       nat64clat_reset_stats },
  496 };
  497 
  498 static int
  499 nat64clat_classify(ipfw_insn *cmd, uint16_t *puidx, uint8_t *ptype)
  500 {
  501         ipfw_insn *icmd;
  502 
  503         icmd = cmd - 1;
  504         if (icmd->opcode != O_EXTERNAL_ACTION ||
  505             icmd->arg1 != V_nat64clat_eid)
  506                 return (1);
  507 
  508         *puidx = cmd->arg1;
  509         *ptype = 0;
  510         return (0);
  511 }
  512 
  513 static void
  514 nat64clat_update_arg1(ipfw_insn *cmd, uint16_t idx)
  515 {
  516 
  517         cmd->arg1 = idx;
  518 }
  519 
  520 static int
  521 nat64clat_findbyname(struct ip_fw_chain *ch, struct tid_info *ti,
  522     struct named_object **pno)
  523 {
  524         int err;
  525 
  526         err = ipfw_objhash_find_type(CHAIN_TO_SRV(ch), ti,
  527             IPFW_TLV_NAT64CLAT_NAME, pno);
  528         return (err);
  529 }
  530 
  531 static struct named_object *
  532 nat64clat_findbykidx(struct ip_fw_chain *ch, uint16_t idx)
  533 {
  534         struct namedobj_instance *ni;
  535         struct named_object *no;
  536 
  537         IPFW_UH_WLOCK_ASSERT(ch);
  538         ni = CHAIN_TO_SRV(ch);
  539         no = ipfw_objhash_lookup_kidx(ni, idx);
  540         KASSERT(no != NULL, ("NAT with index %d not found", idx));
  541 
  542         return (no);
  543 }
  544 
  545 static int
  546 nat64clat_manage_sets(struct ip_fw_chain *ch, uint16_t set, uint8_t new_set,
  547     enum ipfw_sets_cmd cmd)
  548 {
  549 
  550         return (ipfw_obj_manage_sets(CHAIN_TO_SRV(ch), IPFW_TLV_NAT64CLAT_NAME,
  551             set, new_set, cmd));
  552 }
  553 
  554 static struct opcode_obj_rewrite opcodes[] = {
  555         {
  556                 .opcode = O_EXTERNAL_INSTANCE,
  557                 .etlv = IPFW_TLV_EACTION /* just show it isn't table */,
  558                 .classifier = nat64clat_classify,
  559                 .update = nat64clat_update_arg1,
  560                 .find_byname = nat64clat_findbyname,
  561                 .find_bykidx = nat64clat_findbykidx,
  562                 .manage_sets = nat64clat_manage_sets,
  563         },
  564 };
  565 
  566 static int
  567 destroy_config_cb(struct namedobj_instance *ni, struct named_object *no,
  568     void *arg)
  569 {
  570         struct nat64clat_cfg *cfg;
  571         struct ip_fw_chain *ch;
  572 
  573         ch = (struct ip_fw_chain *)arg;
  574         cfg = (struct nat64clat_cfg *)SRV_OBJECT(ch, no->kidx);
  575         SRV_OBJECT(ch, no->kidx) = NULL;
  576         nat64clat_detach_config(ch, cfg);
  577         nat64clat_free_config(cfg);
  578         return (0);
  579 }
  580 
  581 int
  582 nat64clat_init(struct ip_fw_chain *ch, int first)
  583 {
  584 
  585         V_nat64clat_eid = ipfw_add_eaction(ch, ipfw_nat64clat, "nat64clat");
  586         if (V_nat64clat_eid == 0)
  587                 return (ENXIO);
  588         IPFW_ADD_SOPT_HANDLER(first, scodes);
  589         IPFW_ADD_OBJ_REWRITER(first, opcodes);
  590         return (0);
  591 }
  592 
  593 void
  594 nat64clat_uninit(struct ip_fw_chain *ch, int last)
  595 {
  596 
  597         IPFW_DEL_OBJ_REWRITER(last, opcodes);
  598         IPFW_DEL_SOPT_HANDLER(last, scodes);
  599         ipfw_del_eaction(ch, V_nat64clat_eid);
  600         /*
  601          * Since we already have deregistered external action,
  602          * our named objects become unaccessible via rules, because
  603          * all rules were truncated by ipfw_del_eaction().
  604          * So, we can unlink and destroy our named objects without holding
  605          * IPFW_WLOCK().
  606          */
  607         IPFW_UH_WLOCK(ch);
  608         ipfw_objhash_foreach_type(CHAIN_TO_SRV(ch), destroy_config_cb, ch,
  609             IPFW_TLV_NAT64CLAT_NAME);
  610         V_nat64clat_eid = 0;
  611         IPFW_UH_WUNLOCK(ch);
  612 }

Cache object: 16f90a60480a95dcb71f92b252811002


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.