xref: /dragonfly/sys/net/pf/pf_if.c (revision 6aa338e1205b533679b84dd50b38f5664f0d9cef)
1 /*        $OpenBSD: pf_if.c,v 1.54 2008/06/14 16:55:28 mk 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 "opt_inet.h"
36 #include "opt_inet6.h"
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/mbuf.h>
42 #include <sys/eventhandler.h>
43 #include <sys/filio.h>
44 #include <sys/msgport2.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/kernel.h>
48 #include <sys/thread2.h>
49 #include <sys/time.h>
50 #include <sys/lock.h>
51 
52 #include <net/if.h>
53 #include <net/if_var.h>
54 #include <net/if_types.h>
55 #include <net/netisr2.h>
56 #include <net/netmsg2.h>
57 #include <net/route.h>
58 
59 #include <netinet/in.h>
60 #include <netinet/in_var.h>
61 #include <netinet/in_systm.h>
62 #include <netinet/ip.h>
63 #include <netinet/ip_var.h>
64 
65 #include <net/pf/pfvar.h>
66 
67 #ifdef INET6
68 #include <netinet/ip6.h>
69 #endif /* INET6 */
70 
71 struct pfi_kif                *pfi_all = NULL;
72 struct pfi_ifhead    pfi_ifs;
73 static long                    pfi_update = 1;
74 static struct pfr_addr        *pfi_buffer;
75 static int                     pfi_buffer_cnt;
76 static int                     pfi_buffer_max;
77 
78 static eventhandler_tag        pfi_attach_cookie;
79 static eventhandler_tag        pfi_detach_cookie;
80 static eventhandler_tag        pfi_attach_group_cookie;
81 static eventhandler_tag        pfi_detach_group_cookie;
82 static eventhandler_tag        pfi_change_group_cookie;
83 static eventhandler_tag        pfi_ifaddr_event_cookie;
84 
85 static void          pfi_kif_update(struct pfi_kif *);
86 static void          pfi_dynaddr_update(struct pfi_dynaddr *);
87 static void          pfi_table_update(struct pfr_ktable *, struct pfi_kif *,
88                         int, int);
89 static void          pfi_instance_add(struct ifnet *, int, int);
90 static void          pfi_address_add(struct sockaddr *, int, int);
91 static int           pfi_if_compare(struct pfi_kif *, struct pfi_kif *);
92 static int           pfi_skip_if(const char *, struct pfi_kif *);
93 static int           pfi_unmask(void *);
94 
95 static void          pfi_attach_ifnet_event(void * __unused, struct ifnet *);
96 static void          pfi_detach_ifnet_event(void * __unused, struct ifnet *);
97 static void          pfi_attach_group_event(void * __unused, struct ifg_group *);
98 static void          pfi_detach_group_event(void * __unused, struct ifg_group *);
99 static void          pfi_change_group_event(void * __unused, char *);
100 static void          pfi_ifaddr_event(void * __unused, struct ifnet *,
101                         enum ifaddr_event __unused, struct ifaddr * __unused);
102 
103 static RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
104 static RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
105 
106 #define PFI_BUFFER_MAX                  0x10000
107 static MALLOC_DEFINE(M_PFI, "pf_if", "pf interface");
108 
109 
110 void
pfi_initialize(void)111 pfi_initialize(void)
112 {
113           struct ifnet *ifp;
114           struct ifg_group *ifg;
115 
116           pfi_attach_cookie = EVENTHANDLER_REGISTER(ifnet_attach_event,
117               pfi_attach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY);
118           pfi_detach_cookie = EVENTHANDLER_REGISTER(ifnet_detach_event,
119               pfi_detach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY);
120           pfi_attach_group_cookie = EVENTHANDLER_REGISTER(group_attach_event,
121               pfi_attach_group_event, NULL, EVENTHANDLER_PRI_ANY);
122           pfi_detach_group_cookie = EVENTHANDLER_REGISTER(group_detach_event,
123               pfi_detach_group_event, NULL, EVENTHANDLER_PRI_ANY);
124           pfi_change_group_cookie = EVENTHANDLER_REGISTER(group_change_event,
125               pfi_change_group_event, NULL, EVENTHANDLER_PRI_ANY);
126           pfi_ifaddr_event_cookie = EVENTHANDLER_REGISTER(ifaddr_event,
127               pfi_ifaddr_event, NULL, EVENTHANDLER_PRI_ANY);
128 
129           pfi_buffer_max = 64;
130           pfi_buffer = kmalloc(pfi_buffer_max * sizeof(*pfi_buffer),
131               M_PFI, M_WAITOK);
132 
133           if ((pfi_all = pfi_kif_get(IFG_ALL)) == NULL)
134                     panic("%s: pfi_kif_get(IFG_ALL) failed", __func__);
135 
136           ifgroup_lockmgr(LK_SHARED);
137           TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
138                     pfi_attach_ifgroup(ifg);
139           ifgroup_lockmgr(LK_RELEASE);
140 
141           /* XXX ALMOST MPSAFE */
142           ifnet_lock();
143           TAILQ_FOREACH(ifp, &ifnetlist, if_link)
144                     pfi_attach_ifnet(ifp);
145           ifnet_unlock();
146 }
147 
148 void
pfi_cleanup(void)149 pfi_cleanup(void)
150 {
151           struct pfi_kif *kif;
152 
153           while ((kif = RB_MIN(pfi_ifhead, &pfi_ifs))) {
154                     RB_REMOVE(pfi_ifhead, &pfi_ifs, kif);
155                     if (kif->pfik_group)
156                               kif->pfik_group->ifg_pf_kif = NULL;
157                     if (kif->pfik_ifp)
158                               kif->pfik_ifp->if_pf_kif = NULL;
159                     kfree(kif, M_PFI);
160           }
161           kfree(pfi_buffer, M_PFI);
162           pfi_buffer = NULL;
163           pfi_all = NULL;
164 
165           EVENTHANDLER_DEREGISTER(ifnet_attach_event, pfi_attach_cookie);
166           EVENTHANDLER_DEREGISTER(ifnet_detach_event, pfi_detach_cookie);
167           EVENTHANDLER_DEREGISTER(group_attach_event, pfi_attach_group_cookie);
168           EVENTHANDLER_DEREGISTER(group_detach_event, pfi_detach_group_cookie);
169           EVENTHANDLER_DEREGISTER(group_change_event, pfi_change_group_cookie);
170           EVENTHANDLER_DEREGISTER(ifaddr_event, pfi_ifaddr_event_cookie);
171 }
172 
173 struct pfi_kif *
pfi_kif_find(const char * kif_name)174 pfi_kif_find(const char *kif_name)
175 {
176           struct pfi_kif_cmp s;
177 
178           bzero(&s, sizeof(s));
179           strlcpy(s.pfik_name, kif_name, sizeof(s.pfik_name));
180 
181           return (RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&s));
182 }
183 
184 struct pfi_kif *
pfi_kif_get(const char * kif_name)185 pfi_kif_get(const char *kif_name)
186 {
187           struct pfi_kif *kif;
188 
189           if ((kif = pfi_kif_find(kif_name)))
190                     return (kif);
191 
192           /*
193            * Create a new one
194            */
195           kif = kmalloc(sizeof(*kif), M_PFI, M_WAITOK | M_ZERO);
196           strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name));
197           kif->pfik_tzero = time_second;
198           TAILQ_INIT(&kif->pfik_dynaddrs);
199 
200           RB_INSERT(pfi_ifhead, &pfi_ifs, kif);
201           return (kif);
202 }
203 
204 void
pfi_kif_ref(struct pfi_kif * kif,enum pfi_kif_refs what)205 pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what)
206 {
207           switch (what) {
208           case PFI_KIF_REF_RULE:
209                     kif->pfik_rules++;
210                     break;
211           case PFI_KIF_REF_STATE:
212                     kif->pfik_states++;
213                     break;
214           default:
215                     panic("%s: unknown type", __func__);
216           }
217 }
218 
219 void
pfi_kif_unref(struct pfi_kif * kif,enum pfi_kif_refs what)220 pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what)
221 {
222           if (kif == NULL)
223                     return;
224 
225           switch (what) {
226           case PFI_KIF_REF_NONE:
227                     break;
228           case PFI_KIF_REF_RULE:
229                     if (kif->pfik_rules <= 0) {
230                               kprintf("%s: rules refcount <= 0\n", __func__);
231                               return;
232                     }
233                     kif->pfik_rules--;
234                     break;
235           case PFI_KIF_REF_STATE:
236                     if (kif->pfik_states <= 0) {
237                               kprintf("%s: state refcount <= 0\n", __func__);
238                               return;
239                     }
240                     kif->pfik_states--;
241                     break;
242           default:
243                     panic("%s: unknown type", __func__);
244           }
245 
246           if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all)
247                     return;
248 
249           if (kif->pfik_rules || kif->pfik_states)
250                     return;
251 
252           RB_REMOVE(pfi_ifhead, &pfi_ifs, kif);
253           kfree(kif, M_PFI);
254 }
255 
256 int
pfi_kif_match(struct pfi_kif * rule_kif,struct pfi_kif * packet_kif)257 pfi_kif_match(struct pfi_kif *rule_kif, struct pfi_kif *packet_kif)
258 {
259           struct ifg_list     *p;
260 
261           if (rule_kif == NULL || rule_kif == packet_kif)
262                     return (1);
263 
264           if (rule_kif->pfik_group != NULL) {
265                     ifgroup_lockmgr(LK_SHARED);
266                     TAILQ_FOREACH(p, &packet_kif->pfik_ifp->if_groups, ifgl_next) {
267                               if (p->ifgl_group == rule_kif->pfik_group) {
268                                         ifgroup_lockmgr(LK_RELEASE);
269                                         return (1);
270                               }
271                     }
272                     ifgroup_lockmgr(LK_RELEASE);
273           }
274 
275           return (0);
276 }
277 
278 void
pfi_attach_ifnet(struct ifnet * ifp)279 pfi_attach_ifnet(struct ifnet *ifp)
280 {
281           struct pfi_kif *kif;
282 
283           if (ifp->if_dunit == IF_DUNIT_NONE)
284                     return;
285 
286           crit_enter();
287           pfi_update++;
288           if ((kif = pfi_kif_get(ifp->if_xname)) == NULL)
289                     panic("%s: pfi_kif_get failed", __func__);
290           kif->pfik_ifp = ifp;
291           ifp->if_pf_kif = kif;
292           pfi_kif_update(kif);
293           crit_exit();
294 }
295 
296 void
pfi_detach_ifnet(struct ifnet * ifp)297 pfi_detach_ifnet(struct ifnet *ifp)
298 {
299           struct pfi_kif *kif;
300 
301           if ((kif = (struct pfi_kif *)ifp->if_pf_kif) == NULL)
302                     return;
303 
304           crit_enter();
305           pfi_update++;
306           pfi_kif_update(kif);
307           kif->pfik_ifp = NULL;
308           ifp->if_pf_kif = NULL;
309           pfi_kif_unref(kif, PFI_KIF_REF_NONE);
310           crit_exit();
311 }
312 
313 void
pfi_attach_ifgroup(struct ifg_group * ifg)314 pfi_attach_ifgroup(struct ifg_group *ifg)
315 {
316           struct pfi_kif *kif;
317 
318           crit_enter();
319           pfi_update++;
320           if ((kif = pfi_kif_get(ifg->ifg_group)) == NULL)
321                     panic("%s: pfi_kif_get failed", __func__);
322           kif->pfik_group = ifg;
323           ifg->ifg_pf_kif = kif;
324           crit_exit();
325 }
326 
327 void
pfi_detach_ifgroup(struct ifg_group * ifg)328 pfi_detach_ifgroup(struct ifg_group *ifg)
329 {
330           struct pfi_kif *kif;
331 
332           if ((kif = (struct pfi_kif *)ifg->ifg_pf_kif) == NULL)
333                     return;
334 
335           crit_enter();
336           pfi_update++;
337           kif->pfik_group = NULL;
338           ifg->ifg_pf_kif = NULL;
339           pfi_kif_unref(kif, PFI_KIF_REF_NONE);
340           crit_exit();
341 }
342 
343 void
pfi_group_change(const char * group)344 pfi_group_change(const char *group)
345 {
346           struct pfi_kif *kif;
347 
348           crit_enter();
349           pfi_update++;
350           if ((kif = pfi_kif_get(group)) == NULL)
351                     panic("%s: pfi_kif_get failed", __func__);
352           pfi_kif_update(kif);
353           crit_exit();
354 }
355 
356 int
pfi_match_addr(struct pfi_dynaddr * dyn,struct pf_addr * a,sa_family_t af)357 pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af)
358 {
359           switch (af) {
360 #ifdef INET
361           case AF_INET:
362                     switch (dyn->pfid_acnt4) {
363                     case 0:
364                               return (0);
365                     case 1:
366                               return (PF_MATCHA(0, &dyn->pfid_addr4,
367                                   &dyn->pfid_mask4, a, AF_INET));
368                     default:
369                               return (pfr_match_addr(dyn->pfid_kt, a, AF_INET));
370                     }
371                     break;
372 #endif /* INET */
373 #ifdef INET6
374           case AF_INET6:
375                     switch (dyn->pfid_acnt6) {
376                     case 0:
377                               return (0);
378                     case 1:
379                               return (PF_MATCHA(0, &dyn->pfid_addr6,
380                                   &dyn->pfid_mask6, a, AF_INET6));
381                     default:
382                               return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6));
383                     }
384                     break;
385 #endif /* INET6 */
386           default:
387                     return (0);
388           }
389 }
390 
391 int
pfi_dynaddr_setup(struct pf_addr_wrap * aw,sa_family_t af)392 pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
393 {
394           struct pfi_dynaddr  *dyn;
395           char                           tblname[PF_TABLE_NAME_SIZE];
396           struct pf_ruleset   *ruleset = NULL;
397           int                            rv = 0;
398 
399           if (aw->type != PF_ADDR_DYNIFTL)
400                     return (0);
401           if ((dyn = kmalloc(sizeof(struct pfi_dynaddr), M_PFI,
402                                  M_WAITOK | M_NULLOK | M_ZERO)) == NULL) {
403                     return (1);
404           }
405 
406           crit_enter();
407           if (strcmp(aw->v.ifname, "self") == 0)
408                     dyn->pfid_kif = pfi_kif_get(IFG_ALL);
409           else
410                     dyn->pfid_kif = pfi_kif_get(aw->v.ifname);
411           if (dyn->pfid_kif == NULL) {
412                     rv = 1;
413                     goto _bad;
414           }
415           pfi_kif_ref(dyn->pfid_kif, PFI_KIF_REF_RULE);
416 
417           dyn->pfid_net = pfi_unmask(&aw->v.a.mask);
418           if (af == AF_INET && dyn->pfid_net == 32)
419                     dyn->pfid_net = 128;
420           strlcpy(tblname, aw->v.ifname, sizeof(tblname));
421           if (aw->iflags & PFI_AFLAG_NETWORK)
422                     strlcat(tblname, ":network", sizeof(tblname));
423           if (aw->iflags & PFI_AFLAG_BROADCAST)
424                     strlcat(tblname, ":broadcast", sizeof(tblname));
425           if (aw->iflags & PFI_AFLAG_PEER)
426                     strlcat(tblname, ":peer", sizeof(tblname));
427           if (aw->iflags & PFI_AFLAG_NOALIAS)
428                     strlcat(tblname, ":0", sizeof(tblname));
429           if (dyn->pfid_net != 128)
430                     ksnprintf(tblname + strlen(tblname),
431                         sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net);
432           if ((ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR)) == NULL) {
433                     rv = 1;
434                     goto _bad;
435           }
436 
437           if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname)) == NULL) {
438                     rv = 1;
439                     goto _bad;
440           }
441 
442           dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE;
443           dyn->pfid_iflags = aw->iflags;
444           dyn->pfid_af = af;
445 
446           TAILQ_INSERT_TAIL(&dyn->pfid_kif->pfik_dynaddrs, dyn, entry);
447           aw->p.dyn = dyn;
448           pfi_kif_update(dyn->pfid_kif);
449           crit_exit();
450           return (0);
451 
452 _bad:
453           if (dyn->pfid_kt != NULL)
454                     pfr_detach_table(dyn->pfid_kt);
455           if (ruleset != NULL)
456                     pf_remove_if_empty_ruleset(ruleset);
457           if (dyn->pfid_kif != NULL)
458                     pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE);
459           kfree(dyn, M_PFI);
460           crit_exit();
461           return (rv);
462 }
463 
464 static void
pfi_kif_update(struct pfi_kif * kif)465 pfi_kif_update(struct pfi_kif *kif)
466 {
467           struct ifg_list               *ifgl;
468           struct pfi_dynaddr  *p;
469 
470           /* update all dynaddr */
471           TAILQ_FOREACH(p, &kif->pfik_dynaddrs, entry)
472                     pfi_dynaddr_update(p);
473 
474           /* and for all groups that the kif belongs to */
475           if (kif->pfik_ifp != NULL) {
476                     ifgroup_lockmgr(LK_SHARED);
477                     TAILQ_FOREACH(ifgl, &kif->pfik_ifp->if_groups, ifgl_next) {
478                               pfi_kif_update((struct pfi_kif *)
479                                   ifgl->ifgl_group->ifg_pf_kif);
480                     }
481                     ifgroup_lockmgr(LK_RELEASE);
482           }
483 }
484 
485 static void
pfi_dynaddr_update(struct pfi_dynaddr * dyn)486 pfi_dynaddr_update(struct pfi_dynaddr *dyn)
487 {
488           struct pfi_kif                *kif;
489           struct pfr_ktable   *kt;
490 
491           if (dyn == NULL || dyn->pfid_kif == NULL || dyn->pfid_kt == NULL)
492                     panic("%s: bad argument", __func__);
493 
494           kif = dyn->pfid_kif;
495           kt = dyn->pfid_kt;
496 
497           if (kt->pfrkt_larg != pfi_update) {
498                     /* this table needs to be brought up-to-date */
499                     pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags);
500                     kt->pfrkt_larg = pfi_update;
501           }
502           pfr_dynaddr_update(kt, dyn);
503 }
504 
505 static void
pfi_table_update(struct pfr_ktable * kt,struct pfi_kif * kif,int net,int flags)506 pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags)
507 {
508           int                            e, size2 = 0;
509           struct ifg_member   *ifgm;
510 
511           pfi_buffer_cnt = 0;
512 
513           if (kif->pfik_ifp != NULL) {
514                     pfi_instance_add(kif->pfik_ifp, net, flags);
515           } else if (kif->pfik_group != NULL) {
516                     ifgroup_lockmgr(LK_SHARED);
517                     TAILQ_FOREACH(ifgm, &kif->pfik_group->ifg_members, ifgm_next)
518                               pfi_instance_add(ifgm->ifgm_ifp, net, flags);
519                     ifgroup_lockmgr(LK_RELEASE);
520           }
521 
522           if ((e = pfr_set_addrs(&kt->pfrkt_t, pfi_buffer, pfi_buffer_cnt,
523                                      &size2, NULL, NULL, NULL, 0,
524                                      PFR_TFLAG_ALLMASK))) {
525                     kprintf("%s: cannot set %d new addresses into table %s: %d\n",
526                         __func__, pfi_buffer_cnt, kt->pfrkt_name, e);
527           }
528 }
529 
530 
531 struct netmsg_pfiadd {
532           struct netmsg_base  base;
533           struct ifnet                  *ifp;
534           int                           net;
535           int                           flags;
536 };
537 
538 static void
pfi_instance_add_dispatch(netmsg_t nmsg)539 pfi_instance_add_dispatch(netmsg_t nmsg)
540 {
541           struct netmsg_pfiadd *msg = (struct netmsg_pfiadd *)nmsg;
542           struct ifaddr_container *ifac;
543           int got4 = 0, got6 = 0;
544           int net2, af;
545           struct ifnet *ifp = msg->ifp;
546           int net = msg->net, flags = msg->flags;
547 
548           if (ifp == NULL)
549                     goto done;
550           /*
551            * The ifaddr processing in the following loop will block,
552            * however, this function is called in netisr0, in which
553            * ifaddr list changes happen, so we don't care about the
554            * blockness of the ifaddr processing here.
555            */
556           TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) {
557                     struct ifaddr *ia = ifac->ifa;
558 
559                     if (ia->ifa_addr == NULL)
560                               continue;
561                     af = ia->ifa_addr->sa_family;
562                     if (af != AF_INET && af != AF_INET6)
563                               continue;
564                     /*
565                      * XXX: For point-to-point interfaces, (ifname:0) and IPv4,
566                      *        jump over address without a proper route to work
567                      *        around a problem with ppp not fully removing the
568                      *        address used during IPCP.
569                      */
570                     if ((ifp->if_flags & IFF_POINTOPOINT) &&
571                         !(ia->ifa_flags & IFA_ROUTE) &&
572                         (flags & PFI_AFLAG_NOALIAS) && (af == AF_INET))
573                               continue;
574                     if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6)
575                               continue;
576                     if ((flags & PFI_AFLAG_BROADCAST) &&
577                         !(ifp->if_flags & IFF_BROADCAST))
578                               continue;
579                     if ((flags & PFI_AFLAG_PEER) &&
580                         !(ifp->if_flags & IFF_POINTOPOINT))
581                               continue;
582                     if ((flags & (PFI_AFLAG_NETWORK | PFI_AFLAG_NOALIAS)) &&
583                         af == AF_INET6 &&
584                         IN6_IS_ADDR_LINKLOCAL(
585                         &((struct sockaddr_in6 *)ia->ifa_addr)->sin6_addr))
586                               continue;
587                     if (flags & PFI_AFLAG_NOALIAS) {
588                               if (af == AF_INET && got4)
589                                         continue;
590                               if (af == AF_INET6 && got6)
591                                         continue;
592                     }
593                     if (af == AF_INET)
594                               got4 = 1;
595                     else if (af == AF_INET6)
596                               got6 = 1;
597                     net2 = net;
598                     if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) {
599                               if (af == AF_INET)
600                                         net2 = pfi_unmask(&((struct sockaddr_in *)
601                                             ia->ifa_netmask)->sin_addr);
602                               else if (af == AF_INET6)
603                                         net2 = pfi_unmask(&((struct sockaddr_in6 *)
604                                             ia->ifa_netmask)->sin6_addr);
605                     }
606                     if (af == AF_INET && net2 > 32)
607                               net2 = 32;
608                     if (flags & PFI_AFLAG_BROADCAST)
609                               pfi_address_add(ia->ifa_broadaddr, af, net2);
610                     else if (flags & PFI_AFLAG_PEER)
611                               pfi_address_add(ia->ifa_dstaddr, af, net2);
612                     else
613                               pfi_address_add(ia->ifa_addr, af, net2);
614           }
615 done:
616           netisr_replymsg(&nmsg->base, 0);
617 }
618 
619 static void
pfi_instance_add(struct ifnet * ifp,int net,int flags)620 pfi_instance_add(struct ifnet *ifp, int net, int flags)
621 {
622           struct netmsg_pfiadd msg;
623 
624           netmsg_init(&msg.base, NULL, &curthread->td_msgport, 0,
625               pfi_instance_add_dispatch);
626           msg.ifp = ifp;
627           msg.net = net;
628           msg.flags = flags;
629           netisr_domsg(&msg.base, 0);
630 }
631 
632 static void
pfi_address_add(struct sockaddr * sa,int af,int net)633 pfi_address_add(struct sockaddr *sa, int af, int net)
634 {
635           struct pfr_addr     *p;
636           int                  i;
637 
638           if (pfi_buffer_cnt >= pfi_buffer_max) {
639                     int                  new_max = pfi_buffer_max * 2;
640 
641                     if (new_max > PFI_BUFFER_MAX) {
642                               kprintf("%s: address buffer full (%d/%d)\n", __func__,
643                                   pfi_buffer_cnt, PFI_BUFFER_MAX);
644                               return;
645                     }
646                     p = kmalloc(new_max * sizeof(*pfi_buffer), M_PFI, M_WAITOK);
647                     memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer));
648                     /* no need to zero buffer */
649                     kfree(pfi_buffer, M_PFI);
650                     pfi_buffer = p;
651                     pfi_buffer_max = new_max;
652           }
653           if (af == AF_INET && net > 32)
654                     net = 128;
655           p = pfi_buffer + pfi_buffer_cnt++;
656           bzero(p, sizeof(*p));
657           p->pfra_af = af;
658           p->pfra_net = net;
659           if (af == AF_INET)
660                     p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr;
661           else if (af == AF_INET6) {
662                     p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr;
663                     if (IN6_IS_SCOPE_EMBED(&p->pfra_ip6addr))
664                               p->pfra_ip6addr.s6_addr16[1] = 0;
665           }
666           /* mask network address bits */
667           if (net < 128)
668                     ((caddr_t)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8));
669           for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++)
670                     ((caddr_t)p)[i] = 0;
671 }
672 
673 void
pfi_dynaddr_remove(struct pf_addr_wrap * aw)674 pfi_dynaddr_remove(struct pf_addr_wrap *aw)
675 {
676           if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL ||
677               aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL)
678                     return;
679 
680           crit_enter();
681           TAILQ_REMOVE(&aw->p.dyn->pfid_kif->pfik_dynaddrs, aw->p.dyn, entry);
682           pfi_kif_unref(aw->p.dyn->pfid_kif, PFI_KIF_REF_RULE);
683           aw->p.dyn->pfid_kif = NULL;
684           pfr_detach_table(aw->p.dyn->pfid_kt);
685           aw->p.dyn->pfid_kt = NULL;
686           kfree(aw->p.dyn, M_PFI);
687           aw->p.dyn = NULL;
688           crit_exit();
689 }
690 
691 void
pfi_dynaddr_copyout(struct pf_addr_wrap * aw)692 pfi_dynaddr_copyout(struct pf_addr_wrap *aw)
693 {
694           if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL ||
695               aw->p.dyn->pfid_kif == NULL)
696                     return;
697           aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6;
698 }
699 
700 static int
pfi_if_compare(struct pfi_kif * p,struct pfi_kif * q)701 pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q)
702 {
703           return (strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ));
704 }
705 
706 void
pfi_update_status(const char * name,struct pf_status * pfs)707 pfi_update_status(const char *name, struct pf_status *pfs)
708 {
709           struct pfi_kif                *p;
710           struct pfi_kif_cmp   key;
711           struct ifg_member    p_member, *ifgm;
712           TAILQ_HEAD(, ifg_member) ifg_members;
713           int                            i, j, k;
714 
715           strlcpy(key.pfik_name, name, sizeof(key.pfik_name));
716           crit_enter();
717           p = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&key);
718           if (p == NULL) {
719                     crit_exit();
720                     return;
721           }
722           if (p->pfik_group != NULL) {
723                     bcopy(&p->pfik_group->ifg_members, &ifg_members,
724                         sizeof(ifg_members));
725           } else {
726                     /* build a temporary list for p only */
727                     bzero(&p_member, sizeof(p_member));
728                     p_member.ifgm_ifp = p->pfik_ifp;
729                     TAILQ_INIT(&ifg_members);
730                     TAILQ_INSERT_TAIL(&ifg_members, &p_member, ifgm_next);
731           }
732           if (pfs) {
733                     bzero(pfs->pcounters, sizeof(pfs->pcounters));
734                     bzero(pfs->bcounters, sizeof(pfs->bcounters));
735           }
736           ifgroup_lockmgr(LK_SHARED);
737           TAILQ_FOREACH(ifgm, &ifg_members, ifgm_next) {
738                     if (ifgm->ifgm_ifp == NULL ||
739                         ifgm->ifgm_ifp->if_pf_kif == NULL)
740                               continue;
741                     p = (struct pfi_kif *)ifgm->ifgm_ifp->if_pf_kif;
742 
743                     /* just clear statistics */
744                     if (pfs == NULL) {
745                               bzero(p->pfik_packets, sizeof(p->pfik_packets));
746                               bzero(p->pfik_bytes, sizeof(p->pfik_bytes));
747                               p->pfik_tzero = time_second;
748                               continue;
749                     }
750                     for (i = 0; i < 2; i++)
751                               for (j = 0; j < 2; j++)
752                                         for (k = 0; k < 2; k++) {
753                                                   pfs->pcounters[i][j][k] +=
754                                                             p->pfik_packets[i][j][k];
755                                                   pfs->bcounters[i][j] +=
756                                                             p->pfik_bytes[i][j][k];
757                                         }
758           }
759           ifgroup_lockmgr(LK_RELEASE);
760           crit_exit();
761 }
762 
763 int
pfi_get_ifaces(const char * name,struct pfi_kif * buf,int * size)764 pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size)
765 {
766           struct pfi_kif      *p, *nextp;
767           int                  n = 0;
768 
769           crit_enter();
770           for (p = RB_MIN(pfi_ifhead, &pfi_ifs); p; p = nextp) {
771                     nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
772                     if (pfi_skip_if(name, p))
773                               continue;
774                     if (*size > n++) {
775                               if (!p->pfik_tzero)
776                                         p->pfik_tzero = time_second;
777                               pfi_kif_ref(p, PFI_KIF_REF_RULE);
778                               if (copyout(p, buf++, sizeof(*buf))) {
779                                         pfi_kif_unref(p, PFI_KIF_REF_RULE);
780                                         crit_exit();
781                                         return (EFAULT);
782                               }
783                               nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
784                               pfi_kif_unref(p, PFI_KIF_REF_RULE);
785                     }
786           }
787           crit_exit();
788           *size = n;
789           return (0);
790 }
791 
792 static int
pfi_skip_if(const char * filter,struct pfi_kif * p)793 pfi_skip_if(const char *filter, struct pfi_kif *p)
794 {
795           struct ifg_list *ifg;
796           int                n;
797 
798           if (filter == NULL || !*filter)
799                     return (0);
800           if (strcmp(p->pfik_name, filter) == 0)
801                     return (0);         /* exact match */
802           n = strlen(filter);
803           if (n < 1 || n >= IFNAMSIZ)
804                     return (1);         /* sanity check */
805           if (filter[n-1] >= '0' && filter[n-1] <= '9')
806                     return (1);         /* group names may not end in a digit */
807           if (p->pfik_ifp != NULL) {
808                     ifgroup_lockmgr(LK_SHARED);
809                     TAILQ_FOREACH(ifg, &p->pfik_ifp->if_groups, ifgl_next) {
810                               if (strcmp(ifg->ifgl_group->ifg_group, filter) == 0) {
811                                         ifgroup_lockmgr(LK_RELEASE);
812                                         return (0); /* iface is in group "filter" */
813                               }
814                     }
815                     ifgroup_lockmgr(LK_RELEASE);
816           }
817           return (1);
818 }
819 
820 int
pfi_set_flags(const char * name,int flags)821 pfi_set_flags(const char *name, int flags)
822 {
823           struct pfi_kif      *p;
824 
825           crit_enter();
826           RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
827                     if (pfi_skip_if(name, p))
828                               continue;
829                     p->pfik_flags |= flags;
830           }
831           crit_exit();
832           return (0);
833 }
834 
835 int
pfi_clear_flags(const char * name,int flags)836 pfi_clear_flags(const char *name, int flags)
837 {
838           struct pfi_kif      *p;
839 
840           crit_enter();
841           RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
842                     if (pfi_skip_if(name, p))
843                               continue;
844                     p->pfik_flags &= ~flags;
845           }
846           crit_exit();
847           return (0);
848 }
849 
850 /* from pf_print_state.c */
851 static int
pfi_unmask(void * addr)852 pfi_unmask(void *addr)
853 {
854           struct pf_addr *m = addr;
855           int i = 31, j = 0, b = 0;
856           u_int32_t tmp;
857 
858           while (j < 4 && m->addr32[j] == 0xffffffff) {
859                     b += 32;
860                     j++;
861           }
862           if (j < 4) {
863                     tmp = ntohl(m->addr32[j]);
864                     for (i = 31; tmp & (1 << i); --i)
865                               b++;
866           }
867           return (b);
868 }
869 
870 
871 /*
872  * eventhandler events
873  */
874 
875 static void
pfi_attach_ifnet_event(void * arg __unused,struct ifnet * ifp)876 pfi_attach_ifnet_event(void *arg __unused, struct ifnet *ifp)
877 {
878           pfi_attach_ifnet(ifp);
879 }
880 
881 static void
pfi_detach_ifnet_event(void * arg __unused,struct ifnet * ifp)882 pfi_detach_ifnet_event(void *arg __unused, struct ifnet *ifp)
883 {
884           pfi_detach_ifnet(ifp);
885 }
886 
887 static void
pfi_attach_group_event(void * arg __unused,struct ifg_group * ifg)888 pfi_attach_group_event(void *arg __unused, struct ifg_group *ifg)
889 {
890           pfi_attach_ifgroup(ifg);
891 }
892 
893 static void
pfi_detach_group_event(void * arg __unused,struct ifg_group * ifg)894 pfi_detach_group_event(void *arg __unused, struct ifg_group *ifg)
895 {
896           pfi_detach_ifgroup(ifg);
897 }
898 
899 static void
pfi_change_group_event(void * arg __unused,char * gname)900 pfi_change_group_event(void *arg __unused, char *gname)
901 {
902           pfi_group_change(gname);
903 }
904 
905 static void
pfi_ifaddr_event(void * arg __unused,struct ifnet * ifp,enum ifaddr_event event __unused,struct ifaddr * ifa __unused)906 pfi_ifaddr_event(void *arg __unused, struct ifnet *ifp,
907                      enum ifaddr_event event __unused,
908                      struct ifaddr *ifa __unused)
909 {
910           if (ifp && ifp->if_pf_kif) {
911                     crit_enter();
912                     pfi_update++;
913                     pfi_kif_update(ifp->if_pf_kif);
914                     crit_exit();
915           }
916 }
917