2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (C) 1999 Apple Computer, Inc. */
25 * NKE management domain - allows control connections to
26 * an NKE and to read/write data.
28 * Christophe Allie, 010928
29 * Justin C. Walker, 990319
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/syslog.h>
36 #include <sys/socket.h>
37 #include <sys/socketvar.h>
38 #include <sys/protosw.h>
39 #include <sys/domain.h>
40 #include <sys/malloc.h>
42 #include <net/kext_net.h>
43 #include <sys/sys_domain.h>
44 #include <sys/kern_event.h>
45 #include <sys/kern_control.h>
46 #include <net/if_var.h>
48 #include <mach/vm_types.h>
49 #include <mach/kmod.h>
51 #include <kern/thread.h>
55 * Definitions and vars for we support
58 #define CTL_SENDSIZE (2 * 1024) /* default buffer size */
59 #define CTL_RECVSIZE (8 * 1024) /* default buffer size */
62 internal structure maintained for each register controller
66 TAILQ_ENTRY(ctl
) next
; /* controller chain */
67 struct socket
*skt
; /* current controlling socket */
69 /* controller information provided when registering */
70 u_int32_t id
; /* unique nke identifier, provided by DTS */
71 u_int32_t unit
; /* unit number for use by the nke */
72 void *userdata
; /* for private use by nke */
74 /* misc communication information */
75 u_int32_t flags
; /* support flags */
76 u_int32_t recvbufsize
; /* request more than the default buffer size */
77 u_int32_t sendbufsize
; /* request more than the default buffer size */
79 /* Dispatch functions */
80 int (*connect
)(kern_ctl_ref
, void *); /* Make contact */
81 void (*disconnect
)(kern_ctl_ref
, void *); /* Break contact */
82 int (*write
) (kern_ctl_ref
, void *, struct mbuf
*); /* Send data to nke */
83 int (*set
)(kern_ctl_ref
, void *, int, void *, size_t ); /* set ctl configuration */
84 int (*get
)(kern_ctl_ref
, void *, int, void *, size_t *); /* get ctl configuration */
88 /* all the controllers are chained */
89 TAILQ_HEAD(, ctl
) ctl_head
;
91 int ctl_attach(struct socket
*, int, struct proc
*);
92 int ctl_connect(struct socket
*, struct sockaddr
*, struct proc
*);
93 int ctl_disconnect(struct socket
*);
94 int ctl_ioctl(struct socket
*so
, u_long cmd
, caddr_t data
,
95 struct ifnet
*ifp
, struct proc
*p
);
96 int ctl_send(struct socket
*, int, struct mbuf
*,
97 struct sockaddr
*, struct mbuf
*, struct proc
*);
98 int ctl_ctloutput(struct socket
*, struct sockopt
*);
100 struct ctl
*ctl_find(u_int32_t
, u_int32_t unit
);
101 void ctl_post_msg(u_long event_code
, u_int32_t id
, u_int32_t unit
);
104 struct pr_usrreqs ctl_usrreqs
=
106 pru_abort_notsupp
, pru_accept_notsupp
, ctl_attach
, pru_bind_notsupp
,
107 ctl_connect
, pru_connect2_notsupp
, ctl_ioctl
, pru_detach_notsupp
,
108 ctl_disconnect
, pru_listen_notsupp
, pru_peeraddr_notsupp
,
109 pru_rcvd_notsupp
, pru_rcvoob_notsupp
, ctl_send
,
110 pru_sense_null
, pru_shutdown_notsupp
, pru_sockaddr_notsupp
,
111 sosend
, soreceive
, sopoll
114 struct protosw ctlsw
=
116 SOCK_DGRAM
, &systemdomain
, SYSPROTO_CONTROL
, PR_ATOMIC
|PR_CONNREQUIRED
,
117 NULL
, NULL
, NULL
, ctl_ctloutput
,
119 NULL
, NULL
, NULL
, NULL
, &ctl_usrreqs
123 * Install the protosw's for the NKE manager.
126 kern_control_init(void)
130 retval
= net_add_proto(&ctlsw
, &systemdomain
);
132 log(LOG_WARNING
, "Can't install Kernel Controller Manager (%d)\n", retval
);
136 TAILQ_INIT(&ctl_head
);
138 return(KERN_SUCCESS
);
143 * Kernel Controller user-request functions
146 ctl_attach (struct socket
*so
, int proto
, struct proc
*p
)
149 * attach function must exist and succeed
150 * detach not necessary since we use
151 * connect/disconnect to handle so_pcb
158 ctl_connect(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
162 struct sockaddr_ctl
*sa
= (struct sockaddr_ctl
*)nam
;
164 ctl
= ctl_find(sa
->sc_id
, sa
->sc_unit
);
166 return(EADDRNOTAVAIL
);
168 if (ctl
->skt
!= NULL
)
171 error
= soreserve(so
,
172 ctl
->sendbufsize
? ctl
->sendbufsize
: CTL_SENDSIZE
,
173 ctl
->recvbufsize
? ctl
->recvbufsize
: CTL_RECVSIZE
);
179 if (ctl
->flags
& CTL_FLAG_PRIVILEGED
) {
182 if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
187 error
= (*ctl
->connect
)(ctl
, ctl
->userdata
);
193 so
->so_pcb
= (caddr_t
)ctl
;
200 ctl_disconnect(struct socket
*so
)
204 if ((ctl
= (struct ctl
*)so
->so_pcb
))
207 (*ctl
->disconnect
)(ctl
, ctl
->userdata
);
210 soisdisconnected(so
);
216 ctl_send(struct socket
*so
, int flags
, struct mbuf
*m
,
217 struct sockaddr
*addr
, struct mbuf
*control
,
220 struct ctl
*ctl
= (struct ctl
*)so
->so_pcb
;
227 error
= (*ctl
->write
)(ctl
, ctl
->userdata
, m
);
233 ctl_enqueuembuf(void *ctlref
, struct mbuf
*m
, u_int32_t flags
)
235 struct ctl
*ctl
= (struct ctl
*)ctlref
;
236 struct socket
*so
= (struct socket
*)ctl
->skt
;
238 if (ctl
== NULL
) /* sanity check */
244 if (sbspace(&so
->so_rcv
) < m
->m_pkthdr
.len
)
247 sbappend(&so
->so_rcv
, m
);
248 if ((flags
& CTL_DATA_NOWAKEUP
) == 0)
254 ctl_enqueuedata(void *ctlref
, void *data
, size_t len
, u_int32_t flags
)
256 struct ctl
*ctl
= (struct ctl
*)ctlref
;
257 struct socket
*so
= (struct socket
*)ctl
->skt
;
260 if (ctl
== NULL
) /* sanity check */
269 if (sbspace(&so
->so_rcv
) < len
)
272 if ((m
= m_gethdr(M_NOWAIT
, MT_DATA
)) == NULL
)
277 if (!(m
->m_flags
& M_EXT
)) {
283 bcopy(data
, mtod(m
, void *), len
);
285 sbappend(&so
->so_rcv
, m
);
286 if ((flags
& CTL_DATA_NOWAKEUP
) == 0)
292 ctl_ctloutput(struct socket
*so
, struct sockopt
*sopt
)
294 struct ctl
*ctl
= (struct ctl
*)so
->so_pcb
;
299 if (sopt
->sopt_level
!= SYSPROTO_CONTROL
) {
306 switch (sopt
->sopt_dir
) {
308 if (ctl
->set
== NULL
)
310 MALLOC(data
, void *, sopt
->sopt_valsize
, M_TEMP
, M_WAITOK
);
313 error
= sooptcopyin(sopt
, data
, sopt
->sopt_valsize
, sopt
->sopt_valsize
);
315 error
= (*ctl
->set
)(ctl
, ctl
->userdata
, sopt
->sopt_name
, data
, sopt
->sopt_valsize
);
320 if (ctl
->get
== NULL
)
323 if (sopt
->sopt_valsize
&& sopt
->sopt_val
) {
324 MALLOC(data
, void *, sopt
->sopt_valsize
, M_TEMP
, M_WAITOK
);
328 len
= sopt
->sopt_valsize
;
329 error
= (*ctl
->get
)(ctl
, ctl
->userdata
, sopt
->sopt_name
, data
, &len
);
332 error
= sooptcopyout(sopt
, data
, len
);
334 sopt
->sopt_valsize
= len
;
343 int ctl_ioctl(struct socket
*so
, u_long cmd
, caddr_t data
,
344 struct ifnet
*ifp
, struct proc
*p
)
346 int error
= ENOTSUP
, s
, n
;
347 struct ctl
*ctl
= (struct ctl
*)so
->so_pcb
;
350 /* get the number of controllers */
353 TAILQ_FOREACH(ctl
, &ctl_head
, next
)
355 *(u_int32_t
*)data
= n
;
360 /* add controls to get list of NKEs */
368 * Register/unregister a NKE
371 ctl_register(struct kern_ctl_reg
*userctl
, void *userdata
, kern_ctl_ref
*ctlref
)
375 if (userctl
== NULL
) /* sanity check */
378 ctl
= ctl_find(userctl
->ctl_id
, userctl
->ctl_unit
);
382 MALLOC(ctl
, struct ctl
*, sizeof(*ctl
), M_TEMP
, M_WAITOK
);
386 bzero((char *)ctl
, sizeof(*ctl
));
388 ctl
->id
= userctl
->ctl_id
;
389 ctl
->unit
= userctl
->ctl_unit
;
390 ctl
->flags
= userctl
->ctl_flags
;
391 ctl
->sendbufsize
= userctl
->ctl_sendsize
;
392 ctl
->recvbufsize
= userctl
->ctl_recvsize
;
393 ctl
->userdata
= userdata
;
394 ctl
->connect
= userctl
->ctl_connect
;
395 ctl
->disconnect
= userctl
->ctl_disconnect
;
396 ctl
->write
= userctl
->ctl_write
;
397 ctl
->set
= userctl
->ctl_set
;
398 ctl
->get
= userctl
->ctl_get
;
400 TAILQ_INSERT_TAIL(&ctl_head
, ctl
, next
);
404 ctl_post_msg(KEV_CTL_REGISTERED
, ctl
->id
, ctl
->unit
);
409 ctl_deregister(void *ctlref
)
411 struct ctl
*ctl
= (struct ctl
*)ctlref
;
414 if (ctl
== NULL
) /* sanity check */
417 TAILQ_REMOVE(&ctl_head
, ctl
, next
);
420 ctl
->skt
->so_pcb
= 0;
421 soisdisconnected(ctl
->skt
);
424 ctl_post_msg(KEV_CTL_DEREGISTERED
, ctl
->id
, ctl
->unit
);
433 ctl_find(u_int32_t id
, u_int32_t unit
)
437 TAILQ_FOREACH(ctl
, &ctl_head
, next
)
438 if ((ctl
->id
== id
) && (ctl
->unit
== unit
))
444 void ctl_post_msg(u_long event_code
, u_int32_t id
, u_int32_t unit
)
446 struct ctl_event_data ctl_ev_data
;
447 struct kev_msg ev_msg
;
449 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
451 ev_msg
.kev_class
= KEV_SYSTEM_CLASS
;
452 ev_msg
.kev_subclass
= KEV_CTL_SUBCLASS
;
453 ev_msg
.event_code
= event_code
;
455 /* common nke subclass data */
456 bzero(&ctl_ev_data
, sizeof(ctl_ev_data
));
457 ctl_ev_data
.ctl_id
= id
;
458 ctl_ev_data
.ctl_unit
= unit
;
459 ev_msg
.dv
[0].data_ptr
= &ctl_ev_data
;
460 ev_msg
.dv
[0].data_length
= sizeof(ctl_ev_data
);
462 ev_msg
.dv
[1].data_length
= 0;
464 kev_post_msg(&ev_msg
);