2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* Copyright (C) 1999 Apple Computer, Inc. */
28 * NKE management domain - allows control connections to
29 * an NKE and to read/write data.
31 * Christophe Allie, 010928
32 * Justin C. Walker, 990319
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/syslog.h>
39 #include <sys/socket.h>
40 #include <sys/socketvar.h>
41 #include <sys/protosw.h>
42 #include <sys/domain.h>
43 #include <sys/malloc.h>
45 #include <net/kext_net.h>
46 #include <sys/sys_domain.h>
47 #include <sys/kern_event.h>
48 #include <sys/kern_control.h>
49 #include <net/if_var.h>
51 #include <mach/vm_types.h>
52 #include <mach/kmod.h>
54 #include <kern/thread.h>
58 * Definitions and vars for we support
61 #define CTL_SENDSIZE (2 * 1024) /* default buffer size */
62 #define CTL_RECVSIZE (8 * 1024) /* default buffer size */
65 internal structure maintained for each register controller
69 TAILQ_ENTRY(ctl
) next
; /* controller chain */
70 struct socket
*skt
; /* current controlling socket */
72 /* controller information provided when registering */
73 u_int32_t id
; /* unique nke identifier, provided by DTS */
74 u_int32_t unit
; /* unit number for use by the nke */
75 void *userdata
; /* for private use by nke */
77 /* misc communication information */
78 u_int32_t flags
; /* support flags */
79 u_int32_t recvbufsize
; /* request more than the default buffer size */
80 u_int32_t sendbufsize
; /* request more than the default buffer size */
82 /* Dispatch functions */
83 int (*connect
)(kern_ctl_ref
, void *); /* Make contact */
84 void (*disconnect
)(kern_ctl_ref
, void *); /* Break contact */
85 int (*write
) (kern_ctl_ref
, void *, struct mbuf
*); /* Send data to nke */
86 int (*set
)(kern_ctl_ref
, void *, int, void *, size_t ); /* set ctl configuration */
87 int (*get
)(kern_ctl_ref
, void *, int, void *, size_t *); /* get ctl configuration */
91 /* all the controllers are chained */
92 TAILQ_HEAD(, ctl
) ctl_head
;
94 int ctl_attach(struct socket
*, int, struct proc
*);
95 int ctl_connect(struct socket
*, struct sockaddr
*, struct proc
*);
96 int ctl_disconnect(struct socket
*);
97 int ctl_ioctl(struct socket
*so
, u_long cmd
, caddr_t data
,
98 struct ifnet
*ifp
, struct proc
*p
);
99 int ctl_send(struct socket
*, int, struct mbuf
*,
100 struct sockaddr
*, struct mbuf
*, struct proc
*);
101 int ctl_ctloutput(struct socket
*, struct sockopt
*);
103 struct ctl
*ctl_find(u_int32_t
, u_int32_t unit
);
104 void ctl_post_msg(u_long event_code
, u_int32_t id
, u_int32_t unit
);
107 struct pr_usrreqs ctl_usrreqs
=
109 pru_abort_notsupp
, pru_accept_notsupp
, ctl_attach
, pru_bind_notsupp
,
110 ctl_connect
, pru_connect2_notsupp
, ctl_ioctl
, pru_detach_notsupp
,
111 ctl_disconnect
, pru_listen_notsupp
, pru_peeraddr_notsupp
,
112 pru_rcvd_notsupp
, pru_rcvoob_notsupp
, ctl_send
,
113 pru_sense_null
, pru_shutdown_notsupp
, pru_sockaddr_notsupp
,
114 sosend
, soreceive
, sopoll
117 struct protosw ctlsw
=
119 SOCK_DGRAM
, &systemdomain
, SYSPROTO_CONTROL
, PR_ATOMIC
|PR_CONNREQUIRED
,
120 NULL
, NULL
, NULL
, ctl_ctloutput
,
122 NULL
, NULL
, NULL
, NULL
, &ctl_usrreqs
126 * Install the protosw's for the NKE manager.
129 kern_control_init(void)
133 retval
= net_add_proto(&ctlsw
, &systemdomain
);
135 log(LOG_WARNING
, "Can't install Kernel Controller Manager (%d)\n", retval
);
139 TAILQ_INIT(&ctl_head
);
141 return(KERN_SUCCESS
);
146 * Kernel Controller user-request functions
149 ctl_attach (struct socket
*so
, int proto
, struct proc
*p
)
152 * attach function must exist and succeed
153 * detach not necessary since we use
154 * connect/disconnect to handle so_pcb
161 ctl_connect(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
165 struct sockaddr_ctl
*sa
= (struct sockaddr_ctl
*)nam
;
167 ctl
= ctl_find(sa
->sc_id
, sa
->sc_unit
);
169 return(EADDRNOTAVAIL
);
171 if (ctl
->skt
!= NULL
)
174 error
= soreserve(so
,
175 ctl
->sendbufsize
? ctl
->sendbufsize
: CTL_SENDSIZE
,
176 ctl
->recvbufsize
? ctl
->recvbufsize
: CTL_RECVSIZE
);
182 if (ctl
->flags
& CTL_FLAG_PRIVILEGED
) {
185 if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
190 error
= (*ctl
->connect
)(ctl
, ctl
->userdata
);
196 so
->so_pcb
= (caddr_t
)ctl
;
203 ctl_disconnect(struct socket
*so
)
207 if ((ctl
= (struct ctl
*)so
->so_pcb
))
210 (*ctl
->disconnect
)(ctl
, ctl
->userdata
);
213 soisdisconnected(so
);
219 ctl_send(struct socket
*so
, int flags
, struct mbuf
*m
,
220 struct sockaddr
*addr
, struct mbuf
*control
,
223 struct ctl
*ctl
= (struct ctl
*)so
->so_pcb
;
230 error
= (*ctl
->write
)(ctl
, ctl
->userdata
, m
);
236 ctl_enqueuembuf(void *ctlref
, struct mbuf
*m
, u_int32_t flags
)
238 struct ctl
*ctl
= (struct ctl
*)ctlref
;
239 struct socket
*so
= (struct socket
*)ctl
->skt
;
241 if (ctl
== NULL
) /* sanity check */
247 if (sbspace(&so
->so_rcv
) < m
->m_pkthdr
.len
)
250 sbappend(&so
->so_rcv
, m
);
251 if ((flags
& CTL_DATA_NOWAKEUP
) == 0)
257 ctl_enqueuedata(void *ctlref
, void *data
, size_t len
, u_int32_t flags
)
259 struct ctl
*ctl
= (struct ctl
*)ctlref
;
260 struct socket
*so
= (struct socket
*)ctl
->skt
;
263 if (ctl
== NULL
) /* sanity check */
272 if (sbspace(&so
->so_rcv
) < len
)
275 if ((m
= m_gethdr(M_NOWAIT
, MT_DATA
)) == NULL
)
280 if (!(m
->m_flags
& M_EXT
)) {
286 bcopy(data
, mtod(m
, void *), len
);
288 sbappend(&so
->so_rcv
, m
);
289 if ((flags
& CTL_DATA_NOWAKEUP
) == 0)
295 ctl_ctloutput(struct socket
*so
, struct sockopt
*sopt
)
297 struct ctl
*ctl
= (struct ctl
*)so
->so_pcb
;
302 if (sopt
->sopt_level
!= SYSPROTO_CONTROL
) {
309 switch (sopt
->sopt_dir
) {
311 if (ctl
->set
== NULL
)
313 MALLOC(data
, void *, sopt
->sopt_valsize
, M_TEMP
, M_WAITOK
);
316 error
= sooptcopyin(sopt
, data
, sopt
->sopt_valsize
, sopt
->sopt_valsize
);
318 error
= (*ctl
->set
)(ctl
, ctl
->userdata
, sopt
->sopt_name
, data
, sopt
->sopt_valsize
);
323 if (ctl
->get
== NULL
)
326 if (sopt
->sopt_valsize
&& sopt
->sopt_val
) {
327 MALLOC(data
, void *, sopt
->sopt_valsize
, M_TEMP
, M_WAITOK
);
331 len
= sopt
->sopt_valsize
;
332 error
= (*ctl
->get
)(ctl
, ctl
->userdata
, sopt
->sopt_name
, data
, &len
);
335 error
= sooptcopyout(sopt
, data
, len
);
337 sopt
->sopt_valsize
= len
;
346 int ctl_ioctl(struct socket
*so
, u_long cmd
, caddr_t data
,
347 struct ifnet
*ifp
, struct proc
*p
)
349 int error
= ENOTSUP
, s
, n
;
350 struct ctl
*ctl
= (struct ctl
*)so
->so_pcb
;
353 /* get the number of controllers */
356 TAILQ_FOREACH(ctl
, &ctl_head
, next
)
358 *(u_int32_t
*)data
= n
;
363 /* add controls to get list of NKEs */
371 * Register/unregister a NKE
374 ctl_register(struct kern_ctl_reg
*userctl
, void *userdata
, kern_ctl_ref
*ctlref
)
378 if (userctl
== NULL
) /* sanity check */
381 ctl
= ctl_find(userctl
->ctl_id
, userctl
->ctl_unit
);
385 MALLOC(ctl
, struct ctl
*, sizeof(*ctl
), M_TEMP
, M_WAITOK
);
389 bzero((char *)ctl
, sizeof(*ctl
));
391 ctl
->id
= userctl
->ctl_id
;
392 ctl
->unit
= userctl
->ctl_unit
;
393 ctl
->flags
= userctl
->ctl_flags
;
394 ctl
->sendbufsize
= userctl
->ctl_sendsize
;
395 ctl
->recvbufsize
= userctl
->ctl_recvsize
;
396 ctl
->userdata
= userdata
;
397 ctl
->connect
= userctl
->ctl_connect
;
398 ctl
->disconnect
= userctl
->ctl_disconnect
;
399 ctl
->write
= userctl
->ctl_write
;
400 ctl
->set
= userctl
->ctl_set
;
401 ctl
->get
= userctl
->ctl_get
;
403 TAILQ_INSERT_TAIL(&ctl_head
, ctl
, next
);
407 ctl_post_msg(KEV_CTL_REGISTERED
, ctl
->id
, ctl
->unit
);
412 ctl_deregister(void *ctlref
)
414 struct ctl
*ctl
= (struct ctl
*)ctlref
;
417 if (ctl
== NULL
) /* sanity check */
420 TAILQ_REMOVE(&ctl_head
, ctl
, next
);
423 ctl
->skt
->so_pcb
= 0;
424 soisdisconnected(ctl
->skt
);
427 ctl_post_msg(KEV_CTL_DEREGISTERED
, ctl
->id
, ctl
->unit
);
436 ctl_find(u_int32_t id
, u_int32_t unit
)
440 TAILQ_FOREACH(ctl
, &ctl_head
, next
)
441 if ((ctl
->id
== id
) && (ctl
->unit
== unit
))
447 void ctl_post_msg(u_long event_code
, u_int32_t id
, u_int32_t unit
)
449 struct ctl_event_data ctl_ev_data
;
450 struct kev_msg ev_msg
;
452 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
454 ev_msg
.kev_class
= KEV_SYSTEM_CLASS
;
455 ev_msg
.kev_subclass
= KEV_CTL_SUBCLASS
;
456 ev_msg
.event_code
= event_code
;
458 /* common nke subclass data */
459 bzero(&ctl_ev_data
, sizeof(ctl_ev_data
));
460 ctl_ev_data
.ctl_id
= id
;
461 ctl_ev_data
.ctl_unit
= unit
;
462 ev_msg
.dv
[0].data_ptr
= &ctl_ev_data
;
463 ev_msg
.dv
[0].data_length
= sizeof(ctl_ev_data
);
465 ev_msg
.dv
[1].data_length
= 0;
467 kev_post_msg(&ev_msg
);