This source file includes following definitions.
- ifinit
- if_attachsetup
- if_alloc_sadl
- if_free_sadl
- if_attachdomain
- if_attachdomain1
- if_attachhead
- if_attach
- if_detach
- if_detach_queues
- if_clone_create
- if_clone_destroy
- if_clone_lookup
- if_clone_attach
- if_clone_detach
- if_clone_list
- if_congestion
- if_congestion_clear
- ifa_ifwithaddr
- ifa_ifwithdstaddr
- ifa_ifwithnet
- ifa_ifwithaf
- ifaof_ifpforaddr
- link_rtrequest
- if_down
- if_up
- if_link_state_change
- if_qflush
- if_slowtimo
- ifunit
- ifioctl
- ifconf
- if_detached_start
- if_detached_ioctl
- if_detached_init
- if_detached_watchdog
- if_creategroup
- if_addgroup
- if_delgroup
- if_getgroup
- if_getgroupmembers
- if_getgroupattribs
- if_setgroupattribs
- if_group_routechange
- if_group_egress_build
- ifpromisc
- sysctl_ifq
- netrndintr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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 #include <dev/rndvar.h>
91
92 #ifdef INET
93 #include <netinet/in.h>
94 #include <netinet/in_var.h>
95 #include <netinet/if_ether.h>
96 #include <netinet/igmp.h>
97 #ifdef MROUTING
98 #include <netinet/ip_mroute.h>
99 #endif
100 #endif
101
102 #ifdef INET6
103 #ifndef INET
104 #include <netinet/in.h>
105 #endif
106 #include <netinet6/in6_ifattach.h>
107 #include <netinet6/nd6.h>
108 #endif
109
110 #if NBPFILTER > 0
111 #include <net/bpf.h>
112 #endif
113
114 #if NTRUNK > 0
115 #include <net/if_trunk.h>
116 #endif
117
118 #if NBRIDGE > 0
119 #include <net/if_bridge.h>
120 #endif
121
122 #if NCARP > 0
123 #include <netinet/ip_carp.h>
124 #endif
125
126 #if NPF > 0
127 #include <net/pfvar.h>
128 #endif
129
130 void if_attachsetup(struct ifnet *);
131 void if_attachdomain1(struct ifnet *);
132
133 int ifqmaxlen = IFQ_MAXLEN;
134
135 void if_detach_queues(struct ifnet *, struct ifqueue *);
136 void if_detached_start(struct ifnet *);
137 int if_detached_ioctl(struct ifnet *, u_long, caddr_t);
138 int if_detached_init(struct ifnet *);
139 void if_detached_watchdog(struct ifnet *);
140
141 int if_getgroup(caddr_t, struct ifnet *);
142 int if_getgroupmembers(caddr_t);
143 int if_getgroupattribs(caddr_t);
144 int if_setgroupattribs(caddr_t);
145
146 int if_clone_list(struct if_clonereq *);
147 struct if_clone *if_clone_lookup(const char *, int *);
148
149 void if_congestion_clear(void *);
150 int if_group_egress_build(void);
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
157
158
159
160
161
162 void
163 ifinit()
164 {
165 static struct timeout if_slowtim;
166
167 timeout_set(&if_slowtim, if_slowtimo, &if_slowtim);
168
169 if_slowtimo(&if_slowtim);
170 }
171
172 static int if_index = 0;
173 int if_indexlim = 0;
174 struct ifaddr **ifnet_addrs = NULL;
175 struct ifnet **ifindex2ifnet = NULL;
176 struct ifnet_head ifnet;
177 struct ifnet *lo0ifp;
178
179
180
181
182
183 void
184 if_attachsetup(struct ifnet *ifp)
185 {
186 struct ifaddr *ifa;
187 int wrapped = 0;
188
189 if (ifindex2ifnet == 0)
190 if_index = 1;
191 else {
192 while (if_index < if_indexlim &&
193 ifindex2ifnet[if_index] != NULL) {
194 if_index++;
195
196
197
198
199
200
201
202
203 if (if_index == USHRT_MAX) {
204 if_index = 1;
205
206
207
208
209
210
211 if (wrapped++)
212 panic("too many interfaces");
213 }
214 }
215 }
216 ifp->if_index = if_index;
217
218
219
220
221
222
223
224 if (ifnet_addrs == 0 || ifindex2ifnet == 0 || if_index >= if_indexlim) {
225 size_t m, n, oldlim;
226 caddr_t q;
227
228 oldlim = if_indexlim;
229 if (if_indexlim == 0)
230 if_indexlim = 8;
231 while (if_index >= if_indexlim)
232 if_indexlim <<= 1;
233
234
235 m = oldlim * sizeof(ifa);
236 n = if_indexlim * sizeof(ifa);
237 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
238 bzero(q, n);
239 if (ifnet_addrs) {
240 bcopy((caddr_t)ifnet_addrs, q, m);
241 free((caddr_t)ifnet_addrs, M_IFADDR);
242 }
243 ifnet_addrs = (struct ifaddr **)q;
244
245
246 m = oldlim * sizeof(struct ifnet *);
247 n = if_indexlim * sizeof(struct ifnet *);
248 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
249 bzero(q, n);
250 if (ifindex2ifnet) {
251 bcopy((caddr_t)ifindex2ifnet, q, m);
252 free((caddr_t)ifindex2ifnet, M_IFADDR);
253 }
254 ifindex2ifnet = (struct ifnet **)q;
255 }
256
257 TAILQ_INIT(&ifp->if_groups);
258
259 if_addgroup(ifp, IFG_ALL);
260
261 ifindex2ifnet[if_index] = ifp;
262
263 if (ifp->if_snd.ifq_maxlen == 0)
264 ifp->if_snd.ifq_maxlen = ifqmaxlen;
265 #ifdef ALTQ
266 ifp->if_snd.altq_type = 0;
267 ifp->if_snd.altq_disc = NULL;
268 ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE;
269 ifp->if_snd.altq_tbr = NULL;
270 ifp->if_snd.altq_ifp = ifp;
271 #endif
272
273 if (domains)
274 if_attachdomain1(ifp);
275 #if NPF > 0
276 pfi_attach_ifnet(ifp);
277 #endif
278
279
280 rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
281 }
282
283
284
285
286
287
288
289 void
290 if_alloc_sadl(struct ifnet *ifp)
291 {
292 unsigned socksize, ifasize;
293 int namelen, masklen;
294 struct sockaddr_dl *sdl;
295 struct ifaddr *ifa;
296
297
298
299
300
301
302 if (ifp->if_sadl != NULL)
303 if_free_sadl(ifp);
304
305 namelen = strlen(ifp->if_xname);
306 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
307 masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
308 socksize = masklen + ifp->if_addrlen;
309 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
310 if (socksize < sizeof(*sdl))
311 socksize = sizeof(*sdl);
312 socksize = ROUNDUP(socksize);
313 ifasize = sizeof(*ifa) + 2 * socksize;
314 ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
315 bzero((caddr_t)ifa, ifasize);
316 sdl = (struct sockaddr_dl *)(ifa + 1);
317 sdl->sdl_len = socksize;
318 sdl->sdl_family = AF_LINK;
319 bcopy(ifp->if_xname, sdl->sdl_data, namelen);
320 sdl->sdl_nlen = namelen;
321 sdl->sdl_alen = ifp->if_addrlen;
322 sdl->sdl_index = ifp->if_index;
323 sdl->sdl_type = ifp->if_type;
324 ifnet_addrs[ifp->if_index] = ifa;
325 ifa->ifa_ifp = ifp;
326 ifa->ifa_rtrequest = link_rtrequest;
327 TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list);
328 ifa->ifa_addr = (struct sockaddr *)sdl;
329 ifp->if_sadl = sdl;
330 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
331 ifa->ifa_netmask = (struct sockaddr *)sdl;
332 sdl->sdl_len = masklen;
333 while (namelen != 0)
334 sdl->sdl_data[--namelen] = 0xff;
335 }
336
337
338
339
340
341
342 void
343 if_free_sadl(struct ifnet *ifp)
344 {
345 struct ifaddr *ifa;
346 int s;
347
348 ifa = ifnet_addrs[ifp->if_index];
349 if (ifa == NULL)
350 return;
351
352 s = splnet();
353 rtinit(ifa, RTM_DELETE, 0);
354 #if 0
355 TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
356 ifnet_addrs[ifp->if_index] = NULL;
357 #endif
358 ifp->if_sadl = NULL;
359
360 splx(s);
361 }
362
363 void
364 if_attachdomain()
365 {
366 struct ifnet *ifp;
367 int s;
368
369 s = splnet();
370 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
371 if_attachdomain1(ifp);
372 splx(s);
373 }
374
375 void
376 if_attachdomain1(struct ifnet *ifp)
377 {
378 struct domain *dp;
379 int s;
380
381 s = splnet();
382
383
384 bzero(ifp->if_afdata, sizeof(ifp->if_afdata));
385 for (dp = domains; dp; dp = dp->dom_next) {
386 if (dp->dom_ifattach)
387 ifp->if_afdata[dp->dom_family] =
388 (*dp->dom_ifattach)(ifp);
389 }
390
391 splx(s);
392 }
393
394 void
395 if_attachhead(struct ifnet *ifp)
396 {
397 if (if_index == 0) {
398 TAILQ_INIT(&ifnet);
399 TAILQ_INIT(&ifg_head);
400 }
401 TAILQ_INIT(&ifp->if_addrlist);
402 ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks),
403 M_TEMP, M_NOWAIT);
404 if (ifp->if_addrhooks == NULL)
405 panic("if_attachhead: malloc");
406 TAILQ_INIT(ifp->if_addrhooks);
407 ifp->if_linkstatehooks = malloc(sizeof(*ifp->if_linkstatehooks),
408 M_TEMP, M_NOWAIT);
409 if (ifp->if_linkstatehooks == NULL)
410 panic("if_attachhead: malloc");
411 TAILQ_INIT(ifp->if_linkstatehooks);
412 ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks),
413 M_TEMP, M_NOWAIT);
414 if (ifp->if_detachhooks == NULL)
415 panic("if_attachhead: malloc");
416 TAILQ_INIT(ifp->if_detachhooks);
417 TAILQ_INSERT_HEAD(&ifnet, ifp, if_list);
418 if_attachsetup(ifp);
419 }
420
421 void
422 if_attach(struct ifnet *ifp)
423 {
424 #if NCARP > 0
425 struct ifnet *before = NULL;
426 #endif
427
428 if (if_index == 0) {
429 TAILQ_INIT(&ifnet);
430 TAILQ_INIT(&ifg_head);
431 }
432 TAILQ_INIT(&ifp->if_addrlist);
433 ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks),
434 M_TEMP, M_NOWAIT);
435 if (ifp->if_addrhooks == NULL)
436 panic("if_attach: malloc");
437 TAILQ_INIT(ifp->if_addrhooks);
438 ifp->if_linkstatehooks = malloc(sizeof(*ifp->if_linkstatehooks),
439 M_TEMP, M_NOWAIT);
440 if (ifp->if_linkstatehooks == NULL)
441 panic("if_attach: malloc");
442 TAILQ_INIT(ifp->if_linkstatehooks);
443 ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks),
444 M_TEMP, M_NOWAIT);
445 if (ifp->if_detachhooks == NULL)
446 panic("if_attach: malloc");
447 TAILQ_INIT(ifp->if_detachhooks);
448
449 #if NCARP > 0
450 if (ifp->if_type != IFT_CARP)
451 TAILQ_FOREACH(before, &ifnet, if_list)
452 if (before->if_type == IFT_CARP)
453 break;
454 if (before == NULL)
455 TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
456 else
457 TAILQ_INSERT_BEFORE(before, ifp, if_list);
458 #else
459 TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
460 #endif
461
462 if_attachsetup(ifp);
463 }
464
465
466
467
468
469
470
471 void
472 if_detach(struct ifnet *ifp)
473 {
474 struct ifaddr *ifa;
475 struct ifg_list *ifg;
476 int s = splnet();
477 struct domain *dp;
478
479 ifp->if_flags &= ~IFF_OACTIVE;
480 ifp->if_start = if_detached_start;
481 ifp->if_ioctl = if_detached_ioctl;
482 ifp->if_init = if_detached_init;
483 ifp->if_watchdog = if_detached_watchdog;
484
485
486 dohooks(ifp->if_detachhooks, HOOK_REMOVE | HOOK_FREE);
487
488 #if NTRUNK > 0
489 if (ifp->if_type == IFT_IEEE8023ADLAG)
490 trunk_port_ifdetach(ifp);
491 #endif
492
493 #if NBRIDGE > 0
494
495 if (ifp->if_bridge)
496 bridge_ifdetach(ifp);
497 #endif
498
499 #if NCARP > 0
500
501 if (ifp->if_carp && ifp->if_type != IFT_CARP)
502 carp_ifdetach(ifp);
503 #endif
504
505 #if NBPFILTER > 0
506 bpfdetach(ifp);
507 #endif
508 #ifdef ALTQ
509 if (ALTQ_IS_ENABLED(&ifp->if_snd))
510 altq_disable(&ifp->if_snd);
511 if (ALTQ_IS_ATTACHED(&ifp->if_snd))
512 altq_detach(&ifp->if_snd);
513 #endif
514 rt_if_remove(ifp);
515 #ifdef INET
516 rti_delete(ifp);
517 #if NETHER > 0
518 myip_ifp = NULL;
519 #endif
520 #ifdef MROUTING
521 vif_delete(ifp);
522 #endif
523 #endif
524 #ifdef INET6
525 in6_ifdetach(ifp);
526 #endif
527
528 #if NPF > 0
529 pfi_detach_ifnet(ifp);
530 #endif
531
532
533
534
535
536
537 #define IF_DETACH_QUEUES(x) \
538 do { \
539 extern struct ifqueue x; \
540 if_detach_queues(ifp, & x); \
541 } while (0)
542 #ifdef INET
543 IF_DETACH_QUEUES(arpintrq);
544 IF_DETACH_QUEUES(ipintrq);
545 #endif
546 #ifdef INET6
547 IF_DETACH_QUEUES(ip6intrq);
548 #endif
549 #ifdef NETATALK
550 IF_DETACH_QUEUES(atintrq1);
551 IF_DETACH_QUEUES(atintrq2);
552 #endif
553 #ifdef NATM
554 IF_DETACH_QUEUES(natmintrq);
555 #endif
556 #undef IF_DETACH_QUEUES
557
558
559
560
561
562
563
564 TAILQ_REMOVE(&ifnet, ifp, if_list);
565
566
567
568
569 while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) {
570 TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
571 #ifdef INET
572 if (ifa->ifa_addr->sa_family == AF_INET)
573 TAILQ_REMOVE(&in_ifaddr, (struct in_ifaddr *)ifa,
574 ia_list);
575 #endif
576
577 if (ifa == ifnet_addrs[ifp->if_index])
578 continue;
579
580 ifa->ifa_ifp = NULL;
581 IFAFREE(ifa);
582 }
583
584 for (ifg = TAILQ_FIRST(&ifp->if_groups); ifg;
585 ifg = TAILQ_FIRST(&ifp->if_groups))
586 if_delgroup(ifp, ifg->ifgl_group->ifg_group);
587
588 if_free_sadl(ifp);
589
590 ifnet_addrs[ifp->if_index]->ifa_ifp = NULL;
591 IFAFREE(ifnet_addrs[ifp->if_index]);
592 ifnet_addrs[ifp->if_index] = NULL;
593
594 free(ifp->if_addrhooks, M_TEMP);
595 free(ifp->if_linkstatehooks, M_TEMP);
596 free(ifp->if_detachhooks, M_TEMP);
597
598 for (dp = domains; dp; dp = dp->dom_next) {
599 if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
600 (*dp->dom_ifdetach)(ifp,
601 ifp->if_afdata[dp->dom_family]);
602 }
603
604
605 rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
606
607 splx(s);
608 }
609
610 void
611 if_detach_queues(struct ifnet *ifp, struct ifqueue *q)
612 {
613 struct mbuf *m, *prev, *next;
614
615 prev = NULL;
616 for (m = q->ifq_head; m; m = next) {
617 next = m->m_nextpkt;
618 #ifdef DIAGNOSTIC
619 if ((m->m_flags & M_PKTHDR) == 0) {
620 prev = m;
621 continue;
622 }
623 #endif
624 if (m->m_pkthdr.rcvif != ifp) {
625 prev = m;
626 continue;
627 }
628
629 if (prev)
630 prev->m_nextpkt = m->m_nextpkt;
631 else
632 q->ifq_head = m->m_nextpkt;
633 if (q->ifq_tail == m)
634 q->ifq_tail = prev;
635 q->ifq_len--;
636
637 m->m_nextpkt = NULL;
638 m_freem(m);
639 IF_DROP(q);
640 }
641 }
642
643
644
645
646 int
647 if_clone_create(const char *name)
648 {
649 struct if_clone *ifc;
650 struct ifnet *ifp;
651 int unit, ret;
652
653 ifc = if_clone_lookup(name, &unit);
654 if (ifc == NULL)
655 return (EINVAL);
656
657 if (ifunit(name) != NULL)
658 return (EEXIST);
659
660 if ((ret = (*ifc->ifc_create)(ifc, unit)) == 0 &&
661 (ifp = ifunit(name)) != NULL)
662 if_addgroup(ifp, ifc->ifc_name);
663
664 return (ret);
665 }
666
667
668
669
670 int
671 if_clone_destroy(const char *name)
672 {
673 struct if_clone *ifc;
674 struct ifnet *ifp;
675 int s, ret;
676
677 ifc = if_clone_lookup(name, NULL);
678 if (ifc == NULL)
679 return (EINVAL);
680
681 ifp = ifunit(name);
682 if (ifp == NULL)
683 return (ENXIO);
684
685 if (ifc->ifc_destroy == NULL)
686 return (EOPNOTSUPP);
687
688 if (ifp->if_flags & IFF_UP) {
689 s = splnet();
690 if_down(ifp);
691 splx(s);
692 }
693
694 if_delgroup(ifp, ifc->ifc_name);
695
696 if ((ret = (*ifc->ifc_destroy)(ifp)) != 0)
697 if_addgroup(ifp, ifc->ifc_name);
698
699 return (ret);
700 }
701
702
703
704
705 struct if_clone *
706 if_clone_lookup(const char *name, int *unitp)
707 {
708 struct if_clone *ifc;
709 const char *cp;
710 int unit;
711
712
713 for (cp = name;
714 cp - name < IFNAMSIZ && *cp && (*cp < '0' || *cp > '9');
715 cp++)
716 continue;
717
718 if (cp == name || cp - name == IFNAMSIZ || !*cp)
719 return (NULL);
720
721 if (cp - name < IFNAMSIZ-1 && *cp == '0' && cp[1] != '\0')
722 return (NULL);
723
724 LIST_FOREACH(ifc, &if_cloners, ifc_list) {
725 if (strlen(ifc->ifc_name) == cp - name &&
726 !strncmp(name, ifc->ifc_name, cp - name))
727 break;
728 }
729
730 if (ifc == NULL)
731 return (NULL);
732
733 unit = 0;
734 while (cp - name < IFNAMSIZ && *cp) {
735 if (*cp < '0' || *cp > '9' ||
736 unit > (INT_MAX - (*cp - '0')) / 10) {
737
738 return (NULL);
739 }
740 unit = (unit * 10) + (*cp++ - '0');
741 }
742
743 if (unitp != NULL)
744 *unitp = unit;
745 return (ifc);
746 }
747
748
749
750
751 void
752 if_clone_attach(struct if_clone *ifc)
753 {
754 LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
755 if_cloners_count++;
756 }
757
758
759
760
761 void
762 if_clone_detach(struct if_clone *ifc)
763 {
764
765 LIST_REMOVE(ifc, ifc_list);
766 if_cloners_count--;
767 }
768
769
770
771
772 int
773 if_clone_list(struct if_clonereq *ifcr)
774 {
775 char outbuf[IFNAMSIZ], *dst;
776 struct if_clone *ifc;
777 int count, error = 0;
778
779 ifcr->ifcr_total = if_cloners_count;
780 if ((dst = ifcr->ifcr_buffer) == NULL) {
781
782 return (0);
783 }
784
785 if (ifcr->ifcr_count < 0)
786 return (EINVAL);
787
788 count = (if_cloners_count < ifcr->ifcr_count) ?
789 if_cloners_count : ifcr->ifcr_count;
790
791 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
792 ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
793 bzero(outbuf, sizeof outbuf);
794 strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
795 error = copyout(outbuf, dst, IFNAMSIZ);
796 if (error)
797 break;
798 }
799
800 return (error);
801 }
802
803
804
805
806 void
807 if_congestion(struct ifqueue *ifq)
808 {
809
810 if (ifq->ifq_congestion)
811 return;
812
813 ifq->ifq_congestion = malloc(sizeof(struct timeout), M_TEMP, M_NOWAIT);
814 if (ifq->ifq_congestion == NULL)
815 return;
816 timeout_set(ifq->ifq_congestion, if_congestion_clear, ifq);
817 timeout_add(ifq->ifq_congestion, hz / 100);
818 }
819
820
821
822
823 void
824 if_congestion_clear(void *arg)
825 {
826 struct ifqueue *ifq = arg;
827 struct timeout *to = ifq->ifq_congestion;
828
829 ifq->ifq_congestion = NULL;
830 free(to, M_TEMP);
831 }
832
833
834
835
836
837 struct ifaddr *
838 ifa_ifwithaddr(struct sockaddr *addr)
839 {
840 struct ifnet *ifp;
841 struct ifaddr *ifa;
842
843 #define equal(a1, a2) \
844 (bcmp((caddr_t)(a1), (caddr_t)(a2), \
845 ((struct sockaddr *)(a1))->sa_len) == 0)
846 TAILQ_FOREACH(ifp, &ifnet, if_list) {
847 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
848 if (ifa->ifa_addr->sa_family != addr->sa_family)
849 continue;
850 if (equal(addr, ifa->ifa_addr))
851 return (ifa);
852 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
853
854 ifa->ifa_broadaddr->sa_len != 0 &&
855 equal(ifa->ifa_broadaddr, addr))
856 return (ifa);
857 }
858 }
859 return (NULL);
860 }
861
862
863
864
865 struct ifaddr *
866 ifa_ifwithdstaddr(struct sockaddr *addr)
867 {
868 struct ifnet *ifp;
869 struct ifaddr *ifa;
870
871 TAILQ_FOREACH(ifp, &ifnet, if_list) {
872 if (ifp->if_flags & IFF_POINTOPOINT)
873 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
874 if (ifa->ifa_addr->sa_family != addr->sa_family ||
875 ifa->ifa_dstaddr == NULL)
876 continue;
877 if (equal(addr, ifa->ifa_dstaddr))
878 return (ifa);
879 }
880 }
881 return (NULL);
882 }
883
884
885
886
887
888 struct ifaddr *
889 ifa_ifwithnet(struct sockaddr *addr)
890 {
891 struct ifnet *ifp;
892 struct ifaddr *ifa;
893 struct ifaddr *ifa_maybe = 0;
894 u_int af = addr->sa_family;
895 char *addr_data = addr->sa_data, *cplim;
896
897 if (af == AF_LINK) {
898 struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
899 if (sdl->sdl_index && sdl->sdl_index < if_indexlim &&
900 ifindex2ifnet[sdl->sdl_index])
901 return (ifnet_addrs[sdl->sdl_index]);
902 }
903 TAILQ_FOREACH(ifp, &ifnet, if_list) {
904 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
905 char *cp, *cp2, *cp3;
906
907 if (ifa->ifa_addr->sa_family != af ||
908 ifa->ifa_netmask == 0)
909 next: continue;
910 cp = addr_data;
911 cp2 = ifa->ifa_addr->sa_data;
912 cp3 = ifa->ifa_netmask->sa_data;
913 cplim = (char *)ifa->ifa_netmask +
914 ifa->ifa_netmask->sa_len;
915 while (cp3 < cplim)
916 if ((*cp++ ^ *cp2++) & *cp3++)
917
918 goto next;
919 if (ifa_maybe == 0 ||
920 rn_refines((caddr_t)ifa->ifa_netmask,
921 (caddr_t)ifa_maybe->ifa_netmask))
922 ifa_maybe = ifa;
923 }
924 }
925 return (ifa_maybe);
926 }
927
928
929
930
931 struct ifaddr *
932 ifa_ifwithaf(int af)
933 {
934 struct ifnet *ifp;
935 struct ifaddr *ifa;
936
937 TAILQ_FOREACH(ifp, &ifnet, if_list) {
938 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
939 if (ifa->ifa_addr->sa_family == af)
940 return (ifa);
941 }
942 }
943 return (NULL);
944 }
945
946
947
948
949
950 struct ifaddr *
951 ifaof_ifpforaddr(struct sockaddr *addr, struct ifnet *ifp)
952 {
953 struct ifaddr *ifa;
954 char *cp, *cp2, *cp3;
955 char *cplim;
956 struct ifaddr *ifa_maybe = NULL;
957 u_int af = addr->sa_family;
958
959 if (af >= AF_MAX)
960 return (NULL);
961 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
962 if (ifa->ifa_addr->sa_family != af)
963 continue;
964 if (ifa_maybe == NULL)
965 ifa_maybe = ifa;
966 if (ifa->ifa_netmask == 0 || ifp->if_flags & IFF_POINTOPOINT) {
967 if (equal(addr, ifa->ifa_addr) ||
968 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
969 return (ifa);
970 continue;
971 }
972 cp = addr->sa_data;
973 cp2 = ifa->ifa_addr->sa_data;
974 cp3 = ifa->ifa_netmask->sa_data;
975 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
976 for (; cp3 < cplim; cp3++)
977 if ((*cp++ ^ *cp2++) & *cp3)
978 break;
979 if (cp3 == cplim)
980 return (ifa);
981 }
982 return (ifa_maybe);
983 }
984
985
986
987
988
989
990 void
991 link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
992 {
993 struct ifaddr *ifa;
994 struct sockaddr *dst;
995 struct ifnet *ifp;
996
997 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
998 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
999 return;
1000 if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
1001 ifa->ifa_refcnt++;
1002 IFAFREE(rt->rt_ifa);
1003 rt->rt_ifa = ifa;
1004 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
1005 ifa->ifa_rtrequest(cmd, rt, info);
1006 }
1007 }
1008
1009
1010
1011
1012
1013
1014 void
1015 if_down(struct ifnet *ifp)
1016 {
1017 struct ifaddr *ifa;
1018
1019 splassert(IPL_SOFTNET);
1020
1021 ifp->if_flags &= ~IFF_UP;
1022 microtime(&ifp->if_lastchange);
1023 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1024 pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
1025 }
1026 IFQ_PURGE(&ifp->if_snd);
1027 #if NCARP > 0
1028 if (ifp->if_carp)
1029 carp_carpdev_state(ifp);
1030 #endif
1031 #if NBRIDGE > 0
1032 if (ifp->if_bridge)
1033 bstp_ifstate(ifp);
1034 #endif
1035 rt_ifmsg(ifp);
1036 }
1037
1038
1039
1040
1041
1042
1043 void
1044 if_up(struct ifnet *ifp)
1045 {
1046 #ifdef notyet
1047 struct ifaddr *ifa;
1048 #endif
1049
1050 splassert(IPL_SOFTNET);
1051
1052 ifp->if_flags |= IFF_UP;
1053 microtime(&ifp->if_lastchange);
1054 #ifdef notyet
1055
1056 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1057 pfctlinput(PRC_IFUP, ifa->ifa_addr);
1058 }
1059 #endif
1060 #if NCARP > 0
1061 if (ifp->if_carp)
1062 carp_carpdev_state(ifp);
1063 #endif
1064 #if NBRIDGE > 0
1065 if (ifp->if_bridge)
1066 bstp_ifstate(ifp);
1067 #endif
1068 rt_ifmsg(ifp);
1069 #ifdef INET6
1070 in6_if_up(ifp);
1071 #endif
1072 }
1073
1074
1075
1076
1077
1078 void
1079 if_link_state_change(struct ifnet *ifp)
1080 {
1081 rt_ifmsg(ifp);
1082 dohooks(ifp->if_linkstatehooks, 0);
1083 }
1084
1085
1086
1087
1088 void
1089 if_qflush(struct ifqueue *ifq)
1090 {
1091 struct mbuf *m, *n;
1092
1093 n = ifq->ifq_head;
1094 while ((m = n) != NULL) {
1095 n = m->m_act;
1096 m_freem(m);
1097 }
1098 ifq->ifq_head = 0;
1099 ifq->ifq_tail = 0;
1100 ifq->ifq_len = 0;
1101 }
1102
1103
1104
1105
1106
1107
1108 void
1109 if_slowtimo(void *arg)
1110 {
1111 struct timeout *to = (struct timeout *)arg;
1112 struct ifnet *ifp;
1113 int s = splnet();
1114
1115 TAILQ_FOREACH(ifp, &ifnet, if_list) {
1116 if (ifp->if_timer == 0 || --ifp->if_timer)
1117 continue;
1118 if (ifp->if_watchdog)
1119 (*ifp->if_watchdog)(ifp);
1120 }
1121 splx(s);
1122 timeout_add(to, hz / IFNET_SLOWHZ);
1123 }
1124
1125
1126
1127
1128
1129 struct ifnet *
1130 ifunit(const char *name)
1131 {
1132 struct ifnet *ifp;
1133
1134 TAILQ_FOREACH(ifp, &ifnet, if_list) {
1135 if (strcmp(ifp->if_xname, name) == 0)
1136 return (ifp);
1137 }
1138 return (NULL);
1139 }
1140
1141
1142
1143
1144 int
1145 ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
1146 {
1147 struct ifnet *ifp;
1148 struct ifreq *ifr;
1149 struct ifaddr *ifa;
1150 struct sockaddr_dl *sdl;
1151 struct ifgroupreq *ifgr;
1152 char ifdescrbuf[IFDESCRSIZE];
1153 char ifrtlabelbuf[RTLABEL_LEN];
1154 int error = 0;
1155 size_t bytesdone;
1156 short oif_flags;
1157 const char *label;
1158
1159 switch (cmd) {
1160
1161 case SIOCGIFCONF:
1162 case OSIOCGIFCONF:
1163 return (ifconf(cmd, data));
1164 }
1165 ifr = (struct ifreq *)data;
1166
1167 switch (cmd) {
1168 case SIOCIFCREATE:
1169 case SIOCIFDESTROY:
1170 if ((error = suser(p, 0)) != 0)
1171 return (error);
1172 return ((cmd == SIOCIFCREATE) ?
1173 if_clone_create(ifr->ifr_name) :
1174 if_clone_destroy(ifr->ifr_name));
1175 case SIOCIFGCLONERS:
1176 return (if_clone_list((struct if_clonereq *)data));
1177 case SIOCGIFGMEMB:
1178 return (if_getgroupmembers(data));
1179 case SIOCGIFGATTR:
1180 return (if_getgroupattribs(data));
1181 case SIOCSIFGATTR:
1182 if ((error = suser(p, 0)) != 0)
1183 return (error);
1184 return (if_setgroupattribs(data));
1185 }
1186
1187 ifp = ifunit(ifr->ifr_name);
1188 if (ifp == 0)
1189 return (ENXIO);
1190 oif_flags = ifp->if_flags;
1191 switch (cmd) {
1192
1193 case SIOCGIFFLAGS:
1194 ifr->ifr_flags = ifp->if_flags;
1195 break;
1196
1197 case SIOCGIFMETRIC:
1198 ifr->ifr_metric = ifp->if_metric;
1199 break;
1200
1201 case SIOCGIFMTU:
1202 ifr->ifr_mtu = ifp->if_mtu;
1203 break;
1204
1205 case SIOCGIFDATA:
1206 error = copyout((caddr_t)&ifp->if_data, ifr->ifr_data,
1207 sizeof(ifp->if_data));
1208 break;
1209
1210 case SIOCSIFFLAGS:
1211 if ((error = suser(p, 0)) != 0)
1212 return (error);
1213 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
1214 int s = splnet();
1215 if_down(ifp);
1216 splx(s);
1217 }
1218 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
1219 int s = splnet();
1220 if_up(ifp);
1221 splx(s);
1222 }
1223 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
1224 (ifr->ifr_flags &~ IFF_CANTCHANGE);
1225 if (ifp->if_ioctl)
1226 (void) (*ifp->if_ioctl)(ifp, cmd, data);
1227 break;
1228
1229 case SIOCSIFMETRIC:
1230 if ((error = suser(p, 0)) != 0)
1231 return (error);
1232 ifp->if_metric = ifr->ifr_metric;
1233 break;
1234
1235 case SIOCSIFMTU:
1236 {
1237 #ifdef INET6
1238 int oldmtu = ifp->if_mtu;
1239 #endif
1240
1241 if ((error = suser(p, 0)) != 0)
1242 return (error);
1243 if (ifp->if_ioctl == NULL)
1244 return (EOPNOTSUPP);
1245 error = (*ifp->if_ioctl)(ifp, cmd, data);
1246
1247
1248
1249
1250 #ifdef INET6
1251 if (ifp->if_mtu != oldmtu)
1252 nd6_setmtu(ifp);
1253 #endif
1254 break;
1255 }
1256
1257 case SIOCSIFPHYADDR:
1258 case SIOCDIFPHYADDR:
1259 #ifdef INET6
1260 case SIOCSIFPHYADDR_IN6:
1261 #endif
1262 case SIOCSLIFPHYADDR:
1263 case SIOCADDMULTI:
1264 case SIOCDELMULTI:
1265 case SIOCSIFMEDIA:
1266 if ((error = suser(p, 0)) != 0)
1267 return (error);
1268
1269 case SIOCGIFPSRCADDR:
1270 case SIOCGIFPDSTADDR:
1271 case SIOCGLIFPHYADDR:
1272 case SIOCGIFMEDIA:
1273 if (ifp->if_ioctl == 0)
1274 return (EOPNOTSUPP);
1275 error = (*ifp->if_ioctl)(ifp, cmd, data);
1276 break;
1277
1278 case SIOCGIFDESCR:
1279 strlcpy(ifdescrbuf, ifp->if_description, IFDESCRSIZE);
1280 error = copyoutstr(ifdescrbuf, ifr->ifr_data, IFDESCRSIZE,
1281 &bytesdone);
1282 break;
1283
1284 case SIOCSIFDESCR:
1285 if ((error = suser(p, 0)) != 0)
1286 return (error);
1287 error = copyinstr(ifr->ifr_data, ifdescrbuf,
1288 IFDESCRSIZE, &bytesdone);
1289 if (error == 0) {
1290 (void)memset(ifp->if_description, 0, IFDESCRSIZE);
1291 strlcpy(ifp->if_description, ifdescrbuf, IFDESCRSIZE);
1292 }
1293 break;
1294
1295 case SIOCGIFRTLABEL:
1296 label = rtlabel_id2name(ifp->if_rtlabelid);
1297 strlcpy(ifrtlabelbuf, label, RTLABEL_LEN);
1298 error = copyoutstr(ifrtlabelbuf, ifr->ifr_data, RTLABEL_LEN,
1299 &bytesdone);
1300 break;
1301
1302 case SIOCSIFRTLABEL:
1303 if ((error = suser(p, 0)) != 0)
1304 return (error);
1305 error = copyinstr(ifr->ifr_data, ifrtlabelbuf,
1306 RTLABEL_LEN, &bytesdone);
1307 if (error == 0) {
1308 rtlabel_unref(ifp->if_rtlabelid);
1309 ifp->if_rtlabelid = rtlabel_name2id(ifrtlabelbuf);
1310 }
1311 break;
1312
1313 case SIOCAIFGROUP:
1314 if ((error = suser(p, 0)))
1315 return (error);
1316 (*ifp->if_ioctl)(ifp, cmd, data);
1317 ifgr = (struct ifgroupreq *)data;
1318 if ((error = if_addgroup(ifp, ifgr->ifgr_group)))
1319 return (error);
1320 break;
1321
1322 case SIOCGIFGROUP:
1323 if ((error = if_getgroup(data, ifp)))
1324 return (error);
1325 break;
1326
1327 case SIOCDIFGROUP:
1328 if ((error = suser(p, 0)))
1329 return (error);
1330 (*ifp->if_ioctl)(ifp, cmd, data);
1331 ifgr = (struct ifgroupreq *)data;
1332 if ((error = if_delgroup(ifp, ifgr->ifgr_group)))
1333 return (error);
1334 break;
1335
1336 case SIOCSIFLLADDR:
1337 if ((error = suser(p, 0)))
1338 return (error);
1339 ifa = ifnet_addrs[ifp->if_index];
1340 if (ifa == NULL)
1341 return (EINVAL);
1342 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
1343 if (sdl == NULL)
1344 return (EINVAL);
1345 if (ifr->ifr_addr.sa_len != ETHER_ADDR_LEN)
1346 return (EINVAL);
1347 if (ETHER_IS_MULTICAST(ifr->ifr_addr.sa_data))
1348 return (EINVAL);
1349 switch (ifp->if_type) {
1350 case IFT_ETHER:
1351 case IFT_CARP:
1352 case IFT_FDDI:
1353 case IFT_XETHER:
1354 case IFT_ISO88025:
1355 case IFT_L2VLAN:
1356 bcopy((caddr_t)ifr->ifr_addr.sa_data,
1357 (caddr_t)((struct arpcom *)ifp)->ac_enaddr,
1358 ETHER_ADDR_LEN);
1359 bcopy((caddr_t)ifr->ifr_addr.sa_data,
1360 LLADDR(sdl), ETHER_ADDR_LEN);
1361 break;
1362 default:
1363 return (ENODEV);
1364 }
1365 if (ifp->if_flags & IFF_UP) {
1366 struct ifreq ifrq;
1367 int s = splnet();
1368 ifp->if_flags &= ~IFF_UP;
1369 ifrq.ifr_flags = ifp->if_flags;
1370 (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
1371 ifp->if_flags |= IFF_UP;
1372 ifrq.ifr_flags = ifp->if_flags;
1373 (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
1374 splx(s);
1375 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1376 if (ifa->ifa_addr != NULL &&
1377 ifa->ifa_addr->sa_family == AF_INET)
1378 arp_ifinit((struct arpcom *)ifp, ifa);
1379 }
1380 }
1381 break;
1382
1383 default:
1384 if (so->so_proto == 0)
1385 return (EOPNOTSUPP);
1386 #if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4)
1387 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
1388 (struct mbuf *) cmd, (struct mbuf *) data,
1389 (struct mbuf *) ifp));
1390 #else
1391 {
1392 u_long ocmd = cmd;
1393
1394 switch (cmd) {
1395
1396 case SIOCSIFADDR:
1397 case SIOCSIFDSTADDR:
1398 case SIOCSIFBRDADDR:
1399 case SIOCSIFNETMASK:
1400 #if BYTE_ORDER != BIG_ENDIAN
1401 if (ifr->ifr_addr.sa_family == 0 &&
1402 ifr->ifr_addr.sa_len < 16) {
1403 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
1404 ifr->ifr_addr.sa_len = 16;
1405 }
1406 #else
1407 if (ifr->ifr_addr.sa_len == 0)
1408 ifr->ifr_addr.sa_len = 16;
1409 #endif
1410 break;
1411
1412 case OSIOCGIFADDR:
1413 cmd = SIOCGIFADDR;
1414 break;
1415
1416 case OSIOCGIFDSTADDR:
1417 cmd = SIOCGIFDSTADDR;
1418 break;
1419
1420 case OSIOCGIFBRDADDR:
1421 cmd = SIOCGIFBRDADDR;
1422 break;
1423
1424 case OSIOCGIFNETMASK:
1425 cmd = SIOCGIFNETMASK;
1426 }
1427 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
1428 (struct mbuf *) cmd, (struct mbuf *) data,
1429 (struct mbuf *) ifp));
1430 switch (ocmd) {
1431
1432 case OSIOCGIFADDR:
1433 case OSIOCGIFDSTADDR:
1434 case OSIOCGIFBRDADDR:
1435 case OSIOCGIFNETMASK:
1436 *(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
1437 }
1438
1439 }
1440 #endif
1441 break;
1442 }
1443
1444 if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
1445 microtime(&ifp->if_lastchange);
1446 #ifdef INET6
1447 if ((ifp->if_flags & IFF_UP) != 0) {
1448 int s = splnet();
1449 in6_if_up(ifp);
1450 splx(s);
1451 }
1452 #endif
1453 }
1454 return (error);
1455 }
1456
1457
1458
1459
1460
1461
1462
1463
1464 int
1465 ifconf(u_long cmd, caddr_t data)
1466 {
1467 struct ifconf *ifc = (struct ifconf *)data;
1468 struct ifnet *ifp;
1469 struct ifaddr *ifa;
1470 struct ifreq ifr, *ifrp;
1471 int space = ifc->ifc_len, error = 0;
1472
1473
1474 if (space == 0) {
1475 TAILQ_FOREACH(ifp, &ifnet, if_list) {
1476 struct sockaddr *sa;
1477
1478 if (TAILQ_EMPTY(&ifp->if_addrlist))
1479 space += sizeof (ifr);
1480 else
1481 TAILQ_FOREACH(ifa,
1482 &ifp->if_addrlist, ifa_list) {
1483 sa = ifa->ifa_addr;
1484 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
1485 if (cmd != OSIOCGIFCONF)
1486 #endif
1487 if (sa->sa_len > sizeof(*sa))
1488 space += sa->sa_len -
1489 sizeof(*sa);
1490 space += sizeof(ifr);
1491 }
1492 }
1493 ifc->ifc_len = space;
1494 return (0);
1495 }
1496
1497 ifrp = ifc->ifc_req;
1498 for (ifp = TAILQ_FIRST(&ifnet); space >= sizeof(ifr) &&
1499 ifp != TAILQ_END(&ifnet); ifp = TAILQ_NEXT(ifp, if_list)) {
1500 bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ);
1501 if (TAILQ_EMPTY(&ifp->if_addrlist)) {
1502 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
1503 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1504 sizeof(ifr));
1505 if (error)
1506 break;
1507 space -= sizeof (ifr), ifrp++;
1508 } else
1509 for (ifa = TAILQ_FIRST(&ifp->if_addrlist);
1510 space >= sizeof (ifr) &&
1511 ifa != TAILQ_END(&ifp->if_addrlist);
1512 ifa = TAILQ_NEXT(ifa, ifa_list)) {
1513 struct sockaddr *sa = ifa->ifa_addr;
1514 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
1515 if (cmd == OSIOCGIFCONF) {
1516 struct osockaddr *osa =
1517 (struct osockaddr *)&ifr.ifr_addr;
1518 ifr.ifr_addr = *sa;
1519 osa->sa_family = sa->sa_family;
1520 error = copyout((caddr_t)&ifr,
1521 (caddr_t)ifrp, sizeof (ifr));
1522 ifrp++;
1523 } else
1524 #endif
1525 if (sa->sa_len <= sizeof(*sa)) {
1526 ifr.ifr_addr = *sa;
1527 error = copyout((caddr_t)&ifr,
1528 (caddr_t)ifrp, sizeof (ifr));
1529 ifrp++;
1530 } else {
1531 space -= sa->sa_len - sizeof(*sa);
1532 if (space < sizeof (ifr))
1533 break;
1534 error = copyout((caddr_t)&ifr,
1535 (caddr_t)ifrp,
1536 sizeof(ifr.ifr_name));
1537 if (error == 0)
1538 error = copyout((caddr_t)sa,
1539 (caddr_t)&ifrp->ifr_addr,
1540 sa->sa_len);
1541 ifrp = (struct ifreq *)(sa->sa_len +
1542 (caddr_t)&ifrp->ifr_addr);
1543 }
1544 if (error)
1545 break;
1546 space -= sizeof (ifr);
1547 }
1548 }
1549 ifc->ifc_len -= space;
1550 return (error);
1551 }
1552
1553
1554
1555
1556
1557 void
1558 if_detached_start(struct ifnet *ifp)
1559 {
1560 struct mbuf *m;
1561
1562 while (1) {
1563 IF_DEQUEUE(&ifp->if_snd, m);
1564
1565 if (m == NULL)
1566 return;
1567 m_freem(m);
1568 }
1569 }
1570
1571 int
1572 if_detached_ioctl(struct ifnet *ifp, u_long a, caddr_t b)
1573 {
1574 return ENODEV;
1575 }
1576
1577 int
1578 if_detached_init(struct ifnet *ifp)
1579 {
1580 return (ENXIO);
1581 }
1582
1583 void
1584 if_detached_watchdog(struct ifnet *ifp)
1585 {
1586
1587 }
1588
1589
1590
1591
1592 struct ifg_group *
1593 if_creategroup(const char *groupname)
1594 {
1595 struct ifg_group *ifg = NULL;
1596
1597 if ((ifg = (struct ifg_group *)malloc(sizeof(struct ifg_group),
1598 M_TEMP, M_NOWAIT)) == NULL)
1599 return (NULL);
1600
1601 strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group));
1602 ifg->ifg_refcnt = 0;
1603 ifg->ifg_carp_demoted = 0;
1604 TAILQ_INIT(&ifg->ifg_members);
1605 #if NPF > 0
1606 pfi_attach_ifgroup(ifg);
1607 #endif
1608 TAILQ_INSERT_TAIL(&ifg_head, ifg, ifg_next);
1609
1610 return (ifg);
1611 }
1612
1613
1614
1615
1616 int
1617 if_addgroup(struct ifnet *ifp, const char *groupname)
1618 {
1619 struct ifg_list *ifgl;
1620 struct ifg_group *ifg = NULL;
1621 struct ifg_member *ifgm;
1622
1623 if (groupname[0] && groupname[strlen(groupname) - 1] >= '0' &&
1624 groupname[strlen(groupname) - 1] <= '9')
1625 return (EINVAL);
1626
1627 TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
1628 if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
1629 return (EEXIST);
1630
1631 if ((ifgl = (struct ifg_list *)malloc(sizeof(struct ifg_list), M_TEMP,
1632 M_NOWAIT)) == NULL)
1633 return (ENOMEM);
1634
1635 if ((ifgm = (struct ifg_member *)malloc(sizeof(struct ifg_member),
1636 M_TEMP, M_NOWAIT)) == NULL) {
1637 free(ifgl, M_TEMP);
1638 return (ENOMEM);
1639 }
1640
1641 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
1642 if (!strcmp(ifg->ifg_group, groupname))
1643 break;
1644
1645 if (ifg == NULL && (ifg = if_creategroup(groupname)) == NULL) {
1646 free(ifgl, M_TEMP);
1647 free(ifgm, M_TEMP);
1648 return (ENOMEM);
1649 }
1650
1651 ifg->ifg_refcnt++;
1652 ifgl->ifgl_group = ifg;
1653 ifgm->ifgm_ifp = ifp;
1654
1655 TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next);
1656 TAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next);
1657
1658 #if NPF > 0
1659 pfi_group_change(groupname);
1660 #endif
1661
1662 return (0);
1663 }
1664
1665
1666
1667
1668 int
1669 if_delgroup(struct ifnet *ifp, const char *groupname)
1670 {
1671 struct ifg_list *ifgl;
1672 struct ifg_member *ifgm;
1673
1674 TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
1675 if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
1676 break;
1677 if (ifgl == NULL)
1678 return (ENOENT);
1679
1680 TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next);
1681
1682 TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
1683 if (ifgm->ifgm_ifp == ifp)
1684 break;
1685
1686 if (ifgm != NULL) {
1687 TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next);
1688 free(ifgm, M_TEMP);
1689 }
1690
1691 if (--ifgl->ifgl_group->ifg_refcnt == 0) {
1692 TAILQ_REMOVE(&ifg_head, ifgl->ifgl_group, ifg_next);
1693 #if NPF > 0
1694 pfi_detach_ifgroup(ifgl->ifgl_group);
1695 #endif
1696 free(ifgl->ifgl_group, M_TEMP);
1697 }
1698
1699 free(ifgl, M_TEMP);
1700
1701 #if NPF > 0
1702 pfi_group_change(groupname);
1703 #endif
1704
1705 return (0);
1706 }
1707
1708
1709
1710
1711
1712 int
1713 if_getgroup(caddr_t data, struct ifnet *ifp)
1714 {
1715 int len, error;
1716 struct ifg_list *ifgl;
1717 struct ifg_req ifgrq, *ifgp;
1718 struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
1719
1720 if (ifgr->ifgr_len == 0) {
1721 TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
1722 ifgr->ifgr_len += sizeof(struct ifg_req);
1723 return (0);
1724 }
1725
1726 len = ifgr->ifgr_len;
1727 ifgp = ifgr->ifgr_groups;
1728 TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) {
1729 if (len < sizeof(ifgrq))
1730 return (EINVAL);
1731 bzero(&ifgrq, sizeof ifgrq);
1732 strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group,
1733 sizeof(ifgrq.ifgrq_group));
1734 if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
1735 sizeof(struct ifg_req))))
1736 return (error);
1737 len -= sizeof(ifgrq);
1738 ifgp++;
1739 }
1740
1741 return (0);
1742 }
1743
1744
1745
1746
1747 int
1748 if_getgroupmembers(caddr_t data)
1749 {
1750 struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
1751 struct ifg_group *ifg;
1752 struct ifg_member *ifgm;
1753 struct ifg_req ifgrq, *ifgp;
1754 int len, error;
1755
1756 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
1757 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
1758 break;
1759 if (ifg == NULL)
1760 return (ENOENT);
1761
1762 if (ifgr->ifgr_len == 0) {
1763 TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
1764 ifgr->ifgr_len += sizeof(ifgrq);
1765 return (0);
1766 }
1767
1768 len = ifgr->ifgr_len;
1769 ifgp = ifgr->ifgr_groups;
1770 TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) {
1771 if (len < sizeof(ifgrq))
1772 return (EINVAL);
1773 bzero(&ifgrq, sizeof ifgrq);
1774 strlcpy(ifgrq.ifgrq_member, ifgm->ifgm_ifp->if_xname,
1775 sizeof(ifgrq.ifgrq_member));
1776 if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
1777 sizeof(struct ifg_req))))
1778 return (error);
1779 len -= sizeof(ifgrq);
1780 ifgp++;
1781 }
1782
1783 return (0);
1784 }
1785
1786 int
1787 if_getgroupattribs(caddr_t data)
1788 {
1789 struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
1790 struct ifg_group *ifg;
1791
1792 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
1793 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
1794 break;
1795 if (ifg == NULL)
1796 return (ENOENT);
1797
1798 ifgr->ifgr_attrib.ifg_carp_demoted = ifg->ifg_carp_demoted;
1799
1800 return (0);
1801 }
1802
1803 int
1804 if_setgroupattribs(caddr_t data)
1805 {
1806 struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
1807 struct ifg_group *ifg;
1808 struct ifg_member *ifgm;
1809 int demote;
1810
1811 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
1812 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
1813 break;
1814 if (ifg == NULL)
1815 return (ENOENT);
1816
1817 demote = ifgr->ifgr_attrib.ifg_carp_demoted;
1818 if (demote + ifg->ifg_carp_demoted > 0xff ||
1819 demote + ifg->ifg_carp_demoted < 0)
1820 return (ERANGE);
1821
1822 ifg->ifg_carp_demoted += demote;
1823
1824 TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
1825 if (ifgm->ifgm_ifp->if_ioctl)
1826 ifgm->ifgm_ifp->if_ioctl(ifgm->ifgm_ifp,
1827 SIOCSIFGATTR, data);
1828 return (0);
1829 }
1830
1831 void
1832 if_group_routechange(struct sockaddr *dst, struct sockaddr *mask)
1833 {
1834 switch (dst->sa_family) {
1835 case AF_INET:
1836 if (satosin(dst)->sin_addr.s_addr == INADDR_ANY)
1837 if_group_egress_build();
1838 break;
1839 #ifdef INET6
1840 case AF_INET6:
1841 if (IN6_ARE_ADDR_EQUAL(&(satosin6(dst))->sin6_addr,
1842 &in6addr_any) &&
1843 mask && IN6_ARE_ADDR_EQUAL(&(satosin6(mask))->sin6_addr,
1844 &in6addr_any))
1845 if_group_egress_build();
1846 break;
1847 #endif
1848 }
1849 }
1850
1851 int
1852 if_group_egress_build(void)
1853 {
1854 struct ifg_group *ifg;
1855 struct ifg_member *ifgm, *next;
1856 struct sockaddr_in sa_in;
1857 #ifdef INET6
1858 struct sockaddr_in6 sa_in6;
1859 #endif
1860 struct radix_node *rn;
1861 struct rtentry *rt;
1862
1863 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
1864 if (!strcmp(ifg->ifg_group, IFG_EGRESS))
1865 break;
1866
1867 if (ifg != NULL)
1868 for (ifgm = TAILQ_FIRST(&ifg->ifg_members); ifgm; ifgm = next) {
1869 next = TAILQ_NEXT(ifgm, ifgm_next);
1870 if_delgroup(ifgm->ifgm_ifp, IFG_EGRESS);
1871 }
1872
1873 bzero(&sa_in, sizeof(sa_in));
1874 sa_in.sin_len = sizeof(sa_in);
1875 sa_in.sin_family = AF_INET;
1876 if ((rn = rt_lookup(sintosa(&sa_in), sintosa(&sa_in), 0)) != NULL) {
1877 do {
1878 rt = (struct rtentry *)rn;
1879 if (rt->rt_ifp)
1880 if_addgroup(rt->rt_ifp, IFG_EGRESS);
1881 #ifndef SMALL_KERNEL
1882 rn = rn_mpath_next(rn);
1883 #else
1884 rn = NULL;
1885 #endif
1886 } while (rn != NULL);
1887 }
1888
1889 #ifdef INET6
1890 bcopy(&sa6_any, &sa_in6, sizeof(sa_in6));
1891 if ((rn = rt_lookup(sin6tosa(&sa_in6), sin6tosa(&sa_in6), 0)) != NULL) {
1892 do {
1893 rt = (struct rtentry *)rn;
1894 if (rt->rt_ifp)
1895 if_addgroup(rt->rt_ifp, IFG_EGRESS);
1896 #ifndef SMALL_KERNEL
1897 rn = rn_mpath_next(rn);
1898 #else
1899 rn = NULL;
1900 #endif
1901 } while (rn != NULL);
1902 }
1903 #endif
1904
1905 return (0);
1906 }
1907
1908
1909
1910
1911
1912
1913
1914 int
1915 ifpromisc(struct ifnet *ifp, int pswitch)
1916 {
1917 struct ifreq ifr;
1918
1919 if (pswitch) {
1920
1921
1922
1923
1924 if ((ifp->if_flags & IFF_UP) == 0)
1925 return (ENETDOWN);
1926 if (ifp->if_pcount++ != 0)
1927 return (0);
1928 ifp->if_flags |= IFF_PROMISC;
1929 } else {
1930 if (--ifp->if_pcount > 0)
1931 return (0);
1932 ifp->if_flags &= ~IFF_PROMISC;
1933
1934
1935
1936
1937
1938
1939 if ((ifp->if_flags & IFF_UP) == 0)
1940 return (0);
1941 }
1942 ifr.ifr_flags = ifp->if_flags;
1943 return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
1944 }
1945
1946 int
1947 sysctl_ifq(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1948 void *newp, size_t newlen, struct ifqueue *ifq)
1949 {
1950
1951 if (namelen != 1)
1952 return (ENOTDIR);
1953
1954 switch (name[0]) {
1955 case IFQCTL_LEN:
1956 return (sysctl_rdint(oldp, oldlenp, newp, ifq->ifq_len));
1957 case IFQCTL_MAXLEN:
1958 return (sysctl_int(oldp, oldlenp, newp, newlen,
1959 &ifq->ifq_maxlen));
1960 case IFQCTL_DROPS:
1961 return (sysctl_rdint(oldp, oldlenp, newp, ifq->ifq_drops));
1962 default:
1963 return (EOPNOTSUPP);
1964 }
1965
1966 }
1967
1968 void
1969 netrndintr(void)
1970 {
1971 add_net_randomness(0);
1972 }