root/net/pf_if.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pfi_initialize
  2. pfi_kif_get
  3. pfi_kif_ref
  4. pfi_kif_unref
  5. pfi_kif_match
  6. pfi_attach_ifnet
  7. pfi_detach_ifnet
  8. pfi_attach_ifgroup
  9. pfi_detach_ifgroup
  10. pfi_group_change
  11. pfi_match_addr
  12. pfi_dynaddr_setup
  13. pfi_kif_update
  14. pfi_dynaddr_update
  15. pfi_table_update
  16. pfi_instance_add
  17. pfi_address_add
  18. pfi_dynaddr_remove
  19. pfi_dynaddr_copyout
  20. pfi_kifaddr_update
  21. pfi_if_compare
  22. pfi_fill_oldstatus
  23. pfi_clr_istats
  24. pfi_get_ifaces
  25. pfi_skip_if
  26. pfi_set_flags
  27. pfi_clear_flags
  28. pfi_unmask

    1 /*      $OpenBSD: pf_if.c,v 1.47 2007/07/13 09:17:48 markus Exp $ */
    2 
    3 /*
    4  * Copyright 2005 Henning Brauer <henning@openbsd.org>
    5  * Copyright 2005 Ryan McBride <mcbride@openbsd.org>
    6  * Copyright (c) 2001 Daniel Hartmeier
    7  * Copyright (c) 2003 Cedric Berger
    8  * All rights reserved.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  *
   14  *    - Redistributions of source code must retain the above copyright
   15  *      notice, this list of conditions and the following disclaimer.
   16  *    - Redistributions in binary form must reproduce the above
   17  *      copyright notice, this list of conditions and the following
   18  *      disclaimer in the documentation and/or other materials provided
   19  *      with the distribution.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32  * POSSIBILITY OF SUCH DAMAGE.
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/mbuf.h>
   38 #include <sys/filio.h>
   39 #include <sys/socket.h>
   40 #include <sys/socketvar.h>
   41 #include <sys/kernel.h>
   42 #include <sys/device.h>
   43 #include <sys/time.h>
   44 
   45 #include <net/if.h>
   46 #include <net/if_types.h>
   47 
   48 #include <netinet/in.h>
   49 #include <netinet/in_var.h>
   50 #include <netinet/in_systm.h>
   51 #include <netinet/ip.h>
   52 #include <netinet/ip_var.h>
   53 
   54 #include <net/pfvar.h>
   55 
   56 #ifdef INET6
   57 #include <netinet/ip6.h>
   58 #endif /* INET6 */
   59 
   60 struct pfi_kif           *pfi_all = NULL;
   61 struct pool               pfi_addr_pl;
   62 struct pfi_ifhead         pfi_ifs;
   63 long                      pfi_update = 1;
   64 struct pfr_addr          *pfi_buffer;
   65 int                       pfi_buffer_cnt;
   66 int                       pfi_buffer_max;
   67 
   68 void             pfi_kif_update(struct pfi_kif *);
   69 void             pfi_dynaddr_update(struct pfi_dynaddr *dyn);
   70 void             pfi_table_update(struct pfr_ktable *, struct pfi_kif *,
   71                     int, int);
   72 void             pfi_kifaddr_update(void *);
   73 void             pfi_instance_add(struct ifnet *, int, int);
   74 void             pfi_address_add(struct sockaddr *, int, int);
   75 int              pfi_if_compare(struct pfi_kif *, struct pfi_kif *);
   76 int              pfi_skip_if(const char *, struct pfi_kif *);
   77 int              pfi_unmask(void *);
   78 
   79 RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
   80 RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
   81 
   82 #define PFI_BUFFER_MAX          0x10000
   83 #define PFI_MTYPE               M_IFADDR
   84 
   85 void
   86 pfi_initialize(void)
   87 {
   88         if (pfi_all != NULL)    /* already initialized */
   89                 return;
   90 
   91         pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0,
   92             "pfiaddrpl", &pool_allocator_nointr);
   93         pfi_buffer_max = 64;
   94         pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer),
   95             PFI_MTYPE, M_WAITOK);
   96 
   97         if ((pfi_all = pfi_kif_get(IFG_ALL)) == NULL)
   98                 panic("pfi_kif_get for pfi_all failed");
   99 }
  100 
  101 struct pfi_kif *
  102 pfi_kif_get(const char *kif_name)
  103 {
  104         struct pfi_kif          *kif;
  105         struct pfi_kif_cmp       s;
  106 
  107         bzero(&s, sizeof(s));
  108         strlcpy(s.pfik_name, kif_name, sizeof(s.pfik_name));
  109         if ((kif = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&s)) != NULL)
  110                 return (kif);
  111 
  112         /* create new one */
  113         if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_DONTWAIT)) == NULL)
  114                 return (NULL);
  115 
  116         bzero(kif, sizeof(*kif));
  117         strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name));
  118         kif->pfik_tzero = time_second;
  119         TAILQ_INIT(&kif->pfik_dynaddrs);
  120 
  121         RB_INSERT(pfi_ifhead, &pfi_ifs, kif);
  122         return (kif);
  123 }
  124 
  125 void
  126 pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what)
  127 {
  128         switch (what) {
  129         case PFI_KIF_REF_RULE:
  130                 kif->pfik_rules++;
  131                 break;
  132         case PFI_KIF_REF_STATE:
  133                 kif->pfik_states++;
  134                 break;
  135         default:
  136                 panic("pfi_kif_ref with unknown type");
  137         }
  138 }
  139 
  140 void
  141 pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what)
  142 {
  143         if (kif == NULL)
  144                 return;
  145 
  146         switch (what) {
  147         case PFI_KIF_REF_NONE:
  148                 break;
  149         case PFI_KIF_REF_RULE:
  150                 if (kif->pfik_rules <= 0) {
  151                         printf("pfi_kif_unref: rules refcount <= 0\n");
  152                         return;
  153                 }
  154                 kif->pfik_rules--;
  155                 break;
  156         case PFI_KIF_REF_STATE:
  157                 if (kif->pfik_states <= 0) {
  158                         printf("pfi_kif_unref: state refcount <= 0\n");
  159                         return;
  160                 }
  161                 kif->pfik_states--;
  162                 break;
  163         default:
  164                 panic("pfi_kif_unref with unknown type");
  165         }
  166 
  167         if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all)
  168                 return;
  169 
  170         if (kif->pfik_rules || kif->pfik_states)
  171                 return;
  172 
  173         RB_REMOVE(pfi_ifhead, &pfi_ifs, kif);
  174         free(kif, PFI_MTYPE);
  175 }
  176 
  177 int
  178 pfi_kif_match(struct pfi_kif *rule_kif, struct pfi_kif *packet_kif)
  179 {
  180         struct ifg_list *p;
  181 
  182         if (rule_kif == NULL || rule_kif == packet_kif)
  183                 return (1);
  184 
  185         if (rule_kif->pfik_group != NULL)
  186                 TAILQ_FOREACH(p, &packet_kif->pfik_ifp->if_groups, ifgl_next)
  187                         if (p->ifgl_group == rule_kif->pfik_group)
  188                                 return (1);
  189 
  190         return (0);
  191 }
  192 
  193 void
  194 pfi_attach_ifnet(struct ifnet *ifp)
  195 {
  196         struct pfi_kif          *kif;
  197         int                      s;
  198 
  199         pfi_initialize();
  200         s = splsoftnet();
  201         pfi_update++;
  202         if ((kif = pfi_kif_get(ifp->if_xname)) == NULL)
  203                 panic("pfi_kif_get failed");
  204 
  205         kif->pfik_ifp = ifp;
  206         ifp->if_pf_kif = (caddr_t)kif;
  207 
  208         if ((kif->pfik_ah_cookie = hook_establish(ifp->if_addrhooks, 1,
  209             pfi_kifaddr_update, kif)) == NULL)
  210                 panic("pfi_attach_ifnet: cannot allocate '%s' address hook",
  211                     ifp->if_xname);
  212 
  213         pfi_kif_update(kif);
  214 
  215         splx(s);
  216 }
  217 
  218 void
  219 pfi_detach_ifnet(struct ifnet *ifp)
  220 {
  221         int                      s;
  222         struct pfi_kif          *kif;
  223 
  224         if ((kif = (struct pfi_kif *)ifp->if_pf_kif) == NULL)
  225                 return;
  226 
  227         s = splsoftnet();
  228         pfi_update++;
  229         hook_disestablish(ifp->if_addrhooks, kif->pfik_ah_cookie);
  230         pfi_kif_update(kif);
  231 
  232         kif->pfik_ifp = NULL;
  233         ifp->if_pf_kif = NULL;
  234         pfi_kif_unref(kif, PFI_KIF_REF_NONE);
  235         splx(s);
  236 }
  237 
  238 void
  239 pfi_attach_ifgroup(struct ifg_group *ifg)
  240 {
  241         struct pfi_kif  *kif;
  242         int              s;
  243 
  244         pfi_initialize();
  245         s = splsoftnet();
  246         pfi_update++;
  247         if ((kif = pfi_kif_get(ifg->ifg_group)) == NULL)
  248                 panic("pfi_kif_get failed");
  249 
  250         kif->pfik_group = ifg;
  251         ifg->ifg_pf_kif = (caddr_t)kif;
  252 
  253         splx(s);
  254 }
  255 
  256 void
  257 pfi_detach_ifgroup(struct ifg_group *ifg)
  258 {
  259         int              s;
  260         struct pfi_kif  *kif;
  261 
  262         if ((kif = (struct pfi_kif *)ifg->ifg_pf_kif) == NULL)
  263                 return;
  264 
  265         s = splsoftnet();
  266         pfi_update++;
  267 
  268         kif->pfik_group = NULL;
  269         ifg->ifg_pf_kif = NULL;
  270         pfi_kif_unref(kif, PFI_KIF_REF_NONE);
  271         splx(s);
  272 }
  273 
  274 void
  275 pfi_group_change(const char *group)
  276 {
  277         struct pfi_kif          *kif;
  278         int                      s;
  279 
  280         s = splsoftnet();
  281         pfi_update++;
  282         if ((kif = pfi_kif_get(group)) == NULL)
  283                 panic("pfi_kif_get failed");
  284 
  285         pfi_kif_update(kif);
  286 
  287         splx(s);
  288 }
  289 
  290 int
  291 pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af)
  292 {
  293         switch (af) {
  294 #ifdef INET
  295         case AF_INET:
  296                 switch (dyn->pfid_acnt4) {
  297                 case 0:
  298                         return (0);
  299                 case 1:
  300                         return (PF_MATCHA(0, &dyn->pfid_addr4,
  301                             &dyn->pfid_mask4, a, AF_INET));
  302                 default:
  303                         return (pfr_match_addr(dyn->pfid_kt, a, AF_INET));
  304                 }
  305                 break;
  306 #endif /* INET */
  307 #ifdef INET6
  308         case AF_INET6:
  309                 switch (dyn->pfid_acnt6) {
  310                 case 0:
  311                         return (0);
  312                 case 1:
  313                         return (PF_MATCHA(0, &dyn->pfid_addr6,
  314                             &dyn->pfid_mask6, a, AF_INET6));
  315                 default:
  316                         return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6));
  317                 }
  318                 break;
  319 #endif /* INET6 */
  320         default:
  321                 return (0);
  322         }
  323 }
  324 
  325 int
  326 pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
  327 {
  328         struct pfi_dynaddr      *dyn;
  329         char                     tblname[PF_TABLE_NAME_SIZE];
  330         struct pf_ruleset       *ruleset = NULL;
  331         int                      s, rv = 0;
  332 
  333         if (aw->type != PF_ADDR_DYNIFTL)
  334                 return (0);
  335         if ((dyn = pool_get(&pfi_addr_pl, PR_NOWAIT)) == NULL)
  336                 return (1);
  337         bzero(dyn, sizeof(*dyn));
  338 
  339         s = splsoftnet();
  340         if (!strcmp(aw->v.ifname, "self"))
  341                 dyn->pfid_kif = pfi_kif_get(IFG_ALL);
  342         else
  343                 dyn->pfid_kif = pfi_kif_get(aw->v.ifname);
  344         if (dyn->pfid_kif == NULL) {
  345                 rv = 1;
  346                 goto _bad;
  347         }
  348         pfi_kif_ref(dyn->pfid_kif, PFI_KIF_REF_RULE);
  349 
  350         dyn->pfid_net = pfi_unmask(&aw->v.a.mask);
  351         if (af == AF_INET && dyn->pfid_net == 32)
  352                 dyn->pfid_net = 128;
  353         strlcpy(tblname, aw->v.ifname, sizeof(tblname));
  354         if (aw->iflags & PFI_AFLAG_NETWORK)
  355                 strlcat(tblname, ":network", sizeof(tblname));
  356         if (aw->iflags & PFI_AFLAG_BROADCAST)
  357                 strlcat(tblname, ":broadcast", sizeof(tblname));
  358         if (aw->iflags & PFI_AFLAG_PEER)
  359                 strlcat(tblname, ":peer", sizeof(tblname));
  360         if (aw->iflags & PFI_AFLAG_NOALIAS)
  361                 strlcat(tblname, ":0", sizeof(tblname));
  362         if (dyn->pfid_net != 128)
  363                 snprintf(tblname + strlen(tblname),
  364                     sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net);
  365         if ((ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR)) == NULL) {
  366                 rv = 1;
  367                 goto _bad;
  368         }
  369 
  370         if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname)) == NULL) {
  371                 rv = 1;
  372                 goto _bad;
  373         }
  374 
  375         dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE;
  376         dyn->pfid_iflags = aw->iflags;
  377         dyn->pfid_af = af;
  378 
  379         TAILQ_INSERT_TAIL(&dyn->pfid_kif->pfik_dynaddrs, dyn, entry);
  380         aw->p.dyn = dyn;
  381         pfi_kif_update(dyn->pfid_kif);
  382         splx(s);
  383         return (0);
  384 
  385 _bad:
  386         if (dyn->pfid_kt != NULL)
  387                 pfr_detach_table(dyn->pfid_kt);
  388         if (ruleset != NULL)
  389                 pf_remove_if_empty_ruleset(ruleset);
  390         if (dyn->pfid_kif != NULL)
  391                 pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE);
  392         pool_put(&pfi_addr_pl, dyn);
  393         splx(s);
  394         return (rv);
  395 }
  396 
  397 void
  398 pfi_kif_update(struct pfi_kif *kif)
  399 {
  400         struct ifg_list         *ifgl;
  401         struct pfi_dynaddr      *p;
  402 
  403         /* update all dynaddr */
  404         TAILQ_FOREACH(p, &kif->pfik_dynaddrs, entry)
  405                 pfi_dynaddr_update(p);
  406 
  407         /* again for all groups kif is member of */
  408         if (kif->pfik_ifp != NULL)
  409                 TAILQ_FOREACH(ifgl, &kif->pfik_ifp->if_groups, ifgl_next)
  410                         pfi_kif_update((struct pfi_kif *)
  411                             ifgl->ifgl_group->ifg_pf_kif);
  412 }
  413 
  414 void
  415 pfi_dynaddr_update(struct pfi_dynaddr *dyn)
  416 {
  417         struct pfi_kif          *kif;
  418         struct pfr_ktable       *kt;
  419 
  420         if (dyn == NULL || dyn->pfid_kif == NULL || dyn->pfid_kt == NULL)
  421                 panic("pfi_dynaddr_update");
  422 
  423         kif = dyn->pfid_kif;
  424         kt = dyn->pfid_kt;
  425 
  426         if (kt->pfrkt_larg != pfi_update) {
  427                 /* this table needs to be brought up-to-date */
  428                 pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags);
  429                 kt->pfrkt_larg = pfi_update;
  430         }
  431         pfr_dynaddr_update(kt, dyn);
  432 }
  433 
  434 void
  435 pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags)
  436 {
  437         int                      e, size2 = 0;
  438         struct ifg_member       *ifgm;
  439 
  440         pfi_buffer_cnt = 0;
  441 
  442         if (kif->pfik_ifp != NULL)
  443                 pfi_instance_add(kif->pfik_ifp, net, flags);
  444         else if (kif->pfik_group != NULL)
  445                 TAILQ_FOREACH(ifgm, &kif->pfik_group->ifg_members, ifgm_next)
  446                         pfi_instance_add(ifgm->ifgm_ifp, net, flags);
  447 
  448         if ((e = pfr_set_addrs(&kt->pfrkt_t, pfi_buffer, pfi_buffer_cnt, &size2,
  449             NULL, NULL, NULL, 0, PFR_TFLAG_ALLMASK)))
  450                 printf("pfi_table_update: cannot set %d new addresses "
  451                     "into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e);
  452 }
  453 
  454 void
  455 pfi_instance_add(struct ifnet *ifp, int net, int flags)
  456 {
  457         struct ifaddr   *ia;
  458         int              got4 = 0, got6 = 0;
  459         int              net2, af;
  460 
  461         if (ifp == NULL)
  462                 return;
  463         TAILQ_FOREACH(ia, &ifp->if_addrlist, ifa_list) {
  464                 if (ia->ifa_addr == NULL)
  465                         continue;
  466                 af = ia->ifa_addr->sa_family;
  467                 if (af != AF_INET && af != AF_INET6)
  468                         continue;
  469                 if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6)
  470                         continue;
  471                 if ((flags & PFI_AFLAG_BROADCAST) &&
  472                     !(ifp->if_flags & IFF_BROADCAST))
  473                         continue;
  474                 if ((flags & PFI_AFLAG_PEER) &&
  475                     !(ifp->if_flags & IFF_POINTOPOINT))
  476                         continue;
  477                 if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 &&
  478                     IN6_IS_ADDR_LINKLOCAL(
  479                     &((struct sockaddr_in6 *)ia->ifa_addr)->sin6_addr))
  480                         continue;
  481                 if (flags & PFI_AFLAG_NOALIAS) {
  482                         if (af == AF_INET && got4)
  483                                 continue;
  484                         if (af == AF_INET6 && got6)
  485                                 continue;
  486                 }
  487                 if (af == AF_INET)
  488                         got4 = 1;
  489                 else if (af == AF_INET6)
  490                         got6 = 1;
  491                 net2 = net;
  492                 if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) {
  493                         if (af == AF_INET)
  494                                 net2 = pfi_unmask(&((struct sockaddr_in *)
  495                                     ia->ifa_netmask)->sin_addr);
  496                         else if (af == AF_INET6)
  497                                 net2 = pfi_unmask(&((struct sockaddr_in6 *)
  498                                     ia->ifa_netmask)->sin6_addr);
  499                 }
  500                 if (af == AF_INET && net2 > 32)
  501                         net2 = 32;
  502                 if (flags & PFI_AFLAG_BROADCAST)
  503                         pfi_address_add(ia->ifa_broadaddr, af, net2);
  504                 else if (flags & PFI_AFLAG_PEER)
  505                         pfi_address_add(ia->ifa_dstaddr, af, net2);
  506                 else
  507                         pfi_address_add(ia->ifa_addr, af, net2);
  508         }
  509 }
  510 
  511 void
  512 pfi_address_add(struct sockaddr *sa, int af, int net)
  513 {
  514         struct pfr_addr *p;
  515         int              i;
  516 
  517         if (pfi_buffer_cnt >= pfi_buffer_max) {
  518                 int              new_max = pfi_buffer_max * 2;
  519 
  520                 if (new_max > PFI_BUFFER_MAX) {
  521                         printf("pfi_address_add: address buffer full (%d/%d)\n",
  522                             pfi_buffer_cnt, PFI_BUFFER_MAX);
  523                         return;
  524                 }
  525                 p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE,
  526                     M_DONTWAIT);
  527                 if (p == NULL) {
  528                         printf("pfi_address_add: no memory to grow buffer "
  529                             "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX);
  530                         return;
  531                 }
  532                 memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer));
  533                 /* no need to zero buffer */
  534                 free(pfi_buffer, PFI_MTYPE);
  535                 pfi_buffer = p;
  536                 pfi_buffer_max = new_max;
  537         }
  538         if (af == AF_INET && net > 32)
  539                 net = 128;
  540         p = pfi_buffer + pfi_buffer_cnt++;
  541         bzero(p, sizeof(*p));
  542         p->pfra_af = af;
  543         p->pfra_net = net;
  544         if (af == AF_INET)
  545                 p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr;
  546         else if (af == AF_INET6) {
  547                 p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr;
  548                 if (IN6_IS_SCOPE_EMBED(&p->pfra_ip6addr))
  549                         p->pfra_ip6addr.s6_addr16[1] = 0;
  550         }
  551         /* mask network address bits */
  552         if (net < 128)
  553                 ((caddr_t)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8));
  554         for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++)
  555                 ((caddr_t)p)[i] = 0;
  556 }
  557 
  558 void
  559 pfi_dynaddr_remove(struct pf_addr_wrap *aw)
  560 {
  561         int     s;
  562 
  563         if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL ||
  564             aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL)
  565                 return;
  566 
  567         s = splsoftnet();
  568         TAILQ_REMOVE(&aw->p.dyn->pfid_kif->pfik_dynaddrs, aw->p.dyn, entry);
  569         pfi_kif_unref(aw->p.dyn->pfid_kif, PFI_KIF_REF_RULE);
  570         aw->p.dyn->pfid_kif = NULL;
  571         pfr_detach_table(aw->p.dyn->pfid_kt);
  572         aw->p.dyn->pfid_kt = NULL;
  573         pool_put(&pfi_addr_pl, aw->p.dyn);
  574         aw->p.dyn = NULL;
  575         splx(s);
  576 }
  577 
  578 void
  579 pfi_dynaddr_copyout(struct pf_addr_wrap *aw)
  580 {
  581         if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL ||
  582             aw->p.dyn->pfid_kif == NULL)
  583                 return;
  584         aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6;
  585 }
  586 
  587 void
  588 pfi_kifaddr_update(void *v)
  589 {
  590         int                      s;
  591         struct pfi_kif          *kif = (struct pfi_kif *)v;
  592 
  593         s = splsoftnet();
  594         pfi_update++;
  595         pfi_kif_update(kif);
  596         splx(s);
  597 }
  598 
  599 int
  600 pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q)
  601 {
  602         return (strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ));
  603 }
  604 
  605 void
  606 pfi_fill_oldstatus(struct pf_status *pfs)
  607 {
  608         struct pfi_kif          *p;
  609         struct pfi_kif_cmp       key;
  610         int                      i, j, k, s;
  611 
  612         strlcpy(key.pfik_name, pfs->ifname, sizeof(key.pfik_name));
  613         s = splsoftnet();
  614         p = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&key);
  615         if (p == NULL) {
  616                 splx(s);
  617                 return;
  618         }
  619         bzero(pfs->pcounters, sizeof(pfs->pcounters));
  620         bzero(pfs->bcounters, sizeof(pfs->bcounters));
  621         for (i = 0; i < 2; i++)
  622                 for (j = 0; j < 2; j++)
  623                         for (k = 0; k < 2; k++) {
  624                                 pfs->pcounters[i][j][k] =
  625                                         p->pfik_packets[i][j][k];
  626                                 pfs->bcounters[i][j] +=
  627                                         p->pfik_bytes[i][j][k];
  628                         }
  629         splx(s);
  630 }
  631 
  632 int
  633 pfi_clr_istats(const char *name)
  634 {
  635         struct pfi_kif  *p;
  636         int              s;
  637 
  638         s = splsoftnet();
  639         RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
  640                 if (pfi_skip_if(name, p))
  641                         continue;
  642                 bzero(p->pfik_packets, sizeof(p->pfik_packets));
  643                 bzero(p->pfik_bytes, sizeof(p->pfik_bytes));
  644                 p->pfik_tzero = time_second;
  645         }
  646         splx(s);
  647 
  648         return (0);
  649 }
  650 
  651 int
  652 pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size)
  653 {
  654         struct pfi_kif  *p, *nextp;
  655         int              s, n = 0;
  656 
  657         s = splsoftnet();
  658         for (p = RB_MIN(pfi_ifhead, &pfi_ifs); p; p = nextp) {
  659                 nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
  660                 if (pfi_skip_if(name, p))
  661                         continue;
  662                 if (*size > n++) {
  663                         if (!p->pfik_tzero)
  664                                 p->pfik_tzero = time_second;
  665                         pfi_kif_ref(p, PFI_KIF_REF_RULE);
  666                         if (copyout(p, buf++, sizeof(*buf))) {
  667                                 pfi_kif_unref(p, PFI_KIF_REF_RULE);
  668                                 splx(s);
  669                                 return (EFAULT);
  670                         }
  671                         nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
  672                         pfi_kif_unref(p, PFI_KIF_REF_RULE);
  673                 }
  674         }
  675         splx(s);
  676         *size = n;
  677         return (0);
  678 }
  679 
  680 int
  681 pfi_skip_if(const char *filter, struct pfi_kif *p)
  682 {
  683         int     n;
  684 
  685         if (filter == NULL || !*filter)
  686                 return (0);
  687         if (!strcmp(p->pfik_name, filter))
  688                 return (0);     /* exact match */
  689         n = strlen(filter);
  690         if (n < 1 || n >= IFNAMSIZ)
  691                 return (1);     /* sanity check */
  692         if (filter[n-1] >= '0' && filter[n-1] <= '9')
  693                 return (1);     /* only do exact match in that case */
  694         if (strncmp(p->pfik_name, filter, n))
  695                 return (1);     /* prefix doesn't match */
  696         return (p->pfik_name[n] < '0' || p->pfik_name[n] > '9');
  697 }
  698 
  699 int
  700 pfi_set_flags(const char *name, int flags)
  701 {
  702         struct pfi_kif  *p;
  703         int              s;
  704 
  705         s = splsoftnet();
  706         RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
  707                 if (pfi_skip_if(name, p))
  708                         continue;
  709                 p->pfik_flags |= flags;
  710         }
  711         splx(s);
  712         return (0);
  713 }
  714 
  715 int
  716 pfi_clear_flags(const char *name, int flags)
  717 {
  718         struct pfi_kif  *p;
  719         int              s;
  720 
  721         s = splsoftnet();
  722         RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
  723                 if (pfi_skip_if(name, p))
  724                         continue;
  725                 p->pfik_flags &= ~flags;
  726         }
  727         splx(s);
  728         return (0);
  729 }
  730 
  731 /* from pf_print_state.c */
  732 int
  733 pfi_unmask(void *addr)
  734 {
  735         struct pf_addr *m = addr;
  736         int i = 31, j = 0, b = 0;
  737         u_int32_t tmp;
  738 
  739         while (j < 4 && m->addr32[j] == 0xffffffff) {
  740                 b += 32;
  741                 j++;
  742         }
  743         if (j < 4) {
  744                 tmp = ntohl(m->addr32[j]);
  745                 for (i = 31; tmp & (1 << i); --i)
  746                         b++;
  747         }
  748         return (b);
  749 }
  750 

/* [<][>][^][v][top][bottom][index][help] */