Deleted Added
sdiff udiff text old ( 130611 ) new ( 130613 )
full compact
1/* $OpenBSD: pf_if.c,v 1.11 2004/03/15 11:38:23 cedric Exp $ */
2
3/*
4 * Copyright (c) 2001 Daniel Hartmeier
5 * Copyright (c) 2003 Cedric Berger
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 16 unchanged lines hidden (view full) ---

25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/mbuf.h>
36#include <sys/filio.h>
37#include <sys/socket.h>
38#include <sys/socketvar.h>
39#include <sys/kernel.h>
40#include <sys/device.h>
41#include <sys/time.h>
42
43#include <net/if.h>
44#include <net/if_types.h>
45
46#include <netinet/in.h>
47#include <netinet/in_var.h>
48#include <netinet/in_systm.h>

--- 11 unchanged lines hidden (view full) ---

60 if ((flags & ~(oklist)) & \
61 PFI_FLAG_ALLMASK) \
62 return (EINVAL); \
63 } while (0)
64
65#define senderr(e) do { rv = (e); goto _bad; } while (0)
66
67struct pfi_kif **pfi_index2kif;
68struct pfi_kif *pfi_self;
69int pfi_indexlim;
70struct pfi_ifhead pfi_ifs;
71struct pfi_statehead pfi_statehead;
72int pfi_ifcnt;
73struct pool pfi_addr_pl;
74long pfi_update = 1;
75struct pfr_addr *pfi_buffer;
76int pfi_buffer_cnt;
77int pfi_buffer_max;
78char pfi_reserved_anchor[PF_ANCHOR_NAME_SIZE] =
79 PF_RESERVED_ANCHOR;
80char pfi_interface_ruleset[PF_RULESET_NAME_SIZE] =
81 PF_INTERFACE_RULESET;
82
83void pfi_dynaddr_update(void *);
84void pfi_kifaddr_update(void *);
85void pfi_table_update(struct pfr_ktable *, struct pfi_kif *,
86 int, int);
87void pfi_instance_add(struct ifnet *, int, int);
88void pfi_address_add(struct sockaddr *, int, int);
89int pfi_if_compare(struct pfi_kif *, struct pfi_kif *);
90struct pfi_kif *pfi_if_create(const char *, struct pfi_kif *, int);
91void pfi_copy_group(char *, const char *, int);
92void pfi_dynamic_drivers(void);
93void pfi_newgroup(const char *, int);
94int pfi_skip_if(const char *, struct pfi_kif *, int);
95int pfi_unmask(void *);
96void pfi_dohooks(struct pfi_kif *);
97
98RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
99RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
100
101#define PFI_DYNAMIC_BUSES { "pcmcia", "cardbus", "uhub" }
102#define PFI_BUFFER_MAX 0x10000
103#define PFI_MTYPE M_IFADDR
104
105void
106pfi_initialize(void)
107{
108 if (pfi_self != NULL) /* already initialized */
109 return;
110
111 TAILQ_INIT(&pfi_statehead);
112 pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0,
113 "pfiaddrpl", &pool_allocator_nointr);
114 pfi_buffer_max = 64;
115 pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer),
116 PFI_MTYPE, M_WAITOK);
117 pfi_self = pfi_if_create("self", NULL, PFI_IFLAG_GROUP);
118 pfi_dynamic_drivers();
119}
120
121void
122pfi_attach_clone(struct if_clone *ifc)
123{
124 pfi_initialize();
125 pfi_newgroup(ifc->ifc_name, PFI_IFLAG_CLONABLE);
126}
127
128void
129pfi_attach_ifnet(struct ifnet *ifp)
130{
131 struct pfi_kif *p, *q, key;
132 int s;
133
134 pfi_initialize();
135 s = splsoftnet();
136 pfi_update++;
137 if (ifp->if_index >= pfi_indexlim) {
138 /*
139 * grow pfi_index2kif, similar to ifindex2ifnet code in if.c
140 */

--- 4 unchanged lines hidden (view full) ---

145 if (pfi_indexlim == 0)
146 pfi_indexlim = 64;
147 while (ifp->if_index >= pfi_indexlim)
148 pfi_indexlim <<= 1;
149
150 m = oldlim * sizeof(struct pfi_kif *);
151 mp = pfi_index2kif;
152 n = pfi_indexlim * sizeof(struct pfi_kif *);
153 np = malloc(n, PFI_MTYPE, M_DONTWAIT);
154 if (np == NULL)
155 panic("pfi_attach_ifnet: "
156 "cannot allocate translation table");
157 bzero(np, n);
158 if (mp != NULL)
159 bcopy(mp, np, m);
160 pfi_index2kif = np;
161 if (mp != NULL)
162 free(mp, PFI_MTYPE);
163 }
164
165 strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name));
166 p = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
167 if (p == NULL) {
168 /* add group */
169 pfi_copy_group(key.pfik_name, ifp->if_xname,
170 sizeof(key.pfik_name));
171 q = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
172 if (q == NULL)
173 q = pfi_if_create(key.pfik_name, pfi_self, PFI_IFLAG_GROUP);
174 if (q == NULL)
175 panic("pfi_attach_ifnet: "
176 "cannot allocate '%s' group", key.pfik_name);
177
178 /* add interface */
179 p = pfi_if_create(ifp->if_xname, q, PFI_IFLAG_INSTANCE);
180 if (p == NULL)
181 panic("pfi_attach_ifnet: "
182 "cannot allocate '%s' interface", ifp->if_xname);
183 } else
184 q = p->pfik_parent;
185 p->pfik_ifp = ifp;
186 p->pfik_flags |= PFI_IFLAG_ATTACHED;
187 p->pfik_ah_cookie =
188 hook_establish(ifp->if_addrhooks, 1, pfi_kifaddr_update, p);
189 pfi_index2kif[ifp->if_index] = p;
190 pfi_dohooks(p);
191 splx(s);
192}
193
194void
195pfi_detach_ifnet(struct ifnet *ifp)
196{

--- 5 unchanged lines hidden (view full) ---

202 s = splsoftnet();
203 pfi_update++;
204 p = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
205 if (p == NULL) {
206 printf("pfi_detach_ifnet: cannot find %s", ifp->if_xname);
207 splx(s);
208 return;
209 }
210 hook_disestablish(p->pfik_ifp->if_addrhooks, p->pfik_ah_cookie);
211 q = p->pfik_parent;
212 p->pfik_ifp = NULL;
213 p->pfik_flags &= ~PFI_IFLAG_ATTACHED;
214 pfi_index2kif[ifp->if_index] = NULL;
215 pfi_dohooks(p);
216 pfi_maybe_destroy(p);
217 splx(s);
218}

