1/*
2 * Copyright (c) 1999-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29/*
30 * Kernel Control domain - allows control connections to
31 *  and to read/write data.
32 *
33 * Vincent Lubet, 040506
34 * Christophe Allie, 010928
35 * Justin C. Walker, 990319
36 */
37
38#include <sys/types.h>
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/syslog.h>
42#include <sys/socket.h>
43#include <sys/socketvar.h>
44#include <sys/protosw.h>
45#include <sys/domain.h>
46#include <sys/malloc.h>
47#include <sys/mbuf.h>
48#include <sys/sys_domain.h>
49#include <sys/kern_event.h>
50#include <sys/kern_control.h>
51#include <sys/kauth.h>
52#include <net/if_var.h>
53
54#include <mach/vm_types.h>
55
56#include <kern/thread.h>
57
58/*
59 * Definitions and vars for we support
60 */
61
62#define CTL_SENDSIZE	(2 * 1024)	/* default buffer size */
63#define CTL_RECVSIZE 	(8 * 1024)	/* default buffer size */
64
65/*
66 * Definitions and vars for we support
67 */
68
69static u_int32_t		ctl_maxunit = 65536;
70static lck_grp_attr_t	*ctl_lck_grp_attr = 0;
71static lck_attr_t		*ctl_lck_attr = 0;
72static lck_grp_t		*ctl_lck_grp = 0;
73static lck_mtx_t 		*ctl_mtx;
74
75
76/* all the controllers are chained */
77TAILQ_HEAD(kctl_list, kctl) 	ctl_head;
78
79static int ctl_attach(struct socket *, int, struct proc *);
80static int ctl_detach(struct socket *);
81static int ctl_sofreelastref(struct socket *so);
82static int ctl_connect(struct socket *, struct sockaddr *, struct proc *);
83static int ctl_disconnect(struct socket *);
84static int ctl_ioctl(struct socket *so, u_long cmd, caddr_t data,
85                  struct ifnet *ifp, struct proc *p);
86static int ctl_send(struct socket *, int, struct mbuf *,
87            struct sockaddr *, struct mbuf *, struct proc *);
88static int ctl_ctloutput(struct socket *, struct sockopt *);
89static int ctl_peeraddr(struct socket *so, struct sockaddr **nam);
90static int ctl_usr_rcvd(struct socket *so, int flags);
91
92static struct kctl *ctl_find_by_name(const char *);
93static struct kctl *ctl_find_by_id_unit(u_int32_t id, u_int32_t unit);
94
95static struct socket *kcb_find_socket(struct kctl *, u_int32_t unit);
96static struct ctl_cb *kcb_find(struct kctl *, u_int32_t unit);
97static void ctl_post_msg(u_int32_t event_code, u_int32_t id);
98
99static int ctl_lock(struct socket *, int, void *);
100static int ctl_unlock(struct socket *, int, void *);
101static lck_mtx_t * ctl_getlock(struct socket *, int);
102
103static struct pr_usrreqs ctl_usrreqs = {
104	.pru_attach =		ctl_attach,
105	.pru_connect =		ctl_connect,
106	.pru_control =		ctl_ioctl,
107	.pru_detach =		ctl_detach,
108	.pru_disconnect =	ctl_disconnect,
109	.pru_peeraddr =		ctl_peeraddr,
110	.pru_rcvd =		ctl_usr_rcvd,
111	.pru_send =		ctl_send,
112	.pru_sosend =		sosend,
113	.pru_soreceive =	soreceive,
114};
115
116static struct protosw kctlsw[] = {
117{
118	.pr_type =		SOCK_DGRAM,
119	.pr_protocol =		SYSPROTO_CONTROL,
120	.pr_flags =		PR_ATOMIC|PR_CONNREQUIRED|PR_PCBLOCK|PR_WANTRCVD,
121	.pr_ctloutput =		ctl_ctloutput,
122	.pr_usrreqs =		&ctl_usrreqs,
123	.pr_lock =		ctl_lock,
124	.pr_unlock =		ctl_unlock,
125	.pr_getlock =		ctl_getlock,
126},
127{
128	.pr_type =		SOCK_STREAM,
129	.pr_protocol =		SYSPROTO_CONTROL,
130	.pr_flags =		PR_CONNREQUIRED|PR_PCBLOCK|PR_WANTRCVD,
131	.pr_ctloutput =		ctl_ctloutput,
132	.pr_usrreqs =		&ctl_usrreqs,
133	.pr_lock =		ctl_lock,
134	.pr_unlock =		ctl_unlock,
135	.pr_getlock =		ctl_getlock,
136}
137};
138
139static int kctl_proto_count = (sizeof (kctlsw) / sizeof (struct protosw));
140
141/*
142 * Install the protosw's for the Kernel Control manager.
143 */
144__private_extern__ void
145kern_control_init(struct domain *dp)
146{
147	struct protosw *pr;
148	int i;
149
150	VERIFY(!(dp->dom_flags & DOM_INITIALIZED));
151	VERIFY(dp == systemdomain);
152
153	ctl_lck_grp_attr = lck_grp_attr_alloc_init();
154	if (ctl_lck_grp_attr == NULL) {
155		panic("%s: lck_grp_attr_alloc_init failed\n", __func__);
156		/* NOTREACHED */
157	}
158
159	ctl_lck_grp = lck_grp_alloc_init("Kernel Control Protocol",
160	    ctl_lck_grp_attr);
161	if (ctl_lck_grp == NULL) {
162		panic("%s: lck_grp_alloc_init failed\n", __func__);
163		/* NOTREACHED */
164	}
165
166	ctl_lck_attr = lck_attr_alloc_init();
167	if (ctl_lck_attr == NULL) {
168		panic("%s: lck_attr_alloc_init failed\n", __func__);
169		/* NOTREACHED */
170	}
171
172	ctl_mtx = lck_mtx_alloc_init(ctl_lck_grp, ctl_lck_attr);
173	if (ctl_mtx == NULL) {
174		panic("%s: lck_mtx_alloc_init failed\n", __func__);
175		/* NOTREACHED */
176	}
177	TAILQ_INIT(&ctl_head);
178
179	for (i = 0, pr = &kctlsw[0]; i < kctl_proto_count; i++, pr++)
180		net_add_proto(pr, dp, 1);
181}
182
183static void
184kcb_delete(struct ctl_cb *kcb)
185{
186	if (kcb != 0) {
187		if (kcb->mtx != 0)
188			lck_mtx_free(kcb->mtx, ctl_lck_grp);
189		FREE(kcb, M_TEMP);
190	}
191}
192
193
194/*
195 * Kernel Controller user-request functions
196 * attach function must exist and succeed
197 * detach not necessary
198 * we need a pcb for the per socket mutex
199 */
200static int
201ctl_attach(__unused struct socket *so, __unused int proto, __unused struct proc *p)
202{
203	int error = 0;
204	struct ctl_cb			*kcb = 0;
205
206	MALLOC(kcb, struct ctl_cb *, sizeof(struct ctl_cb), M_TEMP, M_WAITOK);
207	if (kcb == NULL) {
208		error = ENOMEM;
209		goto quit;
210	}
211	bzero(kcb, sizeof(struct ctl_cb));
212
213	kcb->mtx = lck_mtx_alloc_init(ctl_lck_grp, ctl_lck_attr);
214	if (kcb->mtx == NULL) {
215		error = ENOMEM;
216		goto quit;
217	}
218	kcb->so = so;
219	so->so_pcb = (caddr_t)kcb;
220
221quit:
222	if (error != 0) {
223		kcb_delete(kcb);
224		kcb = 0;
225	}
226	return error;
227}
228
229static int
230ctl_sofreelastref(struct socket *so)
231{
232    struct ctl_cb 	*kcb = (struct ctl_cb *)so->so_pcb;
233
234    so->so_pcb = 0;
235
236    if (kcb != 0) {
237        struct kctl		*kctl;
238        if ((kctl = kcb->kctl) != 0) {
239            lck_mtx_lock(ctl_mtx);
240            TAILQ_REMOVE(&kctl->kcb_head, kcb, next);
241            lck_mtx_unlock(ctl_mtx);
242    	}
243    	kcb_delete(kcb);
244    }
245    sofreelastref(so, 1);
246    return 0;
247}
248
249static int
250ctl_detach(struct socket *so)
251{
252    struct ctl_cb 	*kcb = (struct ctl_cb *)so->so_pcb;
253
254    if (kcb == 0)
255    	return 0;
256
257    soisdisconnected(so);
258    so->so_flags |= SOF_PCBCLEARING;
259    return 0;
260}
261
262
263static int
264ctl_connect(struct socket *so, struct sockaddr *nam, __unused struct proc *p)
265{
266    struct kctl			*kctl;
267    int					error = 0;
268    struct sockaddr_ctl	sa;
269    struct ctl_cb		*kcb = (struct ctl_cb *)so->so_pcb;
270    struct ctl_cb		*kcb_next = NULL;
271
272    if (kcb == 0)
273    	panic("ctl_connect so_pcb null\n");
274
275    if (nam->sa_len !=  sizeof(struct sockaddr_ctl))
276    	return(EINVAL);
277
278    bcopy(nam, &sa, sizeof(struct sockaddr_ctl));
279
280    lck_mtx_lock(ctl_mtx);
281    kctl = ctl_find_by_id_unit(sa.sc_id, sa.sc_unit);
282    if (kctl == NULL) {
283        lck_mtx_unlock(ctl_mtx);
284        return ENOENT;
285    }
286
287	if (((kctl->flags & CTL_FLAG_REG_SOCK_STREAM) && (so->so_type != SOCK_STREAM)) ||
288		(!(kctl->flags & CTL_FLAG_REG_SOCK_STREAM) && (so->so_type != SOCK_DGRAM))) {
289        lck_mtx_unlock(ctl_mtx);
290        return EPROTOTYPE;
291	}
292
293    if (kctl->flags & CTL_FLAG_PRIVILEGED) {
294        if (p == 0) {
295            lck_mtx_unlock(ctl_mtx);
296            return(EINVAL);
297        }
298        if (kauth_cred_issuser(kauth_cred_get()) == 0) {
299            lck_mtx_unlock(ctl_mtx);
300            return EPERM;
301        }
302    }
303
304	if ((kctl->flags & CTL_FLAG_REG_ID_UNIT) || sa.sc_unit != 0) {
305		if (kcb_find(kctl, sa.sc_unit) != NULL) {
306			lck_mtx_unlock(ctl_mtx);
307			return EBUSY;
308		}
309	} else {
310		/* Find an unused ID, assumes control IDs are listed in order */
311    	u_int32_t	unit = 1;
312
313    	TAILQ_FOREACH(kcb_next, &kctl->kcb_head, next) {
314    		if (kcb_next->unit > unit) {
315    			/* Found a gap, lets fill it in */
316    			break;
317    		}
318    		unit = kcb_next->unit + 1;
319    		if (unit == ctl_maxunit)
320    			break;
321    	}
322
323		if (unit == ctl_maxunit) {
324			lck_mtx_unlock(ctl_mtx);
325			return EBUSY;
326		}
327
328		sa.sc_unit = unit;
329    }
330
331	kcb->unit = sa.sc_unit;
332    kcb->kctl = kctl;
333    if (kcb_next != NULL) {
334    	TAILQ_INSERT_BEFORE(kcb_next, kcb, next);
335    }
336    else {
337		TAILQ_INSERT_TAIL(&kctl->kcb_head, kcb, next);
338	}
339    lck_mtx_unlock(ctl_mtx);
340
341    error = soreserve(so, kctl->sendbufsize, kctl->recvbufsize);
342    if (error)
343		goto done;
344    soisconnecting(so);
345
346	socket_unlock(so, 0);
347    error = (*kctl->connect)(kctl, &sa, &kcb->userdata);
348	socket_lock(so, 0);
349    if (error)
350		goto end;
351
352    soisconnected(so);
353
354end:
355	if (error && kctl->disconnect) {
356		socket_unlock(so, 0);
357		(*kctl->disconnect)(kctl, kcb->unit, kcb->userdata);
358		socket_lock(so, 0);
359	}
360done:
361    if (error) {
362        soisdisconnected(so);
363        lck_mtx_lock(ctl_mtx);
364        kcb->kctl = 0;
365        kcb->unit = 0;
366        TAILQ_REMOVE(&kctl->kcb_head, kcb, next);
367        lck_mtx_unlock(ctl_mtx);
368    }
369    return error;
370}
371
372static int
373ctl_disconnect(struct socket *so)
374{
375    struct ctl_cb 	*kcb = (struct ctl_cb *)so->so_pcb;
376
377    if ((kcb = (struct ctl_cb *)so->so_pcb)) {
378        struct kctl		*kctl = kcb->kctl;
379
380        if (kctl && kctl->disconnect) {
381            socket_unlock(so, 0);
382            (*kctl->disconnect)(kctl, kcb->unit, kcb->userdata);
383            socket_lock(so, 0);
384        }
385
386        soisdisconnected(so);
387
388		socket_unlock(so, 0);
389        lck_mtx_lock(ctl_mtx);
390        kcb->kctl = 0;
391    	kcb->unit = 0;
392    	while (kcb->usecount != 0) {
393    		msleep(&kcb->usecount, ctl_mtx, 0, "kcb->usecount", 0);
394    	}
395        TAILQ_REMOVE(&kctl->kcb_head, kcb, next);
396        lck_mtx_unlock(ctl_mtx);
397		socket_lock(so, 0);
398    }
399    return 0;
400}
401
402static int
403ctl_peeraddr(struct socket *so, struct sockaddr **nam)
404{
405	struct ctl_cb 		*kcb = (struct ctl_cb *)so->so_pcb;
406	struct kctl			*kctl;
407	struct sockaddr_ctl	sc;
408
409	if (kcb == NULL)	/* sanity check */
410		return(ENOTCONN);
411
412	if ((kctl = kcb->kctl) == NULL)
413		return(EINVAL);
414
415	bzero(&sc, sizeof(struct sockaddr_ctl));
416	sc.sc_len = sizeof(struct sockaddr_ctl);
417	sc.sc_family = AF_SYSTEM;
418	sc.ss_sysaddr = AF_SYS_CONTROL;
419	sc.sc_id =  kctl->id;
420	sc.sc_unit = kcb->unit;
421
422	*nam = dup_sockaddr((struct sockaddr *)&sc, 1);
423
424	return 0;
425}
426
427static int
428ctl_usr_rcvd(struct socket *so, int flags)
429{
430	struct ctl_cb		*kcb = (struct ctl_cb *)so->so_pcb;
431	struct kctl			*kctl;
432
433	if ((kctl = kcb->kctl) == NULL) {
434		return EINVAL;
435	}
436
437	if (kctl->rcvd) {
438		socket_unlock(so, 0);
439		(*kctl->rcvd)(kctl, kcb->unit, kcb->userdata, flags);
440		socket_lock(so, 0);
441	}
442
443	return 0;
444}
445
446static int
447ctl_send(struct socket *so, int flags, struct mbuf *m,
448            __unused struct sockaddr *addr, struct mbuf *control,
449            __unused struct proc *p)
450{
451	int	 	error = 0;
452	struct ctl_cb 	*kcb = (struct ctl_cb *)so->so_pcb;
453	struct kctl		*kctl;
454
455	if (control) m_freem(control);
456
457	if (kcb == NULL)	/* sanity check */
458		error = ENOTCONN;
459
460	if (error == 0 && (kctl = kcb->kctl) == NULL)
461		error = EINVAL;
462
463	if (error == 0 && kctl->send) {
464		socket_unlock(so, 0);
465		error = (*kctl->send)(kctl, kcb->unit, kcb->userdata, m, flags);
466		socket_lock(so, 0);
467	} else {
468		m_freem(m);
469		if (error == 0)
470			error = ENOTSUP;
471	}
472	return error;
473}
474
475errno_t
476ctl_enqueuembuf(void *kctlref, u_int32_t unit, struct mbuf *m, u_int32_t flags)
477{
478	struct socket 	*so;
479	errno_t 		error = 0;
480	struct kctl		*kctl = (struct kctl *)kctlref;
481
482	if (kctl == NULL)
483		return EINVAL;
484
485	so = kcb_find_socket(kctl, unit);
486
487	if (so == NULL)
488		return EINVAL;
489
490	if (sbspace(&so->so_rcv) < m->m_pkthdr.len) {
491		error = ENOBUFS;
492		goto bye;
493	}
494	if ((flags & CTL_DATA_EOR))
495		m->m_flags |= M_EOR;
496	if (sbappend(&so->so_rcv, m) && (flags & CTL_DATA_NOWAKEUP) == 0)
497		sorwakeup(so);
498bye:
499	socket_unlock(so, 1);
500	return error;
501}
502
503errno_t
504ctl_enqueuedata(void *kctlref, u_int32_t unit, void *data, size_t len, u_int32_t flags)
505{
506	struct socket 	*so;
507	struct mbuf 	*m;
508	errno_t			error = 0;
509	struct kctl		*kctl = (struct kctl *)kctlref;
510	unsigned int 	num_needed;
511	struct mbuf 	*n;
512	size_t			curlen = 0;
513
514	if (kctlref == NULL)
515		return EINVAL;
516
517	so = kcb_find_socket(kctl, unit);
518	if (so == NULL)
519		return EINVAL;
520
521	if (sbspace(&so->so_rcv) < (int)len) {
522		error = ENOBUFS;
523		goto bye;
524	}
525
526	num_needed = 1;
527	m = m_allocpacket_internal(&num_needed, len, NULL, M_NOWAIT, 1, 0);
528	if (m == NULL) {
529		printf("ctl_enqueuedata: m_allocpacket_internal(%lu) failed\n", len);
530		error = ENOBUFS;
531		goto bye;
532	}
533
534	for (n = m; n != NULL; n = n->m_next) {
535		size_t mlen = mbuf_maxlen(n);
536
537		if (mlen + curlen > len)
538			mlen = len - curlen;
539		n->m_len = mlen;
540		bcopy((char *)data + curlen, n->m_data, mlen);
541		curlen += mlen;
542	}
543	mbuf_pkthdr_setlen(m, curlen);
544
545	if ((flags & CTL_DATA_EOR))
546		m->m_flags |= M_EOR;
547	if (sbappend(&so->so_rcv, m) && (flags & CTL_DATA_NOWAKEUP) == 0)
548		sorwakeup(so);
549bye:
550	socket_unlock(so, 1);
551	return error;
552}
553
554
555errno_t
556ctl_getenqueuespace(kern_ctl_ref kctlref, u_int32_t unit, size_t *space)
557{
558	struct kctl		*kctl = (struct kctl *)kctlref;
559	struct socket 	*so;
560	long avail;
561
562	if (kctlref == NULL || space == NULL)
563		return EINVAL;
564
565	so = kcb_find_socket(kctl, unit);
566	if (so == NULL)
567		return EINVAL;
568
569	avail = sbspace(&so->so_rcv);
570	*space = (avail < 0) ? 0 : avail;
571	socket_unlock(so, 1);
572
573	return 0;
574}
575
576static int
577ctl_ctloutput(struct socket *so, struct sockopt *sopt)
578{
579	struct ctl_cb 	*kcb = (struct ctl_cb *)so->so_pcb;
580	struct kctl	*kctl;
581	int 	error = 0;
582	void 	*data;
583	size_t	len;
584
585	if (sopt->sopt_level != SYSPROTO_CONTROL) {
586		return(EINVAL);
587	}
588
589	if (kcb == NULL)	/* sanity check */
590		return(ENOTCONN);
591
592	if ((kctl = kcb->kctl) == NULL)
593		return(EINVAL);
594
595	switch (sopt->sopt_dir) {
596		case SOPT_SET:
597			if (kctl->setopt == NULL)
598				return(ENOTSUP);
599			if (sopt->sopt_valsize == 0) {
600				data = NULL;
601			} else {
602				MALLOC(data, void *, sopt->sopt_valsize, M_TEMP, M_WAITOK);
603				if (data == NULL)
604					return(ENOMEM);
605				error = sooptcopyin(sopt, data, sopt->sopt_valsize, sopt->sopt_valsize);
606			}
607			if (error == 0) {
608				socket_unlock(so, 0);
609				error = (*kctl->setopt)(kcb->kctl, kcb->unit, kcb->userdata, sopt->sopt_name,
610							data, sopt->sopt_valsize);
611				socket_lock(so, 0);
612			}
613			FREE(data, M_TEMP);
614			break;
615
616		case SOPT_GET:
617			if (kctl->getopt == NULL)
618				return(ENOTSUP);
619			data = NULL;
620			if (sopt->sopt_valsize && sopt->sopt_val) {
621				MALLOC(data, void *, sopt->sopt_valsize, M_TEMP, M_WAITOK);
622				if (data == NULL)
623					return(ENOMEM);
624				/* 4108337 - copy in data for get socket option */
625				error = sooptcopyin(sopt, data, sopt->sopt_valsize, sopt->sopt_valsize);
626			}
627			len = sopt->sopt_valsize;
628			socket_unlock(so, 0);
629			error = (*kctl->getopt)(kcb->kctl, kcb->unit, kcb->userdata, sopt->sopt_name,
630						data, &len);
631			if (data != NULL && len > sopt->sopt_valsize)
632				panic_plain("ctl_ctloutput: ctl %s returned len (%lu) > sopt_valsize (%lu)\n",
633					kcb->kctl->name, len, sopt->sopt_valsize);
634			socket_lock(so, 0);
635			if (error == 0) {
636				if (data != NULL)
637					error = sooptcopyout(sopt, data, len);
638				else
639					sopt->sopt_valsize = len;
640			}
641			if (data != NULL)
642				FREE(data, M_TEMP);
643			break;
644	}
645	return error;
646}
647
648static int
649ctl_ioctl(__unused struct socket *so, u_long cmd, caddr_t data,
650			__unused struct ifnet *ifp, __unused struct proc *p)
651{
652	int 	error = ENOTSUP;
653
654	switch (cmd) {
655		/* get the number of controllers */
656		case CTLIOCGCOUNT: {
657			struct kctl	*kctl;
658			u_int32_t n = 0;
659
660			lck_mtx_lock(ctl_mtx);
661			TAILQ_FOREACH(kctl, &ctl_head, next)
662				n++;
663			lck_mtx_unlock(ctl_mtx);
664
665			bcopy(&n, data, sizeof (n));
666			error = 0;
667			break;
668		}
669		case CTLIOCGINFO: {
670			struct ctl_info ctl_info;
671			struct kctl 	*kctl = 0;
672			size_t name_len;
673
674			bcopy(data, &ctl_info, sizeof (ctl_info));
675			name_len = strnlen(ctl_info.ctl_name, MAX_KCTL_NAME);
676
677			if (name_len == 0 || name_len + 1 > MAX_KCTL_NAME) {
678				error = EINVAL;
679				break;
680			}
681			lck_mtx_lock(ctl_mtx);
682			kctl = ctl_find_by_name(ctl_info.ctl_name);
683			lck_mtx_unlock(ctl_mtx);
684			if (kctl == 0) {
685				error = ENOENT;
686				break;
687			}
688			ctl_info.ctl_id = kctl->id;
689			bcopy(&ctl_info, data, sizeof (ctl_info));
690			error = 0;
691			break;
692		}
693
694		/* add controls to get list of NKEs */
695
696	}
697
698	return error;
699}
700
701/*
702 * Register/unregister a NKE
703 */
704errno_t
705ctl_register(struct kern_ctl_reg *userkctl, kern_ctl_ref *kctlref)
706{
707	struct kctl 	*kctl = NULL;
708	struct kctl 	*kctl_next = NULL;
709	u_int32_t		id = 1;
710	size_t			name_len;
711	int				is_extended = 0;
712
713	if (userkctl == NULL)	/* sanity check */
714		return(EINVAL);
715	if (userkctl->ctl_connect == NULL)
716		return(EINVAL);
717	name_len = strlen(userkctl->ctl_name);
718	if (name_len == 0 || name_len + 1 > MAX_KCTL_NAME)
719		return(EINVAL);
720
721	MALLOC(kctl, struct kctl *, sizeof(*kctl), M_TEMP, M_WAITOK);
722	if (kctl == NULL)
723		return(ENOMEM);
724	bzero((char *)kctl, sizeof(*kctl));
725
726	lck_mtx_lock(ctl_mtx);
727
728	/*
729	 * Kernel Control IDs
730	 *
731	 * CTL_FLAG_REG_ID_UNIT indicates the control ID and unit number are
732	 * static. If they do not exist, add them to the list in order. If the
733	 * flag is not set, we must find a new unique value. We assume the
734	 * list is in order. We find the last item in the list and add one. If
735	 * this leads to wrapping the id around, we start at the front of the
736	 * list and look for a gap.
737	 */
738
739	if ((userkctl->ctl_flags & CTL_FLAG_REG_ID_UNIT) == 0) {
740		/* Must dynamically assign an unused ID */
741
742		/* Verify the same name isn't already registered */
743		if (ctl_find_by_name(userkctl->ctl_name) != NULL) {
744			lck_mtx_unlock(ctl_mtx);
745			FREE(kctl, M_TEMP);
746			return(EEXIST);
747		}
748
749		/* Start with 1 in case the list is empty */
750		id = 1;
751		kctl_next = TAILQ_LAST(&ctl_head, kctl_list);
752
753		if (kctl_next != NULL) {
754			/* List was not empty, add one to the last item in the list */
755			id = kctl_next->id + 1;
756			kctl_next = NULL;
757
758			/*
759			 * If this wrapped the id number, start looking at the front
760			 * of the list for an unused id.
761			 */
762			if (id == 0) {
763				/* Find the next unused ID */
764				id = 1;
765
766				TAILQ_FOREACH(kctl_next, &ctl_head, next) {
767					if (kctl_next->id > id) {
768						/* We found a gap */
769						break;
770					}
771
772					id = kctl_next->id + 1;
773				}
774			}
775		}
776
777		userkctl->ctl_id = id;
778		kctl->id = id;
779		kctl->reg_unit = -1;
780	} else {
781		TAILQ_FOREACH(kctl_next, &ctl_head, next) {
782			if (kctl_next->id > userkctl->ctl_id)
783				break;
784		}
785
786		if (ctl_find_by_id_unit(userkctl->ctl_id, userkctl->ctl_unit) != NULL) {
787			lck_mtx_unlock(ctl_mtx);
788			FREE(kctl, M_TEMP);
789			return(EEXIST);
790		}
791		kctl->id = userkctl->ctl_id;
792		kctl->reg_unit = userkctl->ctl_unit;
793	}
794
795	is_extended = (userkctl->ctl_flags & CTL_FLAG_REG_EXTENDED);
796
797	strlcpy(kctl->name, userkctl->ctl_name, MAX_KCTL_NAME);
798	kctl->flags = userkctl->ctl_flags;
799
800	/* Let the caller know the default send and receive sizes */
801	if (userkctl->ctl_sendsize == 0)
802		userkctl->ctl_sendsize = CTL_SENDSIZE;
803	kctl->sendbufsize = userkctl->ctl_sendsize;
804
805	if (userkctl->ctl_recvsize == 0)
806		userkctl->ctl_recvsize = CTL_RECVSIZE;
807	kctl->recvbufsize = userkctl->ctl_recvsize;
808
809	kctl->connect = userkctl->ctl_connect;
810	kctl->disconnect = userkctl->ctl_disconnect;
811	kctl->send = userkctl->ctl_send;
812	kctl->setopt = userkctl->ctl_setopt;
813	kctl->getopt = userkctl->ctl_getopt;
814	if (is_extended) {
815		kctl->rcvd = userkctl->ctl_rcvd;
816	}
817
818	TAILQ_INIT(&kctl->kcb_head);
819
820	if (kctl_next)
821		TAILQ_INSERT_BEFORE(kctl_next, kctl, next);
822	else
823		TAILQ_INSERT_TAIL(&ctl_head, kctl, next);
824
825	lck_mtx_unlock(ctl_mtx);
826
827	*kctlref = kctl;
828
829	ctl_post_msg(KEV_CTL_REGISTERED, kctl->id);
830	return(0);
831}
832
833errno_t
834ctl_deregister(void *kctlref)
835{
836    struct kctl		*kctl;
837
838    if (kctlref == NULL)	/* sanity check */
839        return(EINVAL);
840
841    lck_mtx_lock(ctl_mtx);
842    TAILQ_FOREACH(kctl, &ctl_head, next) {
843    	if (kctl == (struct kctl *)kctlref)
844    		break;
845    }
846    if (kctl != (struct kctl *)kctlref) {
847        lck_mtx_unlock(ctl_mtx);
848        return EINVAL;
849    }
850	if (!TAILQ_EMPTY(&kctl->kcb_head)) {
851        lck_mtx_unlock(ctl_mtx);
852		return EBUSY;
853	}
854
855    TAILQ_REMOVE(&ctl_head, kctl, next);
856
857    lck_mtx_unlock(ctl_mtx);
858
859    ctl_post_msg(KEV_CTL_DEREGISTERED, kctl->id);
860    FREE(kctl, M_TEMP);
861    return(0);
862}
863
864/*
865 * Must be called with global ctl_mtx lock taked
866 */
867static struct kctl *
868ctl_find_by_name(const char *name)
869{
870    struct kctl 	*kctl;
871
872    TAILQ_FOREACH(kctl, &ctl_head, next)
873        if (strncmp(kctl->name, name, sizeof(kctl->name)) == 0)
874            return kctl;
875
876    return NULL;
877}
878
879u_int32_t
880ctl_id_by_name(const char *name)
881{
882	u_int32_t	ctl_id = 0;
883
884	lck_mtx_lock(ctl_mtx);
885	struct kctl *kctl = ctl_find_by_name(name);
886	if (kctl) ctl_id = kctl->id;
887	lck_mtx_unlock(ctl_mtx);
888
889	return ctl_id;
890}
891
892errno_t
893ctl_name_by_id(
894	u_int32_t id,
895	char	*out_name,
896	size_t	maxsize)
897{
898	int 		found = 0;
899
900	lck_mtx_lock(ctl_mtx);
901	struct kctl *kctl;
902    TAILQ_FOREACH(kctl, &ctl_head, next) {
903        if (kctl->id == id)
904            break;
905    }
906
907    if (kctl && kctl->name)
908    {
909    	if (maxsize > MAX_KCTL_NAME)
910    		maxsize = MAX_KCTL_NAME;
911    	strlcpy(out_name, kctl->name, maxsize);
912    	found = 1;
913    }
914	lck_mtx_unlock(ctl_mtx);
915
916	return found ? 0 : ENOENT;
917}
918
919/*
920 * Must be called with global ctl_mtx lock taked
921 *
922 */
923static struct kctl *
924ctl_find_by_id_unit(u_int32_t id, u_int32_t unit)
925{
926    struct kctl 	*kctl;
927
928    TAILQ_FOREACH(kctl, &ctl_head, next) {
929        if (kctl->id == id && (kctl->flags & CTL_FLAG_REG_ID_UNIT) == 0)
930            return kctl;
931        else if (kctl->id == id && kctl->reg_unit == unit)
932            return kctl;
933    }
934    return NULL;
935}
936
937/*
938 * Must be called with kernel controller lock taken
939 */
940static struct ctl_cb *
941kcb_find(struct kctl *kctl, u_int32_t unit)
942{
943    struct ctl_cb 	*kcb;
944
945    TAILQ_FOREACH(kcb, &kctl->kcb_head, next)
946        if (kcb->unit == unit)
947            return kcb;
948
949    return NULL;
950}
951
952static struct socket *
953kcb_find_socket(struct kctl *kctl, u_int32_t unit)
954{
955	struct socket *so = NULL;
956
957	lck_mtx_lock(ctl_mtx);
958	struct ctl_cb	*kcb = kcb_find(kctl, unit);
959	if (kcb && kcb->kctl == kctl) {
960		so = kcb->so;
961		if (so) {
962			kcb->usecount++;
963		}
964	}
965	lck_mtx_unlock(ctl_mtx);
966
967	if (so == NULL) {
968		return NULL;
969	}
970
971	socket_lock(so, 1);
972
973	lck_mtx_lock(ctl_mtx);
974	if (kcb->kctl == NULL)
975	{
976		lck_mtx_unlock(ctl_mtx);
977		socket_unlock(so, 1);
978		so = NULL;
979		lck_mtx_lock(ctl_mtx);
980	}
981	kcb->usecount--;
982	if (kcb->usecount == 0)
983		wakeup((event_t)&kcb->usecount);
984	lck_mtx_unlock(ctl_mtx);
985
986	return so;
987}
988
989static void
990ctl_post_msg(u_int32_t event_code, u_int32_t id)
991{
992    struct ctl_event_data  	ctl_ev_data;
993    struct kev_msg  		ev_msg;
994
995    lck_mtx_assert(ctl_mtx, LCK_MTX_ASSERT_NOTOWNED);
996
997    bzero(&ev_msg, sizeof(struct kev_msg));
998    ev_msg.vendor_code    = KEV_VENDOR_APPLE;
999
1000    ev_msg.kev_class      = KEV_SYSTEM_CLASS;
1001    ev_msg.kev_subclass   = KEV_CTL_SUBCLASS;
1002    ev_msg.event_code 	  = event_code;
1003
1004    /* common nke subclass data */
1005    bzero(&ctl_ev_data, sizeof(ctl_ev_data));
1006    ctl_ev_data.ctl_id = id;
1007    ev_msg.dv[0].data_ptr    = &ctl_ev_data;
1008    ev_msg.dv[0].data_length = sizeof(ctl_ev_data);
1009
1010    ev_msg.dv[1].data_length = 0;
1011
1012    kev_post_msg(&ev_msg);
1013}
1014
1015static int
1016ctl_lock(struct socket *so, int refcount, void *lr)
1017{
1018	void *lr_saved;
1019
1020	if (lr == NULL)
1021		lr_saved = __builtin_return_address(0);
1022	else
1023		lr_saved = lr;
1024
1025	if (so->so_pcb != NULL) {
1026		lck_mtx_lock(((struct ctl_cb *)so->so_pcb)->mtx);
1027	} else  {
1028		panic("ctl_lock: so=%p NO PCB! lr=%p lrh= %s\n",
1029		    so, lr_saved, solockhistory_nr(so));
1030		/* NOTREACHED */
1031	}
1032
1033	if (so->so_usecount < 0) {
1034		panic("ctl_lock: so=%p so_pcb=%p lr=%p ref=%x lrh= %s\n",
1035		    so, so->so_pcb, lr_saved, so->so_usecount, solockhistory_nr(so));
1036		/* NOTREACHED */
1037	}
1038
1039	if (refcount)
1040		so->so_usecount++;
1041
1042	so->lock_lr[so->next_lock_lr] = lr_saved;
1043	so->next_lock_lr = (so->next_lock_lr+1) % SO_LCKDBG_MAX;
1044	return (0);
1045}
1046
1047static int
1048ctl_unlock(struct socket *so, int refcount, void *lr)
1049{
1050	void *lr_saved;
1051	lck_mtx_t *mutex_held;
1052
1053	if (lr == NULL)
1054		lr_saved = __builtin_return_address(0);
1055	else
1056		lr_saved = lr;
1057
1058#ifdef MORE_KCTLLOCK_DEBUG
1059	printf("ctl_unlock: so=%x sopcb=%x lock=%x ref=%x lr=%p\n",
1060	    so, so->so_pcb, ((struct ctl_cb *)so->so_pcb)->mtx,
1061	    so->so_usecount, lr_saved);
1062#endif
1063	if (refcount)
1064		so->so_usecount--;
1065
1066	if (so->so_usecount < 0) {
1067		panic("ctl_unlock: so=%p usecount=%x lrh= %s\n",
1068		    so, so->so_usecount, solockhistory_nr(so));
1069		/* NOTREACHED */
1070	}
1071	if (so->so_pcb == NULL) {
1072		panic("ctl_unlock: so=%p NO PCB usecount=%x lr=%p lrh= %s\n",
1073		    so, so->so_usecount, (void *)lr_saved, solockhistory_nr(so));
1074		/* NOTREACHED */
1075	}
1076	mutex_held = ((struct ctl_cb *)so->so_pcb)->mtx;
1077
1078	lck_mtx_assert(mutex_held, LCK_MTX_ASSERT_OWNED);
1079	so->unlock_lr[so->next_unlock_lr] = lr_saved;
1080	so->next_unlock_lr = (so->next_unlock_lr+1) % SO_LCKDBG_MAX;
1081	lck_mtx_unlock(mutex_held);
1082
1083	if (so->so_usecount == 0)
1084		ctl_sofreelastref(so);
1085
1086	return (0);
1087}
1088
1089static lck_mtx_t *
1090ctl_getlock(struct socket *so, __unused int locktype)
1091{
1092	struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
1093
1094	if (so->so_pcb)  {
1095		if (so->so_usecount < 0)
1096			panic("ctl_getlock: so=%p usecount=%x lrh= %s\n",
1097			    so, so->so_usecount, solockhistory_nr(so));
1098		return(kcb->mtx);
1099	} else {
1100		panic("ctl_getlock: so=%p NULL NO so_pcb %s\n",
1101		    so, solockhistory_nr(so));
1102		return (so->so_proto->pr_domain->dom_mtx);
1103	}
1104}
1105