No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dist / pf / net / if_compat.c
blob87f25e6f991529c43e17d207d57ef31930f8bc24
1 /* $OpenBSD: if.c,v 1.165 2007/07/06 14:00:59 naddy Exp $ */
2 /* $NetBSD$ */
4 /*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
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 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
34 * Copyright (c) 1980, 1986, 1993
35 * The Regents of the University of California. All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
61 * @(#)if.c 8.3 (Berkeley) 1/4/94
64 #include <sys/cdefs.h>
65 __KERNEL_RCSID(0, "$NetBSD$");
67 #include "pf.h"
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/malloc.h>
72 #include <sys/socket.h>
73 #include <sys/socketvar.h>
75 #include <net/if.h>
77 #include <netinet/in.h>
78 #include <netinet/in_var.h>
80 #include <net/if_compat.h>
82 #if NPF > 0
83 #include <net/pfvar.h>
84 #endif
86 #if 0 /* XXX unused - remove later */
87 static int if_getgroup(void *, struct ifnet *);
88 static int if_getgroupmembers(void *);
90 static int if_group_egress_build(void);
91 #endif
93 TAILQ_HEAD(, ifg_group) ifg_head = TAILQ_HEAD_INITIALIZER(ifg_head);
95 void
96 if_init_groups(struct ifnet *ifp)
98 struct ifg_list_head *ifgh;
100 ifgh = malloc(sizeof(struct ifg_list_head), M_TEMP, M_WAITOK);
101 TAILQ_INIT(ifgh);
103 ifp->if_pf_groups = ifgh;
106 void
107 if_destroy_groups(struct ifnet *ifp)
109 struct ifg_list_head *ifgh = if_get_groups(ifp);
111 free(ifgh, M_TEMP);
114 struct ifg_list_head *
115 if_get_groups(struct ifnet *ifp)
117 return (ifp->if_pf_groups);
121 * Create interface group without members.
123 struct ifg_group *
124 if_creategroup(const char *groupname)
126 struct ifg_group *ifg = NULL;
128 if ((ifg = (struct ifg_group *)malloc(sizeof(struct ifg_group),
129 M_TEMP, M_NOWAIT)) == NULL)
130 return (NULL);
132 strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group));
133 ifg->ifg_refcnt = 0;
134 ifg->ifg_carp_demoted = 0;
135 TAILQ_INIT(&ifg->ifg_members);
136 #if NPF > 0
137 pfi_attach_ifgroup(ifg);
138 #endif
139 TAILQ_INSERT_TAIL(&ifg_head, ifg, ifg_next);
141 return (ifg);
145 * Add a group to an interface.
148 if_addgroup(struct ifnet *ifp, const char *groupname)
150 struct ifg_list_head *ifgh = if_get_groups(ifp);
151 struct ifg_list *ifgl;
152 struct ifg_group *ifg = NULL;
153 struct ifg_member *ifgm;
155 if (groupname[0] && groupname[strlen(groupname) - 1] >= '0' &&
156 groupname[strlen(groupname) - 1] <= '9')
157 return (EINVAL);
159 TAILQ_FOREACH(ifgl, ifgh, ifgl_next)
160 if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
161 return (EEXIST);
163 if ((ifgl = (struct ifg_list *)malloc(sizeof(struct ifg_list), M_TEMP,
164 M_NOWAIT)) == NULL)
165 return (ENOMEM);
167 if ((ifgm = (struct ifg_member *)malloc(sizeof(struct ifg_member),
168 M_TEMP, M_NOWAIT)) == NULL) {
169 free(ifgl, M_TEMP);
170 return (ENOMEM);
173 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
174 if (!strcmp(ifg->ifg_group, groupname))
175 break;
177 if (ifg == NULL && (ifg = if_creategroup(groupname)) == NULL) {
178 free(ifgl, M_TEMP);
179 free(ifgm, M_TEMP);
180 return (ENOMEM);
183 ifg->ifg_refcnt++;
184 ifgl->ifgl_group = ifg;
185 ifgm->ifgm_ifp = ifp;
187 TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next);
188 TAILQ_INSERT_TAIL(ifgh, ifgl, ifgl_next);
190 #if NPF > 0
191 pfi_group_change(groupname);
192 #endif
194 return (0);
198 * Remove a group from an interface.
201 if_delgroup(struct ifnet *ifp, const char *groupname)
203 struct ifg_list_head *ifgh = if_get_groups(ifp);
204 struct ifg_list *ifgl;
205 struct ifg_member *ifgm;
207 TAILQ_FOREACH(ifgl, ifgh, ifgl_next)
208 if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
209 break;
210 if (ifgl == NULL)
211 return (ENOENT);
213 TAILQ_REMOVE(ifgh, ifgl, ifgl_next);
215 TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
216 if (ifgm->ifgm_ifp == ifp)
217 break;
219 if (ifgm != NULL) {
220 TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next);
221 free(ifgm, M_TEMP);
224 if (--ifgl->ifgl_group->ifg_refcnt == 0) {
225 TAILQ_REMOVE(&ifg_head, ifgl->ifgl_group, ifg_next);
226 #if NPF > 0
227 pfi_detach_ifgroup(ifgl->ifgl_group);
228 #endif
229 free(ifgl->ifgl_group, M_TEMP);
232 free(ifgl, M_TEMP);
234 #if NPF > 0
235 pfi_group_change(groupname);
236 #endif
238 return (0);
241 #if 0
243 * Stores all groups from an interface in memory pointed
244 * to by data.
246 static int
247 if_getgroup(void *data, struct ifnet *ifp)
249 int len, error;
250 struct ifg_list_head *ifgh = if_get_groups(ifp);
251 struct ifg_list *ifgl;
252 struct ifg_req ifgrq, *ifgp;
253 struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
255 if (ifgr->ifgr_len == 0) {
256 TAILQ_FOREACH(ifgl, ifgh, ifgl_next)
257 ifgr->ifgr_len += sizeof(struct ifg_req);
258 return (0);
261 len = ifgr->ifgr_len;
262 ifgp = ifgr->ifgr_groups;
263 TAILQ_FOREACH(ifgl, ifgh, ifgl_next) {
264 if (len < sizeof(ifgrq))
265 return (EINVAL);
266 bzero(&ifgrq, sizeof ifgrq);
267 strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group,
268 sizeof(ifgrq.ifgrq_group));
269 if ((error = copyout(&ifgrq, ifgp, sizeof(struct ifg_req))))
270 return (error);
271 len -= sizeof(ifgrq);
272 ifgp++;
275 return (0);
279 * Stores all members of a group in memory pointed to by data.
281 static int
282 if_getgroupmembers(void *data)
284 struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
285 struct ifg_group *ifg;
286 struct ifg_member *ifgm;
287 struct ifg_req ifgrq, *ifgp;
288 int len, error;
290 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
291 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
292 break;
293 if (ifg == NULL)
294 return (ENOENT);
296 if (ifgr->ifgr_len == 0) {
297 TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
298 ifgr->ifgr_len += sizeof(ifgrq);
299 return (0);
302 len = ifgr->ifgr_len;
303 ifgp = ifgr->ifgr_groups;
304 TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) {
305 if (len < sizeof(ifgrq))
306 return (EINVAL);
307 bzero(&ifgrq, sizeof ifgrq);
308 strlcpy(ifgrq.ifgrq_member, ifgm->ifgm_ifp->if_xname,
309 sizeof(ifgrq.ifgrq_member));
310 if ((error = copyout(&ifgrq, ifgp, sizeof(struct ifg_req))))
311 return (error);
312 len -= sizeof(ifgrq);
313 ifgp++;
316 return (0);
319 void
320 if_group_routechange(struct sockaddr *dst, struct sockaddr *mask)
322 switch (dst->sa_family) {
323 case AF_INET:
324 if (satosin(dst)->sin_addr.s_addr == INADDR_ANY)
325 if_group_egress_build();
326 break;
327 #ifdef INET6
328 case AF_INET6:
329 if (IN6_ARE_ADDR_EQUAL(&(satosin6(dst))->sin6_addr,
330 &in6addr_any) &&
331 mask && IN6_ARE_ADDR_EQUAL(&(satosin6(mask))->sin6_addr,
332 &in6addr_any))
333 if_group_egress_build();
334 break;
335 #endif
339 static int
340 if_group_egress_build(void)
342 struct ifg_group *ifg;
343 struct ifg_member *ifgm, *next;
344 struct sockaddr_in sa_in;
345 #ifdef INET6
346 struct sockaddr_in6 sa_in6;
347 #endif
348 struct radix_node *rn;
349 struct rtentry *rt;
351 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
352 if (!strcmp(ifg->ifg_group, IFG_EGRESS))
353 break;
355 if (ifg != NULL)
356 for (ifgm = TAILQ_FIRST(&ifg->ifg_members); ifgm; ifgm = next) {
357 next = TAILQ_NEXT(ifgm, ifgm_next);
358 if_delgroup(ifgm->ifgm_ifp, IFG_EGRESS);
361 bzero(&sa_in, sizeof(sa_in));
362 sa_in.sin_len = sizeof(sa_in);
363 sa_in.sin_family = AF_INET;
364 if ((rn = rt_lookup(sintosa(&sa_in), sintosa(&sa_in), 0)) != NULL) {
365 do {
366 rt = (struct rtentry *)rn;
367 if (rt->rt_ifp)
368 if_addgroup(rt->rt_ifp, IFG_EGRESS);
369 #ifndef SMALL_KERNEL
370 rn = rn_mpath_next(rn);
371 #else
372 rn = NULL;
373 #endif
374 } while (rn != NULL);
377 #ifdef INET6
378 bcopy(&sa6_any, &sa_in6, sizeof(sa_in6));
379 if ((rn = rt_lookup(sin6tosa(&sa_in6), sin6tosa(&sa_in6), 0)) != NULL) {
380 do {
381 rt = (struct rtentry *)rn;
382 if (rt->rt_ifp)
383 if_addgroup(rt->rt_ifp, IFG_EGRESS);
384 #ifndef SMALL_KERNEL
385 rn = rn_mpath_next(rn);
386 #else
387 rn = NULL;
388 #endif
389 } while (rn != NULL);
391 #endif
393 return (0);
395 #endif