--- 4 unchanged lines hidden (view full) ---

223 struct pfi_kif *p, *q, key;
224 int s;
225
226 s = splsoftnet();
227 p = pfi_lookup_if(name);
228 if (p == NULL) {
229 pfi_copy_group(key.pfik_name, name, sizeof(key.pfik_name));
230 q = pfi_lookup_if(key.pfik_name);
231 if (q != NULL)
232 p = pfi_if_create(name, q, PFI_IFLAG_INSTANCE);
233 }
234 splx(s);
235 return (p);
236}
237
238struct pfi_kif *
239pfi_attach_rule(const char *name)
240{

--- 221 unchanged lines hidden (view full) ---

462 if (pfi_buffer_cnt >= pfi_buffer_max) {
463 int new_max = pfi_buffer_max * 2;
464
465 if (new_max > PFI_BUFFER_MAX) {
466 printf("pfi_address_add: address buffer full (%d/%d)\n",
467 pfi_buffer_cnt, PFI_BUFFER_MAX);
468 return;
469 }
470 p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE,
471 M_DONTWAIT);
472 if (p == NULL) {
473 printf("pfi_address_add: no memory to grow buffer "
474 "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX);
475 return;
476 }
477 memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer));
478 /* no need to zero buffer */
479 free(pfi_buffer, PFI_MTYPE);

--- 67 unchanged lines hidden (view full) ---

