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