1 /* $NetBSD: if_agr.c,v 1.23 2009/05/29 04:57:05 darran Exp $ */
4 * Copyright (c)2005 YAMAMOTO Takashi,
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: if_agr.c,v 1.23 2009/05/29 04:57:05 darran Exp $");
35 #include <sys/param.h>
36 #include <sys/callout.h>
37 #include <sys/malloc.h>
39 #include <sys/systm.h>
40 #include <sys/types.h>
41 #include <sys/queue.h>
42 #include <sys/sockio.h>
43 #include <sys/proc.h> /* XXX for curproc */
44 #include <sys/kauth.h>
50 #include <net/if_dl.h>
51 #include <net/if_types.h>
52 #include <net/if_ether.h>
55 #include <netinet/in.h>
56 #include <netinet/if_inarp.h>
59 #include <net/agr/if_agrvar.h>
60 #include <net/agr/if_agrvar_impl.h>
61 #include <net/agr/if_agrioctl.h>
62 #include <net/agr/if_agrsubr.h>
63 #include <net/agr/if_agrethervar.h>
67 static int agr_clone_create(struct if_clone
*, int);
68 static int agr_clone_destroy(struct ifnet
*);
69 static void agr_start(struct ifnet
*);
70 static int agr_setconfig(struct ifnet
*, const struct agrreq
*);
71 static int agr_getconfig(struct ifnet
*, struct agrreq
*);
72 static int agr_getportlist(struct ifnet
*, struct agrreq
*);
73 static int agr_addport(struct ifnet
*, struct ifnet
*);
74 static int agr_remport(struct ifnet
*, struct ifnet
*);
75 static int agrreq_copyin(const void *, struct agrreq
*);
76 static int agrreq_copyout(void *, struct agrreq
*);
77 static int agr_ioctl(struct ifnet
*, u_long
, void *);
78 static struct agr_port
*agr_select_tx_port(struct agr_softc
*, struct mbuf
*);
79 static int agr_ioctl_filter(struct ifnet
*, u_long
, void *);
80 static void agr_reset_iftype(struct ifnet
*);
81 static int agr_config_promisc(struct agr_softc
*);
82 static int agrport_config_promisc_callback(struct agr_port
*, void *);
83 static int agrport_config_promisc(struct agr_port
*, bool);
84 static int agrport_cleanup(struct agr_softc
*, struct agr_port
*);
86 static struct if_clone agr_cloner
=
87 IF_CLONE_INITIALIZER("agr", agr_clone_create
, agr_clone_destroy
);
94 * agrattch: device attach routine.
101 if_clone_attach(&agr_cloner
);
105 * agr_input: frame collector.
109 agr_input(struct ifnet
*ifp_port
, struct mbuf
*m
)
111 struct agr_port
*port
;
117 port
= ifp_port
->if_agrprivate
;
119 ifp
= port
->port_agrifp
;
120 if ((port
->port_flags
& AGRPORT_COLLECTING
) == 0) {
127 m
->m_pkthdr
.rcvif
= ifp
;
131 /* got a vlan packet? */
132 if ((mtag
= m_tag_find(m
, PACKET_TAG_VLAN
, NULL
)) != NULL
) {
134 printf("%s: vlan tag %d attached\n",
136 htole16((*(u_int
*)(mtag
+ 1)) & 0xffff));
137 printf("%s: vlan input\n", ifp
->if_xname
);
143 struct ethercom
*ec
= (void *)ifp
;
144 printf("%s: no vlan tag attached, ec_nvlans=%d\n",
145 ifp
->if_xname
, ec
->ec_nvlans
);
152 bpf_mtap(ifp
->if_bpf
, m
);
156 (*ifp
->if_input
)(ifp
, m
);
160 * EXPORTED AGR-INTERNAL FUNCTIONS
164 agr_lock(struct agr_softc
*sc
)
167 mutex_enter(&sc
->sc_lock
);
171 agr_unlock(struct agr_softc
*sc
)
174 mutex_exit(&sc
->sc_lock
);
178 agr_ioctl_lock(struct agr_softc
*sc
)
181 mutex_enter(&sc
->sc_ioctl_lock
);
185 agr_ioctl_unlock(struct agr_softc
*sc
)
188 mutex_exit(&sc
->sc_ioctl_lock
);
192 * agr_xmit_frame: transmit a pre-built frame.
196 agr_xmit_frame(struct ifnet
*ifp_port
, struct mbuf
*m
)
200 struct sockaddr_storage dst0
;
201 struct sockaddr
*dst
;
205 * trim off link level header and let if_output re-add it.
206 * XXX better to introduce an API to transmit pre-built frames.
209 hdrlen
= ifp_port
->if_hdrlen
;
210 if (m
->m_pkthdr
.len
< hdrlen
) {
214 memset(&dst0
, 0, sizeof(dst0
));
215 dst
= (struct sockaddr
*)&dst0
;
216 dst
->sa_family
= pseudo_AF_HDRCMPLT
;
217 dst
->sa_len
= hdrlen
;
218 m_copydata(m
, 0, hdrlen
, &dst
->sa_data
);
221 error
= (*ifp_port
->if_output
)(ifp_port
, m
, dst
, NULL
);
227 agrport_ioctl(struct agr_port
*port
, u_long cmd
, void *arg
)
229 struct ifnet
*ifp
= port
->port_ifp
;
231 KASSERT(ifp
->if_agrprivate
== (void *)port
);
232 KASSERT(ifp
->if_ioctl
== agr_ioctl_filter
);
234 return (*port
->port_ioctl
)(ifp
, cmd
, arg
);
242 * Enable vlan hardware assist for the specified port.
245 agr_vlan_add(struct agr_port
*port
, void *arg
)
247 struct ifnet
*ifp
= port
->port_ifp
;
248 struct ethercom
*ec_port
= (void *)ifp
;
252 if (ec_port
->ec_nvlans
++ == 0 &&
253 (ec_port
->ec_capabilities
& ETHERCAP_VLAN_MTU
) != 0) {
254 struct ifnet
*p
= port
->port_ifp
;
256 * Enable Tx/Rx of VLAN-sized frames.
258 ec_port
->ec_capenable
|= ETHERCAP_VLAN_MTU
;
259 if (p
->if_flags
& IFF_UP
) {
260 ifr
.ifr_flags
= p
->if_flags
;
261 error
= (*p
->if_ioctl
)(p
, SIOCSIFFLAGS
,
264 if (ec_port
->ec_nvlans
-- == 1)
265 ec_port
->ec_capenable
&=
276 * Disable vlan hardware assist for the specified port.
279 agr_vlan_del(struct agr_port
*port
, void *arg
)
281 struct ethercom
*ec_port
= (void *)port
->port_ifp
;
284 /* Disable vlan support */
285 if (ec_port
->ec_nvlans
-- == 1) {
287 * Disable Tx/Rx of VLAN-sized frames.
289 ec_port
->ec_capenable
&= ~ETHERCAP_VLAN_MTU
;
290 if (port
->port_ifp
->if_flags
& IFF_UP
) {
291 ifr
.ifr_flags
= port
->port_ifp
->if_flags
;
292 (void) (*port
->port_ifp
->if_ioctl
)(port
->port_ifp
,
293 SIOCSIFFLAGS
, (void *) &ifr
);
302 * Check for vlan attach/detach.
303 * ec->ec_nvlans is directly modified by the vlan driver.
304 * We keep a local count in sc (sc->sc_nvlans) to detect
305 * when the vlan driver attaches or detaches.
306 * Note the agr interface must be up for this to work.
309 agr_vlan_check(struct ifnet
*ifp
, struct agr_softc
*sc
)
311 struct ethercom
*ec
= (void *)ifp
;
315 if (sc
->sc_nvlans
== ec
->ec_nvlans
) {
319 if (sc
->sc_nvlans
== 0) {
321 error
= agr_port_foreach(sc
, agr_vlan_add
, NULL
);
322 sc
->sc_nvlans
= ec
->ec_nvlans
;
323 } else if (ec
->ec_nvlans
== 0) {
325 error
= agr_port_foreach(sc
, agr_vlan_del
, NULL
);
331 agr_clone_create(struct if_clone
*ifc
, int unit
)
333 struct agr_softc
*sc
;
336 sc
= agr_alloc_softc();
337 TAILQ_INIT(&sc
->sc_ports
);
338 mutex_init(&sc
->sc_ioctl_lock
, MUTEX_DRIVER
, IPL_NONE
);
339 mutex_init(&sc
->sc_lock
, MUTEX_DRIVER
, IPL_NET
);
342 snprintf(ifp
->if_xname
, sizeof(ifp
->if_xname
), "%s%d",
343 ifc
->ifc_name
, unit
);
346 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_MULTICAST
;
347 ifp
->if_start
= agr_start
;
348 ifp
->if_ioctl
= agr_ioctl
;
349 IFQ_SET_READY(&ifp
->if_snd
);
353 agr_reset_iftype(ifp
);
359 agr_reset_iftype(struct ifnet
*ifp
)
362 ifp
->if_type
= IFT_OTHER
;
363 ifp
->if_dlt
= DLT_NULL
;
369 agr_clone_destroy(struct ifnet
*ifp
)
371 struct agr_softc
*sc
= ifp
->if_softc
;
377 if (sc
->sc_nports
> 0) {
384 agr_ioctl_unlock(sc
);
388 mutex_destroy(&sc
->sc_ioctl_lock
);
389 mutex_destroy(&sc
->sc_lock
);
396 static struct agr_port
*
397 agr_select_tx_port(struct agr_softc
*sc
, struct mbuf
*m
)
400 return (*sc
->sc_iftop
->iftop_select_tx_port
)(sc
, m
);
403 #if 0 /* "generic" version */
404 static struct agr_port
*
405 agr_select_tx_port(struct agr_softc
*sc
, struct mbuf
*m
)
407 struct agr_port
*port
;
410 hash
= (*sc
->sc_iftop
->iftop_hashmbuf
)(sc
, m
);
411 if (sc
->sc_nports
== 0)
413 hash
%= sc
->sc_nports
;
414 port
= TAILQ_FIRST(&sc
->sc_ports
);
415 KASSERT(port
!= NULL
);
417 port
= TAILQ_NEXT(port
, port_q
);
418 KASSERT(port
!= NULL
);
426 agr_start(struct ifnet
*ifp
)
428 struct agr_softc
*sc
= ifp
->if_softc
;
433 while (/* CONSTCOND */ 1) {
434 struct agr_port
*port
;
436 IFQ_DEQUEUE(&ifp
->if_snd
, m
);
442 bpf_mtap(ifp
->if_bpf
, m
);
445 port
= agr_select_tx_port(sc
, m
);
449 error
= agr_xmit_frame(port
->port_ifp
, m
);
463 ifp
->if_flags
&= ~IFF_OACTIVE
;
467 agr_setconfig(struct ifnet
*ifp
, const struct agrreq
*ar
)
469 int cmd
= ar
->ar_cmd
;
470 struct ifnet
*ifp_port
;
472 char ifname
[IFNAMSIZ
];
474 memset(ifname
, 0, sizeof(ifname
));
475 error
= copyin(ar
->ar_buf
, ifname
,
476 MIN(ar
->ar_buflen
, sizeof(ifname
) - 1));
480 ifp_port
= ifunit(ifname
);
481 if (ifp_port
== NULL
) {
487 error
= agr_addport(ifp
, ifp_port
);
491 error
= agr_remport(ifp
, ifp_port
);
503 agr_getportlist(struct ifnet
*ifp
, struct agrreq
*ar
)
505 struct agr_softc
*sc
= ifp
->if_softc
;
506 struct agr_port
*port
;
507 struct agrportlist apl
;
508 struct agrportinfo api
;
509 char *cp
= ar
->ar_buf
;
510 size_t bufleft
= (cp
== NULL
) ? 0 : ar
->ar_buflen
;
514 memset(&apl
, 0, sizeof(apl
));
515 memset(&api
, 0, sizeof(api
));
517 if (bufleft
< sizeof(apl
)) {
520 apl
.apl_nports
= sc
->sc_nports
;
521 error
= copyout(&apl
, cp
, sizeof(apl
));
527 bufleft
-= sizeof(apl
);
529 TAILQ_FOREACH(port
, &sc
->sc_ports
, port_q
) {
531 if (bufleft
< sizeof(api
)) {
534 memcpy(api
.api_ifname
, port
->port_ifp
->if_xname
,
535 sizeof(api
.api_ifname
));
537 if (port
->port_flags
& AGRPORT_COLLECTING
) {
538 api
.api_flags
|= AGRPORTINFO_COLLECTING
;
540 if (port
->port_flags
& AGRPORT_DISTRIBUTING
) {
541 api
.api_flags
|= AGRPORTINFO_DISTRIBUTING
;
543 error
= copyout(&api
, cp
, sizeof(api
));
549 bufleft
-= sizeof(api
);
553 ar
->ar_buflen
= -bufleft
; /* necessary buffer size */
560 agr_getconfig(struct ifnet
*ifp
, struct agrreq
*ar
)
562 int cmd
= ar
->ar_cmd
;
566 case AGRCMD_PORTLIST
:
567 error
= agr_getportlist(ifp
, ar
);
579 agr_addport(struct ifnet
*ifp
, struct ifnet
*ifp_port
)
581 const struct ifaddr
*ifa
;
582 struct agr_softc
*sc
= ifp
->if_softc
;
583 struct agr_port
*port
= NULL
;
586 if (ifp_port
->if_ioctl
== NULL
) {
591 if (ifp_port
->if_agrprivate
) {
596 if (ifp_port
->if_start
== agr_start
) {
601 port
= malloc(sizeof(*port
) + ifp_port
->if_addrlen
, M_DEVBUF
,
607 port
->port_flags
= AGRPORT_LARVAL
;
609 IFADDR_FOREACH(ifa
, ifp_port
) {
610 if (ifa
->ifa_addr
->sa_family
!= AF_LINK
) {
616 if (sc
->sc_nports
== 0) {
617 switch (ifp_port
->if_type
) {
619 sc
->sc_iftop
= &agrether_ops
;
623 error
= EPROTONOSUPPORT
; /* XXX */
627 error
= (*sc
->sc_iftop
->iftop_ctor
)(sc
, ifp_port
);
632 if (ifp
->if_type
!= ifp_port
->if_type
) {
636 if (ifp
->if_addrlen
!= ifp_port
->if_addrlen
) {
642 memcpy(port
->port_origlladdr
, CLLADDR(ifp_port
->if_sadl
),
643 ifp_port
->if_addrlen
);
646 * start to modify ifp_port.
650 * XXX this should probably be SIOCALIFADDR but that doesn't
651 * appear to work (ENOTTY). We want to change the mac address
652 * of each port to that of the first port. No need for arps
653 * since there are no inet addresses assigned to the ports.
655 error
= (*ifp_port
->if_ioctl
)(ifp_port
, SIOCINITIFADDR
, ifp
->if_dl
);
658 printf("%s: SIOCINITIFADDR error %d\n", __func__
, error
);
661 port
->port_flags
|= AGRPORT_LADDRCHANGED
;
663 ifp
->if_type
= ifp_port
->if_type
;
666 port
->port_ifp
= ifp_port
;
667 ifp_port
->if_agrprivate
= port
;
668 port
->port_agrifp
= ifp
;
669 TAILQ_INSERT_TAIL(&sc
->sc_ports
, port
, port_q
);
672 port
->port_ioctl
= ifp_port
->if_ioctl
;
673 ifp_port
->if_ioctl
= agr_ioctl_filter
;
675 port
->port_flags
|= AGRPORT_ATTACHED
;
679 error
= (*sc
->sc_iftop
->iftop_portinit
)(sc
, port
);
681 printf("%s: portinit error %d\n", __func__
, error
);
685 ifp
->if_flags
|= IFF_RUNNING
;
687 agrport_config_promisc(port
, (ifp
->if_flags
& IFF_PROMISC
) != 0);
688 error
= (*sc
->sc_iftop
->iftop_configmulti_port
)(sc
, port
, true);
690 printf("%s: configmulti error %d\n", __func__
, error
);
695 port
->port_flags
&= ~AGRPORT_LARVAL
;
699 free(port
, M_DEVBUF
);
704 if (agrport_cleanup(sc
, port
)) {
705 printf("%s: error on cleanup\n", __func__
);
707 port
= NULL
; /* XXX */
710 if (sc
->sc_nports
== 0) {
711 KASSERT(TAILQ_EMPTY(&sc
->sc_ports
));
713 (*sc
->sc_iftop
->iftop_dtor
)(sc
);
715 agr_reset_iftype(ifp
);
717 KASSERT(!TAILQ_EMPTY(&sc
->sc_ports
));
724 agr_remport(struct ifnet
*ifp
, struct ifnet
*ifp_port
)
726 struct agr_softc
*sc
= ifp
->if_softc
;
727 struct agr_port
*port
;
730 if (ifp_port
->if_agrprivate
== NULL
) {
735 port
= ifp_port
->if_agrprivate
;
736 if (port
->port_agrifp
!= ifp
) {
741 KASSERT(sc
->sc_nports
> 0);
744 port
->port_flags
|= AGRPORT_DETACHING
;
747 error
= (*sc
->sc_iftop
->iftop_portfini
)(sc
, port
);
750 printf("%s: portfini error %d\n", __func__
, error
);
754 error
= (*sc
->sc_iftop
->iftop_configmulti_port
)(sc
, port
, false);
757 printf("%s: configmulti_port error %d\n", __func__
, error
);
761 error
= agrport_cleanup(sc
, port
);
764 printf("%s: agrport_cleanup error %d\n", __func__
, error
);
768 free(port
, M_DEVBUF
);
771 if (sc
->sc_nports
== 0) {
772 KASSERT(TAILQ_EMPTY(&sc
->sc_ports
));
774 (*sc
->sc_iftop
->iftop_dtor
)(sc
);
776 /* XXX should purge all addresses? */
777 agr_reset_iftype(ifp
);
779 KASSERT(!TAILQ_EMPTY(&sc
->sc_ports
));
786 agrport_cleanup(struct agr_softc
*sc
, struct agr_port
*port
)
788 struct ifnet
*ifp_port
= port
->port_ifp
;
792 error
= agrport_config_promisc(port
, false);
794 printf("%s: config_promisc error %d\n", __func__
, error
);
798 if ((port
->port_flags
& AGRPORT_LADDRCHANGED
)) {
800 memcpy(LLADDR(ifp_port
->if_sadl
), port
->port_origlladdr
,
801 ifp_port
->if_addrlen
);
802 if (ifp_port
->if_init
!= NULL
) {
803 error
= (*ifp_port
->if_init
)(ifp_port
);
808 struct sockaddr_dl sdl
;
809 struct sockaddr_storage ss
;
813 sockaddr_dl_init(&u
.sdl
, sizeof(u
.ss
),
814 0, ifp_port
->if_type
, NULL
, 0,
815 port
->port_origlladdr
, ifp_port
->if_addrlen
);
816 memset(&ifa
, 0, sizeof(ifa
));
817 ifa
.ifa_addr
= &u
.sa
;
818 error
= agrport_ioctl(port
, SIOCINITIFADDR
, &ifa
);
821 printf("%s: if_init error %d\n", __func__
, error
);
824 port
->port_flags
&= ~AGRPORT_LADDRCHANGED
;
829 if ((port
->port_flags
& AGRPORT_ATTACHED
)) {
830 ifp_port
->if_agrprivate
= NULL
;
832 TAILQ_REMOVE(&sc
->sc_ports
, port
, port_q
);
835 KASSERT(ifp_port
->if_ioctl
== agr_ioctl_filter
);
836 ifp_port
->if_ioctl
= port
->port_ioctl
;
838 port
->port_flags
&= ~AGRPORT_ATTACHED
;
846 agr_ioctl_multi(struct ifnet
*ifp
, u_long cmd
, struct ifreq
*ifr
)
848 struct agr_softc
*sc
= ifp
->if_softc
;
851 error
= (*sc
->sc_iftop
->iftop_configmulti_ifreq
)(sc
, ifr
,
852 (cmd
== SIOCADDMULTI
));
858 * XXX an incomplete hack; can't filter ioctls handled ifioctl().
860 * the intention here is to prevent operations on underlying interfaces
861 * so that their states are not changed in the way that agr(4) doesn't
862 * expect. cf. the BUGS section in the agr(4) manual page.
865 agr_ioctl_filter(struct ifnet
*ifp
, u_long cmd
, void *arg
)
867 struct agr_port
*port
= ifp
->if_agrprivate
;
873 case SIOCADDMULTI
: /* add m'cast addr */
874 case SIOCAIFADDR
: /* add/chg IF alias */
875 case SIOCALIFADDR
: /* add IF addr */
876 case SIOCDELMULTI
: /* del m'cast addr */
877 case SIOCDIFADDR
: /* delete IF addr */
878 case SIOCDIFPHYADDR
: /* delete gif addrs */
879 case SIOCDLIFADDR
: /* delete IF addr */
881 case SIOCSDRVSPEC
: /* set driver-specific parameters */
882 case SIOCSIFADDR
: /* set ifnet address */
883 case SIOCSIFBRDADDR
: /* set broadcast addr */
884 case SIOCSIFDSTADDR
: /* set p-p address */
885 case SIOCSIFGENERIC
: /* generic IF set op */
886 case SIOCSIFMEDIA
: /* set net media */
887 case SIOCSIFMETRIC
: /* set IF metric */
888 case SIOCSIFMTU
: /* set ifnet mtu */
889 case SIOCSIFNETMASK
: /* set net addr mask */
890 case SIOCSIFPHYADDR
: /* set gif addres */
891 case SIOCSLIFPHYADDR
: /* set gif addrs */
892 case SIOCSVH
: /* set carp param */
895 case SIOCSIFCAP
: /* XXX */
896 case SIOCSIFFLAGS
: /* XXX */
898 error
= agrport_ioctl(port
, cmd
, arg
);
905 agrreq_copyin(const void *ubuf
, struct agrreq
*ar
)
909 error
= copyin(ubuf
, ar
, sizeof(*ar
));
914 if (ar
->ar_version
!= AGRREQ_VERSION
) {
922 agrreq_copyout(void *ubuf
, struct agrreq
*ar
)
926 KASSERT(ar
->ar_version
== AGRREQ_VERSION
);
928 error
= copyout(ar
, ubuf
, sizeof(*ar
));
937 agr_ioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
939 struct agr_softc
*sc
= ifp
->if_softc
;
940 struct ifreq
*ifr
= (struct ifreq
*)data
;
941 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
952 if (sc
->sc_nports
== 0) {
956 ifp
->if_flags
|= IFF_UP
;
957 switch (ifa
->ifa_addr
->sa_family
) {
960 arp_ifinit(ifp
, ifa
);
974 * Check for a change in vlan status. This ioctl is the
975 * only way we can tell that a vlan has attached or detached.
976 * Note the agr interface must be up.
978 agr_vlan_check(ifp
, sc
);
980 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
982 agr_config_promisc(sc
);
987 error
= kauth_authorize_network(kauth_cred_get(),
988 KAUTH_NETWORK_INTERFACE
,
989 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV
, ifp
, (void *)cmd
,
992 error
= agrreq_copyin(ifr
->ifr_data
, &ar
);
995 error
= agr_setconfig(ifp
, &ar
);
1002 error
= agrreq_copyin(ifr
->ifr_data
, &ar
);
1004 error
= agr_getconfig(ifp
, &ar
);
1007 error
= agrreq_copyout(ifr
->ifr_data
, &ar
);
1014 if (sc
->sc_nports
== 0) {
1018 error
= agr_ioctl_multi(ifp
, cmd
, ifr
);
1022 error
= ifioctl_common(ifp
, cmd
, data
);
1028 agr_ioctl_unlock(sc
);
1034 agr_config_promisc(struct agr_softc
*sc
)
1038 agr_port_foreach(sc
, agrport_config_promisc_callback
, &error
);
1044 agrport_config_promisc_callback(struct agr_port
*port
, void *arg
)
1046 struct agr_softc
*sc
= AGR_SC_FROM_PORT(port
);
1051 promisc
= (sc
->sc_if
.if_flags
& IFF_PROMISC
) != 0;
1053 error
= agrport_config_promisc(port
, promisc
);
1062 agrport_config_promisc(struct agr_port
*port
, bool promisc
)
1066 if (( promisc
&& (port
->port_flags
& AGRPORT_PROMISC
) != 0) ||
1067 (!promisc
&& (port
->port_flags
& AGRPORT_PROMISC
) == 0)) {
1071 error
= ifpromisc(port
->port_ifp
, promisc
);
1074 port
->port_flags
|= AGRPORT_PROMISC
;
1076 port
->port_flags
&= ~AGRPORT_PROMISC
;