547 return (strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ));
548}
549
550struct pfi_kif *
551pfi_if_create(const char *name, struct pfi_kif *q, int flags)
552{
553 struct pfi_kif *p;
554
555 p = malloc(sizeof(*p), PFI_MTYPE, M_DONTWAIT);
556 if (p == NULL)
557 return (NULL);
558 bzero(p, sizeof(*p));
559 p->pfik_ah_head = malloc(sizeof(*p->pfik_ah_head), PFI_MTYPE,
560 M_DONTWAIT);
561 if (p->pfik_ah_head == NULL) {
562 free(p, PFI_MTYPE);
563 return (NULL);
564 }
565 bzero(p->pfik_ah_head, sizeof(*p->pfik_ah_head));
566 TAILQ_INIT(p->pfik_ah_head);
567 TAILQ_INIT(&p->pfik_grouphead);
568 strlcpy(p->pfik_name, name, sizeof(p->pfik_name));
569 RB_INIT(&p->pfik_lan_ext);
570 RB_INIT(&p->pfik_ext_gwy);
571 p->pfik_flags = flags;
572 p->pfik_parent = q;
573 p->pfik_tzero = time.tv_sec;
574
575 RB_INSERT(pfi_ifhead, &pfi_ifs, p);
576 if (q != NULL) {
577 q->pfik_addcnt++;
578 TAILQ_INSERT_TAIL(&q->pfik_grouphead, p, pfik_instances);
579 }
580 pfi_ifcnt++;
581 return (p);
582}
583
584int
585pfi_maybe_destroy(struct pfi_kif *p)
586{
587 int i, j, k, s;
588 struct pfi_kif *q = p->pfik_parent;
589
590 if ((p->pfik_flags & (PFI_IFLAG_ATTACHED | PFI_IFLAG_GROUP)) ||
591 p->pfik_rules > 0 || p->pfik_states > 0)
592 return (0);
593
594 s = splsoftnet();
595 if (q != NULL) {
596 for (i = 0; i < 2; i++)
597 for (j = 0; j < 2; j++)
598 for (k = 0; k < 2; k++) {
599 q->pfik_bytes[i][j][k] +=
600 p->pfik_bytes[i][j][k];
601 q->pfik_packets[i][j][k] +=
602 p->pfik_packets[i][j][k];
603 }
604 q->pfik_delcnt++;
605 TAILQ_REMOVE(&q->pfik_grouphead, p, pfik_instances);
606 }
607 pfi_ifcnt--;
608 RB_REMOVE(pfi_ifhead, &pfi_ifs, p);
609 splx(s);
610
611 free(p->pfik_ah_head, PFI_MTYPE);
612 free(p, PFI_MTYPE);
613 return (1);
614}

--- 7 unchanged lines hidden (view full) ---

622 }
623 if (m > 0)
624 *p++ = '\0';
625}
626
627void
628pfi_dynamic_drivers(void)
629{
630 char *buses[] = PFI_DYNAMIC_BUSES;
631 int nbuses = sizeof(buses)/sizeof(buses[0]);
632 int enabled[sizeof(buses)/sizeof(buses[0])];
633 struct device *dev;
634 struct cfdata *cf;
635 struct cfdriver *drv;
636 short *p;
637 int i;

--- 19 unchanged lines hidden (view full) ---

657 break;
658 if (i < nbuses) {
659 pfi_newgroup(cf->cf_driver->cd_name,
660 PFI_IFLAG_DYNAMIC);
661 break;
662 }
663 }
664 }
665}
666
667void
668pfi_newgroup(const char *name, int flags)
669{
670 struct pfi_kif *p;
671
672 p = pfi_lookup_if(name);

--- 32 unchanged lines hidden (view full) ---

705 splx(s);
706}
707
708int
709pfi_clr_istats(const char *name, int *nzero, int flags)
710{
711 struct pfi_kif *p;
712 int n = 0, s;
713 long tzero = time.tv_sec;
714
715 s = splsoftnet();
716 ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE);
717 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
718 if (pfi_skip_if(name, p, flags))
719 continue;
720 bzero(p->pfik_packets, sizeof(p->pfik_packets));
721 bzero(p->pfik_bytes, sizeof(p->pfik_bytes));

--- 6 unchanged lines hidden (view full) ---

728 return (0);
729}
730
731int
732pfi_get_ifaces(const char *name, struct pfi_if *buf, int *size, int flags)
733{
734 struct pfi_kif *p;
735 int s, n = 0;
736
737 ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE);
738 s = splsoftnet();
739 RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
740 if (pfi_skip_if(name, p, flags))
741 continue;
742 if (*size > n++) {
743 if (!p->pfik_tzero)
744 p->pfik_tzero = boottime.tv_sec;
745 if (copyout(p, buf++, sizeof(*buf))) {
746 splx(s);
747 return (EFAULT);
748 }
749 }
750 }
751 splx(s);
752 *size = n;
753 return (0);

--- 87 unchanged lines hidden ---