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/nat64stl_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) 2015-2019 Yandex LLC
    5  * Copyright (c) 2015 Alexander V. Chernikov <melifaro@FreeBSD.org>
    6  * Copyright (c) 2015-2019 Andrey V. Elsukov <ae@FreeBSD.org>
    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/queue.h>
   47 #include <sys/syslog.h>
   48 #include <sys/sysctl.h>
   49 
   50 #include <net/if.h>
   51 #include <net/if_var.h>
   52 #include <net/pfil.h>
   53 #include <net/route.h>
   54 #include <net/vnet.h>
   55 
   56 #include <netinet/in.h>
   57 #include <netinet/ip_var.h>
   58 #include <netinet/ip_fw.h>
   59 #include <netinet6/in6_var.h>
   60 #include <netinet6/ip6_var.h>
   61 #include <netinet6/ip_fw_nat64.h>
   62 
   63 #include <netpfil/ipfw/ip_fw_private.h>
   64 
   65 #include "nat64stl.h"
   66 
   67 VNET_DEFINE(uint16_t, nat64stl_eid) = 0;
   68 
   69 static struct nat64stl_cfg *nat64stl_alloc_config(const char *name,
   70     uint8_t set);
   71 static void nat64stl_free_config(struct nat64stl_cfg *cfg);
   72 static struct nat64stl_cfg *nat64stl_find(struct namedobj_instance *ni,
   73     const char *name, uint8_t set);
   74 
   75 static struct nat64stl_cfg *
   76 nat64stl_alloc_config(const char *name, uint8_t set)
   77 {
   78         struct nat64stl_cfg *cfg;
   79 
   80         cfg = malloc(sizeof(struct nat64stl_cfg), M_IPFW, M_WAITOK | M_ZERO);
   81         COUNTER_ARRAY_ALLOC(cfg->base.stats.cnt, NAT64STATS, M_WAITOK);
   82         cfg->no.name = cfg->name;
   83         cfg->no.etlv = IPFW_TLV_NAT64STL_NAME;
   84         cfg->no.set = set;
   85         strlcpy(cfg->name, name, sizeof(cfg->name));
   86         return (cfg);
   87 }
   88 
   89 static void
   90 nat64stl_free_config(struct nat64stl_cfg *cfg)
   91 {
   92 
   93         COUNTER_ARRAY_FREE(cfg->base.stats.cnt, NAT64STATS);
   94         free(cfg, M_IPFW);
   95 }
   96 
   97 static void
   98 nat64stl_export_config(struct ip_fw_chain *ch, struct nat64stl_cfg *cfg,
   99     ipfw_nat64stl_cfg *uc)
  100 {
  101         struct named_object *no;
  102 
  103         uc->prefix6 = cfg->base.plat_prefix;
  104         uc->plen6 = cfg->base.plat_plen;
  105         uc->flags = cfg->base.flags & NAT64STL_FLAGSMASK;
  106         uc->set = cfg->no.set;
  107         strlcpy(uc->name, cfg->no.name, sizeof(uc->name));
  108 
  109         no = ipfw_objhash_lookup_table_kidx(ch, cfg->map64);
  110         ipfw_export_obj_ntlv(no, &uc->ntlv6);
  111         no = ipfw_objhash_lookup_table_kidx(ch, cfg->map46);
  112         ipfw_export_obj_ntlv(no, &uc->ntlv4);
  113 }
  114 
  115 struct nat64stl_dump_arg {
  116         struct ip_fw_chain *ch;
  117         struct sockopt_data *sd;
  118 };
  119 
  120 static int
  121 export_config_cb(struct namedobj_instance *ni, struct named_object *no,
  122     void *arg)
  123 {
  124         struct nat64stl_dump_arg *da = (struct nat64stl_dump_arg *)arg;
  125         ipfw_nat64stl_cfg *uc;
  126 
  127         uc = (ipfw_nat64stl_cfg *)ipfw_get_sopt_space(da->sd, sizeof(*uc));
  128         nat64stl_export_config(da->ch, (struct nat64stl_cfg *)no, uc);
  129         return (0);
  130 }
  131 
  132 static struct nat64stl_cfg *
  133 nat64stl_find(struct namedobj_instance *ni, const char *name, uint8_t set)
  134 {
  135         struct nat64stl_cfg *cfg;
  136 
  137         cfg = (struct nat64stl_cfg *)ipfw_objhash_lookup_name_type(ni, set,
  138             IPFW_TLV_NAT64STL_NAME, name);
  139 
  140         return (cfg);
  141 }
  142 
  143 static int
  144 nat64stl_create_internal(struct ip_fw_chain *ch, struct nat64stl_cfg *cfg,
  145     ipfw_nat64stl_cfg *i)
  146 {
  147 
  148         IPFW_UH_WLOCK_ASSERT(ch);
  149 
  150         if (ipfw_objhash_alloc_idx(CHAIN_TO_SRV(ch), &cfg->no.kidx) != 0)
  151                 return (ENOSPC);
  152         cfg->base.flags |= NAT64STL_KIDX;
  153 
  154         if (ipfw_ref_table(ch, &i->ntlv4, &cfg->map46) != 0)
  155                 return (EINVAL);
  156         cfg->base.flags |= NAT64STL_46T;
  157 
  158         if (ipfw_ref_table(ch, &i->ntlv6, &cfg->map64) != 0)
  159                 return (EINVAL);
  160         cfg->base.flags |= NAT64STL_64T;
  161 
  162         ipfw_objhash_add(CHAIN_TO_SRV(ch), &cfg->no);
  163 
  164         return (0);
  165 }
  166 
  167 /*
  168  * Creates new nat64 instance.
  169  * Data layout (v0)(current):
  170  * Request: [ ipfw_obj_lheader ipfw_nat64stl_cfg ]
  171  *
  172  * Returns 0 on success
  173  */
  174 static int
  175 nat64stl_create(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
  176     struct sockopt_data *sd)
  177 {
  178         ipfw_obj_lheader *olh;
  179         ipfw_nat64stl_cfg *uc;
  180         struct namedobj_instance *ni;
  181         struct nat64stl_cfg *cfg;
  182         int error;
  183 
  184         if (sd->valsize != sizeof(*olh) + sizeof(*uc))
  185                 return (EINVAL);
  186 
  187         olh = (ipfw_obj_lheader *)sd->kbuf;
  188         uc = (ipfw_nat64stl_cfg *)(olh + 1);
  189 
  190         if (ipfw_check_object_name_generic(uc->name) != 0)
  191                 return (EINVAL);
  192         if (uc->set >= IPFW_MAX_SETS ||
  193             nat64_check_prefix6(&uc->prefix6, uc->plen6) != 0)
  194                 return (EINVAL);
  195 
  196         /* XXX: check types of tables */
  197 
  198         ni = CHAIN_TO_SRV(ch);
  199         error = 0;
  200 
  201         IPFW_UH_RLOCK(ch);
  202         if (nat64stl_find(ni, uc->name, uc->set) != NULL) {
  203                 IPFW_UH_RUNLOCK(ch);
  204                 return (EEXIST);
  205         }
  206         IPFW_UH_RUNLOCK(ch);
  207 
  208         cfg = nat64stl_alloc_config(uc->name, uc->set);
  209         cfg->base.plat_prefix = uc->prefix6;
  210         cfg->base.plat_plen = uc->plen6;
  211         cfg->base.flags = (uc->flags & NAT64STL_FLAGSMASK) | NAT64_PLATPFX;
  212         if (IN6_IS_ADDR_WKPFX(&cfg->base.plat_prefix))
  213                 cfg->base.flags |= NAT64_WKPFX;
  214 
  215         IPFW_UH_WLOCK(ch);
  216 
  217         if (nat64stl_find(ni, uc->name, uc->set) != NULL) {
  218                 IPFW_UH_WUNLOCK(ch);
  219                 nat64stl_free_config(cfg);
  220                 return (EEXIST);
  221         }
  222         error = nat64stl_create_internal(ch, cfg, uc);
  223         if (error == 0) {
  224                 /* Okay, let's link data */
  225                 SRV_OBJECT(ch, cfg->no.kidx) = cfg;
  226                 IPFW_UH_WUNLOCK(ch);
  227                 return (0);
  228         }
  229 
  230         if (cfg->base.flags & NAT64STL_KIDX)
  231                 ipfw_objhash_free_idx(ni, cfg->no.kidx);
  232         if (cfg->base.flags & NAT64STL_46T)
  233                 ipfw_unref_table(ch, cfg->map46);
  234         if (cfg->base.flags & NAT64STL_64T)
  235                 ipfw_unref_table(ch, cfg->map64);
  236 
  237         IPFW_UH_WUNLOCK(ch);
  238         nat64stl_free_config(cfg);
  239         return (error);
  240 }
  241 
  242 /*
  243  * Change existing nat64stl instance configuration.
  244  * Data layout (v0)(current):
  245  * Request: [ ipfw_obj_header ipfw_nat64stl_cfg ]
  246  * Reply: [ ipfw_obj_header ipfw_nat64stl_cfg ]
  247  *
  248  * Returns 0 on success
  249  */
  250 static int
  251 nat64stl_config(struct ip_fw_chain *ch, ip_fw3_opheader *op,
  252     struct sockopt_data *sd)
  253 {
  254         ipfw_obj_header *oh;
  255         ipfw_nat64stl_cfg *uc;
  256         struct nat64stl_cfg *cfg;
  257         struct namedobj_instance *ni;
  258 
  259         if (sd->valsize != sizeof(*oh) + sizeof(*uc))
  260                 return (EINVAL);
  261 
  262         oh = (ipfw_obj_header *)ipfw_get_sopt_space(sd,
  263             sizeof(*oh) + sizeof(*uc));
  264         uc = (ipfw_nat64stl_cfg *)(oh + 1);
  265 
  266         if (ipfw_check_object_name_generic(oh->ntlv.name) != 0 ||
  267             oh->ntlv.set >= IPFW_MAX_SETS)
  268                 return (EINVAL);
  269 
  270         ni = CHAIN_TO_SRV(ch);
  271         if (sd->sopt->sopt_dir == SOPT_GET) {
  272                 IPFW_UH_RLOCK(ch);
  273                 cfg = nat64stl_find(ni, oh->ntlv.name, oh->ntlv.set);
  274                 if (cfg == NULL) {
  275                         IPFW_UH_RUNLOCK(ch);
  276                         return (EEXIST);
  277                 }
  278                 nat64stl_export_config(ch, cfg, uc);
  279                 IPFW_UH_RUNLOCK(ch);
  280                 return (0);
  281         }
  282 
  283         IPFW_UH_WLOCK(ch);
  284         cfg = nat64stl_find(ni, oh->ntlv.name, oh->ntlv.set);
  285         if (cfg == NULL) {
  286                 IPFW_UH_WUNLOCK(ch);
  287                 return (EEXIST);
  288         }
  289 
  290         /*
  291          * For now allow to change only following values:
  292          *  flags.
  293          */
  294         cfg->base.flags &= ~NAT64STL_FLAGSMASK;
  295         cfg->base.flags |= uc->flags & NAT64STL_FLAGSMASK;
  296 
  297         IPFW_UH_WUNLOCK(ch);
  298         return (0);
  299 }
  300 
  301 static void
  302 nat64stl_detach_config(struct ip_fw_chain *ch, struct nat64stl_cfg *cfg)
  303 {
  304 
  305         IPFW_UH_WLOCK_ASSERT(ch);
  306 
  307         ipfw_objhash_del(CHAIN_TO_SRV(ch), &cfg->no);
  308         ipfw_objhash_free_idx(CHAIN_TO_SRV(ch), cfg->no.kidx);
  309         ipfw_unref_table(ch, cfg->map46);
  310         ipfw_unref_table(ch, cfg->map64);
  311 }
  312 
  313 /*
  314  * Destroys nat64 instance.
  315  * Data layout (v0)(current):
  316  * Request: [ ipfw_obj_header ]
  317  *
  318  * Returns 0 on success
  319  */
  320 static int
  321 nat64stl_destroy(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
  322     struct sockopt_data *sd)
  323 {
  324         ipfw_obj_header *oh;
  325         struct nat64stl_cfg *cfg;
  326 
  327         if (sd->valsize != sizeof(*oh))
  328                 return (EINVAL);
  329 
  330         oh = (ipfw_obj_header *)sd->kbuf;
  331         if (ipfw_check_object_name_generic(oh->ntlv.name) != 0)
  332                 return (EINVAL);
  333 
  334         IPFW_UH_WLOCK(ch);
  335         cfg = nat64stl_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set);
  336         if (cfg == NULL) {
  337                 IPFW_UH_WUNLOCK(ch);
  338                 return (ESRCH);
  339         }
  340         if (cfg->no.refcnt > 0) {
  341                 IPFW_UH_WUNLOCK(ch);
  342                 return (EBUSY);
  343         }
  344 
  345         ipfw_reset_eaction_instance(ch, V_nat64stl_eid, cfg->no.kidx);
  346         SRV_OBJECT(ch, cfg->no.kidx) = NULL;
  347         nat64stl_detach_config(ch, cfg);
  348         IPFW_UH_WUNLOCK(ch);
  349 
  350         nat64stl_free_config(cfg);
  351         return (0);
  352 }
  353 
  354 /*
  355  * Lists all nat64stl instances currently available in kernel.
  356  * Data layout (v0)(current):
  357  * Request: [ ipfw_obj_lheader ]
  358  * Reply: [ ipfw_obj_lheader ipfw_nat64stl_cfg x N ]
  359  *
  360  * Returns 0 on success
  361  */
  362 static int
  363 nat64stl_list(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
  364     struct sockopt_data *sd)
  365 {
  366         ipfw_obj_lheader *olh;
  367         struct nat64stl_dump_arg da;
  368 
  369         /* Check minimum header size */
  370         if (sd->valsize < sizeof(ipfw_obj_lheader))
  371                 return (EINVAL);
  372 
  373         olh = (ipfw_obj_lheader *)ipfw_get_sopt_header(sd, sizeof(*olh));
  374 
  375         IPFW_UH_RLOCK(ch);
  376         olh->count = ipfw_objhash_count_type(CHAIN_TO_SRV(ch),
  377             IPFW_TLV_NAT64STL_NAME);
  378         olh->objsize = sizeof(ipfw_nat64stl_cfg);
  379         olh->size = sizeof(*olh) + olh->count * olh->objsize;
  380 
  381         if (sd->valsize < olh->size) {
  382                 IPFW_UH_RUNLOCK(ch);
  383                 return (ENOMEM);
  384         }
  385         memset(&da, 0, sizeof(da));
  386         da.ch = ch;
  387         da.sd = sd;
  388         ipfw_objhash_foreach_type(CHAIN_TO_SRV(ch), export_config_cb,
  389             &da, IPFW_TLV_NAT64STL_NAME);
  390         IPFW_UH_RUNLOCK(ch);
  391 
  392         return (0);
  393 }
  394 
  395 #define __COPY_STAT_FIELD(_cfg, _stats, _field) \
  396         (_stats)->_field = NAT64STAT_FETCH(&(_cfg)->base.stats, _field)
  397 static void
  398 export_stats(struct ip_fw_chain *ch, struct nat64stl_cfg *cfg,
  399     struct ipfw_nat64stl_stats *stats)
  400 {
  401 
  402         __COPY_STAT_FIELD(cfg, stats, opcnt64);
  403         __COPY_STAT_FIELD(cfg, stats, opcnt46);
  404         __COPY_STAT_FIELD(cfg, stats, ofrags);
  405         __COPY_STAT_FIELD(cfg, stats, ifrags);
  406         __COPY_STAT_FIELD(cfg, stats, oerrors);
  407         __COPY_STAT_FIELD(cfg, stats, noroute4);
  408         __COPY_STAT_FIELD(cfg, stats, noroute6);
  409         __COPY_STAT_FIELD(cfg, stats, noproto);
  410         __COPY_STAT_FIELD(cfg, stats, nomem);
  411         __COPY_STAT_FIELD(cfg, stats, dropped);
  412 }
  413 
  414 /*
  415  * Get nat64stl statistics.
  416  * Data layout (v0)(current):
  417  * Request: [ ipfw_obj_header ]
  418  * Reply: [ ipfw_obj_header ipfw_obj_ctlv [ uint64_t x N ]]
  419  *
  420  * Returns 0 on success
  421  */
  422 static int
  423 nat64stl_stats(struct ip_fw_chain *ch, ip_fw3_opheader *op,
  424     struct sockopt_data *sd)
  425 {
  426         struct ipfw_nat64stl_stats stats;
  427         struct nat64stl_cfg *cfg;
  428         ipfw_obj_header *oh;
  429         ipfw_obj_ctlv *ctlv;
  430         size_t sz;
  431 
  432         sz = sizeof(ipfw_obj_header) + sizeof(ipfw_obj_ctlv) + sizeof(stats);
  433         if (sd->valsize % sizeof(uint64_t))
  434                 return (EINVAL);
  435         if (sd->valsize < sz)
  436                 return (ENOMEM);
  437         oh = (ipfw_obj_header *)ipfw_get_sopt_header(sd, sz);
  438         if (oh == NULL)
  439                 return (EINVAL);
  440         memset(&stats, 0, sizeof(stats));
  441 
  442         IPFW_UH_RLOCK(ch);
  443         cfg = nat64stl_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set);
  444         if (cfg == NULL) {
  445                 IPFW_UH_RUNLOCK(ch);
  446                 return (ESRCH);
  447         }
  448         export_stats(ch, cfg, &stats);
  449         IPFW_UH_RUNLOCK(ch);
  450 
  451         ctlv = (ipfw_obj_ctlv *)(oh + 1);
  452         memset(ctlv, 0, sizeof(*ctlv));
  453         ctlv->head.type = IPFW_TLV_COUNTERS;
  454         ctlv->head.length = sz - sizeof(ipfw_obj_header);
  455         ctlv->count = sizeof(stats) / sizeof(uint64_t);
  456         ctlv->objsize = sizeof(uint64_t);
  457         ctlv->version = IPFW_NAT64_VERSION;
  458         memcpy(ctlv + 1, &stats, sizeof(stats));
  459         return (0);
  460 }
  461 
  462 /*
  463  * Reset nat64stl statistics.
  464  * Data layout (v0)(current):
  465  * Request: [ ipfw_obj_header ]
  466  *
  467  * Returns 0 on success
  468  */
  469 static int
  470 nat64stl_reset_stats(struct ip_fw_chain *ch, ip_fw3_opheader *op,
  471     struct sockopt_data *sd)
  472 {
  473         struct nat64stl_cfg *cfg;
  474         ipfw_obj_header *oh;
  475 
  476         if (sd->valsize != sizeof(*oh))
  477                 return (EINVAL);
  478         oh = (ipfw_obj_header *)sd->kbuf;
  479         if (ipfw_check_object_name_generic(oh->ntlv.name) != 0 ||
  480             oh->ntlv.set >= IPFW_MAX_SETS)
  481                 return (EINVAL);
  482 
  483         IPFW_UH_WLOCK(ch);
  484         cfg = nat64stl_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set);
  485         if (cfg == NULL) {
  486                 IPFW_UH_WUNLOCK(ch);
  487                 return (ESRCH);
  488         }
  489         COUNTER_ARRAY_ZERO(cfg->base.stats.cnt, NAT64STATS);
  490         IPFW_UH_WUNLOCK(ch);
  491         return (0);
  492 }
  493 
  494 static struct ipfw_sopt_handler scodes[] = {
  495         { IP_FW_NAT64STL_CREATE, 0,     HDIR_SET,       nat64stl_create },
  496         { IP_FW_NAT64STL_DESTROY,0,     HDIR_SET,       nat64stl_destroy },
  497         { IP_FW_NAT64STL_CONFIG, 0,     HDIR_BOTH,      nat64stl_config },
  498         { IP_FW_NAT64STL_LIST,   0,     HDIR_GET,       nat64stl_list },
  499         { IP_FW_NAT64STL_STATS,  0,     HDIR_GET,       nat64stl_stats },
  500         { IP_FW_NAT64STL_RESET_STATS,0, HDIR_SET,       nat64stl_reset_stats },
  501 };
  502 
  503 static int
  504 nat64stl_classify(ipfw_insn *cmd, uint16_t *puidx, uint8_t *ptype)
  505 {
  506         ipfw_insn *icmd;
  507 
  508         icmd = cmd - 1;
  509         if (icmd->opcode != O_EXTERNAL_ACTION ||
  510             icmd->arg1 != V_nat64stl_eid)
  511                 return (1);
  512 
  513         *puidx = cmd->arg1;
  514         *ptype = 0;
  515         return (0);
  516 }
  517 
  518 static void
  519 nat64stl_update_arg1(ipfw_insn *cmd, uint16_t idx)
  520 {
  521 
  522         cmd->arg1 = idx;
  523 }
  524 
  525 static int
  526 nat64stl_findbyname(struct ip_fw_chain *ch, struct tid_info *ti,
  527     struct named_object **pno)
  528 {
  529         int err;
  530 
  531         err = ipfw_objhash_find_type(CHAIN_TO_SRV(ch), ti,
  532             IPFW_TLV_NAT64STL_NAME, pno);
  533         return (err);
  534 }
  535 
  536 static struct named_object *
  537 nat64stl_findbykidx(struct ip_fw_chain *ch, uint16_t idx)
  538 {
  539         struct namedobj_instance *ni;
  540         struct named_object *no;
  541 
  542         IPFW_UH_WLOCK_ASSERT(ch);
  543         ni = CHAIN_TO_SRV(ch);
  544         no = ipfw_objhash_lookup_kidx(ni, idx);
  545         KASSERT(no != NULL, ("NAT with index %d not found", idx));
  546 
  547         return (no);
  548 }
  549 
  550 static int
  551 nat64stl_manage_sets(struct ip_fw_chain *ch, uint16_t set, uint8_t new_set,
  552     enum ipfw_sets_cmd cmd)
  553 {
  554 
  555         return (ipfw_obj_manage_sets(CHAIN_TO_SRV(ch), IPFW_TLV_NAT64STL_NAME,
  556             set, new_set, cmd));
  557 }
  558 
  559 static struct opcode_obj_rewrite opcodes[] = {
  560         {
  561                 .opcode = O_EXTERNAL_INSTANCE,
  562                 .etlv = IPFW_TLV_EACTION /* just show it isn't table */,
  563                 .classifier = nat64stl_classify,
  564                 .update = nat64stl_update_arg1,
  565                 .find_byname = nat64stl_findbyname,
  566                 .find_bykidx = nat64stl_findbykidx,
  567                 .manage_sets = nat64stl_manage_sets,
  568         },
  569 };
  570 
  571 static int
  572 destroy_config_cb(struct namedobj_instance *ni, struct named_object *no,
  573     void *arg)
  574 {
  575         struct nat64stl_cfg *cfg;
  576         struct ip_fw_chain *ch;
  577 
  578         ch = (struct ip_fw_chain *)arg;
  579         cfg = (struct nat64stl_cfg *)SRV_OBJECT(ch, no->kidx);
  580         SRV_OBJECT(ch, no->kidx) = NULL;
  581         nat64stl_detach_config(ch, cfg);
  582         nat64stl_free_config(cfg);
  583         return (0);
  584 }
  585 
  586 int
  587 nat64stl_init(struct ip_fw_chain *ch, int first)
  588 {
  589 
  590         V_nat64stl_eid = ipfw_add_eaction(ch, ipfw_nat64stl, "nat64stl");
  591         if (V_nat64stl_eid == 0)
  592                 return (ENXIO);
  593         IPFW_ADD_SOPT_HANDLER(first, scodes);
  594         IPFW_ADD_OBJ_REWRITER(first, opcodes);
  595         return (0);
  596 }
  597 
  598 void
  599 nat64stl_uninit(struct ip_fw_chain *ch, int last)
  600 {
  601 
  602         IPFW_DEL_OBJ_REWRITER(last, opcodes);
  603         IPFW_DEL_SOPT_HANDLER(last, scodes);
  604         ipfw_del_eaction(ch, V_nat64stl_eid);
  605         /*
  606          * Since we already have deregistered external action,
  607          * our named objects become unaccessible via rules, because
  608          * all rules were truncated by ipfw_del_eaction().
  609          * So, we can unlink and destroy our named objects without holding
  610          * IPFW_WLOCK().
  611          */
  612         IPFW_UH_WLOCK(ch);
  613         ipfw_objhash_foreach_type(CHAIN_TO_SRV(ch), destroy_config_cb, ch,
  614             IPFW_TLV_NAT64STL_NAME);
  615         V_nat64stl_eid = 0;
  616         IPFW_UH_WUNLOCK(ch);
  617 }

Cache object: 2d236dd9e30a9704363ea3de13a91fd7


[ 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.