Annotation of src/sys/net/if.c, Revision 1.277
1.277 ! rmind 1: /* $NetBSD: if.c,v 1.276 2014/06/05 23:48:16 rmind Exp $ */
1.53 thorpej 2:
3: /*-
1.219 ad 4: * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
1.53 thorpej 5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
1.150 peter 8: * by William Studenmund and Jason R. Thorpe.
1.53 thorpej 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: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29: * POSSIBILITY OF SUCH DAMAGE.
30: */
1.49 itojun 31:
32: /*
33: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
34: * All rights reserved.
1.154 perry 35: *
1.49 itojun 36: * Redistribution and use in source and binary forms, with or without
37: * modification, are permitted provided that the following conditions
38: * are met:
39: * 1. Redistributions of source code must retain the above copyright
40: * notice, this list of conditions and the following disclaimer.
41: * 2. Redistributions in binary form must reproduce the above copyright
42: * notice, this list of conditions and the following disclaimer in the
43: * documentation and/or other materials provided with the distribution.
44: * 3. Neither the name of the project nor the names of its contributors
45: * may be used to endorse or promote products derived from this software
46: * without specific prior written permission.
1.154 perry 47: *
1.49 itojun 48: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
49: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
52: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58: * SUCH DAMAGE.
59: */
1.16 cgd 60:
1.1 cgd 61: /*
1.15 mycroft 62: * Copyright (c) 1980, 1986, 1993
63: * The Regents of the University of California. All rights reserved.
1.1 cgd 64: *
65: * Redistribution and use in source and binary forms, with or without
66: * modification, are permitted provided that the following conditions
67: * are met:
68: * 1. Redistributions of source code must retain the above copyright
69: * notice, this list of conditions and the following disclaimer.
70: * 2. Redistributions in binary form must reproduce the above copyright
71: * notice, this list of conditions and the following disclaimer in the
72: * documentation and/or other materials provided with the distribution.
1.126 agc 73: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 74: * may be used to endorse or promote products derived from this software
75: * without specific prior written permission.
76: *
77: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
78: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
79: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
80: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
81: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
82: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
83: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
84: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
85: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
86: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
87: * SUCH DAMAGE.
88: *
1.44 fvdl 89: * @(#)if.c 8.5 (Berkeley) 1/9/95
1.1 cgd 90: */
1.99 lukem 91:
92: #include <sys/cdefs.h>
1.277 ! rmind 93: __KERNEL_RCSID(0, "$NetBSD: if.c,v 1.276 2014/06/05 23:48:16 rmind Exp $");
1.50 thorpej 94:
95: #include "opt_inet.h"
1.46 thorpej 96:
1.51 bouyer 97: #include "opt_atalk.h"
1.120 martin 98: #include "opt_natm.h"
1.1 cgd 99:
1.8 mycroft 100: #include <sys/param.h>
101: #include <sys/mbuf.h>
102: #include <sys/systm.h>
1.59 thorpej 103: #include <sys/callout.h>
1.15 mycroft 104: #include <sys/proc.h>
1.8 mycroft 105: #include <sys/socket.h>
106: #include <sys/socketvar.h>
1.56 thorpej 107: #include <sys/domain.h>
1.8 mycroft 108: #include <sys/protosw.h>
109: #include <sys/kernel.h>
110: #include <sys/ioctl.h>
1.133 jonathan 111: #include <sys/sysctl.h>
1.159 dyoung 112: #include <sys/syslog.h>
1.165 elad 113: #include <sys/kauth.h>
1.254 dyoung 114: #include <sys/kmem.h>
1.276 rmind 115: #include <sys/xcall.h>
1.1 cgd 116:
1.8 mycroft 117: #include <net/if.h>
118: #include <net/if_dl.h>
1.66 onoe 119: #include <net/if_ether.h>
1.124 dyoung 120: #include <net/if_media.h>
1.132 dyoung 121: #include <net80211/ieee80211.h>
122: #include <net80211/ieee80211_ioctl.h>
1.8 mycroft 123: #include <net/if_types.h>
1.24 christos 124: #include <net/radix.h>
1.53 thorpej 125: #include <net/route.h>
1.95 itojun 126: #include <net/netisr.h>
1.262 christos 127: #include <sys/module.h>
1.51 bouyer 128: #ifdef NETATALK
129: #include <netatalk/at_extern.h>
130: #include <netatalk/at.h>
131: #endif
1.143 itojun 132: #include <net/pfil.h>
1.276 rmind 133: #include <netinet/in_var.h>
1.1 cgd 134:
1.49 itojun 135: #ifdef INET6
136: #include <netinet/in.h>
1.72 thorpej 137: #include <netinet6/in6_var.h>
1.108 itojun 138: #include <netinet6/nd6.h>
1.49 itojun 139: #endif
1.117 thorpej 140:
1.166 liamjfoy 141: #include "carp.h"
142: #if NCARP > 0
143: #include <netinet/ip_carp.h>
144: #endif
145:
1.186 christos 146: #include <compat/sys/sockio.h>
1.161 christos 147: #include <compat/sys/socket.h>
148:
1.117 thorpej 149: MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
150: MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
1.49 itojun 151:
1.274 rmind 152: /*
153: * Global list of interfaces.
154: */
155: struct ifnet_head ifnet_list;
156: static ifnet_t ** ifindex2ifnet = NULL;
157:
158: static u_int if_index = 1;
159: static size_t if_indexlim = 0;
160: static uint64_t index_gen;
161: static kmutex_t index_gen_mtx;
162:
163: static struct ifaddr ** ifnet_addrs = NULL;
164:
165: static callout_t if_slowtimo_ch;
166:
167: struct ifnet *lo0ifp;
1.1 cgd 168: int ifqmaxlen = IFQ_MAXLEN;
1.104 matt 169:
1.192 dyoung 170: static int if_rt_walktree(struct rtentry *, void *);
1.53 thorpej 171:
1.163 thorpej 172: static struct if_clone *if_clone_lookup(const char *, int *);
173: static int if_clone_list(struct if_clonereq *);
1.63 thorpej 174:
1.163 thorpej 175: static LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
176: static int if_cloners_count;
1.63 thorpej 177:
1.265 rmind 178: /* Packet filtering hook for interfaces. */
179: pfil_head_t * if_pfil;
1.143 itojun 180:
1.239 elad 181: static kauth_listener_t if_listener;
182:
1.273 pooka 183: static int doifioctl(struct socket *, u_long, void *, struct lwp *);
1.252 dyoung 184: static int ifioctl_attach(struct ifnet *);
185: static void ifioctl_detach(struct ifnet *);
1.254 dyoung 186: static void ifnet_lock_enter(struct ifnet_lock *);
187: static void ifnet_lock_exit(struct ifnet_lock *);
1.163 thorpej 188: static void if_detach_queues(struct ifnet *, struct ifqueue *);
1.234 dyoung 189: static void sysctl_sndq_setup(struct sysctllog **, const char *,
190: struct ifaltq *);
1.95 itojun 191:
1.240 cegger 192: #if defined(INET) || defined(INET6)
1.276 rmind 193: static void sysctl_net_pktq_setup(struct sysctllog **, int);
1.240 cegger 194: #endif
1.237 pooka 195:
1.239 elad 196: static int
197: if_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
198: void *arg0, void *arg1, void *arg2, void *arg3)
199: {
200: int result;
201: enum kauth_network_req req;
202:
203: result = KAUTH_RESULT_DEFER;
204: req = (enum kauth_network_req)arg1;
205:
206: if (action != KAUTH_NETWORK_INTERFACE)
207: return result;
208:
209: if ((req == KAUTH_REQ_NETWORK_INTERFACE_GET) ||
210: (req == KAUTH_REQ_NETWORK_INTERFACE_SET))
211: result = KAUTH_RESULT_ALLOW;
212:
213: return result;
214: }
215:
1.1 cgd 216: /*
217: * Network interface utility routines.
218: *
219: * Routines with ifa_ifwith* names take sockaddr *'s as
220: * parameters.
221: */
1.4 andrew 222: void
1.163 thorpej 223: ifinit(void)
1.1 cgd 224: {
1.276 rmind 225: #if defined(INET)
226: sysctl_net_pktq_setup(NULL, PF_INET);
227: #endif
1.237 pooka 228: #ifdef INET6
1.276 rmind 229: sysctl_net_pktq_setup(NULL, PF_INET6);
230: #endif
1.1 cgd 231:
1.193 ad 232: callout_init(&if_slowtimo_ch, 0);
1.4 andrew 233: if_slowtimo(NULL);
1.239 elad 234:
235: if_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
236: if_listener_cb, NULL);
1.273 pooka 237:
238: /* interfaces are available, inform socket code */
239: ifioctl = doifioctl;
1.227 yamt 240: }
241:
242: /*
243: * XXX Initialization before configure().
244: * XXX hack to get pfil_add_hook working in autoconf.
245: */
246: void
247: ifinit1(void)
248: {
1.238 skrll 249: mutex_init(&index_gen_mtx, MUTEX_DEFAULT, IPL_NONE);
1.274 rmind 250: TAILQ_INIT(&ifnet_list);
251: if_indexlim = 8;
252:
1.265 rmind 253: if_pfil = pfil_head_create(PFIL_TYPE_IFNET, NULL);
254: KASSERT(if_pfil != NULL);
1.1 cgd 255: }
256:
1.274 rmind 257: ifnet_t *
1.226 christos 258: if_alloc(u_char type)
259: {
1.274 rmind 260: return kmem_zalloc(sizeof(ifnet_t), KM_SLEEP);
1.226 christos 261: }
262:
263: void
1.274 rmind 264: if_free(ifnet_t *ifp)
1.251 dyoung 265: {
1.274 rmind 266: kmem_free(ifp, sizeof(ifnet_t));
1.251 dyoung 267: }
268:
269: void
1.226 christos 270: if_initname(struct ifnet *ifp, const char *name, int unit)
271: {
272: (void)snprintf(ifp->if_xname, sizeof(ifp->if_xname),
273: "%s%d", name, unit);
274: }
275:
1.53 thorpej 276: /*
277: * Null routines used while an interface is going away. These routines
278: * just return an error.
279: */
280:
281: int
1.177 christos 282: if_nulloutput(struct ifnet *ifp, struct mbuf *m,
1.181 dyoung 283: const struct sockaddr *so, struct rtentry *rt)
1.53 thorpej 284: {
285:
1.185 dyoung 286: return ENXIO;
1.53 thorpej 287: }
288:
289: void
1.177 christos 290: if_nullinput(struct ifnet *ifp, struct mbuf *m)
1.53 thorpej 291: {
292:
293: /* Nothing. */
294: }
295:
296: void
1.177 christos 297: if_nullstart(struct ifnet *ifp)
1.53 thorpej 298: {
299:
300: /* Nothing. */
301: }
302:
303: int
1.183 christos 304: if_nullioctl(struct ifnet *ifp, u_long cmd, void *data)
1.53 thorpej 305: {
306:
1.255 dyoung 307: /* Wake ifioctl_detach(), who may wait for all threads to
308: * quit the critical section.
309: */
1.254 dyoung 310: cv_signal(&ifp->if_ioctl_lock->il_emptied);
1.185 dyoung 311: return ENXIO;
1.53 thorpej 312: }
313:
314: int
1.177 christos 315: if_nullinit(struct ifnet *ifp)
1.53 thorpej 316: {
317:
1.185 dyoung 318: return ENXIO;
1.53 thorpej 319: }
320:
321: void
1.177 christos 322: if_nullstop(struct ifnet *ifp, int disable)
1.75 thorpej 323: {
324:
325: /* Nothing. */
326: }
327:
328: void
1.177 christos 329: if_nullwatchdog(struct ifnet *ifp)
1.53 thorpej 330: {
331:
332: /* Nothing. */
333: }
334:
335: void
1.177 christos 336: if_nulldrain(struct ifnet *ifp)
1.53 thorpej 337: {
338:
339: /* Nothing. */
340: }
341:
1.210 dyoung 342: void
1.231 dyoung 343: if_set_sadl(struct ifnet *ifp, const void *lla, u_char addrlen, bool factory)
1.210 dyoung 344: {
345: struct ifaddr *ifa;
346: struct sockaddr_dl *sdl;
347:
348: ifp->if_addrlen = addrlen;
349: if_alloc_sadl(ifp);
350: ifa = ifp->if_dl;
351: sdl = satosdl(ifa->ifa_addr);
352:
353: (void)sockaddr_dl_setaddr(sdl, sdl->sdl_len, lla, ifp->if_addrlen);
1.231 dyoung 354: if (factory) {
355: ifp->if_hwdl = ifp->if_dl;
356: IFAREF(ifp->if_hwdl);
357: }
1.223 dyoung 358: /* TBD routing socket */
1.210 dyoung 359: }
360:
1.211 dyoung 361: struct ifaddr *
362: if_dl_create(const struct ifnet *ifp, const struct sockaddr_dl **sdlp)
363: {
364: unsigned socksize, ifasize;
365: int addrlen, namelen;
366: struct sockaddr_dl *mask, *sdl;
367: struct ifaddr *ifa;
368:
369: namelen = strlen(ifp->if_xname);
370: addrlen = ifp->if_addrlen;
371: socksize = roundup(sockaddr_dl_measure(namelen, addrlen), sizeof(long));
372: ifasize = sizeof(*ifa) + 2 * socksize;
373: ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK|M_ZERO);
374:
375: sdl = (struct sockaddr_dl *)(ifa + 1);
376: mask = (struct sockaddr_dl *)(socksize + (char *)sdl);
377:
378: sockaddr_dl_init(sdl, socksize, ifp->if_index, ifp->if_type,
379: ifp->if_xname, namelen, NULL, addrlen);
380: mask->sdl_len = sockaddr_dl_measure(namelen, 0);
381: memset(&mask->sdl_data[0], 0xff, namelen);
382: ifa->ifa_rtrequest = link_rtrequest;
383: ifa->ifa_addr = (struct sockaddr *)sdl;
384: ifa->ifa_netmask = (struct sockaddr *)mask;
385:
386: *sdlp = sdl;
387:
388: return ifa;
389: }
390:
1.223 dyoung 391: static void
392: if_sadl_setrefs(struct ifnet *ifp, struct ifaddr *ifa)
393: {
394: const struct sockaddr_dl *sdl;
395: ifnet_addrs[ifp->if_index] = ifa;
396: IFAREF(ifa);
397: ifp->if_dl = ifa;
398: IFAREF(ifa);
399: sdl = satosdl(ifa->ifa_addr);
400: ifp->if_sadl = sdl;
401: }
402:
1.1 cgd 403: /*
1.81 thorpej 404: * Allocate the link level name for the specified interface. This
405: * is an attachment helper. It must be called after ifp->if_addrlen
406: * is initialized, which may not be the case when if_attach() is
407: * called.
408: */
409: void
410: if_alloc_sadl(struct ifnet *ifp)
411: {
412: struct ifaddr *ifa;
1.211 dyoung 413: const struct sockaddr_dl *sdl;
1.84 thorpej 414:
415: /*
416: * If the interface already has a link name, release it
417: * now. This is useful for interfaces that can change
418: * link types, and thus switch link names often.
419: */
420: if (ifp->if_sadl != NULL)
421: if_free_sadl(ifp);
1.81 thorpej 422:
1.211 dyoung 423: ifa = if_dl_create(ifp, &sdl);
1.195 dyoung 424:
1.207 dyoung 425: ifa_insert(ifp, ifa);
1.223 dyoung 426: if_sadl_setrefs(ifp, ifa);
427: }
428:
429: static void
430: if_deactivate_sadl(struct ifnet *ifp)
431: {
432: struct ifaddr *ifa;
433:
434: KASSERT(ifp->if_dl != NULL);
435:
436: ifa = ifp->if_dl;
437:
438: ifp->if_sadl = NULL;
439:
440: ifnet_addrs[ifp->if_index] = NULL;
441: IFAFREE(ifa);
442: ifp->if_dl = NULL;
443: IFAFREE(ifa);
444: }
445:
1.224 dyoung 446: void
1.223 dyoung 447: if_activate_sadl(struct ifnet *ifp, struct ifaddr *ifa,
448: const struct sockaddr_dl *sdl)
449: {
450: int s;
451:
452: s = splnet();
453:
454: if_deactivate_sadl(ifp);
455:
456: if_sadl_setrefs(ifp, ifa);
1.231 dyoung 457: IFADDR_FOREACH(ifa, ifp)
458: rtinit(ifa, RTM_LLINFO_UPD, 0);
1.223 dyoung 459: splx(s);
1.81 thorpej 460: }
461:
462: /*
463: * Free the link level name for the specified interface. This is
464: * a detach helper. This is called from if_detach() or from
465: * link layer type specific detach functions.
466: */
467: void
468: if_free_sadl(struct ifnet *ifp)
469: {
470: struct ifaddr *ifa;
471: int s;
472:
473: ifa = ifnet_addrs[ifp->if_index];
474: if (ifa == NULL) {
475: KASSERT(ifp->if_sadl == NULL);
1.209 dyoung 476: KASSERT(ifp->if_dl == NULL);
1.81 thorpej 477: return;
478: }
479:
480: KASSERT(ifp->if_sadl != NULL);
1.209 dyoung 481: KASSERT(ifp->if_dl != NULL);
1.81 thorpej 482:
1.88 thorpej 483: s = splnet();
1.81 thorpej 484: rtinit(ifa, RTM_DELETE, 0);
1.207 dyoung 485: ifa_remove(ifp, ifa);
1.223 dyoung 486: if_deactivate_sadl(ifp);
1.231 dyoung 487: if (ifp->if_hwdl == ifa) {
488: IFAFREE(ifa);
489: ifp->if_hwdl = NULL;
490: }
1.81 thorpej 491: splx(s);
492: }
493:
1.274 rmind 494: static void
495: if_getindex(ifnet_t *ifp)
1.1 cgd 496: {
1.274 rmind 497: bool hitlimit = false;
1.231 dyoung 498:
1.234 dyoung 499: mutex_enter(&index_gen_mtx);
500: ifp->if_index_gen = index_gen++;
501: mutex_exit(&index_gen_mtx);
502:
1.102 atatat 503: ifp->if_index = if_index;
1.274 rmind 504: if (ifindex2ifnet == NULL) {
1.102 atatat 505: if_index++;
1.274 rmind 506: goto skip;
507: }
508: while (if_byindex(ifp->if_index)) {
509: /*
510: * If we hit USHRT_MAX, we skip back to 0 since
511: * there are a number of places where the value
512: * of if_index or if_index itself is compared
513: * to or stored in an unsigned short. By
514: * jumping back, we won't botch those assignments
515: * or comparisons.
516: */
517: if (++if_index == 0) {
518: if_index = 1;
519: } else if (if_index == USHRT_MAX) {
1.102 atatat 520: /*
1.274 rmind 521: * However, if we have to jump back to
522: * zero *twice* without finding an empty
523: * slot in ifindex2ifnet[], then there
524: * there are too many (>65535) interfaces.
1.102 atatat 525: */
1.274 rmind 526: if (hitlimit) {
527: panic("too many interfaces");
1.102 atatat 528: }
1.274 rmind 529: hitlimit = true;
530: if_index = 1;
1.102 atatat 531: }
1.274 rmind 532: ifp->if_index = if_index;
533: }
534: skip:
1.49 itojun 535: /*
536: * We have some arrays that should be indexed by if_index.
537: * since if_index will grow dynamically, they should grow too.
538: * struct ifadd **ifnet_addrs
539: * struct ifnet **ifindex2ifnet
540: */
1.185 dyoung 541: if (ifnet_addrs == NULL || ifindex2ifnet == NULL ||
1.53 thorpej 542: ifp->if_index >= if_indexlim) {
1.131 itojun 543: size_t m, n, oldlim;
1.183 christos 544: void *q;
1.154 perry 545:
1.131 itojun 546: oldlim = if_indexlim;
1.53 thorpej 547: while (ifp->if_index >= if_indexlim)
1.49 itojun 548: if_indexlim <<= 1;
549:
550: /* grow ifnet_addrs */
1.131 itojun 551: m = oldlim * sizeof(struct ifaddr *);
1.81 thorpej 552: n = if_indexlim * sizeof(struct ifaddr *);
1.230 dyoung 553: q = malloc(n, M_IFADDR, M_WAITOK|M_ZERO);
1.185 dyoung 554: if (ifnet_addrs != NULL) {
555: memcpy(q, ifnet_addrs, m);
1.230 dyoung 556: free(ifnet_addrs, M_IFADDR);
1.1 cgd 557: }
1.49 itojun 558: ifnet_addrs = (struct ifaddr **)q;
559:
560: /* grow ifindex2ifnet */
1.131 itojun 561: m = oldlim * sizeof(struct ifnet *);
1.49 itojun 562: n = if_indexlim * sizeof(struct ifnet *);
1.230 dyoung 563: q = malloc(n, M_IFADDR, M_WAITOK|M_ZERO);
1.185 dyoung 564: if (ifindex2ifnet != NULL) {
1.230 dyoung 565: memcpy(q, ifindex2ifnet, m);
566: free(ifindex2ifnet, M_IFADDR);
1.49 itojun 567: }
568: ifindex2ifnet = (struct ifnet **)q;
1.1 cgd 569: }
1.274 rmind 570: ifindex2ifnet[ifp->if_index] = ifp;
571: }
572:
573: /*
574: * Attach an interface to the list of "active" interfaces.
575: */
576: void
577: if_attach(ifnet_t *ifp)
578: {
579: KASSERT(if_indexlim > 0);
580: TAILQ_INIT(&ifp->if_addrlist);
581: TAILQ_INSERT_TAIL(&ifnet_list, ifp, if_list);
582:
583: if (ifioctl_attach(ifp) != 0)
584: panic("%s: ifioctl_attach() failed", __func__);
1.49 itojun 585:
1.274 rmind 586: if_getindex(ifp);
1.49 itojun 587:
1.1 cgd 588: /*
1.81 thorpej 589: * Link level name is allocated later by a separate call to
590: * if_alloc_sadl().
1.1 cgd 591: */
1.81 thorpej 592:
1.40 thorpej 593: if (ifp->if_snd.ifq_maxlen == 0)
1.94 itojun 594: ifp->if_snd.ifq_maxlen = ifqmaxlen;
1.234 dyoung 595:
596: sysctl_sndq_setup(&ifp->if_sysctl_log, ifp->if_xname, &ifp->if_snd);
597:
1.42 is 598: ifp->if_broadcastaddr = 0; /* reliably crash if used uninitialized */
1.57 thorpej 599:
600: ifp->if_link_state = LINK_STATE_UNKNOWN;
601:
1.89 thorpej 602: ifp->if_capenable = 0;
1.97 thorpej 603: ifp->if_csum_flags_tx = 0;
604: ifp->if_csum_flags_rx = 0;
1.89 thorpej 605:
1.86 thorpej 606: #ifdef ALTQ
607: ifp->if_snd.altq_type = 0;
608: ifp->if_snd.altq_disc = NULL;
609: ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE;
610: ifp->if_snd.altq_tbr = NULL;
611: ifp->if_snd.altq_ifp = ifp;
612: #endif
613:
1.265 rmind 614: ifp->if_pfil = pfil_head_create(PFIL_TYPE_IFNET, ifp);
615: (void)pfil_run_hooks(if_pfil,
1.144 yamt 616: (struct mbuf **)PFIL_IFNET_ATTACH, ifp, PFIL_IFNET);
1.87 thorpej 617:
1.152 matt 618: if (!STAILQ_EMPTY(&domains))
1.147 tron 619: if_attachdomain1(ifp);
620:
1.107 itojun 621: /* Announce the interface. */
622: rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
623: }
624:
625: void
1.163 thorpej 626: if_attachdomain(void)
1.107 itojun 627: {
628: struct ifnet *ifp;
1.110 itojun 629: int s;
1.107 itojun 630:
1.110 itojun 631: s = splnet();
1.185 dyoung 632: IFNET_FOREACH(ifp)
1.107 itojun 633: if_attachdomain1(ifp);
1.110 itojun 634: splx(s);
1.107 itojun 635: }
636:
637: void
1.163 thorpej 638: if_attachdomain1(struct ifnet *ifp)
1.107 itojun 639: {
640: struct domain *dp;
1.109 itojun 641: int s;
642:
643: s = splnet();
1.107 itojun 644:
1.106 itojun 645: /* address family dependent data region */
646: memset(ifp->if_afdata, 0, sizeof(ifp->if_afdata));
1.152 matt 647: DOMAIN_FOREACH(dp) {
1.185 dyoung 648: if (dp->dom_ifattach != NULL)
1.106 itojun 649: ifp->if_afdata[dp->dom_family] =
650: (*dp->dom_ifattach)(ifp);
651: }
1.109 itojun 652:
653: splx(s);
1.1 cgd 654: }
1.53 thorpej 655:
656: /*
657: * Deactivate an interface. This points all of the procedure
658: * handles at error stubs. May be called from interrupt context.
659: */
660: void
1.163 thorpej 661: if_deactivate(struct ifnet *ifp)
1.53 thorpej 662: {
663: int s;
664:
1.88 thorpej 665: s = splnet();
1.53 thorpej 666:
667: ifp->if_output = if_nulloutput;
668: ifp->if_input = if_nullinput;
669: ifp->if_start = if_nullstart;
670: ifp->if_ioctl = if_nullioctl;
1.75 thorpej 671: ifp->if_init = if_nullinit;
672: ifp->if_stop = if_nullstop;
1.53 thorpej 673: ifp->if_watchdog = if_nullwatchdog;
674: ifp->if_drain = if_nulldrain;
675:
676: /* No more packets may be enqueued. */
677: ifp->if_snd.ifq_maxlen = 0;
678:
679: splx(s);
680: }
681:
1.206 dyoung 682: void
1.218 dyoung 683: if_purgeaddrs(struct ifnet *ifp, int family, void (*purgeaddr)(struct ifaddr *))
1.206 dyoung 684: {
685: struct ifaddr *ifa, *nifa;
686:
687: for (ifa = IFADDR_FIRST(ifp); ifa != NULL; ifa = nifa) {
688: nifa = IFADDR_NEXT(ifa);
689: if (ifa->ifa_addr->sa_family != family)
690: continue;
691: (*purgeaddr)(ifa);
692: }
693: }
694:
1.53 thorpej 695: /*
696: * Detach an interface from the list of "active" interfaces,
697: * freeing any resources as we go along.
698: *
699: * NOTE: This routine must be called with a valid thread context,
700: * as it may block.
701: */
702: void
1.163 thorpej 703: if_detach(struct ifnet *ifp)
1.53 thorpej 704: {
1.56 thorpej 705: struct socket so;
1.178 dyoung 706: struct ifaddr *ifa;
1.53 thorpej 707: #ifdef IFAREF_DEBUG
708: struct ifaddr *last_ifa = NULL;
709: #endif
1.56 thorpej 710: struct domain *dp;
1.141 matt 711: const struct protosw *pr;
1.56 thorpej 712: int s, i, family, purged;
1.276 rmind 713: uint64_t xc;
1.53 thorpej 714:
1.56 thorpej 715: /*
716: * XXX It's kind of lame that we have to have the
717: * XXX socket structure...
718: */
719: memset(&so, 0, sizeof(so));
1.53 thorpej 720:
1.88 thorpej 721: s = splnet();
1.53 thorpej 722:
723: /*
724: * Do an if_down() to give protocols a chance to do something.
725: */
726: if_down(ifp);
1.86 thorpej 727:
728: #ifdef ALTQ
729: if (ALTQ_IS_ENABLED(&ifp->if_snd))
730: altq_disable(&ifp->if_snd);
731: if (ALTQ_IS_ATTACHED(&ifp->if_snd))
732: altq_detach(&ifp->if_snd);
1.87 thorpej 733: #endif
734:
1.234 dyoung 735: sysctl_teardown(&ifp->if_sysctl_log);
1.166 liamjfoy 736:
737: #if NCARP > 0
738: /* Remove the interface from any carp group it is a part of. */
1.185 dyoung 739: if (ifp->if_carp != NULL && ifp->if_type != IFT_CARP)
1.166 liamjfoy 740: carp_ifdetach(ifp);
741: #endif
742:
1.53 thorpej 743: /*
744: * Rip all the addresses off the interface. This should make
745: * all of the routes go away.
1.178 dyoung 746: *
747: * pr_usrreq calls can remove an arbitrary number of ifaddrs
748: * from the list, including our "cursor", ifa. For safety,
749: * and to honor the TAILQ abstraction, I just restart the
750: * loop after each removal. Note that the loop will exit
751: * when all of the remaining ifaddrs belong to the AF_LINK
752: * family. I am counting on the historical fact that at
753: * least one pr_usrreq in each address domain removes at
754: * least one ifaddr.
1.53 thorpej 755: */
1.178 dyoung 756: again:
1.204 dyoung 757: IFADDR_FOREACH(ifa, ifp) {
1.56 thorpej 758: family = ifa->ifa_addr->sa_family;
1.53 thorpej 759: #ifdef IFAREF_DEBUG
760: printf("if_detach: ifaddr %p, family %d, refcnt %d\n",
1.56 thorpej 761: ifa, family, ifa->ifa_refcnt);
1.53 thorpej 762: if (last_ifa != NULL && ifa == last_ifa)
1.56 thorpej 763: panic("if_detach: loop detected");
1.53 thorpej 764: last_ifa = ifa;
765: #endif
1.178 dyoung 766: if (family == AF_LINK)
1.118 itojun 767: continue;
768: dp = pffinddomain(family);
1.56 thorpej 769: #ifdef DIAGNOSTIC
1.118 itojun 770: if (dp == NULL)
771: panic("if_detach: no domain for AF %d",
772: family);
1.56 thorpej 773: #endif
1.160 gdt 774: /*
775: * XXX These PURGEIF calls are redundant with the
776: * purge-all-families calls below, but are left in for
777: * now both to make a smaller change, and to avoid
778: * unplanned interactions with clearing of
779: * ifp->if_addrlist.
780: */
1.118 itojun 781: purged = 0;
782: for (pr = dp->dom_protosw;
783: pr < dp->dom_protoswNPROTOSW; pr++) {
784: so.so_proto = pr;
1.275 rmind 785: if (pr->pr_usrreqs) {
786: (void) (*pr->pr_usrreqs->pr_generic)(&so,
1.118 itojun 787: PRU_PURGEIF, NULL, NULL,
1.162 christos 788: (struct mbuf *) ifp, curlwp);
1.118 itojun 789: purged = 1;
1.53 thorpej 790: }
1.118 itojun 791: }
792: if (purged == 0) {
793: /*
794: * XXX What's really the best thing to do
1.135 keihan 795: * XXX here? --thorpej@NetBSD.org
1.118 itojun 796: */
797: printf("if_detach: WARNING: AF %d not purged\n",
798: family);
1.207 dyoung 799: ifa_remove(ifp, ifa);
1.53 thorpej 800: }
1.178 dyoung 801: goto again;
1.53 thorpej 802: }
1.118 itojun 803:
804: if_free_sadl(ifp);
1.53 thorpej 805:
1.180 dyoung 806: /* Walk the routing table looking for stragglers. */
1.243 dyoung 807: for (i = 0; i <= AF_MAX; i++) {
808: while (rt_walktree(i, if_rt_walktree, ifp) == ERESTART)
1.260 christos 809: continue;
1.243 dyoung 810: }
1.106 itojun 811:
1.152 matt 812: DOMAIN_FOREACH(dp) {
1.185 dyoung 813: if (dp->dom_ifdetach != NULL && ifp->if_afdata[dp->dom_family])
1.260 christos 814: {
815: void *p = ifp->if_afdata[dp->dom_family];
816: if (p) {
817: ifp->if_afdata[dp->dom_family] = NULL;
818: (*dp->dom_ifdetach)(ifp, p);
819: }
820: }
1.160 gdt 821:
822: /*
823: * One would expect multicast memberships (INET and
824: * INET6) on UDP sockets to be purged by the PURGEIF
825: * calls above, but if all addresses were removed from
826: * the interface prior to destruction, the calls will
827: * not be made (e.g. ppp, for which pppd(8) generally
828: * removes addresses before destroying the interface).
829: * Because there is no invariant that multicast
830: * memberships only exist for interfaces with IPv4
831: * addresses, we must call PURGEIF regardless of
832: * addresses. (Protocols which might store ifnet
833: * pointers are marked with PR_PURGEIF.)
834: */
1.185 dyoung 835: for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
1.160 gdt 836: so.so_proto = pr;
1.275 rmind 837: if (pr->pr_usrreqs && pr->pr_flags & PR_PURGEIF)
838: (void)(*pr->pr_usrreqs->pr_generic)(&so,
839: PRU_PURGEIF, NULL, NULL,
840: (struct mbuf *)ifp, curlwp);
1.160 gdt 841: }
1.53 thorpej 842: }
1.57 thorpej 843:
1.265 rmind 844: (void)pfil_run_hooks(if_pfil,
1.184 dyoung 845: (struct mbuf **)PFIL_IFNET_DETACH, ifp, PFIL_IFNET);
1.265 rmind 846: (void)pfil_head_destroy(ifp->if_pfil);
1.184 dyoung 847:
1.57 thorpej 848: /* Announce that the interface is gone. */
849: rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
1.93 itojun 850:
851: ifindex2ifnet[ifp->if_index] = NULL;
1.53 thorpej 852:
1.274 rmind 853: TAILQ_REMOVE(&ifnet_list, ifp, if_list);
1.53 thorpej 854:
1.252 dyoung 855: ifioctl_detach(ifp);
856:
1.95 itojun 857: /*
1.168 matt 858: * remove packets that came from ifp, from software interrupt queues.
1.95 itojun 859: */
1.168 matt 860: DOMAIN_FOREACH(dp) {
861: for (i = 0; i < __arraycount(dp->dom_ifqueues); i++) {
1.260 christos 862: struct ifqueue *iq = dp->dom_ifqueues[i];
863: if (iq == NULL)
1.168 matt 864: break;
1.260 christos 865: dp->dom_ifqueues[i] = NULL;
866: if_detach_queues(ifp, iq);
1.168 matt 867: }
868: }
1.95 itojun 869:
1.276 rmind 870: /*
871: * IP queues have to be processed separately: net-queue barrier
872: * ensures that the packets are dequeued while a cross-call will
873: * ensure that the interrupts have completed. FIXME: not quite..
874: */
875: pktq_barrier(ip_pktq);
876: xc = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL);
877: xc_wait(xc);
878:
1.53 thorpej 879: splx(s);
1.95 itojun 880: }
881:
882: static void
1.163 thorpej 883: if_detach_queues(struct ifnet *ifp, struct ifqueue *q)
1.95 itojun 884: {
885: struct mbuf *m, *prev, *next;
886:
887: prev = NULL;
1.185 dyoung 888: for (m = q->ifq_head; m != NULL; m = next) {
1.274 rmind 889: KASSERT((m->m_flags & M_PKTHDR) != 0);
890:
1.95 itojun 891: next = m->m_nextpkt;
1.96 itojun 892: if (m->m_pkthdr.rcvif != ifp) {
893: prev = m;
1.95 itojun 894: continue;
1.96 itojun 895: }
1.95 itojun 896:
1.185 dyoung 897: if (prev != NULL)
1.95 itojun 898: prev->m_nextpkt = m->m_nextpkt;
899: else
900: q->ifq_head = m->m_nextpkt;
901: if (q->ifq_tail == m)
902: q->ifq_tail = prev;
903: q->ifq_len--;
904:
905: m->m_nextpkt = NULL;
906: m_freem(m);
907: IF_DROP(q);
908: }
1.53 thorpej 909: }
910:
911: /*
912: * Callback for a radix tree walk to delete all references to an
913: * ifnet.
914: */
1.163 thorpej 915: static int
1.192 dyoung 916: if_rt_walktree(struct rtentry *rt, void *v)
1.53 thorpej 917: {
1.55 itojun 918: struct ifnet *ifp = (struct ifnet *)v;
1.53 thorpej 919: int error;
920:
1.185 dyoung 921: if (rt->rt_ifp != ifp)
922: return 0;
923:
924: /* Delete the entry. */
925: ++rt->rt_refcnt;
1.194 dyoung 926: error = rtrequest(RTM_DELETE, rt_getkey(rt), rt->rt_gateway,
1.185 dyoung 927: rt_mask(rt), rt->rt_flags, NULL);
928: KASSERT((rt->rt_flags & RTF_UP) == 0);
929: rt->rt_ifp = NULL;
1.277 ! rmind 930: rtfree(rt);
1.185 dyoung 931: if (error != 0)
932: printf("%s: warning: unable to delete rtentry @ %p, "
933: "error = %d\n", ifp->if_xname, rt, error);
1.243 dyoung 934: return ERESTART;
1.53 thorpej 935: }
936:
1.1 cgd 937: /*
1.63 thorpej 938: * Create a clone network interface.
939: */
940: int
1.163 thorpej 941: if_clone_create(const char *name)
1.63 thorpej 942: {
943: struct if_clone *ifc;
944: int unit;
945:
946: ifc = if_clone_lookup(name, &unit);
947: if (ifc == NULL)
1.185 dyoung 948: return EINVAL;
1.63 thorpej 949:
950: if (ifunit(name) != NULL)
1.185 dyoung 951: return EEXIST;
1.63 thorpej 952:
1.185 dyoung 953: return (*ifc->ifc_create)(ifc, unit);
1.63 thorpej 954: }
955:
956: /*
957: * Destroy a clone network interface.
958: */
959: int
1.163 thorpej 960: if_clone_destroy(const char *name)
1.63 thorpej 961: {
962: struct if_clone *ifc;
963: struct ifnet *ifp;
964:
965: ifc = if_clone_lookup(name, NULL);
966: if (ifc == NULL)
1.185 dyoung 967: return EINVAL;
1.63 thorpej 968:
969: ifp = ifunit(name);
970: if (ifp == NULL)
1.185 dyoung 971: return ENXIO;
1.63 thorpej 972:
973: if (ifc->ifc_destroy == NULL)
1.185 dyoung 974: return EOPNOTSUPP;
1.63 thorpej 975:
1.185 dyoung 976: return (*ifc->ifc_destroy)(ifp);
1.63 thorpej 977: }
978:
979: /*
980: * Look up a network interface cloner.
981: */
1.163 thorpej 982: static struct if_clone *
983: if_clone_lookup(const char *name, int *unitp)
1.63 thorpej 984: {
985: struct if_clone *ifc;
986: const char *cp;
1.262 christos 987: char *dp, ifname[IFNAMSIZ + 3];
1.128 itojun 988: int unit;
1.63 thorpej 989:
1.262 christos 990: strcpy(ifname, "if_");
1.128 itojun 991: /* separate interface name from unit */
1.262 christos 992: for (dp = ifname + 3, cp = name; cp - name < IFNAMSIZ &&
993: *cp && (*cp < '0' || *cp > '9');)
994: *dp++ = *cp++;
1.128 itojun 995:
996: if (cp == name || cp - name == IFNAMSIZ || !*cp)
1.185 dyoung 997: return NULL; /* No name or unit number */
1.262 christos 998: *dp++ = '\0';
1.128 itojun 999:
1.262 christos 1000: again:
1.128 itojun 1001: LIST_FOREACH(ifc, &if_cloners, ifc_list) {
1.262 christos 1002: if (strcmp(ifname + 3, ifc->ifc_name) == 0)
1.128 itojun 1003: break;
1.63 thorpej 1004: }
1005:
1.262 christos 1006: if (ifc == NULL) {
1007: if (*ifname == '\0' ||
1.267 christos 1008: module_autoload(ifname, MODULE_CLASS_DRIVER))
1.262 christos 1009: return NULL;
1010: *ifname = '\0';
1011: goto again;
1012: }
1.63 thorpej 1013:
1.128 itojun 1014: unit = 0;
1.129 itojun 1015: while (cp - name < IFNAMSIZ && *cp) {
1.245 christos 1016: if (*cp < '0' || *cp > '9' || unit >= INT_MAX / 10) {
1.63 thorpej 1017: /* Bogus unit number. */
1.185 dyoung 1018: return NULL;
1.63 thorpej 1019: }
1.128 itojun 1020: unit = (unit * 10) + (*cp++ - '0');
1.63 thorpej 1021: }
1022:
1023: if (unitp != NULL)
1.128 itojun 1024: *unitp = unit;
1.185 dyoung 1025: return ifc;
1.63 thorpej 1026: }
1027:
1028: /*
1029: * Register a network interface cloner.
1030: */
1031: void
1.163 thorpej 1032: if_clone_attach(struct if_clone *ifc)
1.63 thorpej 1033: {
1034:
1035: LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
1.67 thorpej 1036: if_cloners_count++;
1.63 thorpej 1037: }
1038:
1039: /*
1040: * Unregister a network interface cloner.
1041: */
1042: void
1.163 thorpej 1043: if_clone_detach(struct if_clone *ifc)
1.63 thorpej 1044: {
1045:
1046: LIST_REMOVE(ifc, ifc_list);
1.67 thorpej 1047: if_cloners_count--;
1048: }
1049:
1050: /*
1051: * Provide list of interface cloners to userspace.
1052: */
1.163 thorpej 1053: static int
1054: if_clone_list(struct if_clonereq *ifcr)
1.67 thorpej 1055: {
1056: char outbuf[IFNAMSIZ], *dst;
1057: struct if_clone *ifc;
1058: int count, error = 0;
1059:
1060: ifcr->ifcr_total = if_cloners_count;
1061: if ((dst = ifcr->ifcr_buffer) == NULL) {
1062: /* Just asking how many there are. */
1.185 dyoung 1063: return 0;
1.67 thorpej 1064: }
1065:
1066: if (ifcr->ifcr_count < 0)
1.185 dyoung 1067: return EINVAL;
1.67 thorpej 1068:
1069: count = (if_cloners_count < ifcr->ifcr_count) ?
1070: if_cloners_count : ifcr->ifcr_count;
1071:
1072: for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
1073: ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
1.175 christos 1074: (void)strncpy(outbuf, ifc->ifc_name, sizeof(outbuf));
1075: if (outbuf[sizeof(outbuf) - 1] != '\0')
1076: return ENAMETOOLONG;
1.172 christos 1077: error = copyout(outbuf, dst, sizeof(outbuf));
1.185 dyoung 1078: if (error != 0)
1.67 thorpej 1079: break;
1080: }
1081:
1.185 dyoung 1082: return error;
1.63 thorpej 1083: }
1084:
1.207 dyoung 1085: void
1086: ifa_insert(struct ifnet *ifp, struct ifaddr *ifa)
1087: {
1088: ifa->ifa_ifp = ifp;
1.208 dyoung 1089: TAILQ_INSERT_TAIL(&ifp->if_addrlist, ifa, ifa_list);
1.207 dyoung 1090: IFAREF(ifa);
1091: }
1092:
1093: void
1094: ifa_remove(struct ifnet *ifp, struct ifaddr *ifa)
1095: {
1096: KASSERT(ifa->ifa_ifp == ifp);
1097: TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
1098: IFAFREE(ifa);
1099: }
1100:
1.194 dyoung 1101: static inline int
1102: equal(const struct sockaddr *sa1, const struct sockaddr *sa2)
1103: {
1104: return sockaddr_cmp(sa1, sa2) == 0;
1105: }
1106:
1.63 thorpej 1107: /*
1.1 cgd 1108: * Locate an interface based on a complete address.
1109: */
1110: /*ARGSUSED*/
1111: struct ifaddr *
1.163 thorpej 1112: ifa_ifwithaddr(const struct sockaddr *addr)
1.1 cgd 1113: {
1.61 augustss 1114: struct ifnet *ifp;
1115: struct ifaddr *ifa;
1.1 cgd 1116:
1.185 dyoung 1117: IFNET_FOREACH(ifp) {
1.53 thorpej 1118: if (ifp->if_output == if_nulloutput)
1.1 cgd 1119: continue;
1.204 dyoung 1120: IFADDR_FOREACH(ifa, ifp) {
1.53 thorpej 1121: if (ifa->ifa_addr->sa_family != addr->sa_family)
1122: continue;
1123: if (equal(addr, ifa->ifa_addr))
1.185 dyoung 1124: return ifa;
1.53 thorpej 1125: if ((ifp->if_flags & IFF_BROADCAST) &&
1126: ifa->ifa_broadaddr &&
1127: /* IP6 doesn't have broadcast */
1128: ifa->ifa_broadaddr->sa_len != 0 &&
1129: equal(ifa->ifa_broadaddr, addr))
1.185 dyoung 1130: return ifa;
1.53 thorpej 1131: }
1.1 cgd 1132: }
1.185 dyoung 1133: return NULL;
1.1 cgd 1134: }
1.49 itojun 1135:
1.1 cgd 1136: /*
1137: * Locate the point to point interface with a given destination address.
1138: */
1139: /*ARGSUSED*/
1140: struct ifaddr *
1.163 thorpej 1141: ifa_ifwithdstaddr(const struct sockaddr *addr)
1.1 cgd 1142: {
1.61 augustss 1143: struct ifnet *ifp;
1144: struct ifaddr *ifa;
1.1 cgd 1145:
1.185 dyoung 1146: IFNET_FOREACH(ifp) {
1.53 thorpej 1147: if (ifp->if_output == if_nulloutput)
1148: continue;
1.185 dyoung 1149: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
1150: continue;
1.204 dyoung 1151: IFADDR_FOREACH(ifa, ifp) {
1.185 dyoung 1152: if (ifa->ifa_addr->sa_family != addr->sa_family ||
1153: ifa->ifa_dstaddr == NULL)
1154: continue;
1155: if (equal(addr, ifa->ifa_dstaddr))
1156: return ifa;
1.53 thorpej 1157: }
1.1 cgd 1158: }
1.185 dyoung 1159: return NULL;
1.1 cgd 1160: }
1161:
1162: /*
1163: * Find an interface on a specific network. If many, choice
1.15 mycroft 1164: * is most specific found.
1.1 cgd 1165: */
1166: struct ifaddr *
1.163 thorpej 1167: ifa_ifwithnet(const struct sockaddr *addr)
1.1 cgd 1168: {
1.61 augustss 1169: struct ifnet *ifp;
1170: struct ifaddr *ifa;
1.140 matt 1171: const struct sockaddr_dl *sdl;
1.15 mycroft 1172: struct ifaddr *ifa_maybe = 0;
1.1 cgd 1173: u_int af = addr->sa_family;
1.171 pooka 1174: const char *addr_data = addr->sa_data, *cplim;
1.1 cgd 1175:
1176: if (af == AF_LINK) {
1.195 dyoung 1177: sdl = satocsdl(addr);
1.137 itojun 1178: if (sdl->sdl_index && sdl->sdl_index < if_indexlim &&
1179: ifindex2ifnet[sdl->sdl_index] &&
1.53 thorpej 1180: ifindex2ifnet[sdl->sdl_index]->if_output != if_nulloutput)
1.185 dyoung 1181: return ifnet_addrs[sdl->sdl_index];
1.1 cgd 1182: }
1.51 bouyer 1183: #ifdef NETATALK
1184: if (af == AF_APPLETALK) {
1.140 matt 1185: const struct sockaddr_at *sat, *sat2;
1.158 christos 1186: sat = (const struct sockaddr_at *)addr;
1.185 dyoung 1187: IFNET_FOREACH(ifp) {
1.53 thorpej 1188: if (ifp->if_output == if_nulloutput)
1189: continue;
1.158 christos 1190: ifa = at_ifawithnet((const struct sockaddr_at *)addr, ifp);
1.62 bouyer 1191: if (ifa == NULL)
1192: continue;
1193: sat2 = (struct sockaddr_at *)ifa->ifa_addr;
1194: if (sat2->sat_addr.s_net == sat->sat_addr.s_net)
1.185 dyoung 1195: return ifa; /* exact match */
1.62 bouyer 1196: if (ifa_maybe == NULL) {
1.112 wiz 1197: /* else keep the if with the right range */
1.62 bouyer 1198: ifa_maybe = ifa;
1199: }
1.51 bouyer 1200: }
1.185 dyoung 1201: return ifa_maybe;
1.51 bouyer 1202: }
1203: #endif
1.185 dyoung 1204: IFNET_FOREACH(ifp) {
1.53 thorpej 1205: if (ifp->if_output == if_nulloutput)
1206: continue;
1.204 dyoung 1207: IFADDR_FOREACH(ifa, ifp) {
1.171 pooka 1208: const char *cp, *cp2, *cp3;
1.15 mycroft 1209:
1210: if (ifa->ifa_addr->sa_family != af ||
1.185 dyoung 1211: ifa->ifa_netmask == NULL)
1.53 thorpej 1212: next: continue;
1.15 mycroft 1213: cp = addr_data;
1214: cp2 = ifa->ifa_addr->sa_data;
1215: cp3 = ifa->ifa_netmask->sa_data;
1.171 pooka 1216: cplim = (const char *)ifa->ifa_netmask +
1.53 thorpej 1217: ifa->ifa_netmask->sa_len;
1218: while (cp3 < cplim) {
1219: if ((*cp++ ^ *cp2++) & *cp3++) {
1220: /* want to continue for() loop */
1.32 mrg 1221: goto next;
1.53 thorpej 1222: }
1223: }
1.185 dyoung 1224: if (ifa_maybe == NULL ||
1.183 christos 1225: rn_refines((void *)ifa->ifa_netmask,
1226: (void *)ifa_maybe->ifa_netmask))
1.15 mycroft 1227: ifa_maybe = ifa;
1228: }
1.53 thorpej 1229: }
1.185 dyoung 1230: return ifa_maybe;
1.26 mrg 1231: }
1.53 thorpej 1232:
1.26 mrg 1233: /*
1234: * Find the interface of the addresss.
1235: */
1236: struct ifaddr *
1.163 thorpej 1237: ifa_ifwithladdr(const struct sockaddr *addr)
1.26 mrg 1238: {
1239: struct ifaddr *ia;
1240:
1.53 thorpej 1241: if ((ia = ifa_ifwithaddr(addr)) || (ia = ifa_ifwithdstaddr(addr)) ||
1242: (ia = ifa_ifwithnet(addr)))
1.185 dyoung 1243: return ia;
1244: return NULL;
1.1 cgd 1245: }
1246:
1247: /*
1248: * Find an interface using a specific address family
1249: */
1250: struct ifaddr *
1.163 thorpej 1251: ifa_ifwithaf(int af)
1.1 cgd 1252: {
1.61 augustss 1253: struct ifnet *ifp;
1254: struct ifaddr *ifa;
1.1 cgd 1255:
1.185 dyoung 1256: IFNET_FOREACH(ifp) {
1.53 thorpej 1257: if (ifp->if_output == if_nulloutput)
1258: continue;
1.204 dyoung 1259: IFADDR_FOREACH(ifa, ifp) {
1.21 mycroft 1260: if (ifa->ifa_addr->sa_family == af)
1.178 dyoung 1261: return ifa;
1.53 thorpej 1262: }
1263: }
1.178 dyoung 1264: return NULL;
1.1 cgd 1265: }
1266:
1267: /*
1268: * Find an interface address specific to an interface best matching
1269: * a given address.
1270: */
1271: struct ifaddr *
1.163 thorpej 1272: ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp)
1.1 cgd 1273: {
1.61 augustss 1274: struct ifaddr *ifa;
1.140 matt 1275: const char *cp, *cp2, *cp3;
1276: const char *cplim;
1.1 cgd 1277: struct ifaddr *ifa_maybe = 0;
1278: u_int af = addr->sa_family;
1279:
1.53 thorpej 1280: if (ifp->if_output == if_nulloutput)
1.185 dyoung 1281: return NULL;
1.53 thorpej 1282:
1.1 cgd 1283: if (af >= AF_MAX)
1.185 dyoung 1284: return NULL;
1.53 thorpej 1285:
1.204 dyoung 1286: IFADDR_FOREACH(ifa, ifp) {
1.1 cgd 1287: if (ifa->ifa_addr->sa_family != af)
1288: continue;
1289: ifa_maybe = ifa;
1.185 dyoung 1290: if (ifa->ifa_netmask == NULL) {
1.1 cgd 1291: if (equal(addr, ifa->ifa_addr) ||
1.53 thorpej 1292: (ifa->ifa_dstaddr &&
1293: equal(addr, ifa->ifa_dstaddr)))
1.185 dyoung 1294: return ifa;
1.1 cgd 1295: continue;
1296: }
1297: cp = addr->sa_data;
1298: cp2 = ifa->ifa_addr->sa_data;
1299: cp3 = ifa->ifa_netmask->sa_data;
1300: cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
1.53 thorpej 1301: for (; cp3 < cplim; cp3++) {
1.1 cgd 1302: if ((*cp++ ^ *cp2++) & *cp3)
1303: break;
1.53 thorpej 1304: }
1.1 cgd 1305: if (cp3 == cplim)
1.185 dyoung 1306: return ifa;
1.1 cgd 1307: }
1.185 dyoung 1308: return ifa_maybe;
1.1 cgd 1309: }
1.9 mycroft 1310:
1.1 cgd 1311: /*
1312: * Default action when installing a route with a Link Level gateway.
1313: * Lookup an appropriate real ifa to point to.
1314: * This should be moved to /sys/net/link.c eventually.
1315: */
1.15 mycroft 1316: void
1.228 dyoung 1317: link_rtrequest(int cmd, struct rtentry *rt, const struct rt_addrinfo *info)
1.1 cgd 1318: {
1.61 augustss 1319: struct ifaddr *ifa;
1.194 dyoung 1320: const struct sockaddr *dst;
1.15 mycroft 1321: struct ifnet *ifp;
1.1 cgd 1322:
1.225 dyoung 1323: if (cmd != RTM_ADD || (ifa = rt->rt_ifa) == NULL ||
1324: (ifp = ifa->ifa_ifp) == NULL || (dst = rt_getkey(rt)) == NULL)
1.1 cgd 1325: return;
1.24 christos 1326: if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
1.176 dyoung 1327: rt_replace_ifa(rt, ifa);
1.1 cgd 1328: if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
1.82 itojun 1329: ifa->ifa_rtrequest(cmd, rt, info);
1.1 cgd 1330: }
1331: }
1332:
1333: /*
1.159 dyoung 1334: * Handle a change in the interface link state.
1.264 roy 1335: * XXX: We should listen to the routing socket in-kernel rather
1336: * than calling in6_if_link_* functions directly from here.
1.159 dyoung 1337: */
1338: void
1339: if_link_state_change(struct ifnet *ifp, int link_state)
1340: {
1.268 martin 1341: int s;
1.269 mrg 1342: #if defined(DEBUG) || defined(INET6)
1.268 martin 1343: int old_link_state;
1344: #endif
1.263 roy 1345:
1.264 roy 1346: s = splnet();
1347: if (ifp->if_link_state == link_state) {
1348: splx(s);
1.185 dyoung 1349: return;
1.264 roy 1350: }
1.263 roy 1351:
1.269 mrg 1352: #if defined(DEBUG) || defined(INET6)
1.263 roy 1353: old_link_state = ifp->if_link_state;
1.268 martin 1354: #endif
1.185 dyoung 1355: ifp->if_link_state = link_state;
1.263 roy 1356: #ifdef DEBUG
1357: log(LOG_DEBUG, "%s: link state %s (was %s)\n", ifp->if_xname,
1358: link_state == LINK_STATE_UP ? "UP" :
1359: link_state == LINK_STATE_DOWN ? "DOWN" :
1360: "UNKNOWN",
1.264 roy 1361: old_link_state == LINK_STATE_UP ? "UP" :
1.263 roy 1362: old_link_state == LINK_STATE_DOWN ? "DOWN" :
1363: "UNKNOWN");
1364: #endif
1365:
1366: #ifdef INET6
1367: /*
1368: * When going from UNKNOWN to UP, we need to mark existing
1369: * IPv6 addresses as tentative and restart DAD as we may have
1370: * erroneously not found a duplicate.
1371: *
1372: * This needs to happen before rt_ifmsg to avoid a race where
1373: * listeners would have an address and expect it to work right
1374: * away.
1375: */
1.270 pooka 1376: if (in6_present && link_state == LINK_STATE_UP &&
1.263 roy 1377: old_link_state == LINK_STATE_UNKNOWN)
1.264 roy 1378: in6_if_link_down(ifp);
1.263 roy 1379: #endif
1380:
1.159 dyoung 1381: /* Notify that the link state has changed. */
1.185 dyoung 1382: rt_ifmsg(ifp);
1.263 roy 1383:
1.166 liamjfoy 1384: #if NCARP > 0
1.185 dyoung 1385: if (ifp->if_carp)
1386: carp_carpdev_state(ifp);
1.166 liamjfoy 1387: #endif
1.263 roy 1388:
1389: #ifdef INET6
1.270 pooka 1390: if (in6_present) {
1391: if (link_state == LINK_STATE_DOWN)
1392: in6_if_link_down(ifp);
1393: else if (link_state == LINK_STATE_UP)
1394: in6_if_link_up(ifp);
1395: }
1.263 roy 1396: #endif
1.264 roy 1397:
1398: splx(s);
1.159 dyoung 1399: }
1400:
1401: /*
1.1 cgd 1402: * Mark an interface down and notify protocols of
1403: * the transition.
1.23 mycroft 1404: * NOTE: must be called at splsoftnet or equivalent.
1.1 cgd 1405: */
1.15 mycroft 1406: void
1.163 thorpej 1407: if_down(struct ifnet *ifp)
1.1 cgd 1408: {
1.61 augustss 1409: struct ifaddr *ifa;
1.1 cgd 1410:
1411: ifp->if_flags &= ~IFF_UP;
1.232 christos 1412: nanotime(&ifp->if_lastchange);
1.204 dyoung 1413: IFADDR_FOREACH(ifa, ifp)
1.1 cgd 1414: pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
1.78 thorpej 1415: IFQ_PURGE(&ifp->if_snd);
1.166 liamjfoy 1416: #if NCARP > 0
1417: if (ifp->if_carp)
1418: carp_carpdev_state(ifp);
1419: #endif
1.15 mycroft 1420: rt_ifmsg(ifp);
1.263 roy 1421: #ifdef INET6
1.270 pooka 1422: if (in6_present)
1423: in6_if_down(ifp);
1.263 roy 1424: #endif
1.15 mycroft 1425: }
1426:
1427: /*
1428: * Mark an interface up and notify protocols of
1429: * the transition.
1.23 mycroft 1430: * NOTE: must be called at splsoftnet or equivalent.
1.15 mycroft 1431: */
1432: void
1.163 thorpej 1433: if_up(struct ifnet *ifp)
1.15 mycroft 1434: {
1.24 christos 1435: #ifdef notyet
1.61 augustss 1436: struct ifaddr *ifa;
1.24 christos 1437: #endif
1.15 mycroft 1438:
1439: ifp->if_flags |= IFF_UP;
1.232 christos 1440: nanotime(&ifp->if_lastchange);
1.15 mycroft 1441: #ifdef notyet
1442: /* this has no effect on IP, and will kill all ISO connections XXX */
1.204 dyoung 1443: IFADDR_FOREACH(ifa, ifp)
1.15 mycroft 1444: pfctlinput(PRC_IFUP, ifa->ifa_addr);
1445: #endif
1.166 liamjfoy 1446: #if NCARP > 0
1447: if (ifp->if_carp)
1448: carp_carpdev_state(ifp);
1449: #endif
1.15 mycroft 1450: rt_ifmsg(ifp);
1.49 itojun 1451: #ifdef INET6
1.270 pooka 1452: if (in6_present)
1453: in6_if_up(ifp);
1.49 itojun 1454: #endif
1.1 cgd 1455: }
1456:
1457: /*
1458: * Handle interface watchdog timer routines. Called
1459: * from softclock, we decrement timers (if set) and
1460: * call the appropriate interface routine on expiration.
1461: */
1.4 andrew 1462: void
1.177 christos 1463: if_slowtimo(void *arg)
1.1 cgd 1464: {
1.61 augustss 1465: struct ifnet *ifp;
1.88 thorpej 1466: int s = splnet();
1.1 cgd 1467:
1.185 dyoung 1468: IFNET_FOREACH(ifp) {
1.1 cgd 1469: if (ifp->if_timer == 0 || --ifp->if_timer)
1470: continue;
1.185 dyoung 1471: if (ifp->if_watchdog != NULL)
1.34 thorpej 1472: (*ifp->if_watchdog)(ifp);
1.1 cgd 1473: }
1474: splx(s);
1.185 dyoung 1475: callout_reset(&if_slowtimo_ch, hz / IFNET_SLOWHZ, if_slowtimo, NULL);
1.65 thorpej 1476: }
1477:
1478: /*
1479: * Set/clear promiscuous mode on interface ifp based on the truth value
1480: * of pswitch. The calls are reference counted so that only the first
1481: * "on" request actually has an effect, as does the final "off" request.
1482: * Results are undefined if the "off" and "on" requests are not matched.
1483: */
1484: int
1.163 thorpej 1485: ifpromisc(struct ifnet *ifp, int pswitch)
1.65 thorpej 1486: {
1487: int pcount, ret;
1.259 dyoung 1488: short nflags;
1.65 thorpej 1489:
1490: pcount = ifp->if_pcount;
1491: if (pswitch) {
1492: /*
1.71 thorpej 1493: * Allow the device to be "placed" into promiscuous
1494: * mode even if it is not configured up. It will
1.242 mbalmer 1495: * consult IFF_PROMISC when it is brought up.
1.65 thorpej 1496: */
1.68 pk 1497: if (ifp->if_pcount++ != 0)
1.185 dyoung 1498: return 0;
1.252 dyoung 1499: nflags = ifp->if_flags | IFF_PROMISC;
1.65 thorpej 1500: } else {
1501: if (--ifp->if_pcount > 0)
1.185 dyoung 1502: return 0;
1.252 dyoung 1503: nflags = ifp->if_flags & ~IFF_PROMISC;
1.65 thorpej 1504: }
1.252 dyoung 1505: ret = if_flags_set(ifp, nflags);
1.65 thorpej 1506: /* Restore interface state if not successful. */
1507: if (ret != 0) {
1508: ifp->if_pcount = pcount;
1509: }
1.185 dyoung 1510: return ret;
1.1 cgd 1511: }
1512:
1513: /*
1514: * Map interface name to
1515: * interface structure pointer.
1516: */
1517: struct ifnet *
1.163 thorpej 1518: ifunit(const char *name)
1.1 cgd 1519: {
1.61 augustss 1520: struct ifnet *ifp;
1.105 matt 1521: const char *cp = name;
1522: u_int unit = 0;
1523: u_int i;
1524:
1525: /*
1526: * If the entire name is a number, treat it as an ifindex.
1527: */
1528: for (i = 0; i < IFNAMSIZ && *cp >= '0' && *cp <= '9'; i++, cp++) {
1529: unit = unit * 10 + (*cp - '0');
1530: }
1531:
1532: /*
1533: * If the number took all of the name, then it's a valid ifindex.
1534: */
1535: if (i == IFNAMSIZ || (cp != name && *cp == '\0')) {
1.137 itojun 1536: if (unit >= if_indexlim)
1.185 dyoung 1537: return NULL;
1.105 matt 1538: ifp = ifindex2ifnet[unit];
1539: if (ifp == NULL || ifp->if_output == if_nulloutput)
1.185 dyoung 1540: return NULL;
1541: return ifp;
1.105 matt 1542: }
1.34 thorpej 1543:
1.185 dyoung 1544: IFNET_FOREACH(ifp) {
1.53 thorpej 1545: if (ifp->if_output == if_nulloutput)
1546: continue;
1547: if (strcmp(ifp->if_xname, name) == 0)
1.185 dyoung 1548: return ifp;
1.53 thorpej 1549: }
1.185 dyoung 1550: return NULL;
1.1 cgd 1551: }
1.49 itojun 1552:
1.250 rmind 1553: ifnet_t *
1554: if_byindex(u_int idx)
1555: {
1556: return (idx < if_indexlim) ? ifindex2ifnet[idx] : NULL;
1557: }
1558:
1.211 dyoung 1559: /* common */
1.215 dyoung 1560: int
1561: ifioctl_common(struct ifnet *ifp, u_long cmd, void *data)
1.211 dyoung 1562: {
1.224 dyoung 1563: int s;
1.215 dyoung 1564: struct ifreq *ifr;
1565: struct ifcapreq *ifcr;
1566: struct ifdatareq *ifdr;
1.211 dyoung 1567:
1568: switch (cmd) {
1569: case SIOCSIFCAP:
1.215 dyoung 1570: ifcr = data;
1.211 dyoung 1571: if ((ifcr->ifcr_capenable & ~ifp->if_capabilities) != 0)
1572: return EINVAL;
1573:
1.213 dyoung 1574: if (ifcr->ifcr_capenable == ifp->if_capenable)
1575: return 0;
1.211 dyoung 1576:
1.213 dyoung 1577: ifp->if_capenable = ifcr->ifcr_capenable;
1.211 dyoung 1578:
1.213 dyoung 1579: /* Pre-compute the checksum flags mask. */
1580: ifp->if_csum_flags_tx = 0;
1581: ifp->if_csum_flags_rx = 0;
1582: if (ifp->if_capenable & IFCAP_CSUM_IPv4_Tx) {
1583: ifp->if_csum_flags_tx |= M_CSUM_IPv4;
1584: }
1585: if (ifp->if_capenable & IFCAP_CSUM_IPv4_Rx) {
1586: ifp->if_csum_flags_rx |= M_CSUM_IPv4;
1587: }
1.211 dyoung 1588:
1.213 dyoung 1589: if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx) {
1590: ifp->if_csum_flags_tx |= M_CSUM_TCPv4;
1591: }
1592: if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Rx) {
1593: ifp->if_csum_flags_rx |= M_CSUM_TCPv4;
1594: }
1.211 dyoung 1595:
1.213 dyoung 1596: if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx) {
1597: ifp->if_csum_flags_tx |= M_CSUM_UDPv4;
1598: }
1599: if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Rx) {
1600: ifp->if_csum_flags_rx |= M_CSUM_UDPv4;
1601: }
1.211 dyoung 1602:
1.213 dyoung 1603: if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Tx) {
1604: ifp->if_csum_flags_tx |= M_CSUM_TCPv6;
1605: }
1606: if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Rx) {
1607: ifp->if_csum_flags_rx |= M_CSUM_TCPv6;
1608: }
1.211 dyoung 1609:
1.213 dyoung 1610: if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Tx) {
1611: ifp->if_csum_flags_tx |= M_CSUM_UDPv6;
1.211 dyoung 1612: }
1.213 dyoung 1613: if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Rx) {
1614: ifp->if_csum_flags_rx |= M_CSUM_UDPv6;
1615: }
1.215 dyoung 1616: if (ifp->if_flags & IFF_UP)
1617: return ENETRESET;
1618: return 0;
1.211 dyoung 1619: case SIOCSIFFLAGS:
1.215 dyoung 1620: ifr = data;
1.211 dyoung 1621: if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
1622: s = splnet();
1623: if_down(ifp);
1624: splx(s);
1625: }
1626: if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
1627: s = splnet();
1628: if_up(ifp);
1629: splx(s);
1630: }
1631: ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
1632: (ifr->ifr_flags &~ IFF_CANTCHANGE);
1633: break;
1634: case SIOCGIFFLAGS:
1.215 dyoung 1635: ifr = data;
1.211 dyoung 1636: ifr->ifr_flags = ifp->if_flags;
1637: break;
1638:
1639: case SIOCGIFMETRIC:
1.215 dyoung 1640: ifr = data;
1.211 dyoung 1641: ifr->ifr_metric = ifp->if_metric;
1642: break;
1643:
1644: case SIOCGIFMTU:
1.215 dyoung 1645: ifr = data;
1.211 dyoung 1646: ifr->ifr_mtu = ifp->if_mtu;
1647: break;
1648:
1649: case SIOCGIFDLT:
1.215 dyoung 1650: ifr = data;
1.211 dyoung 1651: ifr->ifr_dlt = ifp->if_dlt;
1652: break;
1653:
1654: case SIOCGIFCAP:
1.215 dyoung 1655: ifcr = data;
1.211 dyoung 1656: ifcr->ifcr_capabilities = ifp->if_capabilities;
1657: ifcr->ifcr_capenable = ifp->if_capenable;
1658: break;
1659:
1660: case SIOCSIFMETRIC:
1.215 dyoung 1661: ifr = data;
1.211 dyoung 1662: ifp->if_metric = ifr->ifr_metric;
1663: break;
1664:
1665: case SIOCGIFDATA:
1.215 dyoung 1666: ifdr = data;
1.211 dyoung 1667: ifdr->ifdr_data = ifp->if_data;
1668: break;
1669:
1.266 christos 1670: case SIOCGIFINDEX:
1671: ifr = data;
1672: ifr->ifr_index = ifp->if_index;
1673: break;
1674:
1.211 dyoung 1675: case SIOCZIFDATA:
1.215 dyoung 1676: ifdr = data;
1.211 dyoung 1677: ifdr->ifdr_data = ifp->if_data;
1678: /*
1679: * Assumes that the volatile counters that can be
1680: * zero'ed are at the end of if_data.
1681: */
1682: memset(&ifp->if_data.ifi_ipackets, 0, sizeof(ifp->if_data) -
1683: offsetof(struct if_data, ifi_ipackets));
1.261 msaitoh 1684: /*
1685: * The memset() clears to the bottm of if_data. In the area,
1686: * if_lastchange is included. Please be careful if new entry
1687: * will be added into if_data or rewite this.
1688: *
1689: * And also, update if_lastchnage.
1690: */
1691: getnanotime(&ifp->if_lastchange);
1.211 dyoung 1692: break;
1.215 dyoung 1693: case SIOCSIFMTU:
1694: ifr = data;
1695: if (ifp->if_mtu == ifr->ifr_mtu)
1696: break;
1697: ifp->if_mtu = ifr->ifr_mtu;
1698: /*
1699: * If the link MTU changed, do network layer specific procedure.
1700: */
1701: #ifdef INET6
1.271 pooka 1702: if (in6_present)
1703: nd6_setmtu(ifp);
1.215 dyoung 1704: #endif
1705: return ENETRESET;
1.211 dyoung 1706: default:
1.223 dyoung 1707: return ENOTTY;
1.211 dyoung 1708: }
1709: return 0;
1710: }
1711:
1.235 dyoung 1712: int
1713: ifaddrpref_ioctl(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
1714: lwp_t *l)
1715: {
1716: struct if_addrprefreq *ifap = (struct if_addrprefreq *)data;
1717: struct ifaddr *ifa;
1718: const struct sockaddr *any, *sa;
1719: union {
1720: struct sockaddr sa;
1721: struct sockaddr_storage ss;
1.236 jakllsch 1722: } u, v;
1.235 dyoung 1723:
1724: switch (cmd) {
1725: case SIOCSIFADDRPREF:
1726: if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
1727: KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
1728: NULL) != 0)
1729: return EPERM;
1730: case SIOCGIFADDRPREF:
1731: break;
1732: default:
1733: return EOPNOTSUPP;
1734: }
1735:
1736: /* sanity checks */
1737: if (data == NULL || ifp == NULL) {
1738: panic("invalid argument to %s", __func__);
1739: /*NOTREACHED*/
1740: }
1741:
1742: /* address must be specified on ADD and DELETE */
1743: sa = sstocsa(&ifap->ifap_addr);
1744: if (sa->sa_family != sofamily(so))
1745: return EINVAL;
1746: if ((any = sockaddr_any(sa)) == NULL || sa->sa_len != any->sa_len)
1747: return EINVAL;
1748:
1.236 jakllsch 1749: sockaddr_externalize(&v.sa, sizeof(v.ss), sa);
1750:
1.235 dyoung 1751: IFADDR_FOREACH(ifa, ifp) {
1752: if (ifa->ifa_addr->sa_family != sa->sa_family)
1753: continue;
1754: sockaddr_externalize(&u.sa, sizeof(u.ss), ifa->ifa_addr);
1.236 jakllsch 1755: if (sockaddr_cmp(&u.sa, &v.sa) == 0)
1.235 dyoung 1756: break;
1757: }
1758: if (ifa == NULL)
1759: return EADDRNOTAVAIL;
1760:
1761: switch (cmd) {
1762: case SIOCSIFADDRPREF:
1763: ifa->ifa_preference = ifap->ifap_preference;
1764: return 0;
1765: case SIOCGIFADDRPREF:
1766: /* fill in the if_laddrreq structure */
1767: (void)sockaddr_copy(sstosa(&ifap->ifap_addr),
1768: sizeof(ifap->ifap_addr), ifa->ifa_addr);
1769: ifap->ifap_preference = ifa->ifa_preference;
1770: return 0;
1771: default:
1772: return EOPNOTSUPP;
1773: }
1774: }
1775:
1.253 dyoung 1776: static void
1.254 dyoung 1777: ifnet_lock_enter(struct ifnet_lock *il)
1.253 dyoung 1778: {
1.254 dyoung 1779: uint64_t *nenter;
1780:
1.255 dyoung 1781: /* Before trying to acquire the mutex, increase the count of threads
1782: * who have entered or who wait to enter the critical section.
1783: * Avoid one costly locked memory transaction by keeping a count for
1784: * each CPU.
1785: */
1.254 dyoung 1786: nenter = percpu_getref(il->il_nenter);
1.253 dyoung 1787: (*nenter)++;
1.254 dyoung 1788: percpu_putref(il->il_nenter);
1789: mutex_enter(&il->il_lock);
1.253 dyoung 1790: }
1791:
1792: static void
1.254 dyoung 1793: ifnet_lock_exit(struct ifnet_lock *il)
1.253 dyoung 1794: {
1.255 dyoung 1795: /* Increase the count of threads who have exited the critical
1796: * section. Increase while we still hold the lock.
1797: */
1.254 dyoung 1798: il->il_nexit++;
1799: mutex_exit(&il->il_lock);
1.253 dyoung 1800: }
1801:
1.1 cgd 1802: /*
1803: * Interface ioctls.
1804: */
1.273 pooka 1805: static int
1806: doifioctl(struct socket *so, u_long cmd, void *data, struct lwp *l)
1.1 cgd 1807: {
1.61 augustss 1808: struct ifnet *ifp;
1809: struct ifreq *ifr;
1.217 martin 1810: int error = 0;
1.191 christos 1811: #if defined(COMPAT_OSOCK) || defined(COMPAT_OIFREQ)
1812: u_long ocmd = cmd;
1813: #endif
1.49 itojun 1814: short oif_flags;
1.186 christos 1815: #ifdef COMPAT_OIFREQ
1816: struct ifreq ifrb;
1.187 xtraeme 1817: struct oifreq *oifr = NULL;
1.186 christos 1818: #endif
1.1 cgd 1819:
1820: switch (cmd) {
1.186 christos 1821: #ifdef COMPAT_OIFREQ
1822: case OSIOCGIFCONF:
1823: case OOSIOCGIFCONF:
1824: return compat_ifconf(cmd, data);
1825: #endif
1.232 christos 1826: #ifdef COMPAT_OIFDATA
1827: case OSIOCGIFDATA:
1828: case OSIOCZIFDATA:
1829: return compat_ifdatareq(l, cmd, data);
1830: #endif
1.1 cgd 1831: case SIOCGIFCONF:
1.185 dyoung 1832: return ifconf(cmd, data);
1.231 dyoung 1833: case SIOCINITIFADDR:
1834: return EPERM;
1.1 cgd 1835: }
1.191 christos 1836:
1.186 christos 1837: #ifdef COMPAT_OIFREQ
1.196 skd 1838: cmd = compat_cvtcmd(cmd);
1.186 christos 1839: if (cmd != ocmd) {
1840: oifr = data;
1841: data = ifr = &ifrb;
1842: ifreqo2n(oifr, ifr);
1843: } else
1844: #endif
1845: ifr = data;
1.63 thorpej 1846:
1.174 elad 1847: ifp = ifunit(ifr->ifr_name);
1848:
1.63 thorpej 1849: switch (cmd) {
1850: case SIOCIFCREATE:
1851: case SIOCIFDESTROY:
1.185 dyoung 1852: if (l != NULL) {
1.174 elad 1853: error = kauth_authorize_network(l->l_cred,
1854: KAUTH_NETWORK_INTERFACE,
1855: KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp,
1856: (void *)cmd, NULL);
1.185 dyoung 1857: if (error != 0)
1.151 yamt 1858: return error;
1859: }
1.185 dyoung 1860: return (cmd == SIOCIFCREATE) ?
1.64 thorpej 1861: if_clone_create(ifr->ifr_name) :
1.185 dyoung 1862: if_clone_destroy(ifr->ifr_name);
1.67 thorpej 1863:
1864: case SIOCIFGCLONERS:
1.185 dyoung 1865: return if_clone_list((struct if_clonereq *)data);
1.63 thorpej 1866: }
1867:
1.185 dyoung 1868: if (ifp == NULL)
1869: return ENXIO;
1.151 yamt 1870:
1871: switch (cmd) {
1.233 christos 1872: case SIOCALIFADDR:
1873: case SIOCDLIFADDR:
1874: case SIOCSIFADDRPREF:
1.151 yamt 1875: case SIOCSIFFLAGS:
1876: case SIOCSIFCAP:
1877: case SIOCSIFMETRIC:
1878: case SIOCZIFDATA:
1879: case SIOCSIFMTU:
1880: case SIOCSIFPHYADDR:
1881: case SIOCDIFPHYADDR:
1882: #ifdef INET6
1883: case SIOCSIFPHYADDR_IN6:
1884: #endif
1885: case SIOCSLIFPHYADDR:
1886: case SIOCADDMULTI:
1887: case SIOCDELMULTI:
1888: case SIOCSIFMEDIA:
1.154 perry 1889: case SIOCSDRVSPEC:
1.196 skd 1890: case SIOCG80211:
1891: case SIOCS80211:
1.151 yamt 1892: case SIOCS80211NWID:
1893: case SIOCS80211NWKEY:
1894: case SIOCS80211POWER:
1895: case SIOCS80211BSSID:
1896: case SIOCS80211CHANNEL:
1.249 pooka 1897: case SIOCSLINKSTR:
1.185 dyoung 1898: if (l != NULL) {
1.174 elad 1899: error = kauth_authorize_network(l->l_cred,
1900: KAUTH_NETWORK_INTERFACE,
1901: KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp,
1902: (void *)cmd, NULL);
1.185 dyoung 1903: if (error != 0)
1.151 yamt 1904: return error;
1905: }
1906: }
1907:
1.49 itojun 1908: oif_flags = ifp->if_flags;
1.1 cgd 1909:
1.254 dyoung 1910: ifnet_lock_enter(ifp->if_ioctl_lock);
1.231 dyoung 1911: error = (*ifp->if_ioctl)(ifp, cmd, data);
1912: if (error != ENOTTY)
1913: ;
1914: else if (so->so_proto == NULL)
1.252 dyoung 1915: error = EOPNOTSUPP;
1.231 dyoung 1916: else {
1.161 christos 1917: #ifdef COMPAT_OSOCK
1.186 christos 1918: error = compat_ifioctl(so, ocmd, cmd, data, l);
1.161 christos 1919: #else
1.275 rmind 1920: error = (*so->so_proto->pr_usrreqs->pr_generic)(so,
1921: PRU_CONTROL, (struct mbuf *)cmd, (struct mbuf *)data,
1.220 martin 1922: (struct mbuf *)ifp, l);
1.1 cgd 1923: #endif
1.49 itojun 1924: }
1.1 cgd 1925:
1.49 itojun 1926: if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
1927: #ifdef INET6
1.270 pooka 1928: if (in6_present && (ifp->if_flags & IFF_UP) != 0) {
1.217 martin 1929: int s = splnet();
1.49 itojun 1930: in6_if_up(ifp);
1931: splx(s);
1932: }
1.1 cgd 1933: #endif
1934: }
1.186 christos 1935: #ifdef COMPAT_OIFREQ
1936: if (cmd != ocmd)
1.246 christos 1937: ifreqn2o(oifr, ifr);
1.186 christos 1938: #endif
1.49 itojun 1939:
1.254 dyoung 1940: ifnet_lock_exit(ifp->if_ioctl_lock);
1.185 dyoung 1941: return error;
1.1 cgd 1942: }
1943:
1.255 dyoung 1944: /* This callback adds to the sum in `arg' the number of
1945: * threads on `ci' who have entered or who wait to enter the
1946: * critical section.
1947: */
1.252 dyoung 1948: static void
1.254 dyoung 1949: ifnet_lock_sum(void *p, void *arg, struct cpu_info *ci)
1.252 dyoung 1950: {
1951: uint64_t *sum = arg, *nenter = p;
1952:
1953: *sum += *nenter;
1954: }
1955:
1.255 dyoung 1956: /* Return the number of threads who have entered or who wait
1957: * to enter the critical section on all CPUs.
1958: */
1.252 dyoung 1959: static uint64_t
1.254 dyoung 1960: ifnet_lock_entrances(struct ifnet_lock *il)
1.252 dyoung 1961: {
1962: uint64_t sum = 0;
1963:
1.254 dyoung 1964: percpu_foreach(il->il_nenter, ifnet_lock_sum, &sum);
1.252 dyoung 1965:
1966: return sum;
1967: }
1968:
1969: static int
1970: ifioctl_attach(struct ifnet *ifp)
1971: {
1.254 dyoung 1972: struct ifnet_lock *il;
1973:
1.255 dyoung 1974: /* If the driver has not supplied its own if_ioctl, then
1975: * supply the default.
1976: */
1.252 dyoung 1977: if (ifp->if_ioctl == NULL)
1978: ifp->if_ioctl = ifioctl_common;
1979:
1.255 dyoung 1980: /* Create an ifnet_lock for synchronizing ifioctls. */
1.254 dyoung 1981: if ((il = kmem_zalloc(sizeof(*il), KM_SLEEP)) == NULL)
1.252 dyoung 1982: return ENOMEM;
1983:
1.254 dyoung 1984: il->il_nenter = percpu_alloc(sizeof(uint64_t));
1985: if (il->il_nenter == NULL) {
1986: kmem_free(il, sizeof(*il));
1987: return ENOMEM;
1988: }
1989:
1990: mutex_init(&il->il_lock, MUTEX_DEFAULT, IPL_NONE);
1991: cv_init(&il->il_emptied, ifp->if_xname);
1992:
1993: ifp->if_ioctl_lock = il;
1.252 dyoung 1994:
1995: return 0;
1996: }
1997:
1.255 dyoung 1998: /*
1999: * This must not be called until after `ifp' has been withdrawn from the
2000: * ifnet tables so that ifioctl() cannot get a handle on it by calling
2001: * ifunit().
2002: */
1.252 dyoung 2003: static void
2004: ifioctl_detach(struct ifnet *ifp)
2005: {
1.254 dyoung 2006: struct ifnet_lock *il;
2007:
2008: il = ifp->if_ioctl_lock;
2009: mutex_enter(&il->il_lock);
1.255 dyoung 2010: /* Install if_nullioctl to make sure that any thread that
2011: * subsequently enters the critical section will quit it
2012: * immediately and signal the condition variable that we
2013: * wait on, below.
2014: */
1.252 dyoung 2015: ifp->if_ioctl = if_nullioctl;
1.255 dyoung 2016: /* Sleep while threads are still in the critical section or
2017: * wait to enter it.
2018: */
1.254 dyoung 2019: while (ifnet_lock_entrances(il) != il->il_nexit)
2020: cv_wait(&il->il_emptied, &il->il_lock);
1.255 dyoung 2021: /* At this point, we are the only thread still in the critical
2022: * section, and no new thread can get a handle on the ifioctl
2023: * lock, so it is safe to free its memory.
2024: */
1.254 dyoung 2025: mutex_exit(&il->il_lock);
2026: ifp->if_ioctl_lock = NULL;
1.255 dyoung 2027: percpu_free(il->il_nenter, sizeof(uint64_t));
2028: il->il_nenter = NULL;
1.258 jakllsch 2029: cv_destroy(&il->il_emptied);
1.257 dyoung 2030: mutex_destroy(&il->il_lock);
1.254 dyoung 2031: kmem_free(il, sizeof(*il));
1.252 dyoung 2032: }
2033:
1.1 cgd 2034: /*
2035: * Return interface configuration
2036: * of system. List may be used
2037: * in later ioctl's (above) to get
2038: * other information.
1.200 gdt 2039: *
2040: * Each record is a struct ifreq. Before the addition of
2041: * sockaddr_storage, the API rule was that sockaddr flavors that did
2042: * not fit would extend beyond the struct ifreq, with the next struct
2043: * ifreq starting sa_len beyond the struct sockaddr. Because the
2044: * union in struct ifreq includes struct sockaddr_storage, every kind
2045: * of sockaddr must fit. Thus, there are no longer any overlength
2046: * records.
2047: *
2048: * Records are added to the user buffer if they fit, and ifc_len is
2049: * adjusted to the length that was written. Thus, the user is only
2050: * assured of getting the complete list if ifc_len on return is at
2051: * least sizeof(struct ifreq) less than it was on entry.
2052: *
2053: * If the user buffer pointer is NULL, this routine copies no data and
2054: * returns the amount of space that would be needed.
2055: *
2056: * Invariants:
2057: * ifrp points to the next part of the user's buffer to be used. If
2058: * ifrp != NULL, space holds the number of bytes remaining that we may
2059: * write at ifrp. Otherwise, space holds the number of bytes that
2060: * would have been written had there been adequate space.
1.1 cgd 2061: */
2062: /*ARGSUSED*/
1.15 mycroft 2063: int
1.183 christos 2064: ifconf(u_long cmd, void *data)
1.1 cgd 2065: {
1.61 augustss 2066: struct ifconf *ifc = (struct ifconf *)data;
2067: struct ifnet *ifp;
2068: struct ifaddr *ifa;
1.1 cgd 2069: struct ifreq ifr, *ifrp;
1.190 enami 2070: int space, error = 0;
1.200 gdt 2071: const int sz = (int)sizeof(struct ifreq);
1.1 cgd 2072:
1.190 enami 2073: if ((ifrp = ifc->ifc_req) == NULL)
1.127 christos 2074: space = 0;
1.190 enami 2075: else
2076: space = ifc->ifc_len;
1.153 matt 2077: IFNET_FOREACH(ifp) {
1.175 christos 2078: (void)strncpy(ifr.ifr_name, ifp->if_xname,
1.173 christos 2079: sizeof(ifr.ifr_name));
1.175 christos 2080: if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0')
2081: return ENAMETOOLONG;
1.205 dyoung 2082: if (IFADDR_EMPTY(ifp)) {
1.200 gdt 2083: /* Interface with no addresses - send zero sockaddr. */
1.127 christos 2084: memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1.218 dyoung 2085: if (ifrp == NULL) {
2086: space += sz;
2087: continue;
2088: }
2089: if (space >= sz) {
2090: error = copyout(&ifr, ifrp, sz);
2091: if (error != 0)
2092: return error;
2093: ifrp++;
2094: space -= sz;
1.70 mellon 2095: }
1.127 christos 2096: }
2097:
1.204 dyoung 2098: IFADDR_FOREACH(ifa, ifp) {
1.61 augustss 2099: struct sockaddr *sa = ifa->ifa_addr;
1.200 gdt 2100: /* all sockaddrs must fit in sockaddr_storage */
2101: KASSERT(sa->sa_len <= sizeof(ifr.ifr_ifru));
2102:
1.218 dyoung 2103: if (ifrp == NULL) {
2104: space += sz;
2105: continue;
2106: }
2107: memcpy(&ifr.ifr_space, sa, sa->sa_len);
2108: if (space >= sz) {
2109: error = copyout(&ifr, ifrp, sz);
2110: if (error != 0)
2111: return (error);
2112: ifrp++; space -= sz;
1.1 cgd 2113: }
2114: }
2115: }
1.218 dyoung 2116: if (ifrp != NULL) {
1.200 gdt 2117: KASSERT(0 <= space && space <= ifc->ifc_len);
1.127 christos 2118: ifc->ifc_len -= space;
1.218 dyoung 2119: } else {
1.200 gdt 2120: KASSERT(space >= 0);
2121: ifc->ifc_len = space;
2122: }
1.190 enami 2123: return (0);
1.1 cgd 2124: }
1.133 jonathan 2125:
1.198 dyoung 2126: int
1.247 christos 2127: ifreq_setaddr(u_long cmd, struct ifreq *ifr, const struct sockaddr *sa)
1.198 dyoung 2128: {
2129: uint8_t len;
1.247 christos 2130: #ifdef COMPAT_OIFREQ
2131: struct ifreq ifrb;
2132: struct oifreq *oifr = NULL;
2133: u_long ocmd = cmd;
2134: cmd = compat_cvtcmd(cmd);
2135: if (cmd != ocmd) {
2136: oifr = (struct oifreq *)(void *)ifr;
2137: ifr = &ifrb;
2138: ifreqo2n(oifr, ifr);
2139: len = sizeof(oifr->ifr_addr);
2140: } else
2141: #endif
2142: len = sizeof(ifr->ifr_ifru.ifru_space);
1.198 dyoung 2143:
2144: if (len < sa->sa_len)
2145: return EFBIG;
1.247 christos 2146:
1.241 joerg 2147: memset(&ifr->ifr_addr, 0, len);
1.202 dyoung 2148: sockaddr_copy(&ifr->ifr_addr, len, sa);
1.247 christos 2149:
2150: #ifdef COMPAT_OIFREQ
2151: if (cmd != ocmd)
2152: ifreqn2o(oifr, ifr);
2153: #endif
1.198 dyoung 2154: return 0;
2155: }
2156:
1.155 christos 2157: /*
2158: * Queue message on interface, and start output if interface
2159: * not yet active.
2160: */
2161: int
2162: ifq_enqueue(struct ifnet *ifp, struct mbuf *m
2163: ALTQ_COMMA ALTQ_DECL(struct altq_pktattr *pktattr))
2164: {
2165: int len = m->m_pkthdr.len;
2166: int mflags = m->m_flags;
2167: int s = splnet();
2168: int error;
2169:
1.156 christos 2170: IFQ_ENQUEUE(&ifp->if_snd, m, pktattr, error);
1.185 dyoung 2171: if (error != 0)
2172: goto out;
1.155 christos 2173: ifp->if_obytes += len;
2174: if (mflags & M_MCAST)
2175: ifp->if_omcasts++;
2176: if ((ifp->if_flags & IFF_OACTIVE) == 0)
2177: (*ifp->if_start)(ifp);
1.185 dyoung 2178: out:
1.155 christos 2179: splx(s);
2180: return error;
2181: }
2182:
2183: /*
2184: * Queue message on interface, possibly using a second fast queue
2185: */
2186: int
2187: ifq_enqueue2(struct ifnet *ifp, struct ifqueue *ifq, struct mbuf *m
2188: ALTQ_COMMA ALTQ_DECL(struct altq_pktattr *pktattr))
2189: {
2190: int error = 0;
2191:
2192: if (ifq != NULL
2193: #ifdef ALTQ
2194: && ALTQ_IS_ENABLED(&ifp->if_snd) == 0
2195: #endif
2196: ) {
2197: if (IF_QFULL(ifq)) {
2198: IF_DROP(&ifp->if_snd);
2199: m_freem(m);
2200: if (error == 0)
2201: error = ENOBUFS;
1.185 dyoung 2202: } else
1.155 christos 2203: IF_ENQUEUE(ifq, m);
2204: } else
1.156 christos 2205: IFQ_ENQUEUE(&ifp->if_snd, m, pktattr, error);
1.155 christos 2206: if (error != 0) {
2207: ++ifp->if_oerrors;
2208: return error;
2209: }
2210: return 0;
2211: }
2212:
1.252 dyoung 2213: int
2214: if_addr_init(ifnet_t *ifp, struct ifaddr *ifa, const bool src)
2215: {
2216: int rc;
2217:
2218: if (ifp->if_initaddr != NULL)
2219: rc = (*ifp->if_initaddr)(ifp, ifa, src);
2220: else if (src ||
2221: (rc = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ifa)) == ENOTTY)
2222: rc = (*ifp->if_ioctl)(ifp, SIOCINITIFADDR, ifa);
2223:
2224: return rc;
2225: }
2226:
2227: int
2228: if_flags_set(ifnet_t *ifp, const short flags)
2229: {
2230: int rc;
2231:
2232: if (ifp->if_setflags != NULL)
2233: rc = (*ifp->if_setflags)(ifp, flags);
2234: else {
1.259 dyoung 2235: short cantflags, chgdflags;
1.256 dyoung 2236: struct ifreq ifr;
2237:
1.259 dyoung 2238: chgdflags = ifp->if_flags ^ flags;
2239: cantflags = chgdflags & IFF_CANTCHANGE;
1.256 dyoung 2240:
2241: if (cantflags != 0)
2242: ifp->if_flags ^= cantflags;
2243:
1.259 dyoung 2244: /* Traditionally, we do not call if_ioctl after
2245: * setting/clearing only IFF_PROMISC if the interface
2246: * isn't IFF_UP. Uphold that tradition.
2247: */
2248: if (chgdflags == IFF_PROMISC && (ifp->if_flags & IFF_UP) == 0)
2249: return 0;
2250:
2251: memset(&ifr, 0, sizeof(ifr));
2252:
1.256 dyoung 2253: ifr.ifr_flags = flags & ~IFF_CANTCHANGE;
1.252 dyoung 2254: rc = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, &ifr);
1.256 dyoung 2255:
2256: if (rc != 0 && cantflags != 0)
2257: ifp->if_flags ^= cantflags;
1.252 dyoung 2258: }
2259:
2260: return rc;
2261: }
2262:
2263: int
2264: if_mcast_op(ifnet_t *ifp, const unsigned long cmd, const struct sockaddr *sa)
2265: {
2266: int rc;
2267: struct ifreq ifr;
2268:
2269: if (ifp->if_mcastop != NULL)
2270: rc = (*ifp->if_mcastop)(ifp, cmd, sa);
2271: else {
2272: ifreq_setaddr(cmd, &ifr, sa);
2273: rc = (*ifp->if_ioctl)(ifp, cmd, &ifr);
2274: }
2275:
2276: return rc;
2277: }
1.155 christos 2278:
1.234 dyoung 2279: static void
2280: sysctl_sndq_setup(struct sysctllog **clog, const char *ifname,
2281: struct ifaltq *ifq)
2282: {
2283: const struct sysctlnode *cnode, *rnode;
2284:
2285: if (sysctl_createv(clog, 0, NULL, &rnode,
2286: CTLFLAG_PERMANENT,
2287: CTLTYPE_NODE, "interfaces",
2288: SYSCTL_DESCR("Per-interface controls"),
2289: NULL, 0, NULL, 0,
1.272 pooka 2290: CTL_NET, CTL_CREATE, CTL_EOL) != 0)
1.234 dyoung 2291: goto bad;
2292:
2293: if (sysctl_createv(clog, 0, &rnode, &rnode,
2294: CTLFLAG_PERMANENT,
2295: CTLTYPE_NODE, ifname,
2296: SYSCTL_DESCR("Interface controls"),
2297: NULL, 0, NULL, 0,
2298: CTL_CREATE, CTL_EOL) != 0)
2299: goto bad;
2300:
2301: if (sysctl_createv(clog, 0, &rnode, &rnode,
2302: CTLFLAG_PERMANENT,
2303: CTLTYPE_NODE, "sndq",
2304: SYSCTL_DESCR("Interface output queue controls"),
2305: NULL, 0, NULL, 0,
2306: CTL_CREATE, CTL_EOL) != 0)
2307: goto bad;
2308:
2309: if (sysctl_createv(clog, 0, &rnode, &cnode,
2310: CTLFLAG_PERMANENT,
2311: CTLTYPE_INT, "len",
2312: SYSCTL_DESCR("Current output queue length"),
2313: NULL, 0, &ifq->ifq_len, 0,
2314: CTL_CREATE, CTL_EOL) != 0)
2315: goto bad;
2316:
2317: if (sysctl_createv(clog, 0, &rnode, &cnode,
2318: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2319: CTLTYPE_INT, "maxlen",
2320: SYSCTL_DESCR("Maximum allowed output queue length"),
2321: NULL, 0, &ifq->ifq_maxlen, 0,
2322: CTL_CREATE, CTL_EOL) != 0)
2323: goto bad;
2324:
2325: if (sysctl_createv(clog, 0, &rnode, &cnode,
2326: CTLFLAG_PERMANENT,
2327: CTLTYPE_INT, "drops",
2328: SYSCTL_DESCR("Packets dropped due to full output queue"),
2329: NULL, 0, &ifq->ifq_drops, 0,
2330: CTL_CREATE, CTL_EOL) != 0)
2331: goto bad;
2332:
2333: return;
2334: bad:
2335: printf("%s: could not attach sysctl nodes\n", ifname);
2336: return;
2337: }
2338:
1.138 drochner 2339: #if defined(INET) || defined(INET6)
1.276 rmind 2340:
2341: static int
2342: sysctl_pktq_count(SYSCTLFN_ARGS, pktqueue_t *pq, u_int count_id)
2343: {
2344: int count = pktq_get_count(pq, count_id);
2345: struct sysctlnode node = *rnode;
2346: node.sysctl_data = &count;
2347: return sysctl_lookup(SYSCTLFN_CALL(&node));
2348: }
2349:
2350: #define SYSCTL_NET_PKTQ(q, cn, c) \
2351: static int \
2352: sysctl_net_##q##_##cn(SYSCTLFN_ARGS) \
2353: { \
2354: return sysctl_pktq_count(SYSCTLFN_CALL(rnode), q, c); \
2355: }
2356:
2357: #if defined(INET)
2358: SYSCTL_NET_PKTQ(ip_pktq, maxlen, PKTQ_MAXLEN)
2359: SYSCTL_NET_PKTQ(ip_pktq, items, PKTQ_NITEMS)
2360: SYSCTL_NET_PKTQ(ip_pktq, drops, PKTQ_DROPS)
2361: #endif
2362: #if defined(INET6)
2363: SYSCTL_NET_PKTQ(ip6_pktq, maxlen, PKTQ_MAXLEN)
2364: SYSCTL_NET_PKTQ(ip6_pktq, items, PKTQ_NITEMS)
2365: SYSCTL_NET_PKTQ(ip6_pktq, drops, PKTQ_DROPS)
2366: #endif
2367:
1.136 atatat 2368: static void
1.276 rmind 2369: sysctl_net_pktq_setup(struct sysctllog **clog, int pf)
1.136 atatat 2370: {
1.276 rmind 2371: sysctlfn len_func = NULL, maxlen_func = NULL, drops_func = NULL;
2372: const char *pfname = NULL, *ipname = NULL;
2373: int ipn = 0, qid = 0;
2374:
2375: switch (pf) {
2376: #if defined(INET)
2377: case PF_INET:
2378: len_func = sysctl_net_ip_pktq_items;
2379: maxlen_func = sysctl_net_ip_pktq_maxlen;
2380: drops_func = sysctl_net_ip_pktq_drops;
2381: pfname = "inet", ipn = IPPROTO_IP;
2382: ipname = "ip", qid = IPCTL_IFQ;
2383: break;
2384: #endif
2385: #if defined(INET6)
2386: case PF_INET6:
2387: len_func = sysctl_net_ip6_pktq_items;
2388: maxlen_func = sysctl_net_ip6_pktq_maxlen;
2389: drops_func = sysctl_net_ip6_pktq_drops;
2390: pfname = "inet6", ipn = IPPROTO_IPV6;
2391: ipname = "ip6", qid = IPV6CTL_IFQ;
2392: break;
2393: #endif
2394: default:
2395: KASSERT(false);
2396: }
1.136 atatat 2397:
1.139 atatat 2398: sysctl_createv(clog, 0, NULL, NULL,
2399: CTLFLAG_PERMANENT,
1.136 atatat 2400: CTLTYPE_NODE, pfname, NULL,
2401: NULL, 0, NULL, 0,
2402: CTL_NET, pf, CTL_EOL);
1.139 atatat 2403: sysctl_createv(clog, 0, NULL, NULL,
2404: CTLFLAG_PERMANENT,
1.136 atatat 2405: CTLTYPE_NODE, ipname, NULL,
2406: NULL, 0, NULL, 0,
2407: CTL_NET, pf, ipn, CTL_EOL);
1.139 atatat 2408: sysctl_createv(clog, 0, NULL, NULL,
2409: CTLFLAG_PERMANENT,
1.142 atatat 2410: CTLTYPE_NODE, "ifq",
2411: SYSCTL_DESCR("Protocol input queue controls"),
1.139 atatat 2412: NULL, 0, NULL, 0,
2413: CTL_NET, pf, ipn, qid, CTL_EOL);
1.136 atatat 2414:
1.139 atatat 2415: sysctl_createv(clog, 0, NULL, NULL,
2416: CTLFLAG_PERMANENT,
1.142 atatat 2417: CTLTYPE_INT, "len",
2418: SYSCTL_DESCR("Current input queue length"),
1.276 rmind 2419: len_func, 0, NULL, 0,
1.136 atatat 2420: CTL_NET, pf, ipn, qid, IFQCTL_LEN, CTL_EOL);
1.139 atatat 2421: sysctl_createv(clog, 0, NULL, NULL,
2422: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1.142 atatat 2423: CTLTYPE_INT, "maxlen",
2424: SYSCTL_DESCR("Maximum allowed input queue length"),
1.276 rmind 2425: maxlen_func, 0, NULL, 0,
1.136 atatat 2426: CTL_NET, pf, ipn, qid, IFQCTL_MAXLEN, CTL_EOL);
1.139 atatat 2427: sysctl_createv(clog, 0, NULL, NULL,
2428: CTLFLAG_PERMANENT,
1.142 atatat 2429: CTLTYPE_INT, "drops",
2430: SYSCTL_DESCR("Packets dropped due to full input queue"),
1.276 rmind 2431: drops_func, 0, NULL, 0,
1.136 atatat 2432: CTL_NET, pf, ipn, qid, IFQCTL_DROPS, CTL_EOL);
2433: }
1.138 drochner 2434: #endif /* INET || INET6 */
CVSweb <webmaster@jp.NetBSD.org>