FreeBSD/Linux Kernel Cross Reference
sys/net/if.c
1 /* $OpenBSD: if.c,v 1.183 2008/11/26 19:07:33 deraadt Exp $ */
2 /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
3
4 /*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 /*
34 * Copyright (c) 1980, 1986, 1993
35 * The Regents of the University of California. All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * @(#)if.c 8.3 (Berkeley) 1/4/94
62 */
63
64 #include "bluetooth.h"
65 #include "bpfilter.h"
66 #include "bridge.h"
67 #include "carp.h"
68 #include "pf.h"
69 #include "trunk.h"
70
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/mbuf.h>
74 #include <sys/proc.h>
75 #include <sys/socket.h>
76 #include <sys/socketvar.h>
77 #include <sys/protosw.h>
78 #include <sys/kernel.h>
79 #include <sys/ioctl.h>
80 #include <sys/domain.h>
81 #include <sys/sysctl.h>
82
83 #include <net/if.h>
84 #include <net/if_dl.h>
85 #include <net/if_media.h>
86 #include <net/if_types.h>
87 #include <net/route.h>
88 #include <net/netisr.h>
89
90 #ifdef INET
91 #include <netinet/in.h>
92 #include <netinet/in_var.h>
93 #include <netinet/if_ether.h>
94 #include <netinet/igmp.h>
95 #ifdef MROUTING
96 #include <netinet/ip_mroute.h>
97 #endif
98 #endif
99
100 #ifdef INET6
101 #ifndef INET
102 #include <netinet/in.h>
103 #endif
104 #include <netinet6/in6_ifattach.h>
105 #include <netinet6/nd6.h>
106 #endif
107
108 #if NBPFILTER > 0
109 #include <net/bpf.h>
110 #endif
111
112 #if NTRUNK > 0
113 #include <net/if_trunk.h>
114 #endif
115
116 #if NBRIDGE > 0
117 #include <net/if_bridge.h>
118 #endif
119
120 #if NCARP > 0
121 #include <netinet/ip_carp.h>
122 #endif
123
124 #if NPF > 0
125 #include <net/pfvar.h>
126 #endif
127
128 void if_attachsetup(struct ifnet *);
129 void if_attachdomain1(struct ifnet *);
130
131 int ifqmaxlen = IFQ_MAXLEN;
132
133 void if_detach_queues(struct ifnet *, struct ifqueue *);
134 void if_detached_start(struct ifnet *);
135 int if_detached_ioctl(struct ifnet *, u_long, caddr_t);
136 int if_detached_init(struct ifnet *);
137 void if_detached_watchdog(struct ifnet *);
138
139 int if_getgroup(caddr_t, struct ifnet *);
140 int if_getgroupmembers(caddr_t);
141 int if_getgroupattribs(caddr_t);
142 int if_setgroupattribs(caddr_t);
143
144 int if_clone_list(struct if_clonereq *);
145 struct if_clone *if_clone_lookup(const char *, int *);
146
147 void if_congestion_clear(void *);
148 int if_group_egress_build(void);
149
150 void m_clinitifp(struct ifnet *);
151
152 TAILQ_HEAD(, ifg_group) ifg_head;
153 LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
154 int if_cloners_count;
155
156 int m_clticks;
157 struct timeout m_cltick_tmo;
158
159 /*
160 * Record when the last timeout has been run. If the delta is
161 * too high, m_cldrop() will notice and decrease the interface
162 * high water marks.
163 */
164 static void
165 m_cltick(void *arg)
166 {
167 extern int ticks;
168
169 m_clticks = ticks;
170 timeout_add(&m_cltick_tmo, 1);
171 }
172
173 /*
174 * Network interface utility routines.
175 *
176 * Routines with ifa_ifwith* names take sockaddr *'s as
177 * parameters.
178 */
179 void
180 ifinit()
181 {
182 static struct timeout if_slowtim;
183
184 timeout_set(&if_slowtim, if_slowtimo, &if_slowtim);
185
186 if_slowtimo(&if_slowtim);
187
188 timeout_set(&m_cltick_tmo, m_cltick, NULL);
189 m_cltick(NULL);
190 }
191
192 static int if_index = 0;
193 int if_indexlim = 0;
194 struct ifaddr **ifnet_addrs = NULL;
195 struct ifnet **ifindex2ifnet = NULL;
196 struct ifnet_head ifnet;
197 struct ifnet_head iftxlist = TAILQ_HEAD_INITIALIZER(iftxlist);
198 struct ifnet *lo0ifp;
199
200 /*
201 * Attach an interface to the
202 * list of "active" interfaces.
203 */
204 void
205 if_attachsetup(struct ifnet *ifp)
206 {
207 struct ifaddr *ifa;
208 int wrapped = 0;
209
210 if (ifindex2ifnet == 0)
211 if_index = 1;
212 else {
213 while (if_index < if_indexlim &&
214 ifindex2ifnet[if_index] != NULL) {
215 if_index++;
216 /*
217 * If we hit USHRT_MAX, we skip back to 1 since
218 * there are a number of places where the value
219 * of ifp->if_index or if_index itself is compared
220 * to or stored in an unsigned short. By
221 * jumping back, we won't botch those assignments
222 * or comparisons.
223 */
224 if (if_index == USHRT_MAX) {
225 if_index = 1;
226 /*
227 * However, if we have to jump back to 1
228 * *twice* without finding an empty
229 * slot in ifindex2ifnet[], then there
230 * there are too many (>65535) interfaces.
231 */
232 if (wrapped++)
233 panic("too many interfaces");
234 }
235 }
236 }
237 ifp->if_index = if_index;
238
239 /*
240 * We have some arrays that should be indexed by if_index.
241 * since if_index will grow dynamically, they should grow too.
242 * struct ifaddr **ifnet_addrs
243 * struct ifnet **ifindex2ifnet
244 */
245 if (ifnet_addrs == 0 || ifindex2ifnet == 0 || if_index >= if_indexlim) {
246 size_t m, n, oldlim;
247 caddr_t q;
248
249 oldlim = if_indexlim;
250 if (if_indexlim == 0)
251 if_indexlim = 8;
252 while (if_index >= if_indexlim)
253 if_indexlim <<= 1;
254
255 /* grow ifnet_addrs */
256 m = oldlim * sizeof(ifa);
257 n = if_indexlim * sizeof(ifa);
258 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK|M_ZERO);
259 if (ifnet_addrs) {
260 bcopy((caddr_t)ifnet_addrs, q, m);
261 free((caddr_t)ifnet_addrs, M_IFADDR);
262 }
263 ifnet_addrs = (struct ifaddr **)q;
264
265 /* grow ifindex2ifnet */
266 m = oldlim * sizeof(struct ifnet *);
267 n = if_indexlim * sizeof(struct ifnet *);
268 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK|M_ZERO);
269 if (ifindex2ifnet) {
270 bcopy((caddr_t)ifindex2ifnet, q, m);
271 free((caddr_t)ifindex2ifnet, M_IFADDR);
272 }
273 ifindex2ifnet = (struct ifnet **)q;
274 }
275
276 TAILQ_INIT(&ifp->if_groups);
277
278 if_addgroup(ifp, IFG_ALL);
279
280 ifindex2ifnet[if_index] = ifp;
281
282 if (ifp->if_snd.ifq_maxlen == 0)
283 ifp->if_snd.ifq_maxlen = ifqmaxlen;
284 #ifdef ALTQ
285 ifp->if_snd.altq_type = 0;
286 ifp->if_snd.altq_disc = NULL;
287 ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE;
288 ifp->if_snd.altq_tbr = NULL;
289 ifp->if_snd.altq_ifp = ifp;
290 #endif
291
292 if (domains)
293 if_attachdomain1(ifp);
294 #if NPF > 0
295 pfi_attach_ifnet(ifp);
296 #endif
297
298 /* Announce the interface. */
299 rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
300 }
301
302 /*
303 * Allocate the link level name for the specified interface. This
304 * is an attachment helper. It must be called after ifp->if_addrlen
305 * is initialized, which may not be the case when if_attach() is
306 * called.
307 */
308 void
309 if_alloc_sadl(struct ifnet *ifp)
310 {
311 unsigned socksize, ifasize;
312 int namelen, masklen;
313 struct sockaddr_dl *sdl;
314 struct ifaddr *ifa;
315
316 /*
317 * If the interface already has a link name, release it
318 * now. This is useful for interfaces that can change
319 * link types, and thus switch link names often.
320 */
321 if (ifp->if_sadl != NULL)
322 if_free_sadl(ifp);
323
324 namelen = strlen(ifp->if_xname);
325 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
326 masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
327 socksize = masklen + ifp->if_addrlen;
328 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
329 if (socksize < sizeof(*sdl))
330 socksize = sizeof(*sdl);
331 socksize = ROUNDUP(socksize);
332 ifasize = sizeof(*ifa) + 2 * socksize;
333 ifa = malloc(ifasize, M_IFADDR, M_WAITOK|M_ZERO);
334 sdl = (struct sockaddr_dl *)(ifa + 1);
335 sdl->sdl_len = socksize;
336 sdl->sdl_family = AF_LINK;
337 bcopy(ifp->if_xname, sdl->sdl_data, namelen);
338 sdl->sdl_nlen = namelen;
339 sdl->sdl_alen = ifp->if_addrlen;
340 sdl->sdl_index = ifp->if_index;
341 sdl->sdl_type = ifp->if_type;
342 ifnet_addrs[ifp->if_index] = ifa;
343 ifa->ifa_ifp = ifp;
344 ifa->ifa_rtrequest = link_rtrequest;
345 TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list);
346 ifa->ifa_addr = (struct sockaddr *)sdl;
347 ifp->if_sadl = sdl;
348 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
349 ifa->ifa_netmask = (struct sockaddr *)sdl;
350 sdl->sdl_len = masklen;
351 while (namelen != 0)
352 sdl->sdl_data[--namelen] = 0xff;
353 }
354
355 /*
356 * Free the link level name for the specified interface. This is
357 * a detach helper. This is called from if_detach() or from
358 * link layer type specific detach functions.
359 */
360 void
361 if_free_sadl(struct ifnet *ifp)
362 {
363 struct ifaddr *ifa;
364 int s;
365
366 ifa = ifnet_addrs[ifp->if_index];
367 if (ifa == NULL)
368 return;
369
370 s = splnet();
371 rtinit(ifa, RTM_DELETE, 0);
372 #if 0
373 TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
374 ifnet_addrs[ifp->if_index] = NULL;
375 #endif
376 ifp->if_sadl = NULL;
377
378 splx(s);
379 }
380
381 void
382 if_attachdomain()
383 {
384 struct ifnet *ifp;
385 int s;
386
387 s = splnet();
388 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
389 if_attachdomain1(ifp);
390 splx(s);
391 }
392
393 void
394 if_attachdomain1(struct ifnet *ifp)
395 {
396 struct domain *dp;
397 int s;
398
399 s = splnet();
400
401 /* address family dependent data region */
402 bzero(ifp->if_afdata, sizeof(ifp->if_afdata));
403 for (dp = domains; dp; dp = dp->dom_next) {
404 if (dp->dom_ifattach)
405 ifp->if_afdata[dp->dom_family] =
406 (*dp->dom_ifattach)(ifp);
407 }
408
409 splx(s);
410 }
411
412 void
413 if_attachhead(struct ifnet *ifp)
414 {
415 if (if_index == 0) {
416 TAILQ_INIT(&ifnet);
417 TAILQ_INIT(&ifg_head);
418 }
419 TAILQ_INIT(&ifp->if_addrlist);
420 ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks),
421 M_TEMP, M_NOWAIT);
422 if (ifp->if_addrhooks == NULL)
423 panic("if_attachhead: malloc");
424 TAILQ_INIT(ifp->if_addrhooks);
425 ifp->if_linkstatehooks = malloc(sizeof(*ifp->if_linkstatehooks),
426 M_TEMP, M_NOWAIT);
427 if (ifp->if_linkstatehooks == NULL)
428 panic("if_attachhead: malloc");
429 TAILQ_INIT(ifp->if_linkstatehooks);
430 ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks),
431 M_TEMP, M_NOWAIT);
432 if (ifp->if_detachhooks == NULL)
433 panic("if_attachhead: malloc");
434 TAILQ_INIT(ifp->if_detachhooks);
435 TAILQ_INSERT_HEAD(&ifnet, ifp, if_list);
436 if_attachsetup(ifp);
437 }
438
439 void
440 if_attach(struct ifnet *ifp)
441 {
442 #if NCARP > 0
443 struct ifnet *before = NULL;
444 #endif
445
446 if (if_index == 0) {
447 TAILQ_INIT(&ifnet);
448 TAILQ_INIT(&ifg_head);
449 }
450 TAILQ_INIT(&ifp->if_addrlist);
451 ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks),
452 M_TEMP, M_NOWAIT);
453 if (ifp->if_addrhooks == NULL)
454 panic("if_attach: malloc");
455 TAILQ_INIT(ifp->if_addrhooks);
456 ifp->if_linkstatehooks = malloc(sizeof(*ifp->if_linkstatehooks),
457 M_TEMP, M_NOWAIT);
458 if (ifp->if_linkstatehooks == NULL)
459 panic("if_attach: malloc");
460 TAILQ_INIT(ifp->if_linkstatehooks);
461 ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks),
462 M_TEMP, M_NOWAIT);
463 if (ifp->if_detachhooks == NULL)
464 panic("if_attach: malloc");
465 TAILQ_INIT(ifp->if_detachhooks);
466
467 #if NCARP > 0
468 if (ifp->if_type != IFT_CARP)
469 TAILQ_FOREACH(before, &ifnet, if_list)
470 if (before->if_type == IFT_CARP)
471 break;
472 if (before == NULL)
473 TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
474 else
475 TAILQ_INSERT_BEFORE(before, ifp, if_list);
476 #else
477 TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
478 #endif
479
480 m_clinitifp(ifp);
481
482 if_attachsetup(ifp);
483 }
484
485 void
486 if_start(struct ifnet *ifp)
487 {
488 if (IF_QFULL(&ifp->if_snd) && !ISSET(ifp->if_flags, IFF_OACTIVE)) {
489 if (ISSET(ifp->if_xflags, IFXF_TXREADY)) {
490 TAILQ_REMOVE(&iftxlist, ifp, if_txlist);
491 CLR(ifp->if_xflags, IFXF_TXREADY);
492 }
493 ifp->if_start(ifp);
494 return;
495 }
496
497 if (!ISSET(ifp->if_xflags, IFXF_TXREADY)) {
498 SET(ifp->if_xflags, IFXF_TXREADY);
499 TAILQ_INSERT_TAIL(&iftxlist, ifp, if_txlist);
500 schednetisr(NETISR_TX);
501 }
502 }
503
504 void
505 nettxintr(void)
506 {
507 struct ifnet *ifp;
508 int s;
509
510 s = splnet();
511 while ((ifp = TAILQ_FIRST(&iftxlist)) != NULL) {
512 TAILQ_REMOVE(&iftxlist, ifp, if_txlist);
513 CLR(ifp->if_xflags, IFXF_TXREADY);
514 ifp->if_start(ifp);
515 }
516 splx(s);
517 }
518
519 /*
520 * Detach an interface from everything in the kernel. Also deallocate
521 * private resources.
522 * XXX So far only the INET protocol family has been looked over
523 * wrt resource usage that needs to be decoupled.
524 */
525 void
526 if_detach(struct ifnet *ifp)
527 {
528 struct ifaddr *ifa;
529 struct ifg_list *ifg;
530 int s = splnet();
531 struct domain *dp;
532
533 ifp->if_flags &= ~IFF_OACTIVE;
534 ifp->if_start = if_detached_start;
535 ifp->if_ioctl = if_detached_ioctl;
536 ifp->if_init = if_detached_init;
537 ifp->if_watchdog = if_detached_watchdog;
538
539 /* Call detach hooks, ie. to remove vlan interfaces */
540 dohooks(ifp->if_detachhooks, HOOK_REMOVE | HOOK_FREE);
541
542 #if NTRUNK > 0
543 if (ifp->if_type == IFT_IEEE8023ADLAG)
544 trunk_port_ifdetach(ifp);
545 #endif
546
547 #if NBRIDGE > 0
548 /* Remove the interface from any bridge it is part of. */
549 if (ifp->if_bridge)
550 bridge_ifdetach(ifp);
551 #endif
552
553 #if NCARP > 0
554 /* Remove the interface from any carp group it is a part of. */
555 if (ifp->if_carp && ifp->if_type != IFT_CARP)
556 carp_ifdetach(ifp);
557 #endif
558
559 #if NBPFILTER > 0
560 bpfdetach(ifp);
561 #endif
562 #ifdef ALTQ
563 if (ALTQ_IS_ENABLED(&ifp->if_snd))
564 altq_disable(&ifp->if_snd);
565 if (ALTQ_IS_ATTACHED(&ifp->if_snd))
566 altq_detach(&ifp->if_snd);
567 #endif
568 rt_if_remove(ifp);
569 #ifdef INET
570 rti_delete(ifp);
571 #if NETHER > 0
572 myip_ifp = NULL;
573 #endif
574 #ifdef MROUTING
575 vif_delete(ifp);
576 #endif
577 #endif
578 #ifdef INET6
579 in6_ifdetach(ifp);
580 #endif
581
582 #if NPF > 0
583 pfi_detach_ifnet(ifp);
584 #endif
585
586 /*
587 * remove packets came from ifp, from software interrupt queues.
588 * net/netisr_dispatch.h is not usable, as some of them use
589 * strange queue names.
590 */
591 #define IF_DETACH_QUEUES(x) \
592 do { \
593 extern struct ifqueue x; \
594 if_detach_queues(ifp, & x); \
595 } while (0)
596 #ifdef INET
597 IF_DETACH_QUEUES(arpintrq);
598 IF_DETACH_QUEUES(ipintrq);
599 #endif
600 #ifdef INET6
601 IF_DETACH_QUEUES(ip6intrq);
602 #endif
603 #ifdef NETATALK
604 IF_DETACH_QUEUES(atintrq1);
605 IF_DETACH_QUEUES(atintrq2);
606 #endif
607 #ifdef NATM
608 IF_DETACH_QUEUES(natmintrq);
609 #endif
610 #undef IF_DETACH_QUEUES
611
612 /*
613 * XXX transient ifp refs? inpcb.ip_moptions.imo_multicast_ifp?
614 * Other network stacks than INET?
615 */
616
617 /* Remove the interface from the list of all interfaces. */
618 TAILQ_REMOVE(&ifnet, ifp, if_list);
619 if (ISSET(ifp->if_xflags, IFXF_TXREADY))
620 TAILQ_REMOVE(&iftxlist, ifp, if_txlist);
621
622 /*
623 * Deallocate private resources.
624 */
625 while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) {
626 TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
627 #ifdef INET
628 if (ifa->ifa_addr->sa_family == AF_INET)
629 TAILQ_REMOVE(&in_ifaddr, (struct in_ifaddr *)ifa,
630 ia_list);
631 #endif
632 /* XXX if_free_sadl needs this */
633 if (ifa == ifnet_addrs[ifp->if_index])
634 continue;
635
636 ifa->ifa_ifp = NULL;
637 IFAFREE(ifa);
638 }
639
640 for (ifg = TAILQ_FIRST(&ifp->if_groups); ifg;
641 ifg = TAILQ_FIRST(&ifp->if_groups))
642 if_delgroup(ifp, ifg->ifgl_group->ifg_group);
643
644 if_free_sadl(ifp);
645
646 ifnet_addrs[ifp->if_index]->ifa_ifp = NULL;
647 IFAFREE(ifnet_addrs[ifp->if_index]);
648 ifnet_addrs[ifp->if_index] = NULL;
649
650 free(ifp->if_addrhooks, M_TEMP);
651 free(ifp->if_linkstatehooks, M_TEMP);
652 free(ifp->if_detachhooks, M_TEMP);
653
654 for (dp = domains; dp; dp = dp->dom_next) {
655 if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
656 (*dp->dom_ifdetach)(ifp,
657 ifp->if_afdata[dp->dom_family]);
658 }
659
660 /* Announce that the interface is gone. */
661 rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
662
663 ifindex2ifnet[ifp->if_index] = NULL;
664 splx(s);
665 }
666
667 void
668 if_detach_queues(struct ifnet *ifp, struct ifqueue *q)
669 {
670 struct mbuf *m, *prev, *next;
671
672 prev = NULL;
673 for (m = q->ifq_head; m; m = next) {
674 next = m->m_nextpkt;
675 #ifdef DIAGNOSTIC
676 if ((m->m_flags & M_PKTHDR) == 0) {
677 prev = m;
678 continue;
679 }
680 #endif
681 if (m->m_pkthdr.rcvif != ifp) {
682 prev = m;
683 continue;
684 }
685
686 if (prev)
687 prev->m_nextpkt = m->m_nextpkt;
688 else
689 q->ifq_head = m->m_nextpkt;
690 if (q->ifq_tail == m)
691 q->ifq_tail = prev;
692 q->ifq_len--;
693
694 m->m_nextpkt = NULL;
695 m_freem(m);
696 IF_DROP(q);
697 }
698 }
699
700 /*
701 * Create a clone network interface.
702 */
703 int
704 if_clone_create(const char *name)
705 {
706 struct if_clone *ifc;
707 struct ifnet *ifp;
708 int unit, ret;
709
710 ifc = if_clone_lookup(name, &unit);
711 if (ifc == NULL)
712 return (EINVAL);
713
714 if (ifunit(name) != NULL)
715 return (EEXIST);
716
717 if ((ret = (*ifc->ifc_create)(ifc, unit)) == 0 &&
718 (ifp = ifunit(name)) != NULL)
719 if_addgroup(ifp, ifc->ifc_name);
720
721 return (ret);
722 }
723
724 /*
725 * Destroy a clone network interface.
726 */
727 int
728 if_clone_destroy(const char *name)
729 {
730 struct if_clone *ifc;
731 struct ifnet *ifp;
732 int s, ret;
733
734 ifc = if_clone_lookup(name, NULL);
735 if (ifc == NULL)
736 return (EINVAL);
737
738 ifp = ifunit(name);
739 if (ifp == NULL)
740 return (ENXIO);
741
742 if (ifc->ifc_destroy == NULL)
743 return (EOPNOTSUPP);
744
745 if (ifp->if_flags & IFF_UP) {
746 s = splnet();
747 if_down(ifp);
748 splx(s);
749 }
750
751 if_delgroup(ifp, ifc->ifc_name);
752
753 if ((ret = (*ifc->ifc_destroy)(ifp)) != 0)
754 if_addgroup(ifp, ifc->ifc_name);
755
756 return (ret);
757 }
758
759 /*
760 * Look up a network interface cloner.
761 */
762 struct if_clone *
763 if_clone_lookup(const char *name, int *unitp)
764 {
765 struct if_clone *ifc;
766 const char *cp;
767 int unit;
768
769 /* separate interface name from unit */
770 for (cp = name;
771 cp - name < IFNAMSIZ && *cp && (*cp < '' || *cp > '9');
772 cp++)
773 continue;
774
775 if (cp == name || cp - name == IFNAMSIZ || !*cp)
776 return (NULL); /* No name or unit number */
777
778 if (cp - name < IFNAMSIZ-1 && *cp == '' && cp[1] != '\0')
779 return (NULL); /* unit number 0 padded */
780
781 LIST_FOREACH(ifc, &if_cloners, ifc_list) {
782 if (strlen(ifc->ifc_name) == cp - name &&
783 !strncmp(name, ifc->ifc_name, cp - name))
784 break;
785 }
786
787 if (ifc == NULL)
788 return (NULL);
789
790 unit = 0;
791 while (cp - name < IFNAMSIZ && *cp) {
792 if (*cp < '' || *cp > '9' ||
793 unit > (INT_MAX - (*cp - '')) / 10) {
794 /* Bogus unit number. */
795 return (NULL);
796 }
797 unit = (unit * 10) + (*cp++ - '');
798 }
799
800 if (unitp != NULL)
801 *unitp = unit;
802 return (ifc);
803 }
804
805 /*
806 * Register a network interface cloner.
807 */
808 void
809 if_clone_attach(struct if_clone *ifc)
810 {
811 LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
812 if_cloners_count++;
813 }
814
815 /*
816 * Unregister a network interface cloner.
817 */
818 void
819 if_clone_detach(struct if_clone *ifc)
820 {
821
822 LIST_REMOVE(ifc, ifc_list);
823 if_cloners_count--;
824 }
825
826 /*
827 * Provide list of interface cloners to userspace.
828 */
829 int
830 if_clone_list(struct if_clonereq *ifcr)
831 {
832 char outbuf[IFNAMSIZ], *dst;
833 struct if_clone *ifc;
834 int count, error = 0;
835
836 ifcr->ifcr_total = if_cloners_count;
837 if ((dst = ifcr->ifcr_buffer) == NULL) {
838 /* Just asking how many there are. */
839 return (0);
840 }
841
842 if (ifcr->ifcr_count < 0)
843 return (EINVAL);
844
845 count = (if_cloners_count < ifcr->ifcr_count) ?
846 if_cloners_count : ifcr->ifcr_count;
847
848 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
849 ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
850 bzero(outbuf, sizeof outbuf);
851 strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
852 error = copyout(outbuf, dst, IFNAMSIZ);
853 if (error)
854 break;
855 }
856
857 return (error);
858 }
859
860 /*
861 * set queue congestion marker and register timeout to clear it
862 */
863 void
864 if_congestion(struct ifqueue *ifq)
865 {
866 /* Not currently needed, all callers check this */
867 if (ifq->ifq_congestion)
868 return;
869
870 ifq->ifq_congestion = malloc(sizeof(struct timeout), M_TEMP, M_NOWAIT);
871 if (ifq->ifq_congestion == NULL)
872 return;
873 timeout_set(ifq->ifq_congestion, if_congestion_clear, ifq);
874 timeout_add(ifq->ifq_congestion, hz / 100);
875 }
876
877 /*
878 * clear the congestion flag
879 */
880 void
881 if_congestion_clear(void *arg)
882 {
883 struct ifqueue *ifq = arg;
884 struct timeout *to = ifq->ifq_congestion;
885
886 ifq->ifq_congestion = NULL;
887 free(to, M_TEMP);
888 }
889
890 /*
891 * Locate an interface based on a complete address.
892 */
893 /*ARGSUSED*/
894 struct ifaddr *
895 ifa_ifwithaddr(struct sockaddr *addr)
896 {
897 struct ifnet *ifp;
898 struct ifaddr *ifa;
899
900 #define equal(a1, a2) \
901 (bcmp((caddr_t)(a1), (caddr_t)(a2), \
902 ((struct sockaddr *)(a1))->sa_len) == 0)
903 TAILQ_FOREACH(ifp, &ifnet, if_list) {
904 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
905 if (ifa->ifa_addr->sa_family != addr->sa_family)
906 continue;
907 if (equal(addr, ifa->ifa_addr))
908 return (ifa);
909 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
910 /* IP6 doesn't have broadcast */
911 ifa->ifa_broadaddr->sa_len != 0 &&
912 equal(ifa->ifa_broadaddr, addr))
913 return (ifa);
914 }
915 }
916 return (NULL);
917 }
918 /*
919 * Locate the point to point interface with a given destination address.
920 */
921 /*ARGSUSED*/
922 struct ifaddr *
923 ifa_ifwithdstaddr(struct sockaddr *addr)
924 {
925 struct ifnet *ifp;
926 struct ifaddr *ifa;
927
928 TAILQ_FOREACH(ifp, &ifnet, if_list) {
929 if (ifp->if_flags & IFF_POINTOPOINT)
930 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
931 if (ifa->ifa_addr->sa_family != addr->sa_family ||
932 ifa->ifa_dstaddr == NULL)
933 continue;
934 if (equal(addr, ifa->ifa_dstaddr))
935 return (ifa);
936 }
937 }
938 return (NULL);
939 }
940
941 /*
942 * Find an interface on a specific network. If many, choice
943 * is most specific found.
944 */
945 struct ifaddr *
946 ifa_ifwithnet(struct sockaddr *addr)
947 {
948 struct ifnet *ifp;
949 struct ifaddr *ifa;
950 struct ifaddr *ifa_maybe = 0;
951 u_int af = addr->sa_family;
952 char *addr_data = addr->sa_data, *cplim;
953
954 if (af == AF_LINK) {
955 struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
956 if (sdl->sdl_index && sdl->sdl_index < if_indexlim &&
957 ifindex2ifnet[sdl->sdl_index])
958 return (ifnet_addrs[sdl->sdl_index]);
959 }
960 TAILQ_FOREACH(ifp, &ifnet, if_list) {
961 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
962 char *cp, *cp2, *cp3;
963
964 if (ifa->ifa_addr->sa_family != af ||
965 ifa->ifa_netmask == 0)
966 next: continue;
967 cp = addr_data;
968 cp2 = ifa->ifa_addr->sa_data;
969 cp3 = ifa->ifa_netmask->sa_data;
970 cplim = (char *)ifa->ifa_netmask +
971 ifa->ifa_netmask->sa_len;
972 while (cp3 < cplim)
973 if ((*cp++ ^ *cp2++) & *cp3++)
974 /* want to continue for() loop */
975 goto next;
976 if (ifa_maybe == 0 ||
977 rn_refines((caddr_t)ifa->ifa_netmask,
978 (caddr_t)ifa_maybe->ifa_netmask))
979 ifa_maybe = ifa;
980 }
981 }
982 return (ifa_maybe);
983 }
984
985 /*
986 * Find an interface using a specific address family
987 */
988 struct ifaddr *
989 ifa_ifwithaf(int af)
990 {
991 struct ifnet *ifp;
992 struct ifaddr *ifa;
993
994 TAILQ_FOREACH(ifp, &ifnet, if_list) {
995 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
996 if (ifa->ifa_addr->sa_family == af)
997 return (ifa);
998 }
999 }
1000 return (NULL);
1001 }
1002
1003 /*
1004 * Find an interface address specific to an interface best matching
1005 * a given address.
1006 */
1007 struct ifaddr *
1008 ifaof_ifpforaddr(struct sockaddr *addr, struct ifnet *ifp)
1009 {
1010 struct ifaddr *ifa;
1011 char *cp, *cp2, *cp3;
1012 char *cplim;
1013 struct ifaddr *ifa_maybe = NULL;
1014 u_int af = addr->sa_family;
1015
1016 if (af >= AF_MAX)
1017 return (NULL);
1018 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1019 if (ifa->ifa_addr->sa_family != af)
1020 continue;
1021 if (ifa_maybe == NULL)
1022 ifa_maybe = ifa;
1023 if (ifa->ifa_netmask == 0 || ifp->if_flags & IFF_POINTOPOINT) {
1024 if (equal(addr, ifa->ifa_addr) ||
1025 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
1026 return (ifa);
1027 continue;
1028 }
1029 cp = addr->sa_data;
1030 cp2 = ifa->ifa_addr->sa_data;
1031 cp3 = ifa->ifa_netmask->sa_data;
1032 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
1033 for (; cp3 < cplim; cp3++)
1034 if ((*cp++ ^ *cp2++) & *cp3)
1035 break;
1036 if (cp3 == cplim)
1037 return (ifa);
1038 }
1039 return (ifa_maybe);
1040 }
1041
1042 /*
1043 * Default action when installing a route with a Link Level gateway.
1044 * Lookup an appropriate real ifa to point to.
1045 * This should be moved to /sys/net/link.c eventually.
1046 */
1047 void
1048 link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
1049 {
1050 struct ifaddr *ifa;
1051 struct sockaddr *dst;
1052 struct ifnet *ifp;
1053
1054 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
1055 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
1056 return;
1057 if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
1058 ifa->ifa_refcnt++;
1059 IFAFREE(rt->rt_ifa);
1060 rt->rt_ifa = ifa;
1061 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
1062 ifa->ifa_rtrequest(cmd, rt, info);
1063 }
1064 }
1065
1066 /*
1067 * Mark an interface down and notify protocols of
1068 * the transition.
1069 * NOTE: must be called at splsoftnet or equivalent.
1070 */
1071 void
1072 if_down(struct ifnet *ifp)
1073 {
1074 struct ifaddr *ifa;
1075
1076 splassert(IPL_SOFTNET);
1077
1078 ifp->if_flags &= ~IFF_UP;
1079 microtime(&ifp->if_lastchange);
1080 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1081 pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
1082 }
1083 IFQ_PURGE(&ifp->if_snd);
1084 #if NCARP > 0
1085 if (ifp->if_carp)
1086 carp_carpdev_state(ifp);
1087 #endif
1088 #if NBRIDGE > 0
1089 if (ifp->if_bridge)
1090 bstp_ifstate(ifp);
1091 #endif
1092 rt_ifmsg(ifp);
1093 #ifndef SMALL_KERNEL
1094 rt_if_track(ifp);
1095 #endif
1096 }
1097
1098 /*
1099 * Mark an interface up and notify protocols of
1100 * the transition.
1101 * NOTE: must be called at splsoftnet or equivalent.
1102 */
1103 void
1104 if_up(struct ifnet *ifp)
1105 {
1106 #ifdef notyet
1107 struct ifaddr *ifa;
1108 #endif
1109
1110 splassert(IPL_SOFTNET);
1111
1112 ifp->if_flags |= IFF_UP;
1113 microtime(&ifp->if_lastchange);
1114 #ifdef notyet
1115 /* this has no effect on IP, and will kill all ISO connections XXX */
1116 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1117 pfctlinput(PRC_IFUP, ifa->ifa_addr);
1118 }
1119 #endif
1120 #if NCARP > 0
1121 if (ifp->if_carp)
1122 carp_carpdev_state(ifp);
1123 #endif
1124 #if NBRIDGE > 0
1125 if (ifp->if_bridge)
1126 bstp_ifstate(ifp);
1127 #endif
1128 rt_ifmsg(ifp);
1129 #ifdef INET6
1130 in6_if_up(ifp);
1131 #endif
1132
1133 #ifndef SMALL_KERNEL
1134 rt_if_track(ifp);
1135 #endif
1136
1137 m_clinitifp(ifp);
1138 }
1139
1140 /*
1141 * Process a link state change.
1142 * NOTE: must be called at splsoftnet or equivalent.
1143 */
1144 void
1145 if_link_state_change(struct ifnet *ifp)
1146 {
1147 rt_ifmsg(ifp);
1148 #ifndef SMALL_KERNEL
1149 rt_if_track(ifp);
1150 #endif
1151 dohooks(ifp->if_linkstatehooks, 0);
1152 }
1153
1154 /*
1155 * Flush an interface queue.
1156 */
1157 void
1158 if_qflush(struct ifqueue *ifq)
1159 {
1160 struct mbuf *m, *n;
1161
1162 n = ifq->ifq_head;
1163 while ((m = n) != NULL) {
1164 n = m->m_act;
1165 m_freem(m);
1166 }
1167 ifq->ifq_head = 0;
1168 ifq->ifq_tail = 0;
1169 ifq->ifq_len = 0;
1170 }
1171
1172 /*
1173 * Handle interface watchdog timer routines. Called
1174 * from softclock, we decrement timers (if set) and
1175 * call the appropriate interface routine on expiration.
1176 */
1177 void
1178 if_slowtimo(void *arg)
1179 {
1180 struct timeout *to = (struct timeout *)arg;
1181 struct ifnet *ifp;
1182 int s = splnet();
1183
1184 TAILQ_FOREACH(ifp, &ifnet, if_list) {
1185 if (ifp->if_timer == 0 || --ifp->if_timer)
1186 continue;
1187 if (ifp->if_watchdog)
1188 (*ifp->if_watchdog)(ifp);
1189 }
1190 splx(s);
1191 timeout_add(to, hz / IFNET_SLOWHZ);
1192 }
1193
1194 /*
1195 * Map interface name to
1196 * interface structure pointer.
1197 */
1198 struct ifnet *
1199 ifunit(const char *name)
1200 {
1201 struct ifnet *ifp;
1202
1203 TAILQ_FOREACH(ifp, &ifnet, if_list) {
1204 if (strcmp(ifp->if_xname, name) == 0)
1205 return (ifp);
1206 }
1207 return (NULL);
1208 }
1209
1210 /*
1211 * Interface ioctls.
1212 */
1213 int
1214 ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
1215 {
1216 struct ifnet *ifp;
1217 struct ifreq *ifr;
1218 struct ifaddr *ifa;
1219 struct sockaddr_dl *sdl;
1220 struct ifgroupreq *ifgr;
1221 char ifdescrbuf[IFDESCRSIZE];
1222 char ifrtlabelbuf[RTLABEL_LEN];
1223 int error = 0;
1224 size_t bytesdone;
1225 short oif_flags;
1226 const char *label;
1227
1228 switch (cmd) {
1229
1230 case SIOCGIFCONF:
1231 case OSIOCGIFCONF:
1232 return (ifconf(cmd, data));
1233 }
1234 ifr = (struct ifreq *)data;
1235
1236 switch (cmd) {
1237 case SIOCIFCREATE:
1238 case SIOCIFDESTROY:
1239 if ((error = suser(p, 0)) != 0)
1240 return (error);
1241 return ((cmd == SIOCIFCREATE) ?
1242 if_clone_create(ifr->ifr_name) :
1243 if_clone_destroy(ifr->ifr_name));
1244 case SIOCIFGCLONERS:
1245 return (if_clone_list((struct if_clonereq *)data));
1246 case SIOCGIFGMEMB:
1247 return (if_getgroupmembers(data));
1248 case SIOCGIFGATTR:
1249 return (if_getgroupattribs(data));
1250 case SIOCSIFGATTR:
1251 if ((error = suser(p, 0)) != 0)
1252 return (error);
1253 return (if_setgroupattribs(data));
1254 }
1255
1256 ifp = ifunit(ifr->ifr_name);
1257 if (ifp == 0)
1258 return (ENXIO);
1259 oif_flags = ifp->if_flags;
1260 switch (cmd) {
1261
1262 case SIOCGIFFLAGS:
1263 ifr->ifr_flags = ifp->if_flags;
1264 break;
1265
1266 case SIOCGIFMETRIC:
1267 ifr->ifr_metric = ifp->if_metric;
1268 break;
1269
1270 case SIOCGIFMTU:
1271 ifr->ifr_mtu = ifp->if_mtu;
1272 break;
1273
1274 case SIOCGIFDATA:
1275 error = copyout((caddr_t)&ifp->if_data, ifr->ifr_data,
1276 sizeof(ifp->if_data));
1277 break;
1278
1279 case SIOCSIFFLAGS:
1280 if ((error = suser(p, 0)) != 0)
1281 return (error);
1282 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
1283 int s = splnet();
1284 if_down(ifp);
1285 splx(s);
1286 }
1287 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
1288 int s = splnet();
1289 if_up(ifp);
1290 splx(s);
1291 }
1292 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
1293 (ifr->ifr_flags &~ IFF_CANTCHANGE);
1294 if (ifp->if_ioctl)
1295 (void) (*ifp->if_ioctl)(ifp, cmd, data);
1296 break;
1297
1298 case SIOCSIFMETRIC:
1299 if ((error = suser(p, 0)) != 0)
1300 return (error);
1301 ifp->if_metric = ifr->ifr_metric;
1302 break;
1303
1304 case SIOCSIFMTU:
1305 {
1306 #ifdef INET6
1307 int oldmtu = ifp->if_mtu;
1308 #endif
1309
1310 if ((error = suser(p, 0)) != 0)
1311 return (error);
1312 if (ifp->if_ioctl == NULL)
1313 return (EOPNOTSUPP);
1314 error = (*ifp->if_ioctl)(ifp, cmd, data);
1315
1316 /*
1317 * If the link MTU changed, do network layer specific procedure.
1318 */
1319 #ifdef INET6
1320 if (ifp->if_mtu != oldmtu)
1321 nd6_setmtu(ifp);
1322 #endif
1323 break;
1324 }
1325
1326 case SIOCSIFPHYADDR:
1327 case SIOCDIFPHYADDR:
1328 #ifdef INET6
1329 case SIOCSIFPHYADDR_IN6:
1330 #endif
1331 case SIOCSLIFPHYADDR:
1332 case SIOCADDMULTI:
1333 case SIOCDELMULTI:
1334 case SIOCSIFMEDIA:
1335 if ((error = suser(p, 0)) != 0)
1336 return (error);
1337 /* FALLTHROUGH */
1338 case SIOCGIFPSRCADDR:
1339 case SIOCGIFPDSTADDR:
1340 case SIOCGLIFPHYADDR:
1341 case SIOCGIFMEDIA:
1342 if (ifp->if_ioctl == 0)
1343 return (EOPNOTSUPP);
1344 error = (*ifp->if_ioctl)(ifp, cmd, data);
1345 break;
1346
1347 case SIOCGIFDESCR:
1348 strlcpy(ifdescrbuf, ifp->if_description, IFDESCRSIZE);
1349 error = copyoutstr(ifdescrbuf, ifr->ifr_data, IFDESCRSIZE,
1350 &bytesdone);
1351 break;
1352
1353 case SIOCSIFDESCR:
1354 if ((error = suser(p, 0)) != 0)
1355 return (error);
1356 error = copyinstr(ifr->ifr_data, ifdescrbuf,
1357 IFDESCRSIZE, &bytesdone);
1358 if (error == 0) {
1359 (void)memset(ifp->if_description, 0, IFDESCRSIZE);
1360 strlcpy(ifp->if_description, ifdescrbuf, IFDESCRSIZE);
1361 }
1362 break;
1363
1364 case SIOCGIFRTLABEL:
1365 if (ifp->if_rtlabelid &&
1366 (label = rtlabel_id2name(ifp->if_rtlabelid)) != NULL) {
1367 strlcpy(ifrtlabelbuf, label, RTLABEL_LEN);
1368 error = copyoutstr(ifrtlabelbuf, ifr->ifr_data,
1369 RTLABEL_LEN, &bytesdone);
1370 } else
1371 error = ENOENT;
1372 break;
1373
1374 case SIOCSIFRTLABEL:
1375 if ((error = suser(p, 0)) != 0)
1376 return (error);
1377 error = copyinstr(ifr->ifr_data, ifrtlabelbuf,
1378 RTLABEL_LEN, &bytesdone);
1379 if (error == 0) {
1380 rtlabel_unref(ifp->if_rtlabelid);
1381 ifp->if_rtlabelid = rtlabel_name2id(ifrtlabelbuf);
1382 }
1383 break;
1384
1385 case SIOCAIFGROUP:
1386 if ((error = suser(p, 0)))
1387 return (error);
1388 (*ifp->if_ioctl)(ifp, cmd, data); /* XXX error check */
1389 ifgr = (struct ifgroupreq *)data;
1390 if ((error = if_addgroup(ifp, ifgr->ifgr_group)))
1391 return (error);
1392 break;
1393
1394 case SIOCGIFGROUP:
1395 if ((error = if_getgroup(data, ifp)))
1396 return (error);
1397 break;
1398
1399 case SIOCDIFGROUP:
1400 if ((error = suser(p, 0)))
1401 return (error);
1402 (*ifp->if_ioctl)(ifp, cmd, data); /* XXX error check */
1403 ifgr = (struct ifgroupreq *)data;
1404 if ((error = if_delgroup(ifp, ifgr->ifgr_group)))
1405 return (error);
1406 break;
1407
1408 case SIOCSIFLLADDR:
1409 if ((error = suser(p, 0)))
1410 return (error);
1411 ifa = ifnet_addrs[ifp->if_index];
1412 if (ifa == NULL)
1413 return (EINVAL);
1414 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
1415 if (sdl == NULL)
1416 return (EINVAL);
1417 if (ifr->ifr_addr.sa_len != ETHER_ADDR_LEN)
1418 return (EINVAL);
1419 if (ETHER_IS_MULTICAST(ifr->ifr_addr.sa_data))
1420 return (EINVAL);
1421 switch (ifp->if_type) {
1422 case IFT_ETHER:
1423 case IFT_CARP:
1424 case IFT_FDDI:
1425 case IFT_XETHER:
1426 case IFT_ISO88025:
1427 case IFT_L2VLAN:
1428 bcopy((caddr_t)ifr->ifr_addr.sa_data,
1429 (caddr_t)((struct arpcom *)ifp)->ac_enaddr,
1430 ETHER_ADDR_LEN);
1431 bcopy((caddr_t)ifr->ifr_addr.sa_data,
1432 LLADDR(sdl), ETHER_ADDR_LEN);
1433 break;
1434 default:
1435 return (ENODEV);
1436 }
1437 if (ifp->if_flags & IFF_UP) {
1438 struct ifreq ifrq;
1439 int s = splnet();
1440 ifp->if_flags &= ~IFF_UP;
1441 ifrq.ifr_flags = ifp->if_flags;
1442 (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
1443 ifp->if_flags |= IFF_UP;
1444 ifrq.ifr_flags = ifp->if_flags;
1445 (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
1446 splx(s);
1447 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1448 if (ifa->ifa_addr != NULL &&
1449 ifa->ifa_addr->sa_family == AF_INET)
1450 arp_ifinit((struct arpcom *)ifp, ifa);
1451 }
1452 }
1453 break;
1454
1455 default:
1456 if (so->so_proto == 0)
1457 return (EOPNOTSUPP);
1458 #if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4)
1459 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
1460 (struct mbuf *) cmd, (struct mbuf *) data,
1461 (struct mbuf *) ifp, p));
1462 #else
1463 {
1464 u_long ocmd = cmd;
1465
1466 switch (cmd) {
1467
1468 case SIOCSIFADDR:
1469 case SIOCSIFDSTADDR:
1470 case SIOCSIFBRDADDR:
1471 case SIOCSIFNETMASK:
1472 #if BYTE_ORDER != BIG_ENDIAN
1473 if (ifr->ifr_addr.sa_family == 0 &&
1474 ifr->ifr_addr.sa_len < 16) {
1475 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
1476 ifr->ifr_addr.sa_len = 16;
1477 }
1478 #else
1479 if (ifr->ifr_addr.sa_len == 0)
1480 ifr->ifr_addr.sa_len = 16;
1481 #endif
1482 break;
1483
1484 case OSIOCGIFADDR:
1485 cmd = SIOCGIFADDR;
1486 break;
1487
1488 case OSIOCGIFDSTADDR:
1489 cmd = SIOCGIFDSTADDR;
1490 break;
1491
1492 case OSIOCGIFBRDADDR:
1493 cmd = SIOCGIFBRDADDR;
1494 break;
1495
1496 case OSIOCGIFNETMASK:
1497 cmd = SIOCGIFNETMASK;
1498 }
1499 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
1500 (struct mbuf *) cmd, (struct mbuf *) data,
1501 (struct mbuf *) ifp, p));
1502 switch (ocmd) {
1503
1504 case OSIOCGIFADDR:
1505 case OSIOCGIFDSTADDR:
1506 case OSIOCGIFBRDADDR:
1507 case OSIOCGIFNETMASK:
1508 *(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
1509 }
1510
1511 }
1512 #endif
1513 break;
1514 }
1515
1516 if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
1517 microtime(&ifp->if_lastchange);
1518 #ifdef INET6
1519 if ((ifp->if_flags & IFF_UP) != 0) {
1520 int s = splnet();
1521 in6_if_up(ifp);
1522 splx(s);
1523 }
1524 #endif
1525 }
1526 return (error);
1527 }
1528
1529 /*
1530 * Return interface configuration
1531 * of system. List may be used
1532 * in later ioctl's (above) to get
1533 * other information.
1534 */
1535 /*ARGSUSED*/
1536 int
1537 ifconf(u_long cmd, caddr_t data)
1538 {
1539 struct ifconf *ifc = (struct ifconf *)data;
1540 struct ifnet *ifp;
1541 struct ifaddr *ifa;
1542 struct ifreq ifr, *ifrp;
1543 int space = ifc->ifc_len, error = 0;
1544
1545 /* If ifc->ifc_len is 0, fill it in with the needed size and return. */
1546 if (space == 0) {
1547 TAILQ_FOREACH(ifp, &ifnet, if_list) {
1548 struct sockaddr *sa;
1549
1550 if (TAILQ_EMPTY(&ifp->if_addrlist))
1551 space += sizeof (ifr);
1552 else
1553 TAILQ_FOREACH(ifa,
1554 &ifp->if_addrlist, ifa_list) {
1555 sa = ifa->ifa_addr;
1556 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
1557 if (cmd != OSIOCGIFCONF)
1558 #endif
1559 if (sa->sa_len > sizeof(*sa))
1560 space += sa->sa_len -
1561 sizeof(*sa);
1562 space += sizeof(ifr);
1563 }
1564 }
1565 ifc->ifc_len = space;
1566 return (0);
1567 }
1568
1569 ifrp = ifc->ifc_req;
1570 for (ifp = TAILQ_FIRST(&ifnet); space >= sizeof(ifr) &&
1571 ifp != TAILQ_END(&ifnet); ifp = TAILQ_NEXT(ifp, if_list)) {
1572 bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ);
1573 if (TAILQ_EMPTY(&ifp->if_addrlist)) {
1574 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
1575 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1576 sizeof(ifr));
1577 if (error)
1578 break;
1579 space -= sizeof (ifr), ifrp++;
1580 } else
1581 for (ifa = TAILQ_FIRST(&ifp->if_addrlist);
1582 space >= sizeof (ifr) &&
1583 ifa != TAILQ_END(&ifp->if_addrlist);
1584 ifa = TAILQ_NEXT(ifa, ifa_list)) {
1585 struct sockaddr *sa = ifa->ifa_addr;
1586 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
1587 if (cmd == OSIOCGIFCONF) {
1588 struct osockaddr *osa =
1589 (struct osockaddr *)&ifr.ifr_addr;
1590 ifr.ifr_addr = *sa;
1591 osa->sa_family = sa->sa_family;
1592 error = copyout((caddr_t)&ifr,
1593 (caddr_t)ifrp, sizeof (ifr));
1594 ifrp++;
1595 } else
1596 #endif
1597 if (sa->sa_len <= sizeof(*sa)) {
1598 ifr.ifr_addr = *sa;
1599 error = copyout((caddr_t)&ifr,
1600 (caddr_t)ifrp, sizeof (ifr));
1601 ifrp++;
1602 } else {
1603 space -= sa->sa_len - sizeof(*sa);
1604 if (space < sizeof (ifr))
1605 break;
1606 error = copyout((caddr_t)&ifr,
1607 (caddr_t)ifrp,
1608 sizeof(ifr.ifr_name));
1609 if (error == 0)
1610 error = copyout((caddr_t)sa,
1611 (caddr_t)&ifrp->ifr_addr,
1612 sa->sa_len);
1613 ifrp = (struct ifreq *)(sa->sa_len +
1614 (caddr_t)&ifrp->ifr_addr);
1615 }
1616 if (error)
1617 break;
1618 space -= sizeof (ifr);
1619 }
1620 }
1621 ifc->ifc_len -= space;
1622 return (error);
1623 }
1624
1625 /*
1626 * Dummy functions replaced in ifnet during detach (if protocols decide to
1627 * fiddle with the if during detach.
1628 */
1629 void
1630 if_detached_start(struct ifnet *ifp)
1631 {
1632 struct mbuf *m;
1633
1634 while (1) {
1635 IF_DEQUEUE(&ifp->if_snd, m);
1636
1637 if (m == NULL)
1638 return;
1639 m_freem(m);
1640 }
1641 }
1642
1643 int
1644 if_detached_ioctl(struct ifnet *ifp, u_long a, caddr_t b)
1645 {
1646 return ENODEV;
1647 }
1648
1649 int
1650 if_detached_init(struct ifnet *ifp)
1651 {
1652 return (ENXIO);
1653 }
1654
1655 void
1656 if_detached_watchdog(struct ifnet *ifp)
1657 {
1658 /* nothing */
1659 }
1660
1661 /*
1662 * Create interface group without members
1663 */
1664 struct ifg_group *
1665 if_creategroup(const char *groupname)
1666 {
1667 struct ifg_group *ifg;
1668
1669 if ((ifg = malloc(sizeof(*ifg), M_TEMP, M_NOWAIT)) == NULL)
1670 return (NULL);
1671
1672 strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group));
1673 ifg->ifg_refcnt = 0;
1674 ifg->ifg_carp_demoted = 0;
1675 TAILQ_INIT(&ifg->ifg_members);
1676 #if NPF > 0
1677 pfi_attach_ifgroup(ifg);
1678 #endif
1679 TAILQ_INSERT_TAIL(&ifg_head, ifg, ifg_next);
1680
1681 return (ifg);
1682 }
1683
1684 /*
1685 * Add a group to an interface
1686 */
1687 int
1688 if_addgroup(struct ifnet *ifp, const char *groupname)
1689 {
1690 struct ifg_list *ifgl;
1691 struct ifg_group *ifg = NULL;
1692 struct ifg_member *ifgm;
1693
1694 if (groupname[0] && groupname[strlen(groupname) - 1] >= '' &&
1695 groupname[strlen(groupname) - 1] <= '9')
1696 return (EINVAL);
1697
1698 TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
1699 if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
1700 return (EEXIST);
1701
1702 if ((ifgl = malloc(sizeof(*ifgl), M_TEMP, M_NOWAIT)) == NULL)
1703 return (ENOMEM);
1704
1705 if ((ifgm = malloc(sizeof(*ifgm), M_TEMP, M_NOWAIT)) == NULL) {
1706 free(ifgl, M_TEMP);
1707 return (ENOMEM);
1708 }
1709
1710 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
1711 if (!strcmp(ifg->ifg_group, groupname))
1712 break;
1713
1714 if (ifg == NULL && (ifg = if_creategroup(groupname)) == NULL) {
1715 free(ifgl, M_TEMP);
1716 free(ifgm, M_TEMP);
1717 return (ENOMEM);
1718 }
1719
1720 ifg->ifg_refcnt++;
1721 ifgl->ifgl_group = ifg;
1722 ifgm->ifgm_ifp = ifp;
1723
1724 TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next);
1725 TAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next);
1726
1727 #if NPF > 0
1728 pfi_group_change(groupname);
1729 #endif
1730
1731 return (0);
1732 }
1733
1734 /*
1735 * Remove a group from an interface
1736 */
1737 int
1738 if_delgroup(struct ifnet *ifp, const char *groupname)
1739 {
1740 struct ifg_list *ifgl;
1741 struct ifg_member *ifgm;
1742
1743 TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
1744 if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
1745 break;
1746 if (ifgl == NULL)
1747 return (ENOENT);
1748
1749 TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next);
1750
1751 TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
1752 if (ifgm->ifgm_ifp == ifp)
1753 break;
1754
1755 if (ifgm != NULL) {
1756 TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next);
1757 free(ifgm, M_TEMP);
1758 }
1759
1760 if (--ifgl->ifgl_group->ifg_refcnt == 0) {
1761 TAILQ_REMOVE(&ifg_head, ifgl->ifgl_group, ifg_next);
1762 #if NPF > 0
1763 pfi_detach_ifgroup(ifgl->ifgl_group);
1764 #endif
1765 free(ifgl->ifgl_group, M_TEMP);
1766 }
1767
1768 free(ifgl, M_TEMP);
1769
1770 #if NPF > 0
1771 pfi_group_change(groupname);
1772 #endif
1773
1774 return (0);
1775 }
1776
1777 /*
1778 * Stores all groups from an interface in memory pointed
1779 * to by data
1780 */
1781 int
1782 if_getgroup(caddr_t data, struct ifnet *ifp)
1783 {
1784 int len, error;
1785 struct ifg_list *ifgl;
1786 struct ifg_req ifgrq, *ifgp;
1787 struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
1788
1789 if (ifgr->ifgr_len == 0) {
1790 TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
1791 ifgr->ifgr_len += sizeof(struct ifg_req);
1792 return (0);
1793 }
1794
1795 len = ifgr->ifgr_len;
1796 ifgp = ifgr->ifgr_groups;
1797 TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) {
1798 if (len < sizeof(ifgrq))
1799 return (EINVAL);
1800 bzero(&ifgrq, sizeof ifgrq);
1801 strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group,
1802 sizeof(ifgrq.ifgrq_group));
1803 if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
1804 sizeof(struct ifg_req))))
1805 return (error);
1806 len -= sizeof(ifgrq);
1807 ifgp++;
1808 }
1809
1810 return (0);
1811 }
1812
1813 /*
1814 * Stores all members of a group in memory pointed to by data
1815 */
1816 int
1817 if_getgroupmembers(caddr_t data)
1818 {
1819 struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
1820 struct ifg_group *ifg;
1821 struct ifg_member *ifgm;
1822 struct ifg_req ifgrq, *ifgp;
1823 int len, error;
1824
1825 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
1826 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
1827 break;
1828 if (ifg == NULL)
1829 return (ENOENT);
1830
1831 if (ifgr->ifgr_len == 0) {
1832 TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
1833 ifgr->ifgr_len += sizeof(ifgrq);
1834 return (0);
1835 }
1836
1837 len = ifgr->ifgr_len;
1838 ifgp = ifgr->ifgr_groups;
1839 TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) {
1840 if (len < sizeof(ifgrq))
1841 return (EINVAL);
1842 bzero(&ifgrq, sizeof ifgrq);
1843 strlcpy(ifgrq.ifgrq_member, ifgm->ifgm_ifp->if_xname,
1844 sizeof(ifgrq.ifgrq_member));
1845 if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
1846 sizeof(struct ifg_req))))
1847 return (error);
1848 len -= sizeof(ifgrq);
1849 ifgp++;
1850 }
1851
1852 return (0);
1853 }
1854
1855 int
1856 if_getgroupattribs(caddr_t data)
1857 {
1858 struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
1859 struct ifg_group *ifg;
1860
1861 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
1862 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
1863 break;
1864 if (ifg == NULL)
1865 return (ENOENT);
1866
1867 ifgr->ifgr_attrib.ifg_carp_demoted = ifg->ifg_carp_demoted;
1868
1869 return (0);
1870 }
1871
1872 int
1873 if_setgroupattribs(caddr_t data)
1874 {
1875 struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
1876 struct ifg_group *ifg;
1877 struct ifg_member *ifgm;
1878 int demote;
1879
1880 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
1881 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
1882 break;
1883 if (ifg == NULL)
1884 return (ENOENT);
1885
1886 demote = ifgr->ifgr_attrib.ifg_carp_demoted;
1887 if (demote + ifg->ifg_carp_demoted > 0xff ||
1888 demote + ifg->ifg_carp_demoted < 0)
1889 return (ERANGE);
1890
1891 ifg->ifg_carp_demoted += demote;
1892
1893 TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
1894 if (ifgm->ifgm_ifp->if_ioctl)
1895 ifgm->ifgm_ifp->if_ioctl(ifgm->ifgm_ifp,
1896 SIOCSIFGATTR, data);
1897 return (0);
1898 }
1899
1900 void
1901 if_group_routechange(struct sockaddr *dst, struct sockaddr *mask)
1902 {
1903 switch (dst->sa_family) {
1904 case AF_INET:
1905 if (satosin(dst)->sin_addr.s_addr == INADDR_ANY &&
1906 mask && (mask->sa_len == 0 ||
1907 satosin(mask)->sin_addr.s_addr == INADDR_ANY))
1908 if_group_egress_build();
1909 break;
1910 #ifdef INET6
1911 case AF_INET6:
1912 if (IN6_ARE_ADDR_EQUAL(&(satosin6(dst))->sin6_addr,
1913 &in6addr_any) && mask &&
1914 IN6_ARE_ADDR_EQUAL(&(satosin6(mask))->sin6_addr,
1915 &in6addr_any))
1916 if_group_egress_build();
1917 break;
1918 #endif
1919 }
1920 }
1921
1922 int
1923 if_group_egress_build(void)
1924 {
1925 struct ifg_group *ifg;
1926 struct ifg_member *ifgm, *next;
1927 struct sockaddr_in sa_in;
1928 #ifdef INET6
1929 struct sockaddr_in6 sa_in6;
1930 #endif
1931 struct radix_node *rn;
1932 struct rtentry *rt;
1933
1934 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
1935 if (!strcmp(ifg->ifg_group, IFG_EGRESS))
1936 break;
1937
1938 if (ifg != NULL)
1939 for (ifgm = TAILQ_FIRST(&ifg->ifg_members); ifgm; ifgm = next) {
1940 next = TAILQ_NEXT(ifgm, ifgm_next);
1941 if_delgroup(ifgm->ifgm_ifp, IFG_EGRESS);
1942 }
1943
1944 bzero(&sa_in, sizeof(sa_in));
1945 sa_in.sin_len = sizeof(sa_in);
1946 sa_in.sin_family = AF_INET;
1947 if ((rn = rt_lookup(sintosa(&sa_in), sintosa(&sa_in), 0)) != NULL) {
1948 do {
1949 rt = (struct rtentry *)rn;
1950 if (rt->rt_ifp)
1951 if_addgroup(rt->rt_ifp, IFG_EGRESS);
1952 #ifndef SMALL_KERNEL
1953 rn = rn_mpath_next(rn, 0);
1954 #else
1955 rn = NULL;
1956 #endif
1957 } while (rn != NULL);
1958 }
1959
1960 #ifdef INET6
1961 bcopy(&sa6_any, &sa_in6, sizeof(sa_in6));
1962 if ((rn = rt_lookup(sin6tosa(&sa_in6), sin6tosa(&sa_in6), 0)) != NULL) {
1963 do {
1964 rt = (struct rtentry *)rn;
1965 if (rt->rt_ifp)
1966 if_addgroup(rt->rt_ifp, IFG_EGRESS);
1967 #ifndef SMALL_KERNEL
1968 rn = rn_mpath_next(rn, 0);
1969 #else
1970 rn = NULL;
1971 #endif
1972 } while (rn != NULL);
1973 }
1974 #endif
1975
1976 return (0);
1977 }
1978
1979 /*
1980 * Set/clear promiscuous mode on interface ifp based on the truth value
1981 * of pswitch. The calls are reference counted so that only the first
1982 * "on" request actually has an effect, as does the final "off" request.
1983 * Results are undefined if the "off" and "on" requests are not matched.
1984 */
1985 int
1986 ifpromisc(struct ifnet *ifp, int pswitch)
1987 {
1988 struct ifreq ifr;
1989
1990 if (pswitch) {
1991 /*
1992 * If the device is not configured up, we cannot put it in
1993 * promiscuous mode.
1994 */
1995 if ((ifp->if_flags & IFF_UP) == 0)
1996 return (ENETDOWN);
1997 if (ifp->if_pcount++ != 0)
1998 return (0);
1999 ifp->if_flags |= IFF_PROMISC;
2000 } else {
2001 if (--ifp->if_pcount > 0)
2002 return (0);
2003 ifp->if_flags &= ~IFF_PROMISC;
2004 /*
2005 * If the device is not configured up, we should not need to
2006 * turn off promiscuous mode (device should have turned it
2007 * off when interface went down; and will look at IFF_PROMISC
2008 * again next time interface comes up).
2009 */
2010 if ((ifp->if_flags & IFF_UP) == 0)
2011 return (0);
2012 }
2013 ifr.ifr_flags = ifp->if_flags;
2014 return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
2015 }
2016
2017 int
2018 sysctl_ifq(int *name, u_int namelen, void *oldp, size_t *oldlenp,
2019 void *newp, size_t newlen, struct ifqueue *ifq)
2020 {
2021 /* All sysctl names at this level are terminal. */
2022 if (namelen != 1)
2023 return (ENOTDIR);
2024
2025 switch (name[0]) {
2026 case IFQCTL_LEN:
2027 return (sysctl_rdint(oldp, oldlenp, newp, ifq->ifq_len));
2028 case IFQCTL_MAXLEN:
2029 return (sysctl_int(oldp, oldlenp, newp, newlen,
2030 &ifq->ifq_maxlen));
2031 case IFQCTL_DROPS:
2032 return (sysctl_rdint(oldp, oldlenp, newp, ifq->ifq_drops));
2033 default:
2034 return (EOPNOTSUPP);
2035 }
2036 /* NOTREACHED */
2037 }
2038
2039 void
2040 m_clinitifp(struct ifnet *ifp)
2041 {
2042 extern u_int mclsizes[];
2043 int i;
2044
2045 /* Initialize high water marks for use of cluster pools */
2046 for (i = 0; i < MCLPOOLS; i++) {
2047 ifp->if_mclstat.mclpool[i].mcl_hwm = MAX(4,
2048 ifp->if_mclstat.mclpool[i].mcl_lwm);
2049 ifp->if_mclstat.mclpool[i].mcl_size = mclsizes[i];
2050 }
2051 }
2052
2053 void
2054 m_clsetlwm(struct ifnet *ifp, u_int pktlen, u_int lwm)
2055 {
2056 extern u_int mclsizes[];
2057 int i;
2058
2059 for (i = 0; i < MCLPOOLS; i++) {
2060 if (pktlen <= mclsizes[i])
2061 break;
2062 }
2063 if (i >= MCLPOOLS)
2064 return;
2065
2066 ifp->if_mclstat.mclpool[i].mcl_lwm = lwm;
2067 }
2068
2069 int
2070 m_cldrop(struct ifnet *ifp, int pi)
2071 {
2072 static int livelock, liveticks;
2073 struct mclstat *mcls;
2074 extern int ticks;
2075 int i;
2076
2077 if (livelock == 0 && ticks - m_clticks > 2) {
2078 struct ifnet *aifp;
2079
2080 /*
2081 * Timeout did not run, so we are in some kind of livelock.
2082 * Decrease the cluster allocation high water marks on all
2083 * interfaces and prevent them from growth for the very near
2084 * future.
2085 */
2086 livelock = 1;
2087 liveticks = ticks;
2088 TAILQ_FOREACH(aifp, &ifnet, if_list) {
2089 mcls = &aifp->if_mclstat;
2090 for (i = 0; i < nitems(mcls->mclpool); i++)
2091 mcls->mclpool[i].mcl_hwm =
2092 max(mcls->mclpool[i].mcl_hwm / 2,
2093 mcls->mclpool[i].mcl_lwm);
2094 }
2095 } else if (livelock && ticks - liveticks > 5)
2096 livelock = 0; /* Let the high water marks grow again */
2097
2098 mcls = &ifp->if_mclstat;
2099 if (mcls->mclpool[pi].mcl_alive <= 2 &&
2100 mcls->mclpool[pi].mcl_hwm < 32768 &&
2101 ISSET(ifp->if_flags, IFF_RUNNING) && livelock == 0) {
2102 /* About to run out, so increase the watermark */
2103 mcls->mclpool[pi].mcl_hwm++;
2104 } else if (mcls->mclpool[pi].mcl_alive >= mcls->mclpool[pi].mcl_hwm)
2105 return (1); /* No more packets given */
2106
2107 return (0);
2108 }
2109
2110 void
2111 m_clcount(struct ifnet *ifp, int pi)
2112 {
2113 ifp->if_mclstat.mclpool[pi].mcl_alive++;
2114 }
2115
2116 void
2117 m_cluncount(struct mbuf *m, int all)
2118 {
2119 struct mbuf_ext *me;
2120
2121 do {
2122 me = &m->m_ext;
2123 if (((m->m_flags & (M_EXT|M_CLUSTER)) != (M_EXT|M_CLUSTER)) ||
2124 (me->ext_ifp == NULL))
2125 continue;
2126
2127 me->ext_ifp->if_mclstat.mclpool[me->ext_backend].mcl_alive--;
2128 me->ext_ifp = NULL;
2129 } while (all && (m = m->m_next));
2130 }
Cache object: 87cefc890a38912d68c23b5e0bd921f3
|