Annotation of src/sys/net/if.c, Revision 1.256.2.1
1.256.2.1! yamt 1: /* $NetBSD: if.c,v 1.256 2011/10/28 20:11:58 dyoung 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.256.2.1! yamt 93: __KERNEL_RCSID(0, "$NetBSD: if.c,v 1.256 2011/10/28 20:11:58 dyoung 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.87 thorpej 99: #include "opt_pfil_hooks.h"
1.1 cgd 100:
1.8 mycroft 101: #include <sys/param.h>
102: #include <sys/mbuf.h>
103: #include <sys/systm.h>
1.59 thorpej 104: #include <sys/callout.h>
1.15 mycroft 105: #include <sys/proc.h>
1.8 mycroft 106: #include <sys/socket.h>
107: #include <sys/socketvar.h>
1.56 thorpej 108: #include <sys/domain.h>
1.8 mycroft 109: #include <sys/protosw.h>
110: #include <sys/kernel.h>
111: #include <sys/ioctl.h>
1.133 jonathan 112: #include <sys/sysctl.h>
1.159 dyoung 113: #include <sys/syslog.h>
1.165 elad 114: #include <sys/kauth.h>
1.254 dyoung 115: #include <sys/kmem.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.51 bouyer 127: #ifdef NETATALK
128: #include <netatalk/at_extern.h>
129: #include <netatalk/at.h>
130: #endif
1.143 itojun 131: #include <net/pfil.h>
1.1 cgd 132:
1.49 itojun 133: #ifdef INET6
134: #include <netinet/in.h>
1.72 thorpej 135: #include <netinet6/in6_var.h>
1.108 itojun 136: #include <netinet6/nd6.h>
1.49 itojun 137: #endif
1.117 thorpej 138:
1.166 liamjfoy 139: #include "carp.h"
140: #if NCARP > 0
141: #include <netinet/ip_carp.h>
142: #endif
143:
1.186 christos 144: #include <compat/sys/sockio.h>
1.161 christos 145: #include <compat/sys/socket.h>
146:
1.117 thorpej 147: MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
148: MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
1.49 itojun 149:
1.1 cgd 150: int ifqmaxlen = IFQ_MAXLEN;
1.193 ad 151: callout_t if_slowtimo_ch;
1.49 itojun 152:
1.104 matt 153: int netisr; /* scheduling bits for network */
154:
1.192 dyoung 155: static int if_rt_walktree(struct rtentry *, void *);
1.53 thorpej 156:
1.163 thorpej 157: static struct if_clone *if_clone_lookup(const char *, int *);
158: static int if_clone_list(struct if_clonereq *);
1.63 thorpej 159:
1.163 thorpej 160: static LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
161: static int if_cloners_count;
1.63 thorpej 162:
1.234 dyoung 163: static uint64_t index_gen;
164: static kmutex_t index_gen_mtx;
165:
1.143 itojun 166: #ifdef PFIL_HOOKS
167: struct pfil_head if_pfil; /* packet filtering hook for interfaces */
168: #endif
169:
1.239 elad 170: static kauth_listener_t if_listener;
171:
1.252 dyoung 172: static int ifioctl_attach(struct ifnet *);
173: static void ifioctl_detach(struct ifnet *);
1.254 dyoung 174: static void ifnet_lock_enter(struct ifnet_lock *);
175: static void ifnet_lock_exit(struct ifnet_lock *);
1.163 thorpej 176: static void if_detach_queues(struct ifnet *, struct ifqueue *);
1.234 dyoung 177: static void sysctl_sndq_setup(struct sysctllog **, const char *,
178: struct ifaltq *);
1.95 itojun 179:
1.240 cegger 180: #if defined(INET) || defined(INET6)
1.237 pooka 181: static void sysctl_net_ifq_setup(struct sysctllog **, int, const char *,
182: int, const char *, int, struct ifqueue *);
1.240 cegger 183: #endif
1.237 pooka 184:
1.239 elad 185: static int
186: if_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
187: void *arg0, void *arg1, void *arg2, void *arg3)
188: {
189: int result;
190: enum kauth_network_req req;
191:
192: result = KAUTH_RESULT_DEFER;
193: req = (enum kauth_network_req)arg1;
194:
195: if (action != KAUTH_NETWORK_INTERFACE)
196: return result;
197:
198: if ((req == KAUTH_REQ_NETWORK_INTERFACE_GET) ||
199: (req == KAUTH_REQ_NETWORK_INTERFACE_SET))
200: result = KAUTH_RESULT_ALLOW;
201:
202: return result;
203: }
204:
1.1 cgd 205: /*
206: * Network interface utility routines.
207: *
208: * Routines with ifa_ifwith* names take sockaddr *'s as
209: * parameters.
210: */
1.4 andrew 211: void
1.163 thorpej 212: ifinit(void)
1.1 cgd 213: {
1.237 pooka 214: #ifdef INET
215: {extern struct ifqueue ipintrq;
216: sysctl_net_ifq_setup(NULL, PF_INET, "inet", IPPROTO_IP, "ip",
217: IPCTL_IFQ, &ipintrq);}
218: #endif /* INET */
219: #ifdef INET6
220: {extern struct ifqueue ip6intrq;
221: sysctl_net_ifq_setup(NULL, PF_INET6, "inet6", IPPROTO_IPV6, "ip6",
222: IPV6CTL_IFQ, &ip6intrq);}
223: #endif /* INET6 */
1.1 cgd 224:
1.193 ad 225: callout_init(&if_slowtimo_ch, 0);
1.4 andrew 226: if_slowtimo(NULL);
1.239 elad 227:
228: if_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
229: if_listener_cb, NULL);
1.227 yamt 230: }
231:
232: /*
233: * XXX Initialization before configure().
234: * XXX hack to get pfil_add_hook working in autoconf.
235: */
236: void
237: ifinit1(void)
238: {
239:
1.238 skrll 240: mutex_init(&index_gen_mtx, MUTEX_DEFAULT, IPL_NONE);
241:
1.143 itojun 242: #ifdef PFIL_HOOKS
243: if_pfil.ph_type = PFIL_TYPE_IFNET;
244: if_pfil.ph_ifnet = NULL;
245: if (pfil_head_register(&if_pfil) != 0)
246: printf("WARNING: unable to register pfil hook\n");
247: #endif
1.1 cgd 248: }
249:
1.226 christos 250: struct ifnet *
251: if_alloc(u_char type)
252: {
253: return malloc(sizeof(struct ifnet), M_DEVBUF, M_WAITOK|M_ZERO);
254: }
255:
256: void
1.251 dyoung 257: if_free(struct ifnet *ifp)
258: {
259: free(ifp, M_DEVBUF);
260: }
261:
262: void
1.226 christos 263: if_initname(struct ifnet *ifp, const char *name, int unit)
264: {
265: (void)snprintf(ifp->if_xname, sizeof(ifp->if_xname),
266: "%s%d", name, unit);
267: }
268:
1.53 thorpej 269: /*
270: * Null routines used while an interface is going away. These routines
271: * just return an error.
272: */
273:
274: int
1.177 christos 275: if_nulloutput(struct ifnet *ifp, struct mbuf *m,
1.181 dyoung 276: const struct sockaddr *so, struct rtentry *rt)
1.53 thorpej 277: {
278:
1.185 dyoung 279: return ENXIO;
1.53 thorpej 280: }
281:
282: void
1.177 christos 283: if_nullinput(struct ifnet *ifp, struct mbuf *m)
1.53 thorpej 284: {
285:
286: /* Nothing. */
287: }
288:
289: void
1.177 christos 290: if_nullstart(struct ifnet *ifp)
1.53 thorpej 291: {
292:
293: /* Nothing. */
294: }
295:
296: int
1.183 christos 297: if_nullioctl(struct ifnet *ifp, u_long cmd, void *data)
1.53 thorpej 298: {
299:
1.255 dyoung 300: /* Wake ifioctl_detach(), who may wait for all threads to
301: * quit the critical section.
302: */
1.254 dyoung 303: cv_signal(&ifp->if_ioctl_lock->il_emptied);
1.185 dyoung 304: return ENXIO;
1.53 thorpej 305: }
306:
307: int
1.177 christos 308: if_nullinit(struct ifnet *ifp)
1.53 thorpej 309: {
310:
1.185 dyoung 311: return ENXIO;
1.53 thorpej 312: }
313:
314: void
1.177 christos 315: if_nullstop(struct ifnet *ifp, int disable)
1.75 thorpej 316: {
317:
318: /* Nothing. */
319: }
320:
321: void
1.177 christos 322: if_nullwatchdog(struct ifnet *ifp)
1.53 thorpej 323: {
324:
325: /* Nothing. */
326: }
327:
328: void
1.177 christos 329: if_nulldrain(struct ifnet *ifp)
1.53 thorpej 330: {
331:
332: /* Nothing. */
333: }
334:
1.137 itojun 335: static u_int if_index = 1;
1.103 simonb 336: struct ifnet_head ifnet;
1.137 itojun 337: size_t if_indexlim = 0;
1.49 itojun 338: struct ifaddr **ifnet_addrs = NULL;
339: struct ifnet **ifindex2ifnet = NULL;
1.148 peter 340: struct ifnet *lo0ifp;
1.1 cgd 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:
494: /*
1.1 cgd 495: * Attach an interface to the
496: * list of "active" interfaces.
497: */
1.15 mycroft 498: void
1.163 thorpej 499: if_attach(struct ifnet *ifp)
1.1 cgd 500: {
1.102 atatat 501: int indexlim = 0;
1.1 cgd 502:
1.102 atatat 503: if (if_indexlim == 0) {
1.22 mycroft 504: TAILQ_INIT(&ifnet);
1.102 atatat 505: if_indexlim = 8;
506: }
1.22 mycroft 507: TAILQ_INIT(&ifp->if_addrlist);
1.21 mycroft 508: TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
1.252 dyoung 509:
1.255 dyoung 510: if (ifioctl_attach(ifp) != 0)
511: panic("%s: ifioctl_attach() failed", __func__);
1.231 dyoung 512:
1.234 dyoung 513: mutex_enter(&index_gen_mtx);
514: ifp->if_index_gen = index_gen++;
515: mutex_exit(&index_gen_mtx);
516:
1.102 atatat 517: ifp->if_index = if_index;
1.185 dyoung 518: if (ifindex2ifnet == NULL)
1.102 atatat 519: if_index++;
520: else
1.131 itojun 521: while (ifp->if_index < if_indexlim &&
522: ifindex2ifnet[ifp->if_index] != NULL) {
1.102 atatat 523: ++if_index;
524: if (if_index == 0)
525: if_index = 1;
526: /*
527: * If we hit USHRT_MAX, we skip back to 0 since
528: * there are a number of places where the value
529: * of if_index or if_index itself is compared
1.111 itojun 530: * to or stored in an unsigned short. By
1.102 atatat 531: * jumping back, we won't botch those assignments
532: * or comparisons.
533: */
534: else if (if_index == USHRT_MAX) {
535: /*
536: * However, if we have to jump back to
537: * zero *twice* without finding an empty
538: * slot in ifindex2ifnet[], then there
539: * there are too many (>65535) interfaces.
540: */
541: if (indexlim++)
542: panic("too many interfaces");
543: else
544: if_index = 1;
545: }
546: ifp->if_index = if_index;
547: }
1.49 itojun 548:
549: /*
550: * We have some arrays that should be indexed by if_index.
551: * since if_index will grow dynamically, they should grow too.
552: * struct ifadd **ifnet_addrs
553: * struct ifnet **ifindex2ifnet
554: */
1.185 dyoung 555: if (ifnet_addrs == NULL || ifindex2ifnet == NULL ||
1.53 thorpej 556: ifp->if_index >= if_indexlim) {
1.131 itojun 557: size_t m, n, oldlim;
1.183 christos 558: void *q;
1.154 perry 559:
1.131 itojun 560: oldlim = if_indexlim;
1.53 thorpej 561: while (ifp->if_index >= if_indexlim)
1.49 itojun 562: if_indexlim <<= 1;
563:
564: /* grow ifnet_addrs */
1.131 itojun 565: m = oldlim * sizeof(struct ifaddr *);
1.81 thorpej 566: n = if_indexlim * sizeof(struct ifaddr *);
1.230 dyoung 567: q = malloc(n, M_IFADDR, M_WAITOK|M_ZERO);
1.185 dyoung 568: if (ifnet_addrs != NULL) {
569: memcpy(q, ifnet_addrs, m);
1.230 dyoung 570: free(ifnet_addrs, M_IFADDR);
1.1 cgd 571: }
1.49 itojun 572: ifnet_addrs = (struct ifaddr **)q;
573:
574: /* grow ifindex2ifnet */
1.131 itojun 575: m = oldlim * sizeof(struct ifnet *);
1.49 itojun 576: n = if_indexlim * sizeof(struct ifnet *);
1.230 dyoung 577: q = malloc(n, M_IFADDR, M_WAITOK|M_ZERO);
1.185 dyoung 578: if (ifindex2ifnet != NULL) {
1.230 dyoung 579: memcpy(q, ifindex2ifnet, m);
580: free(ifindex2ifnet, M_IFADDR);
1.49 itojun 581: }
582: ifindex2ifnet = (struct ifnet **)q;
1.1 cgd 583: }
1.49 itojun 584:
1.53 thorpej 585: ifindex2ifnet[ifp->if_index] = ifp;
1.49 itojun 586:
1.1 cgd 587: /*
1.81 thorpej 588: * Link level name is allocated later by a separate call to
589: * if_alloc_sadl().
1.1 cgd 590: */
1.81 thorpej 591:
1.40 thorpej 592: if (ifp->if_snd.ifq_maxlen == 0)
1.94 itojun 593: ifp->if_snd.ifq_maxlen = ifqmaxlen;
1.234 dyoung 594:
595: sysctl_sndq_setup(&ifp->if_sysctl_log, ifp->if_xname, &ifp->if_snd);
596:
1.42 is 597: ifp->if_broadcastaddr = 0; /* reliably crash if used uninitialized */
1.57 thorpej 598:
599: ifp->if_link_state = LINK_STATE_UNKNOWN;
600:
1.89 thorpej 601: ifp->if_capenable = 0;
1.97 thorpej 602: ifp->if_csum_flags_tx = 0;
603: ifp->if_csum_flags_rx = 0;
1.89 thorpej 604:
1.86 thorpej 605: #ifdef ALTQ
606: ifp->if_snd.altq_type = 0;
607: ifp->if_snd.altq_disc = NULL;
608: ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE;
609: ifp->if_snd.altq_tbr = NULL;
610: ifp->if_snd.altq_ifp = ifp;
611: #endif
612:
1.87 thorpej 613: #ifdef PFIL_HOOKS
614: ifp->if_pfil.ph_type = PFIL_TYPE_IFNET;
615: ifp->if_pfil.ph_ifnet = ifp;
616: if (pfil_head_register(&ifp->if_pfil) != 0)
617: printf("%s: WARNING: unable to register pfil hook\n",
618: ifp->if_xname);
1.144 yamt 619: (void)pfil_run_hooks(&if_pfil,
620: (struct mbuf **)PFIL_IFNET_ATTACH, ifp, PFIL_IFNET);
1.87 thorpej 621: #endif
622:
1.152 matt 623: if (!STAILQ_EMPTY(&domains))
1.147 tron 624: if_attachdomain1(ifp);
625:
1.107 itojun 626: /* Announce the interface. */
627: rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
628: }
629:
630: void
1.163 thorpej 631: if_attachdomain(void)
1.107 itojun 632: {
633: struct ifnet *ifp;
1.110 itojun 634: int s;
1.107 itojun 635:
1.110 itojun 636: s = splnet();
1.185 dyoung 637: IFNET_FOREACH(ifp)
1.107 itojun 638: if_attachdomain1(ifp);
1.110 itojun 639: splx(s);
1.107 itojun 640: }
641:
642: void
1.163 thorpej 643: if_attachdomain1(struct ifnet *ifp)
1.107 itojun 644: {
645: struct domain *dp;
1.109 itojun 646: int s;
647:
648: s = splnet();
1.107 itojun 649:
1.106 itojun 650: /* address family dependent data region */
651: memset(ifp->if_afdata, 0, sizeof(ifp->if_afdata));
1.152 matt 652: DOMAIN_FOREACH(dp) {
1.185 dyoung 653: if (dp->dom_ifattach != NULL)
1.106 itojun 654: ifp->if_afdata[dp->dom_family] =
655: (*dp->dom_ifattach)(ifp);
656: }
1.109 itojun 657:
658: splx(s);
1.1 cgd 659: }
1.53 thorpej 660:
661: /*
662: * Deactivate an interface. This points all of the procedure
663: * handles at error stubs. May be called from interrupt context.
664: */
665: void
1.163 thorpej 666: if_deactivate(struct ifnet *ifp)
1.53 thorpej 667: {
668: int s;
669:
1.88 thorpej 670: s = splnet();
1.53 thorpej 671:
672: ifp->if_output = if_nulloutput;
673: ifp->if_input = if_nullinput;
674: ifp->if_start = if_nullstart;
675: ifp->if_ioctl = if_nullioctl;
1.75 thorpej 676: ifp->if_init = if_nullinit;
677: ifp->if_stop = if_nullstop;
1.53 thorpej 678: ifp->if_watchdog = if_nullwatchdog;
679: ifp->if_drain = if_nulldrain;
680:
681: /* No more packets may be enqueued. */
682: ifp->if_snd.ifq_maxlen = 0;
683:
684: splx(s);
685: }
686:
1.206 dyoung 687: void
1.218 dyoung 688: if_purgeaddrs(struct ifnet *ifp, int family, void (*purgeaddr)(struct ifaddr *))
1.206 dyoung 689: {
690: struct ifaddr *ifa, *nifa;
691:
692: for (ifa = IFADDR_FIRST(ifp); ifa != NULL; ifa = nifa) {
693: nifa = IFADDR_NEXT(ifa);
694: if (ifa->ifa_addr->sa_family != family)
695: continue;
696: (*purgeaddr)(ifa);
697: }
698: }
699:
1.53 thorpej 700: /*
701: * Detach an interface from the list of "active" interfaces,
702: * freeing any resources as we go along.
703: *
704: * NOTE: This routine must be called with a valid thread context,
705: * as it may block.
706: */
707: void
1.163 thorpej 708: if_detach(struct ifnet *ifp)
1.53 thorpej 709: {
1.56 thorpej 710: struct socket so;
1.178 dyoung 711: struct ifaddr *ifa;
1.53 thorpej 712: #ifdef IFAREF_DEBUG
713: struct ifaddr *last_ifa = NULL;
714: #endif
1.56 thorpej 715: struct domain *dp;
1.141 matt 716: const struct protosw *pr;
1.56 thorpej 717: int s, i, family, purged;
1.53 thorpej 718:
1.56 thorpej 719: /*
720: * XXX It's kind of lame that we have to have the
721: * XXX socket structure...
722: */
723: memset(&so, 0, sizeof(so));
1.53 thorpej 724:
1.88 thorpej 725: s = splnet();
1.53 thorpej 726:
727: /*
728: * Do an if_down() to give protocols a chance to do something.
729: */
730: if_down(ifp);
1.86 thorpej 731:
732: #ifdef ALTQ
733: if (ALTQ_IS_ENABLED(&ifp->if_snd))
734: altq_disable(&ifp->if_snd);
735: if (ALTQ_IS_ATTACHED(&ifp->if_snd))
736: altq_detach(&ifp->if_snd);
1.87 thorpej 737: #endif
738:
1.234 dyoung 739: sysctl_teardown(&ifp->if_sysctl_log);
1.166 liamjfoy 740:
741: #if NCARP > 0
742: /* Remove the interface from any carp group it is a part of. */
1.185 dyoung 743: if (ifp->if_carp != NULL && ifp->if_type != IFT_CARP)
1.166 liamjfoy 744: carp_ifdetach(ifp);
745: #endif
746:
1.53 thorpej 747: /*
748: * Rip all the addresses off the interface. This should make
749: * all of the routes go away.
1.178 dyoung 750: *
751: * pr_usrreq calls can remove an arbitrary number of ifaddrs
752: * from the list, including our "cursor", ifa. For safety,
753: * and to honor the TAILQ abstraction, I just restart the
754: * loop after each removal. Note that the loop will exit
755: * when all of the remaining ifaddrs belong to the AF_LINK
756: * family. I am counting on the historical fact that at
757: * least one pr_usrreq in each address domain removes at
758: * least one ifaddr.
1.53 thorpej 759: */
1.178 dyoung 760: again:
1.204 dyoung 761: IFADDR_FOREACH(ifa, ifp) {
1.56 thorpej 762: family = ifa->ifa_addr->sa_family;
1.53 thorpej 763: #ifdef IFAREF_DEBUG
764: printf("if_detach: ifaddr %p, family %d, refcnt %d\n",
1.56 thorpej 765: ifa, family, ifa->ifa_refcnt);
1.53 thorpej 766: if (last_ifa != NULL && ifa == last_ifa)
1.56 thorpej 767: panic("if_detach: loop detected");
1.53 thorpej 768: last_ifa = ifa;
769: #endif
1.178 dyoung 770: if (family == AF_LINK)
1.118 itojun 771: continue;
772: dp = pffinddomain(family);
1.56 thorpej 773: #ifdef DIAGNOSTIC
1.118 itojun 774: if (dp == NULL)
775: panic("if_detach: no domain for AF %d",
776: family);
1.56 thorpej 777: #endif
1.160 gdt 778: /*
779: * XXX These PURGEIF calls are redundant with the
780: * purge-all-families calls below, but are left in for
781: * now both to make a smaller change, and to avoid
782: * unplanned interactions with clearing of
783: * ifp->if_addrlist.
784: */
1.118 itojun 785: purged = 0;
786: for (pr = dp->dom_protosw;
787: pr < dp->dom_protoswNPROTOSW; pr++) {
788: so.so_proto = pr;
789: if (pr->pr_usrreq != NULL) {
790: (void) (*pr->pr_usrreq)(&so,
791: PRU_PURGEIF, NULL, NULL,
1.162 christos 792: (struct mbuf *) ifp, curlwp);
1.118 itojun 793: purged = 1;
1.53 thorpej 794: }
1.118 itojun 795: }
796: if (purged == 0) {
797: /*
798: * XXX What's really the best thing to do
1.135 keihan 799: * XXX here? --thorpej@NetBSD.org
1.118 itojun 800: */
801: printf("if_detach: WARNING: AF %d not purged\n",
802: family);
1.207 dyoung 803: ifa_remove(ifp, ifa);
1.53 thorpej 804: }
1.178 dyoung 805: goto again;
1.53 thorpej 806: }
1.118 itojun 807:
808: if_free_sadl(ifp);
1.53 thorpej 809:
1.180 dyoung 810: /* Walk the routing table looking for stragglers. */
1.243 dyoung 811: for (i = 0; i <= AF_MAX; i++) {
812: while (rt_walktree(i, if_rt_walktree, ifp) == ERESTART)
1.256.2.1! yamt 813: continue;
1.243 dyoung 814: }
1.106 itojun 815:
1.152 matt 816: DOMAIN_FOREACH(dp) {
1.185 dyoung 817: if (dp->dom_ifdetach != NULL && ifp->if_afdata[dp->dom_family])
1.256.2.1! yamt 818: {
! 819: void *p = ifp->if_afdata[dp->dom_family];
! 820: if (p) {
! 821: ifp->if_afdata[dp->dom_family] = NULL;
! 822: (*dp->dom_ifdetach)(ifp, p);
! 823: }
! 824: }
1.160 gdt 825:
826: /*
827: * One would expect multicast memberships (INET and
828: * INET6) on UDP sockets to be purged by the PURGEIF
829: * calls above, but if all addresses were removed from
830: * the interface prior to destruction, the calls will
831: * not be made (e.g. ppp, for which pppd(8) generally
832: * removes addresses before destroying the interface).
833: * Because there is no invariant that multicast
834: * memberships only exist for interfaces with IPv4
835: * addresses, we must call PURGEIF regardless of
836: * addresses. (Protocols which might store ifnet
837: * pointers are marked with PR_PURGEIF.)
838: */
1.185 dyoung 839: for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
1.160 gdt 840: so.so_proto = pr;
1.185 dyoung 841: if (pr->pr_usrreq != NULL && pr->pr_flags & PR_PURGEIF)
842: (void)(*pr->pr_usrreq)(&so, PRU_PURGEIF, NULL,
843: NULL, (struct mbuf *)ifp, curlwp);
1.160 gdt 844: }
1.53 thorpej 845: }
1.57 thorpej 846:
1.184 dyoung 847: #ifdef PFIL_HOOKS
848: (void)pfil_run_hooks(&if_pfil,
849: (struct mbuf **)PFIL_IFNET_DETACH, ifp, PFIL_IFNET);
850: (void)pfil_head_unregister(&ifp->if_pfil);
851: #endif
852:
1.57 thorpej 853: /* Announce that the interface is gone. */
854: rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
1.93 itojun 855:
856: ifindex2ifnet[ifp->if_index] = NULL;
1.53 thorpej 857:
858: TAILQ_REMOVE(&ifnet, ifp, if_list);
859:
1.252 dyoung 860: ifioctl_detach(ifp);
861:
1.95 itojun 862: /*
1.168 matt 863: * remove packets that came from ifp, from software interrupt queues.
1.95 itojun 864: */
1.168 matt 865: DOMAIN_FOREACH(dp) {
866: for (i = 0; i < __arraycount(dp->dom_ifqueues); i++) {
1.256.2.1! yamt 867: struct ifqueue *iq = dp->dom_ifqueues[i];
! 868: if (iq == NULL)
1.168 matt 869: break;
1.256.2.1! yamt 870: dp->dom_ifqueues[i] = NULL;
! 871: if_detach_queues(ifp, iq);
1.168 matt 872: }
873: }
1.95 itojun 874:
1.53 thorpej 875: splx(s);
1.95 itojun 876: }
877:
878: static void
1.163 thorpej 879: if_detach_queues(struct ifnet *ifp, struct ifqueue *q)
1.95 itojun 880: {
881: struct mbuf *m, *prev, *next;
882:
883: prev = NULL;
1.185 dyoung 884: for (m = q->ifq_head; m != NULL; m = next) {
1.95 itojun 885: next = m->m_nextpkt;
886: #ifdef DIAGNOSTIC
1.96 itojun 887: if ((m->m_flags & M_PKTHDR) == 0) {
888: prev = m;
1.95 itojun 889: continue;
1.96 itojun 890: }
1.95 itojun 891: #endif
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;
930: RTFREE(rt);
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.128 itojun 987: int unit;
1.63 thorpej 988:
1.128 itojun 989: /* separate interface name from unit */
990: for (cp = name;
1.130 itojun 991: cp - name < IFNAMSIZ && *cp && (*cp < '0' || *cp > '9');
1.128 itojun 992: cp++)
993: continue;
994:
995: if (cp == name || cp - name == IFNAMSIZ || !*cp)
1.185 dyoung 996: return NULL; /* No name or unit number */
1.128 itojun 997:
998: LIST_FOREACH(ifc, &if_cloners, ifc_list) {
999: if (strlen(ifc->ifc_name) == cp - name &&
1.185 dyoung 1000: strncmp(name, ifc->ifc_name, cp - name) == 0)
1.128 itojun 1001: break;
1.63 thorpej 1002: }
1003:
1.128 itojun 1004: if (ifc == NULL)
1.185 dyoung 1005: return NULL;
1.63 thorpej 1006:
1.128 itojun 1007: unit = 0;
1.129 itojun 1008: while (cp - name < IFNAMSIZ && *cp) {
1.245 christos 1009: if (*cp < '0' || *cp > '9' || unit >= INT_MAX / 10) {
1.63 thorpej 1010: /* Bogus unit number. */
1.185 dyoung 1011: return NULL;
1.63 thorpej 1012: }
1.128 itojun 1013: unit = (unit * 10) + (*cp++ - '0');
1.63 thorpej 1014: }
1015:
1016: if (unitp != NULL)
1.128 itojun 1017: *unitp = unit;
1.185 dyoung 1018: return ifc;
1.63 thorpej 1019: }
1020:
1021: /*
1022: * Register a network interface cloner.
1023: */
1024: void
1.163 thorpej 1025: if_clone_attach(struct if_clone *ifc)
1.63 thorpej 1026: {
1027:
1028: LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
1.67 thorpej 1029: if_cloners_count++;
1.63 thorpej 1030: }
1031:
1032: /*
1033: * Unregister a network interface cloner.
1034: */
1035: void
1.163 thorpej 1036: if_clone_detach(struct if_clone *ifc)
1.63 thorpej 1037: {
1038:
1039: LIST_REMOVE(ifc, ifc_list);
1.67 thorpej 1040: if_cloners_count--;
1041: }
1042:
1043: /*
1044: * Provide list of interface cloners to userspace.
1045: */
1.163 thorpej 1046: static int
1047: if_clone_list(struct if_clonereq *ifcr)
1.67 thorpej 1048: {
1049: char outbuf[IFNAMSIZ], *dst;
1050: struct if_clone *ifc;
1051: int count, error = 0;
1052:
1053: ifcr->ifcr_total = if_cloners_count;
1054: if ((dst = ifcr->ifcr_buffer) == NULL) {
1055: /* Just asking how many there are. */
1.185 dyoung 1056: return 0;
1.67 thorpej 1057: }
1058:
1059: if (ifcr->ifcr_count < 0)
1.185 dyoung 1060: return EINVAL;
1.67 thorpej 1061:
1062: count = (if_cloners_count < ifcr->ifcr_count) ?
1063: if_cloners_count : ifcr->ifcr_count;
1064:
1065: for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
1066: ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
1.175 christos 1067: (void)strncpy(outbuf, ifc->ifc_name, sizeof(outbuf));
1068: if (outbuf[sizeof(outbuf) - 1] != '\0')
1069: return ENAMETOOLONG;
1.172 christos 1070: error = copyout(outbuf, dst, sizeof(outbuf));
1.185 dyoung 1071: if (error != 0)
1.67 thorpej 1072: break;
1073: }
1074:
1.185 dyoung 1075: return error;
1.63 thorpej 1076: }
1077:
1.207 dyoung 1078: void
1079: ifa_insert(struct ifnet *ifp, struct ifaddr *ifa)
1080: {
1081: ifa->ifa_ifp = ifp;
1.208 dyoung 1082: TAILQ_INSERT_TAIL(&ifp->if_addrlist, ifa, ifa_list);
1.207 dyoung 1083: IFAREF(ifa);
1084: }
1085:
1086: void
1087: ifa_remove(struct ifnet *ifp, struct ifaddr *ifa)
1088: {
1089: KASSERT(ifa->ifa_ifp == ifp);
1090: TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
1091: IFAFREE(ifa);
1092: }
1093:
1.194 dyoung 1094: static inline int
1095: equal(const struct sockaddr *sa1, const struct sockaddr *sa2)
1096: {
1097: return sockaddr_cmp(sa1, sa2) == 0;
1098: }
1099:
1.63 thorpej 1100: /*
1.1 cgd 1101: * Locate an interface based on a complete address.
1102: */
1103: /*ARGSUSED*/
1104: struct ifaddr *
1.163 thorpej 1105: ifa_ifwithaddr(const struct sockaddr *addr)
1.1 cgd 1106: {
1.61 augustss 1107: struct ifnet *ifp;
1108: struct ifaddr *ifa;
1.1 cgd 1109:
1.185 dyoung 1110: IFNET_FOREACH(ifp) {
1.53 thorpej 1111: if (ifp->if_output == if_nulloutput)
1.1 cgd 1112: continue;
1.204 dyoung 1113: IFADDR_FOREACH(ifa, ifp) {
1.53 thorpej 1114: if (ifa->ifa_addr->sa_family != addr->sa_family)
1115: continue;
1116: if (equal(addr, ifa->ifa_addr))
1.185 dyoung 1117: return ifa;
1.53 thorpej 1118: if ((ifp->if_flags & IFF_BROADCAST) &&
1119: ifa->ifa_broadaddr &&
1120: /* IP6 doesn't have broadcast */
1121: ifa->ifa_broadaddr->sa_len != 0 &&
1122: equal(ifa->ifa_broadaddr, addr))
1.185 dyoung 1123: return ifa;
1.53 thorpej 1124: }
1.1 cgd 1125: }
1.185 dyoung 1126: return NULL;
1.1 cgd 1127: }
1.49 itojun 1128:
1.1 cgd 1129: /*
1130: * Locate the point to point interface with a given destination address.
1131: */
1132: /*ARGSUSED*/
1133: struct ifaddr *
1.163 thorpej 1134: ifa_ifwithdstaddr(const struct sockaddr *addr)
1.1 cgd 1135: {
1.61 augustss 1136: struct ifnet *ifp;
1137: struct ifaddr *ifa;
1.1 cgd 1138:
1.185 dyoung 1139: IFNET_FOREACH(ifp) {
1.53 thorpej 1140: if (ifp->if_output == if_nulloutput)
1141: continue;
1.185 dyoung 1142: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
1143: continue;
1.204 dyoung 1144: IFADDR_FOREACH(ifa, ifp) {
1.185 dyoung 1145: if (ifa->ifa_addr->sa_family != addr->sa_family ||
1146: ifa->ifa_dstaddr == NULL)
1147: continue;
1148: if (equal(addr, ifa->ifa_dstaddr))
1149: return ifa;
1.53 thorpej 1150: }
1.1 cgd 1151: }
1.185 dyoung 1152: return NULL;
1.1 cgd 1153: }
1154:
1155: /*
1156: * Find an interface on a specific network. If many, choice
1.15 mycroft 1157: * is most specific found.
1.1 cgd 1158: */
1159: struct ifaddr *
1.163 thorpej 1160: ifa_ifwithnet(const struct sockaddr *addr)
1.1 cgd 1161: {
1.61 augustss 1162: struct ifnet *ifp;
1163: struct ifaddr *ifa;
1.140 matt 1164: const struct sockaddr_dl *sdl;
1.15 mycroft 1165: struct ifaddr *ifa_maybe = 0;
1.1 cgd 1166: u_int af = addr->sa_family;
1.171 pooka 1167: const char *addr_data = addr->sa_data, *cplim;
1.1 cgd 1168:
1169: if (af == AF_LINK) {
1.195 dyoung 1170: sdl = satocsdl(addr);
1.137 itojun 1171: if (sdl->sdl_index && sdl->sdl_index < if_indexlim &&
1172: ifindex2ifnet[sdl->sdl_index] &&
1.53 thorpej 1173: ifindex2ifnet[sdl->sdl_index]->if_output != if_nulloutput)
1.185 dyoung 1174: return ifnet_addrs[sdl->sdl_index];
1.1 cgd 1175: }
1.51 bouyer 1176: #ifdef NETATALK
1177: if (af == AF_APPLETALK) {
1.140 matt 1178: const struct sockaddr_at *sat, *sat2;
1.158 christos 1179: sat = (const struct sockaddr_at *)addr;
1.185 dyoung 1180: IFNET_FOREACH(ifp) {
1.53 thorpej 1181: if (ifp->if_output == if_nulloutput)
1182: continue;
1.158 christos 1183: ifa = at_ifawithnet((const struct sockaddr_at *)addr, ifp);
1.62 bouyer 1184: if (ifa == NULL)
1185: continue;
1186: sat2 = (struct sockaddr_at *)ifa->ifa_addr;
1187: if (sat2->sat_addr.s_net == sat->sat_addr.s_net)
1.185 dyoung 1188: return ifa; /* exact match */
1.62 bouyer 1189: if (ifa_maybe == NULL) {
1.112 wiz 1190: /* else keep the if with the right range */
1.62 bouyer 1191: ifa_maybe = ifa;
1192: }
1.51 bouyer 1193: }
1.185 dyoung 1194: return ifa_maybe;
1.51 bouyer 1195: }
1196: #endif
1.185 dyoung 1197: IFNET_FOREACH(ifp) {
1.53 thorpej 1198: if (ifp->if_output == if_nulloutput)
1199: continue;
1.204 dyoung 1200: IFADDR_FOREACH(ifa, ifp) {
1.171 pooka 1201: const char *cp, *cp2, *cp3;
1.15 mycroft 1202:
1203: if (ifa->ifa_addr->sa_family != af ||
1.185 dyoung 1204: ifa->ifa_netmask == NULL)
1.53 thorpej 1205: next: continue;
1.15 mycroft 1206: cp = addr_data;
1207: cp2 = ifa->ifa_addr->sa_data;
1208: cp3 = ifa->ifa_netmask->sa_data;
1.171 pooka 1209: cplim = (const char *)ifa->ifa_netmask +
1.53 thorpej 1210: ifa->ifa_netmask->sa_len;
1211: while (cp3 < cplim) {
1212: if ((*cp++ ^ *cp2++) & *cp3++) {
1213: /* want to continue for() loop */
1.32 mrg 1214: goto next;
1.53 thorpej 1215: }
1216: }
1.185 dyoung 1217: if (ifa_maybe == NULL ||
1.183 christos 1218: rn_refines((void *)ifa->ifa_netmask,
1219: (void *)ifa_maybe->ifa_netmask))
1.15 mycroft 1220: ifa_maybe = ifa;
1221: }
1.53 thorpej 1222: }
1.185 dyoung 1223: return ifa_maybe;
1.26 mrg 1224: }
1.53 thorpej 1225:
1.26 mrg 1226: /*
1227: * Find the interface of the addresss.
1228: */
1229: struct ifaddr *
1.163 thorpej 1230: ifa_ifwithladdr(const struct sockaddr *addr)
1.26 mrg 1231: {
1232: struct ifaddr *ia;
1233:
1.53 thorpej 1234: if ((ia = ifa_ifwithaddr(addr)) || (ia = ifa_ifwithdstaddr(addr)) ||
1235: (ia = ifa_ifwithnet(addr)))
1.185 dyoung 1236: return ia;
1237: return NULL;
1.1 cgd 1238: }
1239:
1240: /*
1241: * Find an interface using a specific address family
1242: */
1243: struct ifaddr *
1.163 thorpej 1244: ifa_ifwithaf(int af)
1.1 cgd 1245: {
1.61 augustss 1246: struct ifnet *ifp;
1247: struct ifaddr *ifa;
1.1 cgd 1248:
1.185 dyoung 1249: IFNET_FOREACH(ifp) {
1.53 thorpej 1250: if (ifp->if_output == if_nulloutput)
1251: continue;
1.204 dyoung 1252: IFADDR_FOREACH(ifa, ifp) {
1.21 mycroft 1253: if (ifa->ifa_addr->sa_family == af)
1.178 dyoung 1254: return ifa;
1.53 thorpej 1255: }
1256: }
1.178 dyoung 1257: return NULL;
1.1 cgd 1258: }
1259:
1260: /*
1261: * Find an interface address specific to an interface best matching
1262: * a given address.
1263: */
1264: struct ifaddr *
1.163 thorpej 1265: ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp)
1.1 cgd 1266: {
1.61 augustss 1267: struct ifaddr *ifa;
1.140 matt 1268: const char *cp, *cp2, *cp3;
1269: const char *cplim;
1.1 cgd 1270: struct ifaddr *ifa_maybe = 0;
1271: u_int af = addr->sa_family;
1272:
1.53 thorpej 1273: if (ifp->if_output == if_nulloutput)
1.185 dyoung 1274: return NULL;
1.53 thorpej 1275:
1.1 cgd 1276: if (af >= AF_MAX)
1.185 dyoung 1277: return NULL;
1.53 thorpej 1278:
1.204 dyoung 1279: IFADDR_FOREACH(ifa, ifp) {
1.1 cgd 1280: if (ifa->ifa_addr->sa_family != af)
1281: continue;
1282: ifa_maybe = ifa;
1.185 dyoung 1283: if (ifa->ifa_netmask == NULL) {
1.1 cgd 1284: if (equal(addr, ifa->ifa_addr) ||
1.53 thorpej 1285: (ifa->ifa_dstaddr &&
1286: equal(addr, ifa->ifa_dstaddr)))
1.185 dyoung 1287: return ifa;
1.1 cgd 1288: continue;
1289: }
1290: cp = addr->sa_data;
1291: cp2 = ifa->ifa_addr->sa_data;
1292: cp3 = ifa->ifa_netmask->sa_data;
1293: cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
1.53 thorpej 1294: for (; cp3 < cplim; cp3++) {
1.1 cgd 1295: if ((*cp++ ^ *cp2++) & *cp3)
1296: break;
1.53 thorpej 1297: }
1.1 cgd 1298: if (cp3 == cplim)
1.185 dyoung 1299: return ifa;
1.1 cgd 1300: }
1.185 dyoung 1301: return ifa_maybe;
1.1 cgd 1302: }
1.9 mycroft 1303:
1.1 cgd 1304: /*
1305: * Default action when installing a route with a Link Level gateway.
1306: * Lookup an appropriate real ifa to point to.
1307: * This should be moved to /sys/net/link.c eventually.
1308: */
1.15 mycroft 1309: void
1.228 dyoung 1310: link_rtrequest(int cmd, struct rtentry *rt, const struct rt_addrinfo *info)
1.1 cgd 1311: {
1.61 augustss 1312: struct ifaddr *ifa;
1.194 dyoung 1313: const struct sockaddr *dst;
1.15 mycroft 1314: struct ifnet *ifp;
1.1 cgd 1315:
1.225 dyoung 1316: if (cmd != RTM_ADD || (ifa = rt->rt_ifa) == NULL ||
1317: (ifp = ifa->ifa_ifp) == NULL || (dst = rt_getkey(rt)) == NULL)
1.1 cgd 1318: return;
1.24 christos 1319: if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
1.176 dyoung 1320: rt_replace_ifa(rt, ifa);
1.1 cgd 1321: if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
1.82 itojun 1322: ifa->ifa_rtrequest(cmd, rt, info);
1.1 cgd 1323: }
1324: }
1325:
1326: /*
1.159 dyoung 1327: * Handle a change in the interface link state.
1328: */
1329: void
1330: if_link_state_change(struct ifnet *ifp, int link_state)
1331: {
1.185 dyoung 1332: if (ifp->if_link_state == link_state)
1333: return;
1334: ifp->if_link_state = link_state;
1.159 dyoung 1335: /* Notify that the link state has changed. */
1.185 dyoung 1336: rt_ifmsg(ifp);
1.166 liamjfoy 1337: #if NCARP > 0
1.185 dyoung 1338: if (ifp->if_carp)
1339: carp_carpdev_state(ifp);
1.166 liamjfoy 1340: #endif
1.159 dyoung 1341: }
1342:
1343: /*
1.1 cgd 1344: * Mark an interface down and notify protocols of
1345: * the transition.
1.23 mycroft 1346: * NOTE: must be called at splsoftnet or equivalent.
1.1 cgd 1347: */
1.15 mycroft 1348: void
1.163 thorpej 1349: if_down(struct ifnet *ifp)
1.1 cgd 1350: {
1.61 augustss 1351: struct ifaddr *ifa;
1.1 cgd 1352:
1353: ifp->if_flags &= ~IFF_UP;
1.232 christos 1354: nanotime(&ifp->if_lastchange);
1.204 dyoung 1355: IFADDR_FOREACH(ifa, ifp)
1.1 cgd 1356: pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
1.78 thorpej 1357: IFQ_PURGE(&ifp->if_snd);
1.166 liamjfoy 1358: #if NCARP > 0
1359: if (ifp->if_carp)
1360: carp_carpdev_state(ifp);
1361: #endif
1.15 mycroft 1362: rt_ifmsg(ifp);
1363: }
1364:
1365: /*
1366: * Mark an interface up and notify protocols of
1367: * the transition.
1.23 mycroft 1368: * NOTE: must be called at splsoftnet or equivalent.
1.15 mycroft 1369: */
1370: void
1.163 thorpej 1371: if_up(struct ifnet *ifp)
1.15 mycroft 1372: {
1.24 christos 1373: #ifdef notyet
1.61 augustss 1374: struct ifaddr *ifa;
1.24 christos 1375: #endif
1.15 mycroft 1376:
1377: ifp->if_flags |= IFF_UP;
1.232 christos 1378: nanotime(&ifp->if_lastchange);
1.15 mycroft 1379: #ifdef notyet
1380: /* this has no effect on IP, and will kill all ISO connections XXX */
1.204 dyoung 1381: IFADDR_FOREACH(ifa, ifp)
1.15 mycroft 1382: pfctlinput(PRC_IFUP, ifa->ifa_addr);
1383: #endif
1.166 liamjfoy 1384: #if NCARP > 0
1385: if (ifp->if_carp)
1386: carp_carpdev_state(ifp);
1387: #endif
1.15 mycroft 1388: rt_ifmsg(ifp);
1.49 itojun 1389: #ifdef INET6
1390: in6_if_up(ifp);
1391: #endif
1.1 cgd 1392: }
1393:
1394: /*
1395: * Handle interface watchdog timer routines. Called
1396: * from softclock, we decrement timers (if set) and
1397: * call the appropriate interface routine on expiration.
1398: */
1.4 andrew 1399: void
1.177 christos 1400: if_slowtimo(void *arg)
1.1 cgd 1401: {
1.61 augustss 1402: struct ifnet *ifp;
1.88 thorpej 1403: int s = splnet();
1.1 cgd 1404:
1.185 dyoung 1405: IFNET_FOREACH(ifp) {
1.1 cgd 1406: if (ifp->if_timer == 0 || --ifp->if_timer)
1407: continue;
1.185 dyoung 1408: if (ifp->if_watchdog != NULL)
1.34 thorpej 1409: (*ifp->if_watchdog)(ifp);
1.1 cgd 1410: }
1411: splx(s);
1.185 dyoung 1412: callout_reset(&if_slowtimo_ch, hz / IFNET_SLOWHZ, if_slowtimo, NULL);
1.65 thorpej 1413: }
1414:
1415: /*
1416: * Set/clear promiscuous mode on interface ifp based on the truth value
1417: * of pswitch. The calls are reference counted so that only the first
1418: * "on" request actually has an effect, as does the final "off" request.
1419: * Results are undefined if the "off" and "on" requests are not matched.
1420: */
1421: int
1.163 thorpej 1422: ifpromisc(struct ifnet *ifp, int pswitch)
1.65 thorpej 1423: {
1424: int pcount, ret;
1.256.2.1! yamt 1425: short nflags;
1.65 thorpej 1426:
1427: pcount = ifp->if_pcount;
1428: if (pswitch) {
1429: /*
1.71 thorpej 1430: * Allow the device to be "placed" into promiscuous
1431: * mode even if it is not configured up. It will
1.242 mbalmer 1432: * consult IFF_PROMISC when it is brought up.
1.65 thorpej 1433: */
1.68 pk 1434: if (ifp->if_pcount++ != 0)
1.185 dyoung 1435: return 0;
1.252 dyoung 1436: nflags = ifp->if_flags | IFF_PROMISC;
1.65 thorpej 1437: } else {
1438: if (--ifp->if_pcount > 0)
1.185 dyoung 1439: return 0;
1.252 dyoung 1440: nflags = ifp->if_flags & ~IFF_PROMISC;
1.65 thorpej 1441: }
1.252 dyoung 1442: ret = if_flags_set(ifp, nflags);
1.65 thorpej 1443: /* Restore interface state if not successful. */
1444: if (ret != 0) {
1445: ifp->if_pcount = pcount;
1446: }
1.185 dyoung 1447: return ret;
1.1 cgd 1448: }
1449:
1450: /*
1451: * Map interface name to
1452: * interface structure pointer.
1453: */
1454: struct ifnet *
1.163 thorpej 1455: ifunit(const char *name)
1.1 cgd 1456: {
1.61 augustss 1457: struct ifnet *ifp;
1.105 matt 1458: const char *cp = name;
1459: u_int unit = 0;
1460: u_int i;
1461:
1462: /*
1463: * If the entire name is a number, treat it as an ifindex.
1464: */
1465: for (i = 0; i < IFNAMSIZ && *cp >= '0' && *cp <= '9'; i++, cp++) {
1466: unit = unit * 10 + (*cp - '0');
1467: }
1468:
1469: /*
1470: * If the number took all of the name, then it's a valid ifindex.
1471: */
1472: if (i == IFNAMSIZ || (cp != name && *cp == '\0')) {
1.137 itojun 1473: if (unit >= if_indexlim)
1.185 dyoung 1474: return NULL;
1.105 matt 1475: ifp = ifindex2ifnet[unit];
1476: if (ifp == NULL || ifp->if_output == if_nulloutput)
1.185 dyoung 1477: return NULL;
1478: return ifp;
1.105 matt 1479: }
1.34 thorpej 1480:
1.185 dyoung 1481: IFNET_FOREACH(ifp) {
1.53 thorpej 1482: if (ifp->if_output == if_nulloutput)
1483: continue;
1484: if (strcmp(ifp->if_xname, name) == 0)
1.185 dyoung 1485: return ifp;
1.53 thorpej 1486: }
1.185 dyoung 1487: return NULL;
1.1 cgd 1488: }
1.49 itojun 1489:
1.250 rmind 1490: ifnet_t *
1491: if_byindex(u_int idx)
1492: {
1493:
1494: return (idx < if_indexlim) ? ifindex2ifnet[idx] : NULL;
1495: }
1496:
1.211 dyoung 1497: /* common */
1.215 dyoung 1498: int
1499: ifioctl_common(struct ifnet *ifp, u_long cmd, void *data)
1.211 dyoung 1500: {
1.224 dyoung 1501: int s;
1.215 dyoung 1502: struct ifreq *ifr;
1503: struct ifcapreq *ifcr;
1504: struct ifdatareq *ifdr;
1.211 dyoung 1505:
1506: switch (cmd) {
1507: case SIOCSIFCAP:
1.215 dyoung 1508: ifcr = data;
1.211 dyoung 1509: if ((ifcr->ifcr_capenable & ~ifp->if_capabilities) != 0)
1510: return EINVAL;
1511:
1.213 dyoung 1512: if (ifcr->ifcr_capenable == ifp->if_capenable)
1513: return 0;
1.211 dyoung 1514:
1.213 dyoung 1515: ifp->if_capenable = ifcr->ifcr_capenable;
1.211 dyoung 1516:
1.213 dyoung 1517: /* Pre-compute the checksum flags mask. */
1518: ifp->if_csum_flags_tx = 0;
1519: ifp->if_csum_flags_rx = 0;
1520: if (ifp->if_capenable & IFCAP_CSUM_IPv4_Tx) {
1521: ifp->if_csum_flags_tx |= M_CSUM_IPv4;
1522: }
1523: if (ifp->if_capenable & IFCAP_CSUM_IPv4_Rx) {
1524: ifp->if_csum_flags_rx |= M_CSUM_IPv4;
1525: }
1.211 dyoung 1526:
1.213 dyoung 1527: if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx) {
1528: ifp->if_csum_flags_tx |= M_CSUM_TCPv4;
1529: }
1530: if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Rx) {
1531: ifp->if_csum_flags_rx |= M_CSUM_TCPv4;
1532: }
1.211 dyoung 1533:
1.213 dyoung 1534: if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx) {
1535: ifp->if_csum_flags_tx |= M_CSUM_UDPv4;
1536: }
1537: if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Rx) {
1538: ifp->if_csum_flags_rx |= M_CSUM_UDPv4;
1539: }
1.211 dyoung 1540:
1.213 dyoung 1541: if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Tx) {
1542: ifp->if_csum_flags_tx |= M_CSUM_TCPv6;
1543: }
1544: if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Rx) {
1545: ifp->if_csum_flags_rx |= M_CSUM_TCPv6;
1546: }
1.211 dyoung 1547:
1.213 dyoung 1548: if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Tx) {
1549: ifp->if_csum_flags_tx |= M_CSUM_UDPv6;
1.211 dyoung 1550: }
1.213 dyoung 1551: if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Rx) {
1552: ifp->if_csum_flags_rx |= M_CSUM_UDPv6;
1553: }
1.215 dyoung 1554: if (ifp->if_flags & IFF_UP)
1555: return ENETRESET;
1556: return 0;
1.211 dyoung 1557: case SIOCSIFFLAGS:
1.215 dyoung 1558: ifr = data;
1.211 dyoung 1559: if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
1560: s = splnet();
1561: if_down(ifp);
1562: splx(s);
1563: }
1564: if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
1565: s = splnet();
1566: if_up(ifp);
1567: splx(s);
1568: }
1569: ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
1570: (ifr->ifr_flags &~ IFF_CANTCHANGE);
1571: break;
1572: case SIOCGIFFLAGS:
1.215 dyoung 1573: ifr = data;
1.211 dyoung 1574: ifr->ifr_flags = ifp->if_flags;
1575: break;
1576:
1577: case SIOCGIFMETRIC:
1.215 dyoung 1578: ifr = data;
1.211 dyoung 1579: ifr->ifr_metric = ifp->if_metric;
1580: break;
1581:
1582: case SIOCGIFMTU:
1.215 dyoung 1583: ifr = data;
1.211 dyoung 1584: ifr->ifr_mtu = ifp->if_mtu;
1585: break;
1586:
1587: case SIOCGIFDLT:
1.215 dyoung 1588: ifr = data;
1.211 dyoung 1589: ifr->ifr_dlt = ifp->if_dlt;
1590: break;
1591:
1592: case SIOCGIFCAP:
1.215 dyoung 1593: ifcr = data;
1.211 dyoung 1594: ifcr->ifcr_capabilities = ifp->if_capabilities;
1595: ifcr->ifcr_capenable = ifp->if_capenable;
1596: break;
1597:
1598: case SIOCSIFMETRIC:
1.215 dyoung 1599: ifr = data;
1.211 dyoung 1600: ifp->if_metric = ifr->ifr_metric;
1601: break;
1602:
1603: case SIOCGIFDATA:
1.215 dyoung 1604: ifdr = data;
1.211 dyoung 1605: ifdr->ifdr_data = ifp->if_data;
1606: break;
1607:
1608: case SIOCZIFDATA:
1.215 dyoung 1609: ifdr = data;
1.211 dyoung 1610: ifdr->ifdr_data = ifp->if_data;
1611: /*
1612: * Assumes that the volatile counters that can be
1613: * zero'ed are at the end of if_data.
1614: */
1615: memset(&ifp->if_data.ifi_ipackets, 0, sizeof(ifp->if_data) -
1616: offsetof(struct if_data, ifi_ipackets));
1617: break;
1.215 dyoung 1618: case SIOCSIFMTU:
1619: ifr = data;
1620: if (ifp->if_mtu == ifr->ifr_mtu)
1621: break;
1622: ifp->if_mtu = ifr->ifr_mtu;
1623: /*
1624: * If the link MTU changed, do network layer specific procedure.
1625: */
1626: #ifdef INET6
1627: nd6_setmtu(ifp);
1628: #endif
1629: return ENETRESET;
1.211 dyoung 1630: default:
1.223 dyoung 1631: return ENOTTY;
1.211 dyoung 1632: }
1633: return 0;
1634: }
1635:
1.235 dyoung 1636: int
1637: ifaddrpref_ioctl(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
1638: lwp_t *l)
1639: {
1640: struct if_addrprefreq *ifap = (struct if_addrprefreq *)data;
1641: struct ifaddr *ifa;
1642: const struct sockaddr *any, *sa;
1643: union {
1644: struct sockaddr sa;
1645: struct sockaddr_storage ss;
1.236 jakllsch 1646: } u, v;
1.235 dyoung 1647:
1648: switch (cmd) {
1649: case SIOCSIFADDRPREF:
1650: if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
1651: KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
1652: NULL) != 0)
1653: return EPERM;
1654: case SIOCGIFADDRPREF:
1655: break;
1656: default:
1657: return EOPNOTSUPP;
1658: }
1659:
1660: /* sanity checks */
1661: if (data == NULL || ifp == NULL) {
1662: panic("invalid argument to %s", __func__);
1663: /*NOTREACHED*/
1664: }
1665:
1666: /* address must be specified on ADD and DELETE */
1667: sa = sstocsa(&ifap->ifap_addr);
1668: if (sa->sa_family != sofamily(so))
1669: return EINVAL;
1670: if ((any = sockaddr_any(sa)) == NULL || sa->sa_len != any->sa_len)
1671: return EINVAL;
1672:
1.236 jakllsch 1673: sockaddr_externalize(&v.sa, sizeof(v.ss), sa);
1674:
1.235 dyoung 1675: IFADDR_FOREACH(ifa, ifp) {
1676: if (ifa->ifa_addr->sa_family != sa->sa_family)
1677: continue;
1678: sockaddr_externalize(&u.sa, sizeof(u.ss), ifa->ifa_addr);
1.236 jakllsch 1679: if (sockaddr_cmp(&u.sa, &v.sa) == 0)
1.235 dyoung 1680: break;
1681: }
1682: if (ifa == NULL)
1683: return EADDRNOTAVAIL;
1684:
1685: switch (cmd) {
1686: case SIOCSIFADDRPREF:
1687: ifa->ifa_preference = ifap->ifap_preference;
1688: return 0;
1689: case SIOCGIFADDRPREF:
1690: /* fill in the if_laddrreq structure */
1691: (void)sockaddr_copy(sstosa(&ifap->ifap_addr),
1692: sizeof(ifap->ifap_addr), ifa->ifa_addr);
1693: ifap->ifap_preference = ifa->ifa_preference;
1694: return 0;
1695: default:
1696: return EOPNOTSUPP;
1697: }
1698: }
1699:
1.253 dyoung 1700: static void
1.254 dyoung 1701: ifnet_lock_enter(struct ifnet_lock *il)
1.253 dyoung 1702: {
1.254 dyoung 1703: uint64_t *nenter;
1704:
1.255 dyoung 1705: /* Before trying to acquire the mutex, increase the count of threads
1706: * who have entered or who wait to enter the critical section.
1707: * Avoid one costly locked memory transaction by keeping a count for
1708: * each CPU.
1709: */
1.254 dyoung 1710: nenter = percpu_getref(il->il_nenter);
1.253 dyoung 1711: (*nenter)++;
1.254 dyoung 1712: percpu_putref(il->il_nenter);
1713: mutex_enter(&il->il_lock);
1.253 dyoung 1714: }
1715:
1716: static void
1.254 dyoung 1717: ifnet_lock_exit(struct ifnet_lock *il)
1.253 dyoung 1718: {
1.255 dyoung 1719: /* Increase the count of threads who have exited the critical
1720: * section. Increase while we still hold the lock.
1721: */
1.254 dyoung 1722: il->il_nexit++;
1723: mutex_exit(&il->il_lock);
1.253 dyoung 1724: }
1725:
1.1 cgd 1726: /*
1727: * Interface ioctls.
1728: */
1.15 mycroft 1729: int
1.183 christos 1730: ifioctl(struct socket *so, u_long cmd, void *data, struct lwp *l)
1.1 cgd 1731: {
1.61 augustss 1732: struct ifnet *ifp;
1733: struct ifreq *ifr;
1.217 martin 1734: int error = 0;
1.191 christos 1735: #if defined(COMPAT_OSOCK) || defined(COMPAT_OIFREQ)
1736: u_long ocmd = cmd;
1737: #endif
1.49 itojun 1738: short oif_flags;
1.186 christos 1739: #ifdef COMPAT_OIFREQ
1740: struct ifreq ifrb;
1.187 xtraeme 1741: struct oifreq *oifr = NULL;
1.186 christos 1742: #endif
1.1 cgd 1743:
1744: switch (cmd) {
1.186 christos 1745: #ifdef COMPAT_OIFREQ
1746: case OSIOCGIFCONF:
1747: case OOSIOCGIFCONF:
1748: return compat_ifconf(cmd, data);
1749: #endif
1.232 christos 1750: #ifdef COMPAT_OIFDATA
1751: case OSIOCGIFDATA:
1752: case OSIOCZIFDATA:
1753: return compat_ifdatareq(l, cmd, data);
1754: #endif
1.1 cgd 1755: case SIOCGIFCONF:
1.185 dyoung 1756: return ifconf(cmd, data);
1.231 dyoung 1757: case SIOCINITIFADDR:
1758: return EPERM;
1.1 cgd 1759: }
1.191 christos 1760:
1.186 christos 1761: #ifdef COMPAT_OIFREQ
1.196 skd 1762: cmd = compat_cvtcmd(cmd);
1.186 christos 1763: if (cmd != ocmd) {
1764: oifr = data;
1765: data = ifr = &ifrb;
1766: ifreqo2n(oifr, ifr);
1767: } else
1768: #endif
1769: ifr = data;
1.63 thorpej 1770:
1.174 elad 1771: ifp = ifunit(ifr->ifr_name);
1772:
1.63 thorpej 1773: switch (cmd) {
1774: case SIOCIFCREATE:
1775: case SIOCIFDESTROY:
1.185 dyoung 1776: if (l != NULL) {
1.174 elad 1777: error = kauth_authorize_network(l->l_cred,
1778: KAUTH_NETWORK_INTERFACE,
1779: KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp,
1780: (void *)cmd, NULL);
1.185 dyoung 1781: if (error != 0)
1.151 yamt 1782: return error;
1783: }
1.185 dyoung 1784: return (cmd == SIOCIFCREATE) ?
1.64 thorpej 1785: if_clone_create(ifr->ifr_name) :
1.185 dyoung 1786: if_clone_destroy(ifr->ifr_name);
1.67 thorpej 1787:
1788: case SIOCIFGCLONERS:
1.185 dyoung 1789: return if_clone_list((struct if_clonereq *)data);
1.63 thorpej 1790: }
1791:
1.185 dyoung 1792: if (ifp == NULL)
1793: return ENXIO;
1.151 yamt 1794:
1795: switch (cmd) {
1.233 christos 1796: case SIOCALIFADDR:
1797: case SIOCDLIFADDR:
1798: case SIOCSIFADDRPREF:
1.151 yamt 1799: case SIOCSIFFLAGS:
1800: case SIOCSIFCAP:
1801: case SIOCSIFMETRIC:
1802: case SIOCZIFDATA:
1803: case SIOCSIFMTU:
1804: case SIOCSIFPHYADDR:
1805: case SIOCDIFPHYADDR:
1806: #ifdef INET6
1807: case SIOCSIFPHYADDR_IN6:
1808: #endif
1809: case SIOCSLIFPHYADDR:
1810: case SIOCADDMULTI:
1811: case SIOCDELMULTI:
1812: case SIOCSIFMEDIA:
1.154 perry 1813: case SIOCSDRVSPEC:
1.196 skd 1814: case SIOCG80211:
1815: case SIOCS80211:
1.151 yamt 1816: case SIOCS80211NWID:
1817: case SIOCS80211NWKEY:
1818: case SIOCS80211POWER:
1819: case SIOCS80211BSSID:
1820: case SIOCS80211CHANNEL:
1.249 pooka 1821: case SIOCSLINKSTR:
1.185 dyoung 1822: if (l != NULL) {
1.174 elad 1823: error = kauth_authorize_network(l->l_cred,
1824: KAUTH_NETWORK_INTERFACE,
1825: KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp,
1826: (void *)cmd, NULL);
1.185 dyoung 1827: if (error != 0)
1.151 yamt 1828: return error;
1829: }
1830: }
1831:
1.49 itojun 1832: oif_flags = ifp->if_flags;
1.1 cgd 1833:
1.254 dyoung 1834: ifnet_lock_enter(ifp->if_ioctl_lock);
1.231 dyoung 1835: error = (*ifp->if_ioctl)(ifp, cmd, data);
1836: if (error != ENOTTY)
1837: ;
1838: else if (so->so_proto == NULL)
1.252 dyoung 1839: error = EOPNOTSUPP;
1.231 dyoung 1840: else {
1.161 christos 1841: #ifdef COMPAT_OSOCK
1.186 christos 1842: error = compat_ifioctl(so, ocmd, cmd, data, l);
1.161 christos 1843: #else
1.219 ad 1844: error = (*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
1.36 mycroft 1845: (struct mbuf *)cmd, (struct mbuf *)data,
1.220 martin 1846: (struct mbuf *)ifp, l);
1.1 cgd 1847: #endif
1.49 itojun 1848: }
1.1 cgd 1849:
1.49 itojun 1850: if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
1851: #ifdef INET6
1852: if ((ifp->if_flags & IFF_UP) != 0) {
1.217 martin 1853: int s = splnet();
1.49 itojun 1854: in6_if_up(ifp);
1855: splx(s);
1856: }
1.1 cgd 1857: #endif
1858: }
1.186 christos 1859: #ifdef COMPAT_OIFREQ
1860: if (cmd != ocmd)
1.246 christos 1861: ifreqn2o(oifr, ifr);
1.186 christos 1862: #endif
1.49 itojun 1863:
1.254 dyoung 1864: ifnet_lock_exit(ifp->if_ioctl_lock);
1.185 dyoung 1865: return error;
1.1 cgd 1866: }
1867:
1.255 dyoung 1868: /* This callback adds to the sum in `arg' the number of
1869: * threads on `ci' who have entered or who wait to enter the
1870: * critical section.
1871: */
1.252 dyoung 1872: static void
1.254 dyoung 1873: ifnet_lock_sum(void *p, void *arg, struct cpu_info *ci)
1.252 dyoung 1874: {
1875: uint64_t *sum = arg, *nenter = p;
1876:
1877: *sum += *nenter;
1878: }
1879:
1.255 dyoung 1880: /* Return the number of threads who have entered or who wait
1881: * to enter the critical section on all CPUs.
1882: */
1.252 dyoung 1883: static uint64_t
1.254 dyoung 1884: ifnet_lock_entrances(struct ifnet_lock *il)
1.252 dyoung 1885: {
1886: uint64_t sum = 0;
1887:
1.254 dyoung 1888: percpu_foreach(il->il_nenter, ifnet_lock_sum, &sum);
1.252 dyoung 1889:
1890: return sum;
1891: }
1892:
1893: static int
1894: ifioctl_attach(struct ifnet *ifp)
1895: {
1.254 dyoung 1896: struct ifnet_lock *il;
1897:
1.255 dyoung 1898: /* If the driver has not supplied its own if_ioctl, then
1899: * supply the default.
1900: */
1.252 dyoung 1901: if (ifp->if_ioctl == NULL)
1902: ifp->if_ioctl = ifioctl_common;
1903:
1.255 dyoung 1904: /* Create an ifnet_lock for synchronizing ifioctls. */
1.254 dyoung 1905: if ((il = kmem_zalloc(sizeof(*il), KM_SLEEP)) == NULL)
1.252 dyoung 1906: return ENOMEM;
1907:
1.254 dyoung 1908: il->il_nenter = percpu_alloc(sizeof(uint64_t));
1909: if (il->il_nenter == NULL) {
1910: kmem_free(il, sizeof(*il));
1911: return ENOMEM;
1912: }
1913:
1914: mutex_init(&il->il_lock, MUTEX_DEFAULT, IPL_NONE);
1915: cv_init(&il->il_emptied, ifp->if_xname);
1916:
1917: ifp->if_ioctl_lock = il;
1.252 dyoung 1918:
1919: return 0;
1920: }
1921:
1.255 dyoung 1922: /*
1923: * This must not be called until after `ifp' has been withdrawn from the
1924: * ifnet tables so that ifioctl() cannot get a handle on it by calling
1925: * ifunit().
1926: */
1.252 dyoung 1927: static void
1928: ifioctl_detach(struct ifnet *ifp)
1929: {
1.254 dyoung 1930: struct ifnet_lock *il;
1931:
1932: il = ifp->if_ioctl_lock;
1933: mutex_enter(&il->il_lock);
1.255 dyoung 1934: /* Install if_nullioctl to make sure that any thread that
1935: * subsequently enters the critical section will quit it
1936: * immediately and signal the condition variable that we
1937: * wait on, below.
1938: */
1.252 dyoung 1939: ifp->if_ioctl = if_nullioctl;
1.255 dyoung 1940: /* Sleep while threads are still in the critical section or
1941: * wait to enter it.
1942: */
1.254 dyoung 1943: while (ifnet_lock_entrances(il) != il->il_nexit)
1944: cv_wait(&il->il_emptied, &il->il_lock);
1.255 dyoung 1945: /* At this point, we are the only thread still in the critical
1946: * section, and no new thread can get a handle on the ifioctl
1947: * lock, so it is safe to free its memory.
1948: */
1.254 dyoung 1949: mutex_exit(&il->il_lock);
1950: ifp->if_ioctl_lock = NULL;
1.255 dyoung 1951: percpu_free(il->il_nenter, sizeof(uint64_t));
1952: il->il_nenter = NULL;
1.256.2.1! yamt 1953: cv_destroy(&il->il_emptied);
! 1954: mutex_destroy(&il->il_lock);
1.254 dyoung 1955: kmem_free(il, sizeof(*il));
1.252 dyoung 1956: }
1957:
1.1 cgd 1958: /*
1959: * Return interface configuration
1960: * of system. List may be used
1961: * in later ioctl's (above) to get
1962: * other information.
1.200 gdt 1963: *
1964: * Each record is a struct ifreq. Before the addition of
1965: * sockaddr_storage, the API rule was that sockaddr flavors that did
1966: * not fit would extend beyond the struct ifreq, with the next struct
1967: * ifreq starting sa_len beyond the struct sockaddr. Because the
1968: * union in struct ifreq includes struct sockaddr_storage, every kind
1969: * of sockaddr must fit. Thus, there are no longer any overlength
1970: * records.
1971: *
1972: * Records are added to the user buffer if they fit, and ifc_len is
1973: * adjusted to the length that was written. Thus, the user is only
1974: * assured of getting the complete list if ifc_len on return is at
1975: * least sizeof(struct ifreq) less than it was on entry.
1976: *
1977: * If the user buffer pointer is NULL, this routine copies no data and
1978: * returns the amount of space that would be needed.
1979: *
1980: * Invariants:
1981: * ifrp points to the next part of the user's buffer to be used. If
1982: * ifrp != NULL, space holds the number of bytes remaining that we may
1983: * write at ifrp. Otherwise, space holds the number of bytes that
1984: * would have been written had there been adequate space.
1.1 cgd 1985: */
1986: /*ARGSUSED*/
1.15 mycroft 1987: int
1.183 christos 1988: ifconf(u_long cmd, void *data)
1.1 cgd 1989: {
1.61 augustss 1990: struct ifconf *ifc = (struct ifconf *)data;
1991: struct ifnet *ifp;
1992: struct ifaddr *ifa;
1.1 cgd 1993: struct ifreq ifr, *ifrp;
1.190 enami 1994: int space, error = 0;
1.200 gdt 1995: const int sz = (int)sizeof(struct ifreq);
1.1 cgd 1996:
1.190 enami 1997: if ((ifrp = ifc->ifc_req) == NULL)
1.127 christos 1998: space = 0;
1.190 enami 1999: else
2000: space = ifc->ifc_len;
1.153 matt 2001: IFNET_FOREACH(ifp) {
1.175 christos 2002: (void)strncpy(ifr.ifr_name, ifp->if_xname,
1.173 christos 2003: sizeof(ifr.ifr_name));
1.175 christos 2004: if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0')
2005: return ENAMETOOLONG;
1.205 dyoung 2006: if (IFADDR_EMPTY(ifp)) {
1.200 gdt 2007: /* Interface with no addresses - send zero sockaddr. */
1.127 christos 2008: memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1.218 dyoung 2009: if (ifrp == NULL) {
2010: space += sz;
2011: continue;
2012: }
2013: if (space >= sz) {
2014: error = copyout(&ifr, ifrp, sz);
2015: if (error != 0)
2016: return error;
2017: ifrp++;
2018: space -= sz;
1.70 mellon 2019: }
1.127 christos 2020: }
2021:
1.204 dyoung 2022: IFADDR_FOREACH(ifa, ifp) {
1.61 augustss 2023: struct sockaddr *sa = ifa->ifa_addr;
1.200 gdt 2024: /* all sockaddrs must fit in sockaddr_storage */
2025: KASSERT(sa->sa_len <= sizeof(ifr.ifr_ifru));
2026:
1.218 dyoung 2027: if (ifrp == NULL) {
2028: space += sz;
2029: continue;
2030: }
2031: memcpy(&ifr.ifr_space, sa, sa->sa_len);
2032: if (space >= sz) {
2033: error = copyout(&ifr, ifrp, sz);
2034: if (error != 0)
2035: return (error);
2036: ifrp++; space -= sz;
1.1 cgd 2037: }
2038: }
2039: }
1.218 dyoung 2040: if (ifrp != NULL) {
1.200 gdt 2041: KASSERT(0 <= space && space <= ifc->ifc_len);
1.127 christos 2042: ifc->ifc_len -= space;
1.218 dyoung 2043: } else {
1.200 gdt 2044: KASSERT(space >= 0);
2045: ifc->ifc_len = space;
2046: }
1.190 enami 2047: return (0);
1.1 cgd 2048: }
1.133 jonathan 2049:
1.198 dyoung 2050: int
1.247 christos 2051: ifreq_setaddr(u_long cmd, struct ifreq *ifr, const struct sockaddr *sa)
1.198 dyoung 2052: {
2053: uint8_t len;
1.247 christos 2054: #ifdef COMPAT_OIFREQ
2055: struct ifreq ifrb;
2056: struct oifreq *oifr = NULL;
2057: u_long ocmd = cmd;
2058: cmd = compat_cvtcmd(cmd);
2059: if (cmd != ocmd) {
2060: oifr = (struct oifreq *)(void *)ifr;
2061: ifr = &ifrb;
2062: ifreqo2n(oifr, ifr);
2063: len = sizeof(oifr->ifr_addr);
2064: } else
2065: #endif
2066: len = sizeof(ifr->ifr_ifru.ifru_space);
1.198 dyoung 2067:
2068: if (len < sa->sa_len)
2069: return EFBIG;
1.247 christos 2070:
1.241 joerg 2071: memset(&ifr->ifr_addr, 0, len);
1.202 dyoung 2072: sockaddr_copy(&ifr->ifr_addr, len, sa);
1.247 christos 2073:
2074: #ifdef COMPAT_OIFREQ
2075: if (cmd != ocmd)
2076: ifreqn2o(oifr, ifr);
2077: #endif
1.198 dyoung 2078: return 0;
2079: }
2080:
1.155 christos 2081: /*
2082: * Queue message on interface, and start output if interface
2083: * not yet active.
2084: */
2085: int
2086: ifq_enqueue(struct ifnet *ifp, struct mbuf *m
2087: ALTQ_COMMA ALTQ_DECL(struct altq_pktattr *pktattr))
2088: {
2089: int len = m->m_pkthdr.len;
2090: int mflags = m->m_flags;
2091: int s = splnet();
2092: int error;
2093:
1.156 christos 2094: IFQ_ENQUEUE(&ifp->if_snd, m, pktattr, error);
1.185 dyoung 2095: if (error != 0)
2096: goto out;
1.155 christos 2097: ifp->if_obytes += len;
2098: if (mflags & M_MCAST)
2099: ifp->if_omcasts++;
2100: if ((ifp->if_flags & IFF_OACTIVE) == 0)
2101: (*ifp->if_start)(ifp);
1.185 dyoung 2102: out:
1.155 christos 2103: splx(s);
2104: return error;
2105: }
2106:
2107: /*
2108: * Queue message on interface, possibly using a second fast queue
2109: */
2110: int
2111: ifq_enqueue2(struct ifnet *ifp, struct ifqueue *ifq, struct mbuf *m
2112: ALTQ_COMMA ALTQ_DECL(struct altq_pktattr *pktattr))
2113: {
2114: int error = 0;
2115:
2116: if (ifq != NULL
2117: #ifdef ALTQ
2118: && ALTQ_IS_ENABLED(&ifp->if_snd) == 0
2119: #endif
2120: ) {
2121: if (IF_QFULL(ifq)) {
2122: IF_DROP(&ifp->if_snd);
2123: m_freem(m);
2124: if (error == 0)
2125: error = ENOBUFS;
1.185 dyoung 2126: } else
1.155 christos 2127: IF_ENQUEUE(ifq, m);
2128: } else
1.156 christos 2129: IFQ_ENQUEUE(&ifp->if_snd, m, pktattr, error);
1.155 christos 2130: if (error != 0) {
2131: ++ifp->if_oerrors;
2132: return error;
2133: }
2134: return 0;
2135: }
2136:
1.252 dyoung 2137: int
2138: if_addr_init(ifnet_t *ifp, struct ifaddr *ifa, const bool src)
2139: {
2140: int rc;
2141:
2142: if (ifp->if_initaddr != NULL)
2143: rc = (*ifp->if_initaddr)(ifp, ifa, src);
2144: else if (src ||
2145: (rc = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ifa)) == ENOTTY)
2146: rc = (*ifp->if_ioctl)(ifp, SIOCINITIFADDR, ifa);
2147:
2148: return rc;
2149: }
2150:
2151: int
2152: if_flags_set(ifnet_t *ifp, const short flags)
2153: {
2154: int rc;
2155:
2156: if (ifp->if_setflags != NULL)
2157: rc = (*ifp->if_setflags)(ifp, flags);
2158: else {
1.256.2.1! yamt 2159: short cantflags, chgdflags;
1.256 dyoung 2160: struct ifreq ifr;
2161:
1.256.2.1! yamt 2162: chgdflags = ifp->if_flags ^ flags;
! 2163: cantflags = chgdflags & IFF_CANTCHANGE;
1.256 dyoung 2164:
2165: if (cantflags != 0)
2166: ifp->if_flags ^= cantflags;
2167:
1.256.2.1! yamt 2168: /* Traditionally, we do not call if_ioctl after
! 2169: * setting/clearing only IFF_PROMISC if the interface
! 2170: * isn't IFF_UP. Uphold that tradition.
! 2171: */
! 2172: if (chgdflags == IFF_PROMISC && (ifp->if_flags & IFF_UP) == 0)
! 2173: return 0;
! 2174:
! 2175: memset(&ifr, 0, sizeof(ifr));
! 2176:
1.256 dyoung 2177: ifr.ifr_flags = flags & ~IFF_CANTCHANGE;
1.252 dyoung 2178: rc = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, &ifr);
1.256 dyoung 2179:
2180: if (rc != 0 && cantflags != 0)
2181: ifp->if_flags ^= cantflags;
1.252 dyoung 2182: }
2183:
2184: return rc;
2185: }
2186:
2187: int
2188: if_mcast_op(ifnet_t *ifp, const unsigned long cmd, const struct sockaddr *sa)
2189: {
2190: int rc;
2191: struct ifreq ifr;
2192:
2193: if (ifp->if_mcastop != NULL)
2194: rc = (*ifp->if_mcastop)(ifp, cmd, sa);
2195: else {
2196: ifreq_setaddr(cmd, &ifr, sa);
2197: rc = (*ifp->if_ioctl)(ifp, cmd, &ifr);
2198: }
2199:
2200: return rc;
2201: }
1.155 christos 2202:
1.234 dyoung 2203: static void
2204: sysctl_sndq_setup(struct sysctllog **clog, const char *ifname,
2205: struct ifaltq *ifq)
2206: {
2207: const struct sysctlnode *cnode, *rnode;
2208:
2209: if (sysctl_createv(clog, 0, NULL, &rnode,
2210: CTLFLAG_PERMANENT,
2211: CTLTYPE_NODE, "net", NULL,
2212: NULL, 0, NULL, 0,
2213: CTL_NET, CTL_EOL) != 0)
2214: goto bad;
2215:
2216: if (sysctl_createv(clog, 0, &rnode, &rnode,
2217: CTLFLAG_PERMANENT,
2218: CTLTYPE_NODE, "interfaces",
2219: SYSCTL_DESCR("Per-interface controls"),
2220: NULL, 0, NULL, 0,
2221: CTL_CREATE, CTL_EOL) != 0)
2222: goto bad;
2223:
2224: if (sysctl_createv(clog, 0, &rnode, &rnode,
2225: CTLFLAG_PERMANENT,
2226: CTLTYPE_NODE, ifname,
2227: SYSCTL_DESCR("Interface controls"),
2228: NULL, 0, NULL, 0,
2229: CTL_CREATE, CTL_EOL) != 0)
2230: goto bad;
2231:
2232: if (sysctl_createv(clog, 0, &rnode, &rnode,
2233: CTLFLAG_PERMANENT,
2234: CTLTYPE_NODE, "sndq",
2235: SYSCTL_DESCR("Interface output queue controls"),
2236: NULL, 0, NULL, 0,
2237: CTL_CREATE, CTL_EOL) != 0)
2238: goto bad;
2239:
2240: if (sysctl_createv(clog, 0, &rnode, &cnode,
2241: CTLFLAG_PERMANENT,
2242: CTLTYPE_INT, "len",
2243: SYSCTL_DESCR("Current output queue length"),
2244: NULL, 0, &ifq->ifq_len, 0,
2245: CTL_CREATE, CTL_EOL) != 0)
2246: goto bad;
2247:
2248: if (sysctl_createv(clog, 0, &rnode, &cnode,
2249: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2250: CTLTYPE_INT, "maxlen",
2251: SYSCTL_DESCR("Maximum allowed output queue length"),
2252: NULL, 0, &ifq->ifq_maxlen, 0,
2253: CTL_CREATE, CTL_EOL) != 0)
2254: goto bad;
2255:
2256: if (sysctl_createv(clog, 0, &rnode, &cnode,
2257: CTLFLAG_PERMANENT,
2258: CTLTYPE_INT, "drops",
2259: SYSCTL_DESCR("Packets dropped due to full output queue"),
2260: NULL, 0, &ifq->ifq_drops, 0,
2261: CTL_CREATE, CTL_EOL) != 0)
2262: goto bad;
2263:
2264: return;
2265: bad:
2266: printf("%s: could not attach sysctl nodes\n", ifname);
2267: return;
2268: }
2269:
1.138 drochner 2270: #if defined(INET) || defined(INET6)
1.136 atatat 2271: static void
1.139 atatat 2272: sysctl_net_ifq_setup(struct sysctllog **clog,
2273: int pf, const char *pfname,
1.136 atatat 2274: int ipn, const char *ipname,
2275: int qid, struct ifqueue *ifq)
2276: {
2277:
1.139 atatat 2278: sysctl_createv(clog, 0, NULL, NULL,
2279: CTLFLAG_PERMANENT,
1.136 atatat 2280: CTLTYPE_NODE, "net", NULL,
2281: NULL, 0, NULL, 0,
2282: CTL_NET, CTL_EOL);
1.139 atatat 2283: sysctl_createv(clog, 0, NULL, NULL,
2284: CTLFLAG_PERMANENT,
1.136 atatat 2285: CTLTYPE_NODE, pfname, NULL,
2286: NULL, 0, NULL, 0,
2287: CTL_NET, pf, CTL_EOL);
1.139 atatat 2288: sysctl_createv(clog, 0, NULL, NULL,
2289: CTLFLAG_PERMANENT,
1.136 atatat 2290: CTLTYPE_NODE, ipname, NULL,
2291: NULL, 0, NULL, 0,
2292: CTL_NET, pf, ipn, CTL_EOL);
1.139 atatat 2293: sysctl_createv(clog, 0, NULL, NULL,
2294: CTLFLAG_PERMANENT,
1.142 atatat 2295: CTLTYPE_NODE, "ifq",
2296: SYSCTL_DESCR("Protocol input queue controls"),
1.139 atatat 2297: NULL, 0, NULL, 0,
2298: CTL_NET, pf, ipn, qid, CTL_EOL);
1.136 atatat 2299:
1.139 atatat 2300: sysctl_createv(clog, 0, NULL, NULL,
2301: CTLFLAG_PERMANENT,
1.142 atatat 2302: CTLTYPE_INT, "len",
2303: SYSCTL_DESCR("Current input queue length"),
1.136 atatat 2304: NULL, 0, &ifq->ifq_len, 0,
2305: CTL_NET, pf, ipn, qid, IFQCTL_LEN, CTL_EOL);
1.139 atatat 2306: sysctl_createv(clog, 0, NULL, NULL,
2307: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1.142 atatat 2308: CTLTYPE_INT, "maxlen",
2309: SYSCTL_DESCR("Maximum allowed input queue length"),
1.136 atatat 2310: NULL, 0, &ifq->ifq_maxlen, 0,
2311: CTL_NET, pf, ipn, qid, IFQCTL_MAXLEN, CTL_EOL);
1.133 jonathan 2312: #ifdef notyet
1.139 atatat 2313: sysctl_createv(clog, 0, NULL, NULL,
2314: CTLFLAG_PERMANENT,
1.142 atatat 2315: CTLTYPE_INT, "peak",
2316: SYSCTL_DESCR("Highest input queue length"),
1.136 atatat 2317: NULL, 0, &ifq->ifq_peak, 0,
2318: CTL_NET, pf, ipn, qid, IFQCTL_PEAK, CTL_EOL);
2319: #endif
1.139 atatat 2320: sysctl_createv(clog, 0, NULL, NULL,
2321: CTLFLAG_PERMANENT,
1.142 atatat 2322: CTLTYPE_INT, "drops",
2323: SYSCTL_DESCR("Packets dropped due to full input queue"),
1.136 atatat 2324: NULL, 0, &ifq->ifq_drops, 0,
2325: CTL_NET, pf, ipn, qid, IFQCTL_DROPS, CTL_EOL);
2326: }
1.138 drochner 2327: #endif /* INET || INET6 */
CVSweb <webmaster@jp.NetBSD.org>