2 * Copyright (c) 1997-2014 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * @(#)ndrv.c 1.1 (MacOSX) 6/10/43
30 * Justin Walker, 970604
32 * 980130 - Cleanup, reorg, performance improvemements
33 * 000816 - Removal of Y adapter cruft
37 * PF_NDRV allows raw access to a specified network device, directly
38 * with a socket. Expected use involves a socket option to request
39 * protocol packets. This lets ndrv_output() call ifnet_output(), and
40 * lets DLIL find the proper recipient for incoming packets.
41 * The purpose here is for user-mode protocol implementation.
42 * Note that "pure raw access" will still be accomplished with BPF.
44 * In addition to the former use, when combined with socket NKEs,
45 * PF_NDRV permits a fairly flexible mechanism for implementing
46 * strange protocol support.
48 #include <mach/mach_types.h>
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/kernel.h>
53 #include <sys/malloc.h>
55 #include <sys/protosw.h>
56 #include <sys/domain.h>
57 #include <sys/socket.h>
58 #include <sys/socketvar.h>
59 #include <sys/ioctl.h>
60 #include <sys/sysctl.h>
61 #include <sys/errno.h>
62 #include <sys/syslog.h>
65 #include <kern/queue.h>
68 #include <net/route.h>
69 #include <net/if_llc.h>
70 #include <net/if_dl.h>
71 #include <net/if_types.h>
72 #include <net/ndrv_var.h>
76 #include <netinet/in.h>
77 #include <netinet/in_var.h>
79 #include <netinet/if_ether.h>
81 static unsigned int ndrv_multi_max_count
= NDRV_DMUX_MAX_DESCR
;
82 SYSCTL_UINT(_net
, OID_AUTO
, ndrv_multi_max_count
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
83 &ndrv_multi_max_count
, 0, "Number of allowed multicast addresses per NRDV socket");
86 * The locking strategy relies on the PF_NRDRV domain mutex that protects both the
87 * PCB list "ndrvl" and the sockets themselves
90 static int ndrv_do_detach(struct ndrv_cb
*);
91 static int ndrv_do_disconnect(struct ndrv_cb
*);
92 static struct ndrv_cb
*ndrv_find_inbound(struct ifnet
*ifp
, u_int32_t protocol_family
);
93 static int ndrv_setspec(struct ndrv_cb
*np
, struct sockopt
*sopt
);
94 static int ndrv_delspec(struct ndrv_cb
*);
95 static int ndrv_to_ifnet_demux(struct ndrv_demux_desc
* ndrv
, struct ifnet_demux_desc
* ifdemux
);
96 static void ndrv_handle_ifp_detach(u_int32_t family
, short unit
);
97 static int ndrv_do_add_multicast(struct ndrv_cb
*np
, struct sockopt
*sopt
);
98 static int ndrv_do_remove_multicast(struct ndrv_cb
*np
, struct sockopt
*sopt
);
99 static struct ndrv_multiaddr
* ndrv_have_multicast(struct ndrv_cb
*np
, struct sockaddr
* addr
);
100 static void ndrv_remove_all_multicast(struct ndrv_cb
*np
);
101 static void ndrv_dominit(struct domain
*);
103 u_int32_t ndrv_sendspace
= NDRVSNDQ
;
104 u_int32_t ndrv_recvspace
= NDRVRCVQ
;
105 TAILQ_HEAD(, ndrv_cb
) ndrvl
= TAILQ_HEAD_INITIALIZER(ndrvl
);
107 static struct domain
*ndrvdomain
= NULL
;
108 extern struct domain ndrvdomain_s
;
110 #define NDRV_PROTODEMUX_COUNT 10
113 * Verify these values match.
114 * To keep clients from including dlil.h, we define
115 * these values independently in ndrv.h. They must
116 * match or a conversion function must be written.
118 #if NDRV_DEMUXTYPE_ETHERTYPE != DLIL_DESC_ETYPE2
119 #error NDRV_DEMUXTYPE_ETHERTYPE must match DLIL_DESC_ETYPE2
121 #if NDRV_DEMUXTYPE_SAP != DLIL_DESC_SAP
122 #error NDRV_DEMUXTYPE_SAP must match DLIL_DESC_SAP
124 #if NDRV_DEMUXTYPE_SNAP != DLIL_DESC_SNAP
125 #error NDRV_DEMUXTYPE_SNAP must match DLIL_DESC_SNAP
129 * Protocol output - Called to output a raw network packet directly
133 ndrv_output(struct mbuf
*m
, struct socket
*so
)
135 struct ndrv_cb
*np
= sotondrvcb(so
);
136 struct ifnet
*ifp
= np
->nd_if
;
140 printf("NDRV output: %x, %x, %x\n", m
, so
, np
);
144 * No header is a format error
146 if ((m
->m_flags
& M_PKTHDR
) == 0) {
150 /* Unlock before calling ifnet_output */
151 socket_unlock(so
, 0);
154 * Call DLIL if we can. DLIL is much safer than calling the
157 result
= ifnet_output_raw(ifp
, np
->nd_proto_family
, m
);
164 /* Our input routine called from DLIL */
168 protocol_family_t proto_family
,
173 struct sockaddr_dl ndrvsrc
= {};
177 ndrvsrc
.sdl_len
= sizeof(struct sockaddr_dl
);
178 ndrvsrc
.sdl_family
= AF_NDRV
;
179 ndrvsrc
.sdl_index
= 0;
181 /* move packet from if queue to socket */
182 /* Should be media-independent */
183 ndrvsrc
.sdl_type
= IFT_ETHER
;
184 ndrvsrc
.sdl_nlen
= 0;
185 ndrvsrc
.sdl_alen
= 6;
186 ndrvsrc
.sdl_slen
= 0;
187 bcopy(frame_header
, &ndrvsrc
.sdl_data
, 6);
189 /* prepend the frame header */
190 m
= m_prepend(m
, ifnet_hdrlen(ifp
), M_NOWAIT
);
194 bcopy(frame_header
, m
->m_data
, ifnet_hdrlen(ifp
));
197 * We need to take the domain mutex before the list RW lock
199 LCK_MTX_ASSERT(ndrvdomain
->dom_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
200 lck_mtx_lock(ndrvdomain
->dom_mtx
);
202 np
= ndrv_find_inbound(ifp
, proto_family
);
204 lck_mtx_unlock(ndrvdomain
->dom_mtx
);
210 if (sbappendaddr(&(so
->so_rcv
), (struct sockaddr
*)&ndrvsrc
,
211 m
, NULL
, &error
) != 0) {
215 lck_mtx_unlock(ndrvdomain
->dom_mtx
);
217 return 0; /* radar 4030377 - always return 0 */
221 * Allocate an ndrv control block and some buffer space for the socket
224 ndrv_attach(struct socket
*so
, int proto
, __unused
struct proc
*p
)
227 struct ndrv_cb
*np
= sotondrvcb(so
);
229 if ((so
->so_state
& SS_PRIV
) == 0) {
234 printf("NDRV attach: %x, %x, %x\n", so
, proto
, np
);
237 if ((error
= soreserve(so
, ndrv_sendspace
, ndrv_recvspace
))) {
241 MALLOC(np
, struct ndrv_cb
*, sizeof(*np
), M_PCB
, M_WAITOK
);
245 so
->so_pcb
= (caddr_t
)np
;
246 bzero(np
, sizeof(*np
));
248 printf("NDRV attach: %x, %x, %x\n", so
, proto
, np
);
250 TAILQ_INIT(&np
->nd_dlist
);
251 np
->nd_signature
= NDRV_SIGNATURE
;
253 np
->nd_proto
.sp_family
= (uint16_t)SOCK_DOM(so
);
254 np
->nd_proto
.sp_protocol
= (uint16_t)proto
;
256 np
->nd_proto_family
= 0;
261 * Use the domain mutex to protect the list
263 LCK_MTX_ASSERT(ndrvdomain
->dom_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
264 lck_mtx_lock(ndrvdomain
->dom_mtx
);
266 TAILQ_INSERT_TAIL(&ndrvl
, np
, nd_next
);
268 lck_mtx_unlock(ndrvdomain
->dom_mtx
);
274 * Destroy state just before socket deallocation.
275 * Flush data or not depending on the options.
279 ndrv_detach(struct socket
*so
)
281 struct ndrv_cb
*np
= sotondrvcb(so
);
286 return ndrv_do_detach(np
);
291 * If a socket isn't bound to a single address,
292 * the ndrv input routine will hand it anything
293 * within that protocol family (assuming there's
294 * nothing else around it should go to).
296 * Don't expect this to be used.
300 ndrv_connect(struct socket
*so
, struct sockaddr
*nam
, __unused
struct proc
*p
)
302 struct ndrv_cb
*np
= sotondrvcb(so
);
312 /* Allocate memory to store the remote address */
313 MALLOC(np
->nd_faddr
, struct sockaddr_ndrv
*,
314 nam
->sa_len
, M_IFADDR
, M_WAITOK
);
315 if (np
->nd_faddr
== NULL
) {
319 bcopy((caddr_t
) nam
, (caddr_t
) np
->nd_faddr
, nam
->sa_len
);
325 ndrv_event(struct ifnet
*ifp
, __unused protocol_family_t protocol
,
326 const struct kev_msg
*event
)
328 if (event
->vendor_code
== KEV_VENDOR_APPLE
&&
329 event
->kev_class
== KEV_NETWORK_CLASS
&&
330 event
->kev_subclass
== KEV_DL_SUBCLASS
&&
331 event
->event_code
== KEV_DL_IF_DETACHING
) {
332 LCK_MTX_ASSERT(ndrvdomain
->dom_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
333 lck_mtx_lock(ndrvdomain
->dom_mtx
);
334 ndrv_handle_ifp_detach(ifnet_family(ifp
), ifp
->if_unit
);
335 lck_mtx_unlock(ndrvdomain
->dom_mtx
);
340 * This is the "driver open" hook - we 'bind' to the
342 * Here's where we latch onto the driver.
345 ndrv_bind(struct socket
*so
, struct sockaddr
*nam
, __unused
struct proc
*p
)
347 struct sockaddr_ndrv
*sa
= (struct sockaddr_ndrv
*) nam
;
353 if (TAILQ_EMPTY(&ifnet_head
)) {
354 return EADDRNOTAVAIL
; /* Quick sanity check */
362 return EINVAL
; /* XXX */
364 /* I think we just latch onto a copy here; the caller frees */
365 np
->nd_laddr
= _MALLOC(sizeof(struct sockaddr_ndrv
), M_IFADDR
, M_WAITOK
);
366 if (np
->nd_laddr
== NULL
) {
369 bcopy((caddr_t
) sa
, (caddr_t
) np
->nd_laddr
, sizeof(struct sockaddr_ndrv
));
370 dname
= (char *) sa
->snd_name
;
371 np
->nd_laddr
->snd_len
= sizeof(struct sockaddr_ndrv
);
372 if (*dname
== '\0') {
376 printf("NDRV bind: %x, %x, %s\n", so
, np
, dname
);
378 /* Track down the driver and its ifnet structure.
379 * There's no internal call for this so we have to dup the code
382 ifnet_head_lock_shared();
383 TAILQ_FOREACH(ifp
, &ifnet_head
, if_link
) {
384 if (strncmp(ifp
->if_xname
, dname
, IFNAMSIZ
) == 0) {
391 return EADDRNOTAVAIL
;
394 // PPP doesn't support PF_NDRV.
395 if (ifnet_family(ifp
) != APPLE_IF_FAM_PPP
) {
396 /* NDRV on this interface */
397 struct ifnet_attach_proto_param ndrv_proto
;
399 bzero(&ndrv_proto
, sizeof(ndrv_proto
));
400 ndrv_proto
.event
= ndrv_event
;
402 /* We aren't worried about double attaching, that should just return an error */
403 socket_unlock(so
, 0);
404 result
= ifnet_attach_protocol(ifp
, PF_NDRV
, &ndrv_proto
);
406 if (result
&& result
!= EEXIST
) {
409 np
->nd_proto_family
= PF_NDRV
;
411 np
->nd_proto_family
= 0;
415 np
->nd_family
= ifnet_family(ifp
);
416 np
->nd_unit
= ifp
->if_unit
;
422 ndrv_disconnect(struct socket
*so
)
424 struct ndrv_cb
*np
= sotondrvcb(so
);
430 if (np
->nd_faddr
== 0) {
434 ndrv_do_disconnect(np
);
439 * Mark the connection as being incapable of further input.
442 ndrv_shutdown(struct socket
*so
)
444 LCK_MTX_ASSERT(ndrvdomain
->dom_mtx
, LCK_MTX_ASSERT_OWNED
);
450 * Ship a packet out. The ndrv output will pass it
451 * to the appropriate driver. The really tricky part
452 * is the destination address...
455 ndrv_send(struct socket
*so
, __unused
int flags
, struct mbuf
*m
,
456 __unused
struct sockaddr
*addr
, struct mbuf
*control
,
457 __unused
struct proc
*p
)
461 if (control
!= NULL
) {
466 error
= ndrv_output(m
, so
);
473 ndrv_abort(struct socket
*so
)
475 struct ndrv_cb
*np
= sotondrvcb(so
);
481 ndrv_do_disconnect(np
);
486 ndrv_sockaddr(struct socket
*so
, struct sockaddr
**nam
)
488 struct ndrv_cb
*np
= sotondrvcb(so
);
495 if (np
->nd_laddr
== 0) {
499 len
= np
->nd_laddr
->snd_len
;
500 MALLOC(*nam
, struct sockaddr
*, len
, M_SONAME
, M_WAITOK
);
504 bcopy((caddr_t
)np
->nd_laddr
, *nam
,
511 ndrv_peeraddr(struct socket
*so
, struct sockaddr
**nam
)
513 struct ndrv_cb
*np
= sotondrvcb(so
);
520 if (np
->nd_faddr
== 0) {
524 len
= np
->nd_faddr
->snd_len
;
525 MALLOC(*nam
, struct sockaddr
*, len
, M_SONAME
, M_WAITOK
);
529 bcopy((caddr_t
)np
->nd_faddr
, *nam
,
538 ndrv_ctloutput(struct socket
*so
, struct sockopt
*sopt
)
540 struct ndrv_cb
*np
= sotondrvcb(so
);
543 switch (sopt
->sopt_name
) {
544 case NDRV_DELDMXSPEC
: /* Delete current spec */
545 /* Verify no parameter was passed */
546 if (sopt
->sopt_val
!= 0 || sopt
->sopt_valsize
!= 0) {
548 * We don't support deleting a specific demux, it's
553 error
= ndrv_delspec(np
);
555 case NDRV_SETDMXSPEC
: /* Set protocol spec */
556 error
= ndrv_setspec(np
, sopt
);
558 case NDRV_ADDMULTICAST
:
559 error
= ndrv_do_add_multicast(np
, sopt
);
561 case NDRV_DELMULTICAST
:
562 error
= ndrv_do_remove_multicast(np
, sopt
);
568 log(LOG_WARNING
, "NDRV CTLOUT: %x returns %d\n", sopt
->sopt_name
,
575 ndrv_do_detach(struct ndrv_cb
*np
)
577 struct ndrv_cb
* cur_np
= NULL
;
578 struct socket
*so
= np
->nd_socket
;
583 printf("NDRV detach: %x, %x\n", so
, np
);
585 ndrv_remove_all_multicast(np
);
587 /* Remove from the linked list of control blocks */
588 LCK_MTX_ASSERT(ndrvdomain
->dom_mtx
, LCK_MTX_ASSERT_OWNED
);
589 TAILQ_REMOVE(&ndrvl
, np
, nd_next
);
593 u_int32_t proto_family
= np
->nd_proto_family
;
595 if (proto_family
!= PF_NDRV
&& proto_family
!= 0) {
596 socket_unlock(so
, 0);
597 ifnet_detach_protocol(ifp
, proto_family
);
601 /* Check if this is the last socket attached to this interface */
602 LCK_MTX_ASSERT(ndrvdomain
->dom_mtx
, LCK_MTX_ASSERT_OWNED
);
603 TAILQ_FOREACH(cur_np
, &ndrvl
, nd_next
) {
604 if (cur_np
->nd_family
== np
->nd_family
&&
605 cur_np
->nd_unit
== np
->nd_unit
) {
610 /* If there are no other interfaces, detach PF_NDRV from the interface */
611 if (cur_np
== NULL
) {
612 socket_unlock(so
, 0);
613 ifnet_detach_protocol(ifp
, PF_NDRV
);
617 if (np
->nd_laddr
!= NULL
) {
618 FREE(np
->nd_laddr
, M_IFADDR
);
623 so
->so_flags
|= SOF_PCBCLEARING
;
629 ndrv_do_disconnect(struct ndrv_cb
*np
)
631 struct socket
* so
= np
->nd_socket
;
633 printf("NDRV disconnect: %x\n", np
);
636 FREE(np
->nd_faddr
, M_IFADDR
);
640 * A multipath subflow socket would have its SS_NOFDREF set by default,
641 * so check for SOF_MP_SUBFLOW socket flag before detaching the PCB;
642 * when the socket is closed for real, SOF_MP_SUBFLOW would be cleared.
644 if (!(so
->so_flags
& SOF_MP_SUBFLOW
) && (so
->so_state
& SS_NOFDREF
)) {
647 soisdisconnected(so
);
654 * When closing, dump any enqueued mbufs.
657 ndrv_flushq(struct ifqueue
*q
)
674 ndrv_setspec(struct ndrv_cb
*np
, struct sockopt
*sopt
)
676 struct ifnet_attach_proto_param proto_param
;
677 struct ndrv_protocol_desc ndrvSpec
;
678 struct ndrv_demux_desc
* ndrvDemux
= NULL
;
680 struct socket
* so
= np
->nd_socket
;
681 user_addr_t user_addr
;
683 /* Sanity checking */
684 if (np
->nd_proto_family
!= PF_NDRV
) {
687 if (np
->nd_if
== NULL
) {
691 /* Copy the ndrvSpec */
692 if (proc_is64bit(sopt
->sopt_p
)) {
693 struct ndrv_protocol_desc64 ndrvSpec64
;
695 if (sopt
->sopt_valsize
!= sizeof(ndrvSpec64
)) {
699 error
= sooptcopyin(sopt
, &ndrvSpec64
, sizeof(ndrvSpec64
), sizeof(ndrvSpec64
));
704 ndrvSpec
.version
= ndrvSpec64
.version
;
705 ndrvSpec
.protocol_family
= ndrvSpec64
.protocol_family
;
706 ndrvSpec
.demux_count
= ndrvSpec64
.demux_count
;
708 user_addr
= CAST_USER_ADDR_T(ndrvSpec64
.demux_list
);
710 struct ndrv_protocol_desc32 ndrvSpec32
;
712 if (sopt
->sopt_valsize
!= sizeof(ndrvSpec32
)) {
716 error
= sooptcopyin(sopt
, &ndrvSpec32
, sizeof(ndrvSpec32
), sizeof(ndrvSpec32
));
721 ndrvSpec
.version
= ndrvSpec32
.version
;
722 ndrvSpec
.protocol_family
= ndrvSpec32
.protocol_family
;
723 ndrvSpec
.demux_count
= ndrvSpec32
.demux_count
;
725 user_addr
= CAST_USER_ADDR_T(ndrvSpec32
.demux_list
);
728 /* Verify the parameter */
729 if (ndrvSpec
.version
> NDRV_PROTOCOL_DESC_VERS
) {
730 return ENOTSUP
; // version is too new!
731 } else if (ndrvSpec
.version
< 1) {
732 return EINVAL
; // version is not valid
733 } else if (ndrvSpec
.demux_count
> NDRV_PROTODEMUX_COUNT
|| ndrvSpec
.demux_count
== 0) {
734 return EINVAL
; // demux_count is not valid
736 bzero(&proto_param
, sizeof(proto_param
));
737 proto_param
.demux_count
= ndrvSpec
.demux_count
;
739 /* Allocate storage for demux array */
740 MALLOC(ndrvDemux
, struct ndrv_demux_desc
*, proto_param
.demux_count
*
741 sizeof(struct ndrv_demux_desc
), M_TEMP
, M_WAITOK
);
742 if (ndrvDemux
== NULL
) {
746 /* Allocate enough ifnet_demux_descs */
747 MALLOC(proto_param
.demux_array
, struct ifnet_demux_desc
*,
748 sizeof(*proto_param
.demux_array
) * ndrvSpec
.demux_count
,
750 if (proto_param
.demux_array
== NULL
) {
755 /* Copy the ndrv demux array from userland */
756 error
= copyin(user_addr
, ndrvDemux
,
757 ndrvSpec
.demux_count
* sizeof(struct ndrv_demux_desc
));
758 ndrvSpec
.demux_list
= ndrvDemux
;
762 /* At this point, we've at least got enough bytes to start looking around */
763 u_int32_t demuxOn
= 0;
765 proto_param
.demux_count
= ndrvSpec
.demux_count
;
766 proto_param
.input
= ndrv_input
;
767 proto_param
.event
= ndrv_event
;
769 for (demuxOn
= 0; demuxOn
< ndrvSpec
.demux_count
; demuxOn
++) {
770 /* Convert an ndrv_demux_desc to a ifnet_demux_desc */
771 error
= ndrv_to_ifnet_demux(&ndrvSpec
.demux_list
[demuxOn
],
772 &proto_param
.demux_array
[demuxOn
]);
780 /* We've got all our ducks lined up...lets attach! */
781 socket_unlock(so
, 0);
782 error
= ifnet_attach_protocol(np
->nd_if
, ndrvSpec
.protocol_family
,
786 np
->nd_proto_family
= ndrvSpec
.protocol_family
;
790 /* Free any memory we've allocated */
791 if (proto_param
.demux_array
) {
792 FREE(proto_param
.demux_array
, M_TEMP
);
795 FREE(ndrvDemux
, M_TEMP
);
803 ndrv_to_ifnet_demux(struct ndrv_demux_desc
* ndrv
, struct ifnet_demux_desc
* ifdemux
)
805 bzero(ifdemux
, sizeof(*ifdemux
));
807 if (ndrv
->type
< DLIL_DESC_ETYPE2
) {
808 /* using old "type", not supported */
812 if (ndrv
->length
> 28) {
816 ifdemux
->type
= ndrv
->type
;
817 ifdemux
->data
= ndrv
->data
.other
;
818 ifdemux
->datalen
= ndrv
->length
;
824 ndrv_delspec(struct ndrv_cb
*np
)
828 if (np
->nd_proto_family
== PF_NDRV
||
829 np
->nd_proto_family
== 0) {
833 /* Detach the protocol */
834 result
= ifnet_detach_protocol(np
->nd_if
, np
->nd_proto_family
);
835 np
->nd_proto_family
= PF_NDRV
;
841 ndrv_find_inbound(struct ifnet
*ifp
, u_int32_t protocol
)
845 LCK_MTX_ASSERT(ndrvdomain
->dom_mtx
, LCK_MTX_ASSERT_OWNED
);
847 if (protocol
== PF_NDRV
) {
851 TAILQ_FOREACH(np
, &ndrvl
, nd_next
) {
852 if (np
->nd_proto_family
== protocol
&&
862 ndrv_handle_ifp_detach(u_int32_t family
, short unit
)
865 struct ifnet
*ifp
= NULL
;
868 /* Find all sockets using this interface. */
869 TAILQ_FOREACH(np
, &ndrvl
, nd_next
) {
870 if (np
->nd_family
== family
&&
871 np
->nd_unit
== unit
) {
872 /* This cb is using the detaching interface, but not for long. */
873 /* Let the protocol go */
875 if (np
->nd_proto_family
!= 0) {
879 /* Delete the multicasts first */
880 ndrv_remove_all_multicast(np
);
882 /* Disavow all knowledge of the ifp */
888 /* Make sure sending returns an error */
889 LCK_MTX_ASSERT(ndrvdomain
->dom_mtx
, LCK_MTX_ASSERT_OWNED
);
895 /* Unregister our protocol */
897 ifnet_detach_protocol(ifp
, PF_NDRV
);
902 ndrv_do_add_multicast(struct ndrv_cb
*np
, struct sockopt
*sopt
)
904 struct ndrv_multiaddr
* ndrv_multi
;
907 if (sopt
->sopt_val
== 0 || sopt
->sopt_valsize
< 2 ||
908 sopt
->sopt_level
!= SOL_NDRVPROTO
|| sopt
->sopt_valsize
> SOCK_MAXADDRLEN
) {
911 if (np
->nd_if
== NULL
) {
914 if (!(np
->nd_dlist_cnt
< ndrv_multi_max_count
)) {
919 MALLOC(ndrv_multi
, struct ndrv_multiaddr
*, sizeof(struct ndrv_multiaddr
) -
920 sizeof(struct sockaddr
) + sopt
->sopt_valsize
, M_IFADDR
, M_WAITOK
);
921 if (ndrv_multi
== NULL
) {
925 // Copy in the address
926 result
= copyin(sopt
->sopt_val
, &ndrv_multi
->addr
, sopt
->sopt_valsize
);
928 // Validate the sockaddr
929 if (result
== 0 && sopt
->sopt_valsize
!= ndrv_multi
->addr
.sa_len
) {
933 if (result
== 0 && ndrv_have_multicast(np
, &ndrv_multi
->addr
)) {
938 // Try adding the multicast
939 result
= ifnet_add_multicast(np
->nd_if
, &ndrv_multi
->addr
,
944 // Add to our linked list
945 ndrv_multi
->next
= np
->nd_multiaddrs
;
946 np
->nd_multiaddrs
= ndrv_multi
;
949 // Free up the memory, something went wrong
950 FREE(ndrv_multi
, M_IFADDR
);
957 ndrv_do_remove_multicast(struct ndrv_cb
*np
, struct sockopt
*sopt
)
959 struct sockaddr
* multi_addr
;
960 struct ndrv_multiaddr
* ndrv_entry
= NULL
;
963 if (sopt
->sopt_val
== 0 || sopt
->sopt_valsize
< 2 ||
964 sopt
->sopt_level
!= SOL_NDRVPROTO
) {
967 if (np
->nd_if
== NULL
|| np
->nd_dlist_cnt
== 0) {
972 MALLOC(multi_addr
, struct sockaddr
*, sopt
->sopt_valsize
,
974 if (multi_addr
== NULL
) {
978 // Copy in the address
979 result
= copyin(sopt
->sopt_val
, multi_addr
, sopt
->sopt_valsize
);
981 // Validate the sockaddr
982 if (result
== 0 && sopt
->sopt_valsize
!= multi_addr
->sa_len
) {
987 /* Find the old entry */
988 ndrv_entry
= ndrv_have_multicast(np
, multi_addr
);
990 if (ndrv_entry
== NULL
) {
996 // Try deleting the multicast
997 result
= ifnet_remove_multicast(ndrv_entry
->ifma
);
1001 // Remove from our linked list
1002 struct ndrv_multiaddr
* cur
= np
->nd_multiaddrs
;
1004 ifmaddr_release(ndrv_entry
->ifma
);
1006 if (cur
== ndrv_entry
) {
1007 np
->nd_multiaddrs
= cur
->next
;
1009 for (cur
= cur
->next
; cur
!= NULL
; cur
= cur
->next
) {
1010 if (cur
->next
== ndrv_entry
) {
1011 cur
->next
= cur
->next
->next
;
1020 FREE(ndrv_entry
, M_IFADDR
);
1022 FREE(multi_addr
, M_TEMP
);
1027 static struct ndrv_multiaddr
*
1028 ndrv_have_multicast(struct ndrv_cb
*np
, struct sockaddr
* inAddr
)
1030 struct ndrv_multiaddr
* cur
;
1031 for (cur
= np
->nd_multiaddrs
; cur
!= NULL
; cur
= cur
->next
) {
1032 if ((inAddr
->sa_len
== cur
->addr
.sa_len
) &&
1033 (bcmp(&cur
->addr
, inAddr
, inAddr
->sa_len
) == 0)) {
1043 ndrv_remove_all_multicast(struct ndrv_cb
* np
)
1045 struct ndrv_multiaddr
* cur
;
1047 if (np
->nd_if
!= NULL
) {
1048 while (np
->nd_multiaddrs
!= NULL
) {
1049 cur
= np
->nd_multiaddrs
;
1050 np
->nd_multiaddrs
= cur
->next
;
1052 ifnet_remove_multicast(cur
->ifma
);
1053 ifmaddr_release(cur
->ifma
);
1054 FREE(cur
, M_IFADDR
);
1059 static struct pr_usrreqs ndrv_usrreqs
= {
1060 .pru_abort
= ndrv_abort
,
1061 .pru_attach
= ndrv_attach
,
1062 .pru_bind
= ndrv_bind
,
1063 .pru_connect
= ndrv_connect
,
1064 .pru_detach
= ndrv_detach
,
1065 .pru_disconnect
= ndrv_disconnect
,
1066 .pru_peeraddr
= ndrv_peeraddr
,
1067 .pru_send
= ndrv_send
,
1068 .pru_shutdown
= ndrv_shutdown
,
1069 .pru_sockaddr
= ndrv_sockaddr
,
1070 .pru_sosend
= sosend
,
1071 .pru_soreceive
= soreceive
,
1074 static struct protosw ndrvsw
[] = {
1076 .pr_type
= SOCK_RAW
,
1077 .pr_protocol
= NDRVPROTO_NDRV
,
1078 .pr_flags
= PR_ATOMIC
| PR_ADDR
,
1079 .pr_output
= ndrv_output
,
1080 .pr_ctloutput
= ndrv_ctloutput
,
1081 .pr_usrreqs
= &ndrv_usrreqs
,
1085 static int ndrv_proto_count
= (sizeof(ndrvsw
) / sizeof(struct protosw
));
1087 struct domain ndrvdomain_s
= {
1088 .dom_family
= PF_NDRV
,
1089 .dom_name
= "NetDriver",
1090 .dom_init
= ndrv_dominit
,
1094 ndrv_dominit(struct domain
*dp
)
1099 VERIFY(!(dp
->dom_flags
& DOM_INITIALIZED
));
1100 VERIFY(ndrvdomain
== NULL
);
1104 for (i
= 0, pr
= &ndrvsw
[0]; i
< ndrv_proto_count
; i
++, pr
++) {
1105 net_add_proto(pr
, dp
, 1);