]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_control.c
xnu-3247.10.11.tar.gz
[apple/xnu.git] / bsd / kern / kern_control.c
CommitLineData
9bccf70c 1/*
04b8595b 2 * Copyright (c) 1999-2015 Apple Inc. All rights reserved.
9bccf70c 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
fe8ab488 5 *
2d21ac55
A
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.
fe8ab488 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
fe8ab488 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
fe8ab488 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
9bccf70c 27 */
9bccf70c
A
28
29/*
91447636
A
30 * Kernel Control domain - allows control connections to
31 * and to read/write data.
9bccf70c 32 *
91447636 33 * Vincent Lubet, 040506
9bccf70c
A
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>
9bccf70c
A
48#include <sys/sys_domain.h>
49#include <sys/kern_event.h>
50#include <sys/kern_control.h>
2d21ac55 51#include <sys/kauth.h>
fe8ab488 52#include <sys/sysctl.h>
3e170ce0 53#include <sys/proc_info.h>
9bccf70c
A
54#include <net/if_var.h>
55
56#include <mach/vm_types.h>
9bccf70c
A
57
58#include <kern/thread.h>
59
3e170ce0
A
60struct kctl {
61 TAILQ_ENTRY(kctl) next; /* controller chain */
62 kern_ctl_ref kctlref;
63
64 /* controller information provided when registering */
65 char name[MAX_KCTL_NAME]; /* unique identifier */
66 u_int32_t id;
67 u_int32_t reg_unit;
68
69 /* misc communication information */
70 u_int32_t flags; /* support flags */
71 u_int32_t recvbufsize; /* request more than the default buffer size */
72 u_int32_t sendbufsize; /* request more than the default buffer size */
73
74 /* Dispatch functions */
75 ctl_connect_func connect; /* Make contact */
76 ctl_disconnect_func disconnect; /* Break contact */
77 ctl_send_func send; /* Send data to nke */
78 ctl_send_list_func send_list; /* Send list of packets */
79 ctl_setopt_func setopt; /* set kctl configuration */
80 ctl_getopt_func getopt; /* get kctl configuration */
81 ctl_rcvd_func rcvd; /* Notify nke when client reads data */
82
83 TAILQ_HEAD(, ctl_cb) kcb_head;
84 u_int32_t lastunit;
85};
86
87struct ctl_cb {
88 TAILQ_ENTRY(ctl_cb) next; /* controller chain */
89 lck_mtx_t *mtx;
90 struct socket *so; /* controlling socket */
91 struct kctl *kctl; /* back pointer to controller */
92 void *userdata;
93 u_int32_t unit;
94 u_int32_t usecount;
95};
96
fe8ab488
A
97#ifndef ROUNDUP64
98#define ROUNDUP64(x) P2ROUNDUP((x), sizeof (u_int64_t))
99#endif
100
101#ifndef ADVANCE64
102#define ADVANCE64(p, n) (void*)((char *)(p) + ROUNDUP64(n))
103#endif
104
9bccf70c
A
105/*
106 * Definitions and vars for we support
107 */
108
fe8ab488
A
109#define CTL_SENDSIZE (2 * 1024) /* default buffer size */
110#define CTL_RECVSIZE (8 * 1024) /* default buffer size */
9bccf70c
A
111
112/*
91447636
A
113 * Definitions and vars for we support
114 */
9bccf70c 115
fe8ab488 116static u_int32_t ctl_maxunit = 65536;
91447636 117static lck_grp_attr_t *ctl_lck_grp_attr = 0;
fe8ab488
A
118static lck_attr_t *ctl_lck_attr = 0;
119static lck_grp_t *ctl_lck_grp = 0;
120static lck_mtx_t *ctl_mtx;
9bccf70c
A
121
122/* all the controllers are chained */
2d21ac55 123TAILQ_HEAD(kctl_list, kctl) ctl_head;
91447636
A
124
125static int ctl_attach(struct socket *, int, struct proc *);
126static int ctl_detach(struct socket *);
127static int ctl_sofreelastref(struct socket *so);
128static int ctl_connect(struct socket *, struct sockaddr *, struct proc *);
129static int ctl_disconnect(struct socket *);
130static int ctl_ioctl(struct socket *so, u_long cmd, caddr_t data,
fe8ab488 131 struct ifnet *ifp, struct proc *p);
91447636 132static int ctl_send(struct socket *, int, struct mbuf *,
fe8ab488
A
133 struct sockaddr *, struct mbuf *, struct proc *);
134static int ctl_send_list(struct socket *, int, struct mbuf *,
135 struct sockaddr *, struct mbuf *, struct proc *);
91447636
A
136static int ctl_ctloutput(struct socket *, struct sockopt *);
137static int ctl_peeraddr(struct socket *so, struct sockaddr **nam);
39236c6e 138static int ctl_usr_rcvd(struct socket *so, int flags);
91447636 139
91447636
A
140static struct kctl *ctl_find_by_name(const char *);
141static struct kctl *ctl_find_by_id_unit(u_int32_t id, u_int32_t unit);
9bccf70c 142
3e170ce0
A
143static struct socket *kcb_find_socket(kern_ctl_ref kctlref, u_int32_t unit,
144 u_int32_t *);
91447636 145static struct ctl_cb *kcb_find(struct kctl *, u_int32_t unit);
b0d623f7 146static void ctl_post_msg(u_int32_t event_code, u_int32_t id);
9bccf70c 147
b0d623f7
A
148static int ctl_lock(struct socket *, int, void *);
149static int ctl_unlock(struct socket *, int, void *);
91447636 150static lck_mtx_t * ctl_getlock(struct socket *, int);
9bccf70c 151
39236c6e
A
152static struct pr_usrreqs ctl_usrreqs = {
153 .pru_attach = ctl_attach,
154 .pru_connect = ctl_connect,
155 .pru_control = ctl_ioctl,
156 .pru_detach = ctl_detach,
157 .pru_disconnect = ctl_disconnect,
158 .pru_peeraddr = ctl_peeraddr,
159 .pru_rcvd = ctl_usr_rcvd,
160 .pru_send = ctl_send,
fe8ab488 161 .pru_send_list = ctl_send_list,
39236c6e 162 .pru_sosend = sosend,
fe8ab488 163 .pru_sosend_list = sosend_list,
39236c6e 164 .pru_soreceive = soreceive,
fe8ab488 165 .pru_soreceive_list = soreceive_list,
91447636
A
166};
167
39236c6e 168static struct protosw kctlsw[] = {
91447636 169{
fe8ab488
A
170 .pr_type = SOCK_DGRAM,
171 .pr_protocol = SYSPROTO_CONTROL,
172 .pr_flags = PR_ATOMIC|PR_CONNREQUIRED|PR_PCBLOCK|PR_WANTRCVD,
173 .pr_ctloutput = ctl_ctloutput,
174 .pr_usrreqs = &ctl_usrreqs,
175 .pr_lock = ctl_lock,
176 .pr_unlock = ctl_unlock,
177 .pr_getlock = ctl_getlock,
39236c6e 178},
9bccf70c 179{
fe8ab488
A
180 .pr_type = SOCK_STREAM,
181 .pr_protocol = SYSPROTO_CONTROL,
182 .pr_flags = PR_CONNREQUIRED|PR_PCBLOCK|PR_WANTRCVD,
183 .pr_ctloutput = ctl_ctloutput,
184 .pr_usrreqs = &ctl_usrreqs,
185 .pr_lock = ctl_lock,
186 .pr_unlock = ctl_unlock,
187 .pr_getlock = ctl_getlock,
39236c6e 188}
9bccf70c
A
189};
190
fe8ab488
A
191__private_extern__ int kctl_reg_list SYSCTL_HANDLER_ARGS;
192__private_extern__ int kctl_pcblist SYSCTL_HANDLER_ARGS;
193__private_extern__ int kctl_getstat SYSCTL_HANDLER_ARGS;
194
91447636 195
fe8ab488
A
196SYSCTL_NODE(_net_systm, OID_AUTO, kctl,
197 CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Kernel control family");
198
199struct kctlstat kctlstat;
200SYSCTL_PROC(_net_systm_kctl, OID_AUTO, stats,
201 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0,
202 kctl_getstat, "S,kctlstat", "");
203
204SYSCTL_PROC(_net_systm_kctl, OID_AUTO, reg_list,
205 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0,
206 kctl_reg_list, "S,xkctl_reg", "");
207
208SYSCTL_PROC(_net_systm_kctl, OID_AUTO, pcblist,
209 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0,
210 kctl_pcblist, "S,xkctlpcb", "");
211
212u_int32_t ctl_autorcvbuf_max = 256 * 1024;
213SYSCTL_INT(_net_systm_kctl, OID_AUTO, autorcvbufmax,
214 CTLFLAG_RW | CTLFLAG_LOCKED, &ctl_autorcvbuf_max, 0, "");
215
216u_int32_t ctl_autorcvbuf_high = 0;
217SYSCTL_INT(_net_systm_kctl, OID_AUTO, autorcvbufhigh,
218 CTLFLAG_RD | CTLFLAG_LOCKED, &ctl_autorcvbuf_high, 0, "");
219
220u_int32_t ctl_debug = 0;
221SYSCTL_INT(_net_systm_kctl, OID_AUTO, debug,
222 CTLFLAG_RW | CTLFLAG_LOCKED, &ctl_debug, 0, "");
223
3e170ce0
A
224#define KCTL_TBL_INC 16
225
226static uintptr_t kctl_tbl_size = 0;
227static u_int32_t kctl_tbl_growing = 0;
228static uintptr_t kctl_tbl_count = 0;
229static struct kctl **kctl_table = NULL;
230static uintptr_t kctl_ref_gencnt = 0;
231
232static void kctl_tbl_grow(void);
233static kern_ctl_ref kctl_make_ref(struct kctl *kctl);
234static void kctl_delete_ref(kern_ctl_ref);
235static struct kctl *kctl_from_ref(kern_ctl_ref);
236
9bccf70c 237/*
91447636 238 * Install the protosw's for the Kernel Control manager.
9bccf70c 239 */
39236c6e
A
240__private_extern__ void
241kern_control_init(struct domain *dp)
9bccf70c 242{
39236c6e
A
243 struct protosw *pr;
244 int i;
3e170ce0 245 int kctl_proto_count = (sizeof (kctlsw) / sizeof (struct protosw));
39236c6e
A
246
247 VERIFY(!(dp->dom_flags & DOM_INITIALIZED));
248 VERIFY(dp == systemdomain);
249
91447636 250 ctl_lck_grp_attr = lck_grp_attr_alloc_init();
39236c6e
A
251 if (ctl_lck_grp_attr == NULL) {
252 panic("%s: lck_grp_attr_alloc_init failed\n", __func__);
253 /* NOTREACHED */
91447636 254 }
39236c6e
A
255
256 ctl_lck_grp = lck_grp_alloc_init("Kernel Control Protocol",
257 ctl_lck_grp_attr);
258 if (ctl_lck_grp == NULL) {
259 panic("%s: lck_grp_alloc_init failed\n", __func__);
260 /* NOTREACHED */
91447636 261 }
39236c6e 262
91447636 263 ctl_lck_attr = lck_attr_alloc_init();
39236c6e
A
264 if (ctl_lck_attr == NULL) {
265 panic("%s: lck_attr_alloc_init failed\n", __func__);
266 /* NOTREACHED */
91447636 267 }
39236c6e 268
91447636 269 ctl_mtx = lck_mtx_alloc_init(ctl_lck_grp, ctl_lck_attr);
39236c6e
A
270 if (ctl_mtx == NULL) {
271 panic("%s: lck_mtx_alloc_init failed\n", __func__);
272 /* NOTREACHED */
91447636
A
273 }
274 TAILQ_INIT(&ctl_head);
39236c6e
A
275
276 for (i = 0, pr = &kctlsw[0]; i < kctl_proto_count; i++, pr++)
277 net_add_proto(pr, dp, 1);
91447636 278}
9bccf70c 279
91447636
A
280static void
281kcb_delete(struct ctl_cb *kcb)
282{
283 if (kcb != 0) {
284 if (kcb->mtx != 0)
285 lck_mtx_free(kcb->mtx, ctl_lck_grp);
286 FREE(kcb, M_TEMP);
287 }
9bccf70c
A
288}
289
9bccf70c
A
290/*
291 * Kernel Controller user-request functions
fe8ab488
A
292 * attach function must exist and succeed
293 * detach not necessary
91447636 294 * we need a pcb for the per socket mutex
9bccf70c 295 */
91447636 296static int
fe8ab488
A
297ctl_attach(struct socket *so, int proto, struct proc *p)
298{
299#pragma unused(proto, p)
91447636
A
300 int error = 0;
301 struct ctl_cb *kcb = 0;
302
303 MALLOC(kcb, struct ctl_cb *, sizeof(struct ctl_cb), M_TEMP, M_WAITOK);
304 if (kcb == NULL) {
305 error = ENOMEM;
306 goto quit;
307 }
308 bzero(kcb, sizeof(struct ctl_cb));
fe8ab488 309
91447636
A
310 kcb->mtx = lck_mtx_alloc_init(ctl_lck_grp, ctl_lck_attr);
311 if (kcb->mtx == NULL) {
312 error = ENOMEM;
313 goto quit;
314 }
315 kcb->so = so;
316 so->so_pcb = (caddr_t)kcb;
fe8ab488 317
91447636
A
318quit:
319 if (error != 0) {
320 kcb_delete(kcb);
321 kcb = 0;
322 }
fe8ab488 323 return (error);
91447636
A
324}
325
326static int
327ctl_sofreelastref(struct socket *so)
328{
fe8ab488
A
329 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
330
331 so->so_pcb = 0;
332
333 if (kcb != 0) {
334 struct kctl *kctl;
335 if ((kctl = kcb->kctl) != 0) {
336 lck_mtx_lock(ctl_mtx);
337 TAILQ_REMOVE(&kctl->kcb_head, kcb, next);
338 kctlstat.kcs_pcbcount--;
339 kctlstat.kcs_gencnt++;
340 lck_mtx_unlock(ctl_mtx);
341 }
342 kcb_delete(kcb);
343 }
344 sofreelastref(so, 1);
345 return (0);
91447636
A
346}
347
348static int
349ctl_detach(struct socket *so)
350{
fe8ab488
A
351 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
352
353 if (kcb == 0)
354 return (0);
355
356 soisdisconnected(so);
357 so->so_flags |= SOF_PCBCLEARING;
358 return (0);
9bccf70c
A
359}
360
91447636 361static int
fe8ab488
A
362ctl_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
363{
364#pragma unused(p)
365 struct kctl *kctl;
366 int error = 0;
367 struct sockaddr_ctl sa;
368 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
369 struct ctl_cb *kcb_next = NULL;
04b8595b
A
370 u_quad_t sbmaxsize;
371 u_int32_t recvbufsize, sendbufsize;
fe8ab488
A
372
373 if (kcb == 0)
374 panic("ctl_connect so_pcb null\n");
375
376 if (nam->sa_len != sizeof(struct sockaddr_ctl))
377 return (EINVAL);
378
379 bcopy(nam, &sa, sizeof(struct sockaddr_ctl));
380
381 lck_mtx_lock(ctl_mtx);
382 kctl = ctl_find_by_id_unit(sa.sc_id, sa.sc_unit);
383 if (kctl == NULL) {
384 lck_mtx_unlock(ctl_mtx);
385 return (ENOENT);
386 }
387
388 if (((kctl->flags & CTL_FLAG_REG_SOCK_STREAM) &&
389 (so->so_type != SOCK_STREAM)) ||
390 (!(kctl->flags & CTL_FLAG_REG_SOCK_STREAM) &&
391 (so->so_type != SOCK_DGRAM))) {
392 lck_mtx_unlock(ctl_mtx);
393 return (EPROTOTYPE);
394 }
395
396 if (kctl->flags & CTL_FLAG_PRIVILEGED) {
397 if (p == 0) {
398 lck_mtx_unlock(ctl_mtx);
399 return (EINVAL);
400 }
401 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
402 lck_mtx_unlock(ctl_mtx);
403 return (EPERM);
404 }
405 }
91447636
A
406
407 if ((kctl->flags & CTL_FLAG_REG_ID_UNIT) || sa.sc_unit != 0) {
408 if (kcb_find(kctl, sa.sc_unit) != NULL) {
409 lck_mtx_unlock(ctl_mtx);
fe8ab488 410 return (EBUSY);
91447636
A
411 }
412 } else {
fe8ab488
A
413 /* Find an unused ID, assumes control IDs are in order */
414 u_int32_t unit = 1;
415
416 TAILQ_FOREACH(kcb_next, &kctl->kcb_head, next) {
417 if (kcb_next->unit > unit) {
418 /* Found a gap, lets fill it in */
419 break;
420 }
421 unit = kcb_next->unit + 1;
422 if (unit == ctl_maxunit)
423 break;
424 }
425
2d21ac55
A
426 if (unit == ctl_maxunit) {
427 lck_mtx_unlock(ctl_mtx);
fe8ab488 428 return (EBUSY);
2d21ac55 429 }
fe8ab488 430
2d21ac55 431 sa.sc_unit = unit;
fe8ab488 432 }
55e303ae 433
91447636 434 kcb->unit = sa.sc_unit;
fe8ab488
A
435 kcb->kctl = kctl;
436 if (kcb_next != NULL) {
437 TAILQ_INSERT_BEFORE(kcb_next, kcb, next);
438 } else {
2d21ac55
A
439 TAILQ_INSERT_TAIL(&kctl->kcb_head, kcb, next);
440 }
fe8ab488
A
441 kctlstat.kcs_pcbcount++;
442 kctlstat.kcs_gencnt++;
443 kctlstat.kcs_connections++;
444 lck_mtx_unlock(ctl_mtx);
9bccf70c 445
04b8595b
A
446 /*
447 * rdar://15526688: Limit the send and receive sizes to sb_max
448 * by using the same scaling as sbreserve()
449 */
450 sbmaxsize = (u_quad_t)sb_max * MCLBYTES / (MSIZE + MCLBYTES);
451
452 if (kctl->sendbufsize > sbmaxsize)
453 sendbufsize = sbmaxsize;
454 else
455 sendbufsize = kctl->sendbufsize;
456
457 if (kctl->recvbufsize > sbmaxsize)
458 recvbufsize = sbmaxsize;
459 else
460 recvbufsize = kctl->recvbufsize;
461
462 error = soreserve(so, sendbufsize, recvbufsize);
fe8ab488
A
463 if (error) {
464 printf("%s - soreserve(%llx, %u, %u) error %d\n", __func__,
465 (uint64_t)VM_KERNEL_ADDRPERM(so),
04b8595b 466 sendbufsize, recvbufsize, error);
91447636 467 goto done;
fe8ab488
A
468 }
469 soisconnecting(so);
470
91447636 471 socket_unlock(so, 0);
3e170ce0 472 error = (*kctl->connect)(kctl->kctlref, &sa, &kcb->userdata);
91447636 473 socket_lock(so, 0);
fe8ab488 474 if (error)
6d2010ae 475 goto end;
fe8ab488
A
476
477 soisconnected(so);
91447636 478
6d2010ae
A
479end:
480 if (error && kctl->disconnect) {
481 socket_unlock(so, 0);
3e170ce0 482 (*kctl->disconnect)(kctl->kctlref, kcb->unit, kcb->userdata);
6d2010ae
A
483 socket_lock(so, 0);
484 }
91447636 485done:
fe8ab488
A
486 if (error) {
487 soisdisconnected(so);
488 lck_mtx_lock(ctl_mtx);
489 kcb->kctl = 0;
490 kcb->unit = 0;
491 TAILQ_REMOVE(&kctl->kcb_head, kcb, next);
492 kctlstat.kcs_pcbcount--;
493 kctlstat.kcs_gencnt++;
494 kctlstat.kcs_conn_fail++;
495 lck_mtx_unlock(ctl_mtx);
496 }
497 return (error);
9bccf70c
A
498}
499
91447636 500static int
9bccf70c
A
501ctl_disconnect(struct socket *so)
502{
fe8ab488
A
503 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
504
505 if ((kcb = (struct ctl_cb *)so->so_pcb)) {
506 struct kctl *kctl = kcb->kctl;
507
508 if (kctl && kctl->disconnect) {
509 socket_unlock(so, 0);
3e170ce0
A
510 (*kctl->disconnect)(kctl->kctlref, kcb->unit,
511 kcb->userdata);
fe8ab488
A
512 socket_lock(so, 0);
513 }
514
515 soisdisconnected(so);
516
6d2010ae 517 socket_unlock(so, 0);
fe8ab488
A
518 lck_mtx_lock(ctl_mtx);
519 kcb->kctl = 0;
520 kcb->unit = 0;
521 while (kcb->usecount != 0) {
522 msleep(&kcb->usecount, ctl_mtx, 0, "kcb->usecount", 0);
523 }
524 TAILQ_REMOVE(&kctl->kcb_head, kcb, next);
525 kctlstat.kcs_pcbcount--;
526 kctlstat.kcs_gencnt++;
527 lck_mtx_unlock(ctl_mtx);
6d2010ae 528 socket_lock(so, 0);
fe8ab488
A
529 }
530 return (0);
9bccf70c
A
531}
532
91447636
A
533static int
534ctl_peeraddr(struct socket *so, struct sockaddr **nam)
9bccf70c 535{
91447636
A
536 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
537 struct kctl *kctl;
538 struct sockaddr_ctl sc;
fe8ab488 539
91447636 540 if (kcb == NULL) /* sanity check */
fe8ab488
A
541 return (ENOTCONN);
542
91447636 543 if ((kctl = kcb->kctl) == NULL)
fe8ab488
A
544 return (EINVAL);
545
91447636
A
546 bzero(&sc, sizeof(struct sockaddr_ctl));
547 sc.sc_len = sizeof(struct sockaddr_ctl);
548 sc.sc_family = AF_SYSTEM;
549 sc.ss_sysaddr = AF_SYS_CONTROL;
550 sc.sc_id = kctl->id;
551 sc.sc_unit = kcb->unit;
fe8ab488 552
91447636 553 *nam = dup_sockaddr((struct sockaddr *)&sc, 1);
fe8ab488
A
554
555 return (0);
556}
557
558static void
559ctl_sbrcv_trim(struct socket *so)
560{
561 struct sockbuf *sb = &so->so_rcv;
562
563 if (sb->sb_hiwat > sb->sb_idealsize) {
564 u_int32_t diff;
565 int32_t trim;
566
567 /*
568 * The difference between the ideal size and the
569 * current size is the upper bound of the trimage
570 */
571 diff = sb->sb_hiwat - sb->sb_idealsize;
572 /*
573 * We cannot trim below the outstanding data
574 */
575 trim = sb->sb_hiwat - sb->sb_cc;
576
577 trim = imin(trim, (int32_t)diff);
578
579 if (trim > 0) {
580 sbreserve(sb, (sb->sb_hiwat - trim));
581
582 if (ctl_debug)
583 printf("%s - shrunk to %d\n",
584 __func__, sb->sb_hiwat);
585 }
586 }
9bccf70c
A
587}
588
39236c6e
A
589static int
590ctl_usr_rcvd(struct socket *so, int flags)
591{
592 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
593 struct kctl *kctl;
594
595 if ((kctl = kcb->kctl) == NULL) {
fe8ab488 596 return (EINVAL);
39236c6e
A
597 }
598
599 if (kctl->rcvd) {
600 socket_unlock(so, 0);
3e170ce0 601 (*kctl->rcvd)(kctl->kctlref, kcb->unit, kcb->userdata, flags);
39236c6e
A
602 socket_lock(so, 0);
603 }
604
fe8ab488
A
605 ctl_sbrcv_trim(so);
606
607 return (0);
39236c6e
A
608}
609
91447636
A
610static int
611ctl_send(struct socket *so, int flags, struct mbuf *m,
fe8ab488
A
612 struct sockaddr *addr, struct mbuf *control,
613 struct proc *p)
9bccf70c 614{
fe8ab488
A
615#pragma unused(addr, p)
616 int error = 0;
91447636 617 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
fe8ab488
A
618 struct kctl *kctl;
619
620 if (control)
621 m_freem(control);
622
91447636 623 if (kcb == NULL) /* sanity check */
6d2010ae 624 error = ENOTCONN;
fe8ab488 625
6d2010ae
A
626 if (error == 0 && (kctl = kcb->kctl) == NULL)
627 error = EINVAL;
fe8ab488 628
6d2010ae 629 if (error == 0 && kctl->send) {
fe8ab488 630 so_tc_update_stats(m, so, m_get_service_class(m));
91447636 631 socket_unlock(so, 0);
3e170ce0
A
632 error = (*kctl->send)(kctl->kctlref, kcb->unit, kcb->userdata,
633 m, flags);
91447636 634 socket_lock(so, 0);
6d2010ae
A
635 } else {
636 m_freem(m);
637 if (error == 0)
638 error = ENOTSUP;
91447636 639 }
fe8ab488
A
640 if (error != 0)
641 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_send_fail);
642 return (error);
643}
644
645static int
646ctl_send_list(struct socket *so, int flags, struct mbuf *m,
647 __unused struct sockaddr *addr, struct mbuf *control,
648 __unused struct proc *p)
649{
650 int error = 0;
651 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
652 struct kctl *kctl;
653
654 if (control)
655 m_freem_list(control);
656
657 if (kcb == NULL) /* sanity check */
658 error = ENOTCONN;
659
660 if (error == 0 && (kctl = kcb->kctl) == NULL)
661 error = EINVAL;
662
663 if (error == 0 && kctl->send_list) {
664 struct mbuf *nxt;
665
666 for (nxt = m; nxt != NULL; nxt = nxt->m_nextpkt)
667 so_tc_update_stats(nxt, so, m_get_service_class(nxt));
668
669 socket_unlock(so, 0);
3e170ce0
A
670 error = (*kctl->send_list)(kctl->kctlref, kcb->unit,
671 kcb->userdata, m, flags);
fe8ab488
A
672 socket_lock(so, 0);
673 } else if (error == 0 && kctl->send) {
674 while (m != NULL && error == 0) {
675 struct mbuf *nextpkt = m->m_nextpkt;
676
677 m->m_nextpkt = NULL;
678 so_tc_update_stats(m, so, m_get_service_class(m));
679 socket_unlock(so, 0);
3e170ce0
A
680 error = (*kctl->send)(kctl->kctlref, kcb->unit,
681 kcb->userdata, m, flags);
fe8ab488
A
682 socket_lock(so, 0);
683 m = nextpkt;
684 }
685 if (m != NULL)
686 m_freem_list(m);
687 } else {
688 m_freem_list(m);
689 if (error == 0)
690 error = ENOTSUP;
691 }
692 if (error != 0)
693 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_send_list_fail);
694 return (error);
695}
696
697static errno_t
3e170ce0
A
698ctl_rcvbspace(struct socket *so, u_int32_t datasize,
699 u_int32_t kctlflags, u_int32_t flags)
fe8ab488
A
700{
701 struct sockbuf *sb = &so->so_rcv;
702 u_int32_t space = sbspace(sb);
703 errno_t error;
04b8595b 704
3e170ce0 705 if ((kctlflags & CTL_FLAG_REG_CRIT) == 0) {
fe8ab488
A
706 if ((u_int32_t) space >= datasize)
707 error = 0;
708 else
709 error = ENOBUFS;
710 } else if ((flags & CTL_DATA_CRIT) == 0) {
3e170ce0
A
711 /*
712 * Reserve 25% for critical messages
713 */
714 if (space < (sb->sb_hiwat >> 2) ||
715 space < datasize)
716 error = ENOBUFS;
717 else
718 error = 0;
fe8ab488
A
719 } else {
720 u_int32_t autorcvbuf_max;
721
722 /*
723 * Allow overcommit of 25%
724 */
725 autorcvbuf_max = min(sb->sb_idealsize + (sb->sb_idealsize >> 2),
726 ctl_autorcvbuf_max);
727
728 if ((u_int32_t) space >= datasize) {
729 error = 0;
730 } else if (tcp_cansbgrow(sb) &&
731 sb->sb_hiwat < autorcvbuf_max) {
732 /*
733 * Grow with a little bit of leeway
734 */
735 u_int32_t grow = datasize - space + MSIZE;
736
737 if (sbreserve(sb,
738 min((sb->sb_hiwat + grow), autorcvbuf_max)) == 1) {
739
740 if (sb->sb_hiwat > ctl_autorcvbuf_high)
741 ctl_autorcvbuf_high = sb->sb_hiwat;
742
3e170ce0
A
743 /*
744 * A final check
745 */
746 if ((u_int32_t) sbspace(sb) >= datasize) {
747 error = 0;
748 } else {
749 error = ENOBUFS;
750 }
751
fe8ab488 752 if (ctl_debug)
3e170ce0
A
753 printf("%s - grown to %d error %d\n",
754 __func__, sb->sb_hiwat, error);
fe8ab488
A
755 } else {
756 error = ENOBUFS;
757 }
758 } else {
759 error = ENOBUFS;
760 }
761 }
762 return (error);
9bccf70c
A
763}
764
91447636 765errno_t
3e170ce0
A
766ctl_enqueuembuf(kern_ctl_ref kctlref, u_int32_t unit, struct mbuf *m,
767 u_int32_t flags)
9bccf70c 768{
91447636 769 struct socket *so;
fe8ab488 770 errno_t error = 0;
fe8ab488 771 int len = m->m_pkthdr.len;
3e170ce0 772 u_int32_t kctlflags;
fe8ab488 773
3e170ce0
A
774 so = kcb_find_socket(kctlref, unit, &kctlflags);
775 if (so == NULL) {
fe8ab488 776 return (EINVAL);
3e170ce0 777 }
fe8ab488 778
3e170ce0 779 if (ctl_rcvbspace(so, len, kctlflags, flags) != 0) {
91447636 780 error = ENOBUFS;
fe8ab488 781 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fullsock);
91447636
A
782 goto bye;
783 }
784 if ((flags & CTL_DATA_EOR))
785 m->m_flags |= M_EOR;
fe8ab488
A
786
787 so_recv_data_stat(so, m, 0);
788 if (sbappend(&so->so_rcv, m) != 0) {
789 if ((flags & CTL_DATA_NOWAKEUP) == 0)
790 sorwakeup(so);
791 } else {
792 error = ENOBUFS;
793 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fullsock);
794 }
91447636 795bye:
fe8ab488
A
796 if (ctl_debug && error != 0 && (flags & CTL_DATA_CRIT))
797 printf("%s - crit data err %d len %d hiwat %d cc: %d\n",
798 __func__, error, len,
799 so->so_rcv.sb_hiwat, so->so_rcv.sb_cc);
800
91447636 801 socket_unlock(so, 1);
fe8ab488
A
802 if (error != 0)
803 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fail);
804
805 return (error);
806}
807
808/*
809 * Compute space occupied by mbuf like sbappendrecord
810 */
811static int
812m_space(struct mbuf *m)
813{
814 int space = 0;
815 struct mbuf *nxt;
816
817 for (nxt = m; nxt != NULL; nxt = nxt->m_next)
818 space += nxt->m_len;
819
820 return (space);
821}
822
823errno_t
824ctl_enqueuembuf_list(void *kctlref, u_int32_t unit, struct mbuf *m_list,
825 u_int32_t flags, struct mbuf **m_remain)
826{
827 struct socket *so = NULL;
828 errno_t error = 0;
fe8ab488
A
829 struct mbuf *m, *nextpkt;
830 int needwakeup = 0;
831 int len;
3e170ce0 832 u_int32_t kctlflags;
fe8ab488
A
833
834 /*
835 * Need to point the beginning of the list in case of early exit
836 */
837 m = m_list;
838
3e170ce0
A
839 /*
840 * kcb_find_socket takes the socket lock with a reference
841 */
842 so = kcb_find_socket(kctlref, unit, &kctlflags);
843 if (so == NULL) {
fe8ab488
A
844 error = EINVAL;
845 goto done;
846 }
3e170ce0
A
847
848 if (kctlflags & CTL_FLAG_REG_SOCK_STREAM) {
fe8ab488
A
849 error = EOPNOTSUPP;
850 goto done;
851 }
852 if (flags & CTL_DATA_EOR) {
853 error = EINVAL;
854 goto done;
855 }
fe8ab488
A
856
857 for (m = m_list; m != NULL; m = nextpkt) {
858 nextpkt = m->m_nextpkt;
859
860 if (m->m_pkthdr.len == 0)
861 printf("%s: %llx m_pkthdr.len is 0",
862 __func__, (uint64_t)VM_KERNEL_ADDRPERM(m));
863
864 /*
865 * The mbuf is either appended or freed by sbappendrecord()
866 * so it's not reliable from a data standpoint
867 */
868 len = m_space(m);
3e170ce0 869 if (ctl_rcvbspace(so, len, kctlflags, flags) != 0) {
fe8ab488
A
870 error = ENOBUFS;
871 OSIncrementAtomic64(
872 (SInt64 *)&kctlstat.kcs_enqueue_fullsock);
873 break;
874 } else {
875 /*
876 * Unlink from the list, m is on its own
877 */
878 m->m_nextpkt = NULL;
879 so_recv_data_stat(so, m, 0);
880 if (sbappendrecord(&so->so_rcv, m) != 0) {
881 needwakeup = 1;
882 } else {
883 /*
884 * We free or return the remaining
885 * mbufs in the list
886 */
887 m = nextpkt;
888 error = ENOBUFS;
889 OSIncrementAtomic64(
890 (SInt64 *)&kctlstat.kcs_enqueue_fullsock);
891 break;
892 }
893 }
894 }
895 if (needwakeup && (flags & CTL_DATA_NOWAKEUP) == 0)
896 sorwakeup(so);
897
898done:
899 if (so != NULL) {
900 if (ctl_debug && error != 0 && (flags & CTL_DATA_CRIT))
901 printf("%s - crit data err %d len %d hiwat %d cc: %d\n",
902 __func__, error, len,
903 so->so_rcv.sb_hiwat, so->so_rcv.sb_cc);
904
905 socket_unlock(so, 1);
906 }
907 if (m_remain) {
908 *m_remain = m;
909
910 if (m != NULL && socket_debug && so != NULL &&
911 (so->so_options & SO_DEBUG)) {
912 struct mbuf *n;
913
914 printf("%s m_list %llx\n", __func__,
915 (uint64_t) VM_KERNEL_ADDRPERM(m_list));
916 for (n = m; n != NULL; n = n->m_nextpkt)
917 printf(" remain %llx m_next %llx\n",
918 (uint64_t) VM_KERNEL_ADDRPERM(n),
919 (uint64_t) VM_KERNEL_ADDRPERM(n->m_next));
920 }
921 } else {
922 if (m != NULL)
923 m_freem_list(m);
924 }
925 if (error != 0)
926 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fail);
927 return (error);
91447636 928}
9bccf70c 929
91447636 930errno_t
fe8ab488
A
931ctl_enqueuedata(void *kctlref, u_int32_t unit, void *data, size_t len,
932 u_int32_t flags)
91447636 933{
91447636
A
934 struct socket *so;
935 struct mbuf *m;
fe8ab488 936 errno_t error = 0;
91447636
A
937 unsigned int num_needed;
938 struct mbuf *n;
fe8ab488 939 size_t curlen = 0;
3e170ce0 940 u_int32_t kctlflags;
fe8ab488 941
3e170ce0
A
942 so = kcb_find_socket(kctlref, unit, &kctlflags);
943 if (so == NULL) {
fe8ab488 944 return (EINVAL);
3e170ce0 945 }
fe8ab488 946
3e170ce0 947 if (ctl_rcvbspace(so, len, kctlflags, flags) != 0) {
91447636 948 error = ENOBUFS;
fe8ab488 949 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fullsock);
91447636
A
950 goto bye;
951 }
952
953 num_needed = 1;
954 m = m_allocpacket_internal(&num_needed, len, NULL, M_NOWAIT, 1, 0);
955 if (m == NULL) {
fe8ab488
A
956 printf("ctl_enqueuedata: m_allocpacket_internal(%lu) failed\n",
957 len);
958 error = ENOMEM;
91447636
A
959 goto bye;
960 }
fe8ab488 961
91447636
A
962 for (n = m; n != NULL; n = n->m_next) {
963 size_t mlen = mbuf_maxlen(n);
fe8ab488 964
91447636
A
965 if (mlen + curlen > len)
966 mlen = len - curlen;
967 n->m_len = mlen;
968 bcopy((char *)data + curlen, n->m_data, mlen);
969 curlen += mlen;
970 }
971 mbuf_pkthdr_setlen(m, curlen);
972
973 if ((flags & CTL_DATA_EOR))
974 m->m_flags |= M_EOR;
fe8ab488
A
975 so_recv_data_stat(so, m, 0);
976 if (sbappend(&so->so_rcv, m) != 0) {
977 if ((flags & CTL_DATA_NOWAKEUP) == 0)
978 sorwakeup(so);
979 } else {
980 error = ENOBUFS;
981 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fullsock);
982 }
983
91447636 984bye:
fe8ab488
A
985 if (ctl_debug && error != 0 && (flags & CTL_DATA_CRIT))
986 printf("%s - crit data err %d len %d hiwat %d cc: %d\n",
987 __func__, error, (int)len,
988 so->so_rcv.sb_hiwat, so->so_rcv.sb_cc);
989
91447636 990 socket_unlock(so, 1);
fe8ab488
A
991 if (error != 0)
992 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fail);
993 return (error);
91447636 994}
9bccf70c 995
3e170ce0
A
996errno_t
997ctl_getenqueuepacketcount(kern_ctl_ref kctlref, u_int32_t unit, u_int32_t *pcnt)
998{
999 struct socket *so;
1000 u_int32_t cnt;
1001 struct mbuf *m1;
1002
1003 if (pcnt == NULL)
1004 return (EINVAL);
1005
1006 so = kcb_find_socket(kctlref, unit, NULL);
1007 if (so == NULL) {
1008 return (EINVAL);
1009 }
1010
1011 cnt = 0;
1012 m1 = so->so_rcv.sb_mb;
1013 while (m1 != NULL) {
1014 if (m1->m_type == MT_DATA ||
1015 m1->m_type == MT_HEADER ||
1016 m1->m_type == MT_OOBDATA)
1017 cnt += 1;
1018 m1 = m1->m_nextpkt;
1019 }
1020 *pcnt = cnt;
1021
1022 socket_unlock(so, 1);
1023
1024 return (0);
1025}
55e303ae 1026
fe8ab488 1027errno_t
91447636
A
1028ctl_getenqueuespace(kern_ctl_ref kctlref, u_int32_t unit, size_t *space)
1029{
91447636 1030 struct socket *so;
2d21ac55 1031 long avail;
fe8ab488 1032
3e170ce0 1033 if (space == NULL)
fe8ab488
A
1034 return (EINVAL);
1035
3e170ce0
A
1036 so = kcb_find_socket(kctlref, unit, NULL);
1037 if (so == NULL) {
fe8ab488 1038 return (EINVAL);
3e170ce0 1039 }
fe8ab488 1040
2d21ac55
A
1041 avail = sbspace(&so->so_rcv);
1042 *space = (avail < 0) ? 0 : avail;
91447636 1043 socket_unlock(so, 1);
fe8ab488
A
1044
1045 return (0);
1046}
1047
1048errno_t
1049ctl_getenqueuereadable(kern_ctl_ref kctlref, u_int32_t unit,
1050 u_int32_t *difference)
1051{
fe8ab488
A
1052 struct socket *so;
1053
3e170ce0 1054 if (difference == NULL)
fe8ab488
A
1055 return (EINVAL);
1056
3e170ce0
A
1057 so = kcb_find_socket(kctlref, unit, NULL);
1058 if (so == NULL) {
fe8ab488 1059 return (EINVAL);
3e170ce0 1060 }
fe8ab488
A
1061
1062 if (so->so_rcv.sb_cc >= so->so_rcv.sb_lowat) {
1063 *difference = 0;
1064 } else {
1065 *difference = (so->so_rcv.sb_lowat - so->so_rcv.sb_cc);
1066 }
1067 socket_unlock(so, 1);
1068
1069 return (0);
9bccf70c
A
1070}
1071
91447636 1072static int
9bccf70c
A
1073ctl_ctloutput(struct socket *so, struct sockopt *sopt)
1074{
91447636
A
1075 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
1076 struct kctl *kctl;
1077 int error = 0;
1078 void *data;
1079 size_t len;
fe8ab488 1080
91447636 1081 if (sopt->sopt_level != SYSPROTO_CONTROL) {
fe8ab488 1082 return (EINVAL);
91447636 1083 }
fe8ab488 1084
91447636 1085 if (kcb == NULL) /* sanity check */
fe8ab488
A
1086 return (ENOTCONN);
1087
91447636 1088 if ((kctl = kcb->kctl) == NULL)
fe8ab488
A
1089 return (EINVAL);
1090
91447636
A
1091 switch (sopt->sopt_dir) {
1092 case SOPT_SET:
1093 if (kctl->setopt == NULL)
fe8ab488 1094 return (ENOTSUP);
2d21ac55
A
1095 if (sopt->sopt_valsize == 0) {
1096 data = NULL;
1097 } else {
fe8ab488
A
1098 MALLOC(data, void *, sopt->sopt_valsize, M_TEMP,
1099 M_WAITOK);
2d21ac55 1100 if (data == NULL)
fe8ab488
A
1101 return (ENOMEM);
1102 error = sooptcopyin(sopt, data,
3e170ce0 1103 sopt->sopt_valsize, sopt->sopt_valsize);
2d21ac55 1104 }
91447636
A
1105 if (error == 0) {
1106 socket_unlock(so, 0);
3e170ce0
A
1107 error = (*kctl->setopt)(kctl->kctlref,
1108 kcb->unit, kcb->userdata, sopt->sopt_name,
1109 data, sopt->sopt_valsize);
91447636
A
1110 socket_lock(so, 0);
1111 }
1112 FREE(data, M_TEMP);
1113 break;
fe8ab488 1114
91447636
A
1115 case SOPT_GET:
1116 if (kctl->getopt == NULL)
fe8ab488 1117 return (ENOTSUP);
91447636
A
1118 data = NULL;
1119 if (sopt->sopt_valsize && sopt->sopt_val) {
fe8ab488
A
1120 MALLOC(data, void *, sopt->sopt_valsize, M_TEMP,
1121 M_WAITOK);
91447636 1122 if (data == NULL)
fe8ab488
A
1123 return (ENOMEM);
1124 /*
1125 * 4108337 - copy user data in case the
1126 * kernel control needs it
1127 */
1128 error = sooptcopyin(sopt, data,
1129 sopt->sopt_valsize, sopt->sopt_valsize);
91447636
A
1130 }
1131 len = sopt->sopt_valsize;
1132 socket_unlock(so, 0);
3e170ce0 1133 error = (*kctl->getopt)(kctl->kctlref, kcb->unit,
fe8ab488 1134 kcb->userdata, sopt->sopt_name,
91447636 1135 data, &len);
6d2010ae 1136 if (data != NULL && len > sopt->sopt_valsize)
fe8ab488
A
1137 panic_plain("ctl_ctloutput: ctl %s returned "
1138 "len (%lu) > sopt_valsize (%lu)\n",
1139 kcb->kctl->name, len,
1140 sopt->sopt_valsize);
1141 socket_lock(so, 0);
91447636
A
1142 if (error == 0) {
1143 if (data != NULL)
1144 error = sooptcopyout(sopt, data, len);
fe8ab488 1145 else
91447636
A
1146 sopt->sopt_valsize = len;
1147 }
1148 if (data != NULL)
fe8ab488 1149 FREE(data, M_TEMP);
91447636
A
1150 break;
1151 }
fe8ab488 1152 return (error);
91447636 1153}
9bccf70c 1154
fe8ab488
A
1155static int
1156ctl_ioctl(struct socket *so, u_long cmd, caddr_t data,
1157 struct ifnet *ifp, struct proc *p)
91447636 1158{
fe8ab488 1159#pragma unused(so, ifp, p)
91447636 1160 int error = ENOTSUP;
fe8ab488 1161
91447636
A
1162 switch (cmd) {
1163 /* get the number of controllers */
1164 case CTLIOCGCOUNT: {
1165 struct kctl *kctl;
316670eb 1166 u_int32_t n = 0;
91447636
A
1167
1168 lck_mtx_lock(ctl_mtx);
1169 TAILQ_FOREACH(kctl, &ctl_head, next)
1170 n++;
1171 lck_mtx_unlock(ctl_mtx);
fe8ab488 1172
316670eb 1173 bcopy(&n, data, sizeof (n));
91447636
A
1174 error = 0;
1175 break;
1176 }
1177 case CTLIOCGINFO: {
316670eb 1178 struct ctl_info ctl_info;
91447636 1179 struct kctl *kctl = 0;
316670eb
A
1180 size_t name_len;
1181
1182 bcopy(data, &ctl_info, sizeof (ctl_info));
1183 name_len = strnlen(ctl_info.ctl_name, MAX_KCTL_NAME);
1184
91447636
A
1185 if (name_len == 0 || name_len + 1 > MAX_KCTL_NAME) {
1186 error = EINVAL;
1187 break;
1188 }
1189 lck_mtx_lock(ctl_mtx);
316670eb 1190 kctl = ctl_find_by_name(ctl_info.ctl_name);
91447636
A
1191 lck_mtx_unlock(ctl_mtx);
1192 if (kctl == 0) {
1193 error = ENOENT;
1194 break;
1195 }
316670eb
A
1196 ctl_info.ctl_id = kctl->id;
1197 bcopy(&ctl_info, data, sizeof (ctl_info));
91447636
A
1198 error = 0;
1199 break;
1200 }
fe8ab488 1201
91447636 1202 /* add controls to get list of NKEs */
fe8ab488 1203
91447636 1204 }
fe8ab488
A
1205
1206 return (error);
91447636 1207}
9bccf70c 1208
3e170ce0
A
1209static void
1210kctl_tbl_grow()
1211{
1212 struct kctl **new_table;
1213 uintptr_t new_size;
1214
1215 lck_mtx_assert(ctl_mtx, LCK_MTX_ASSERT_OWNED);
1216
1217 while (kctl_tbl_growing) {
1218 /* Another thread is allocating */
1219 (void) msleep((caddr_t) &kctl_tbl_growing, ctl_mtx,
1220 PSOCK | PCATCH, "kctl_tbl_growing", 0);
1221 }
1222 /* Another thread grew the table */
1223 if (kctl_table != NULL && kctl_tbl_count < kctl_tbl_size)
1224 return;
1225
1226 /* Verify we have a sane size */
1227 if (kctl_tbl_size + KCTL_TBL_INC >= UINT16_MAX) {
1228 printf("%s kctl_tbl_size %lu too big\n",
1229 __func__, kctl_tbl_size);
1230 return;
1231 }
1232 kctl_tbl_growing = 1;
1233
1234 new_size = kctl_tbl_size + KCTL_TBL_INC;
1235
1236 lck_mtx_unlock(ctl_mtx);
1237 new_table = _MALLOC(sizeof(struct kctl *) * new_size,
1238 M_TEMP, M_WAIT | M_ZERO);
1239 lck_mtx_lock(ctl_mtx);
1240
1241 if (new_table != NULL) {
1242 if (kctl_table != NULL) {
1243 bcopy(kctl_table, new_table,
1244 kctl_tbl_size * sizeof(struct kctl *));
1245
1246 _FREE(kctl_table, M_TEMP);
1247 }
1248 kctl_table = new_table;
1249 kctl_tbl_size = new_size;
1250 }
1251
1252 kctl_tbl_growing = 0;
1253}
1254
1255#define KCTLREF_INDEX_MASK 0x0000FFFF
1256#define KCTLREF_GENCNT_MASK 0xFFFF0000
1257#define KCTLREF_GENCNT_SHIFT 16
1258
1259static kern_ctl_ref
1260kctl_make_ref(struct kctl *kctl)
1261{
1262 uintptr_t i;
1263
1264 lck_mtx_assert(ctl_mtx, LCK_MTX_ASSERT_OWNED);
1265
1266 if (kctl_tbl_count >= kctl_tbl_size)
1267 kctl_tbl_grow();
1268
1269 kctl->kctlref = NULL;
1270 for (i = 0; i < kctl_tbl_size; i++) {
1271 if (kctl_table[i] == NULL) {
1272 uintptr_t ref;
1273
1274 /*
1275 * Reference is index plus one
1276 */
1277 kctl_ref_gencnt += 1;
1278
1279 /*
1280 * Add generation count as salt to reference to prevent
1281 * use after deregister
1282 */
1283 ref = ((kctl_ref_gencnt << KCTLREF_GENCNT_SHIFT) &
1284 KCTLREF_GENCNT_MASK) +
1285 ((i + 1) & KCTLREF_INDEX_MASK);
1286
1287 kctl->kctlref = (void *)(ref);
1288 kctl_table[i] = kctl;
1289 kctl_tbl_count++;
1290 break;
1291 }
1292 }
1293
1294 if (kctl->kctlref == NULL)
1295 panic("%s no space in table", __func__);
1296
1297 if (ctl_debug > 0)
1298 printf("%s %p for %p\n",
1299 __func__, kctl->kctlref, kctl);
1300
1301 return (kctl->kctlref);
1302}
1303
1304static void
1305kctl_delete_ref(kern_ctl_ref kctlref)
1306{
1307 /*
1308 * Reference is index plus one
1309 */
1310 uintptr_t i = (((uintptr_t)kctlref) & KCTLREF_INDEX_MASK) - 1;
1311
1312 lck_mtx_assert(ctl_mtx, LCK_MTX_ASSERT_OWNED);
1313
1314 if (i < kctl_tbl_size) {
1315 struct kctl *kctl = kctl_table[i];
1316
1317 if (kctl->kctlref == kctlref) {
1318 kctl_table[i] = NULL;
1319 kctl_tbl_count--;
1320 } else {
1321 kctlstat.kcs_bad_kctlref++;
1322 }
1323 } else {
1324 kctlstat.kcs_bad_kctlref++;
1325 }
1326}
1327
1328static struct kctl *
1329kctl_from_ref(kern_ctl_ref kctlref)
1330{
1331 /*
1332 * Reference is index plus one
1333 */
1334 uintptr_t i = (((uintptr_t)kctlref) & KCTLREF_INDEX_MASK) - 1;
1335 struct kctl *kctl = NULL;
1336
1337 lck_mtx_assert(ctl_mtx, LCK_MTX_ASSERT_OWNED);
1338
1339 if (i >= kctl_tbl_size) {
1340 kctlstat.kcs_bad_kctlref++;
1341 return (NULL);
1342 }
1343 kctl = kctl_table[i];
1344 if (kctl->kctlref != kctlref) {
1345 kctlstat.kcs_bad_kctlref++;
1346 return (NULL);
1347 }
1348 return (kctl);
1349}
1350
91447636
A
1351/*
1352 * Register/unregister a NKE
1353 */
1354errno_t
1355ctl_register(struct kern_ctl_reg *userkctl, kern_ctl_ref *kctlref)
2d21ac55
A
1356{
1357 struct kctl *kctl = NULL;
1358 struct kctl *kctl_next = NULL;
04b8595b
A
1359 u_int32_t id = 1;
1360 size_t name_len;
1361 int is_extended = 0;
fe8ab488 1362
91447636 1363 if (userkctl == NULL) /* sanity check */
fe8ab488 1364 return (EINVAL);
91447636 1365 if (userkctl->ctl_connect == NULL)
fe8ab488 1366 return (EINVAL);
91447636
A
1367 name_len = strlen(userkctl->ctl_name);
1368 if (name_len == 0 || name_len + 1 > MAX_KCTL_NAME)
fe8ab488
A
1369 return (EINVAL);
1370
91447636
A
1371 MALLOC(kctl, struct kctl *, sizeof(*kctl), M_TEMP, M_WAITOK);
1372 if (kctl == NULL)
fe8ab488 1373 return (ENOMEM);
91447636 1374 bzero((char *)kctl, sizeof(*kctl));
fe8ab488 1375
91447636 1376 lck_mtx_lock(ctl_mtx);
fe8ab488 1377
3e170ce0
A
1378 if (kctl_make_ref(kctl) == NULL) {
1379 lck_mtx_unlock(ctl_mtx);
1380 FREE(kctl, M_TEMP);
1381 return (ENOMEM);
1382 }
1383
2d21ac55
A
1384 /*
1385 * Kernel Control IDs
1386 *
1387 * CTL_FLAG_REG_ID_UNIT indicates the control ID and unit number are
1388 * static. If they do not exist, add them to the list in order. If the
1389 * flag is not set, we must find a new unique value. We assume the
1390 * list is in order. We find the last item in the list and add one. If
1391 * this leads to wrapping the id around, we start at the front of the
1392 * list and look for a gap.
1393 */
fe8ab488 1394
2d21ac55
A
1395 if ((userkctl->ctl_flags & CTL_FLAG_REG_ID_UNIT) == 0) {
1396 /* Must dynamically assign an unused ID */
fe8ab488 1397
2d21ac55 1398 /* Verify the same name isn't already registered */
91447636 1399 if (ctl_find_by_name(userkctl->ctl_name) != NULL) {
3e170ce0 1400 kctl_delete_ref(kctl->kctlref);
91447636
A
1401 lck_mtx_unlock(ctl_mtx);
1402 FREE(kctl, M_TEMP);
fe8ab488 1403 return (EEXIST);
91447636 1404 }
fe8ab488 1405
2d21ac55
A
1406 /* Start with 1 in case the list is empty */
1407 id = 1;
1408 kctl_next = TAILQ_LAST(&ctl_head, kctl_list);
fe8ab488 1409
2d21ac55 1410 if (kctl_next != NULL) {
fe8ab488 1411 /* List was not empty, add one to the last item */
2d21ac55
A
1412 id = kctl_next->id + 1;
1413 kctl_next = NULL;
fe8ab488 1414
2d21ac55 1415 /*
fe8ab488
A
1416 * If this wrapped the id number, start looking at
1417 * the front of the list for an unused id.
2d21ac55 1418 */
91447636 1419 if (id == 0) {
2d21ac55
A
1420 /* Find the next unused ID */
1421 id = 1;
fe8ab488 1422
2d21ac55
A
1423 TAILQ_FOREACH(kctl_next, &ctl_head, next) {
1424 if (kctl_next->id > id) {
1425 /* We found a gap */
1426 break;
1427 }
fe8ab488 1428
2d21ac55
A
1429 id = kctl_next->id + 1;
1430 }
91447636 1431 }
91447636 1432 }
fe8ab488 1433
2d21ac55 1434 userkctl->ctl_id = id;
91447636
A
1435 kctl->id = id;
1436 kctl->reg_unit = -1;
1437 } else {
2d21ac55
A
1438 TAILQ_FOREACH(kctl_next, &ctl_head, next) {
1439 if (kctl_next->id > userkctl->ctl_id)
1440 break;
1441 }
fe8ab488
A
1442
1443 if (ctl_find_by_id_unit(userkctl->ctl_id, userkctl->ctl_unit)) {
3e170ce0 1444 kctl_delete_ref(kctl->kctlref);
91447636
A
1445 lck_mtx_unlock(ctl_mtx);
1446 FREE(kctl, M_TEMP);
fe8ab488 1447 return (EEXIST);
91447636
A
1448 }
1449 kctl->id = userkctl->ctl_id;
1450 kctl->reg_unit = userkctl->ctl_unit;
1451 }
39236c6e
A
1452
1453 is_extended = (userkctl->ctl_flags & CTL_FLAG_REG_EXTENDED);
1454
2d21ac55 1455 strlcpy(kctl->name, userkctl->ctl_name, MAX_KCTL_NAME);
91447636
A
1456 kctl->flags = userkctl->ctl_flags;
1457
fe8ab488
A
1458 /*
1459 * Let the caller know the default send and receive sizes
fe8ab488 1460 */
04b8595b 1461 if (userkctl->ctl_sendsize == 0) {
fe8ab488 1462 kctl->sendbufsize = CTL_SENDSIZE;
04b8595b
A
1463 userkctl->ctl_sendsize = kctl->sendbufsize;
1464 } else {
1465 kctl->sendbufsize = userkctl->ctl_sendsize;
1466 }
1467 if (userkctl->ctl_recvsize == 0) {
fe8ab488 1468 kctl->recvbufsize = CTL_RECVSIZE;
04b8595b
A
1469 userkctl->ctl_recvsize = kctl->recvbufsize;
1470 } else {
1471 kctl->recvbufsize = userkctl->ctl_recvsize;
1472 }
91447636
A
1473
1474 kctl->connect = userkctl->ctl_connect;
1475 kctl->disconnect = userkctl->ctl_disconnect;
1476 kctl->send = userkctl->ctl_send;
1477 kctl->setopt = userkctl->ctl_setopt;
1478 kctl->getopt = userkctl->ctl_getopt;
39236c6e
A
1479 if (is_extended) {
1480 kctl->rcvd = userkctl->ctl_rcvd;
fe8ab488 1481 kctl->send_list = userkctl->ctl_send_list;
39236c6e 1482 }
fe8ab488 1483
91447636 1484 TAILQ_INIT(&kctl->kcb_head);
fe8ab488 1485
2d21ac55
A
1486 if (kctl_next)
1487 TAILQ_INSERT_BEFORE(kctl_next, kctl, next);
1488 else
1489 TAILQ_INSERT_TAIL(&ctl_head, kctl, next);
fe8ab488
A
1490
1491 kctlstat.kcs_reg_count++;
1492 kctlstat.kcs_gencnt++;
1493
91447636 1494 lck_mtx_unlock(ctl_mtx);
fe8ab488 1495
3e170ce0 1496 *kctlref = kctl->kctlref;
fe8ab488 1497
91447636 1498 ctl_post_msg(KEV_CTL_REGISTERED, kctl->id);
fe8ab488 1499 return (0);
9bccf70c
A
1500}
1501
91447636
A
1502errno_t
1503ctl_deregister(void *kctlref)
fe8ab488
A
1504{
1505 struct kctl *kctl;
1506
fe8ab488 1507 lck_mtx_lock(ctl_mtx);
3e170ce0
A
1508 if ((kctl = kctl_from_ref(kctlref)) == NULL) {
1509 kctlstat.kcs_bad_kctlref++;
fe8ab488 1510 lck_mtx_unlock(ctl_mtx);
3e170ce0
A
1511 if (ctl_debug != 0)
1512 printf("%s invalid kctlref %p\n",
1513 __func__, kctlref);
fe8ab488
A
1514 return (EINVAL);
1515 }
3e170ce0 1516
91447636 1517 if (!TAILQ_EMPTY(&kctl->kcb_head)) {
fe8ab488
A
1518 lck_mtx_unlock(ctl_mtx);
1519 return (EBUSY);
91447636
A
1520 }
1521
fe8ab488
A
1522 TAILQ_REMOVE(&ctl_head, kctl, next);
1523
1524 kctlstat.kcs_reg_count--;
1525 kctlstat.kcs_gencnt++;
91447636 1526
3e170ce0 1527 kctl_delete_ref(kctl->kctlref);
fe8ab488
A
1528 lck_mtx_unlock(ctl_mtx);
1529
1530 ctl_post_msg(KEV_CTL_DEREGISTERED, kctl->id);
1531 FREE(kctl, M_TEMP);
1532 return (0);
9bccf70c
A
1533}
1534
91447636
A
1535/*
1536 * Must be called with global ctl_mtx lock taked
1537 */
1538static struct kctl *
1539ctl_find_by_name(const char *name)
fe8ab488
A
1540{
1541 struct kctl *kctl;
1542
1543 lck_mtx_assert(ctl_mtx, LCK_MTX_ASSERT_OWNED);
9bccf70c 1544
fe8ab488
A
1545 TAILQ_FOREACH(kctl, &ctl_head, next)
1546 if (strncmp(kctl->name, name, sizeof(kctl->name)) == 0)
1547 return (kctl);
9bccf70c 1548
fe8ab488 1549 return (NULL);
91447636 1550}
9bccf70c 1551
6d2010ae
A
1552u_int32_t
1553ctl_id_by_name(const char *name)
1554{
1555 u_int32_t ctl_id = 0;
fe8ab488
A
1556 struct kctl *kctl;
1557
6d2010ae 1558 lck_mtx_lock(ctl_mtx);
fe8ab488
A
1559 kctl = ctl_find_by_name(name);
1560 if (kctl)
1561 ctl_id = kctl->id;
6d2010ae 1562 lck_mtx_unlock(ctl_mtx);
fe8ab488
A
1563
1564 return (ctl_id);
6d2010ae
A
1565}
1566
1567errno_t
fe8ab488 1568ctl_name_by_id(u_int32_t id, char *out_name, size_t maxsize)
6d2010ae
A
1569{
1570 int found = 0;
6d2010ae 1571 struct kctl *kctl;
fe8ab488
A
1572
1573 lck_mtx_lock(ctl_mtx);
1574 TAILQ_FOREACH(kctl, &ctl_head, next) {
1575 if (kctl->id == id)
1576 break;
1577 }
1578
3e170ce0 1579 if (kctl) {
fe8ab488
A
1580 if (maxsize > MAX_KCTL_NAME)
1581 maxsize = MAX_KCTL_NAME;
1582 strlcpy(out_name, kctl->name, maxsize);
1583 found = 1;
1584 }
6d2010ae 1585 lck_mtx_unlock(ctl_mtx);
fe8ab488
A
1586
1587 return (found ? 0 : ENOENT);
6d2010ae
A
1588}
1589
91447636
A
1590/*
1591 * Must be called with global ctl_mtx lock taked
1592 *
1593 */
1594static struct kctl *
1595ctl_find_by_id_unit(u_int32_t id, u_int32_t unit)
fe8ab488
A
1596{
1597 struct kctl *kctl;
1598
1599 lck_mtx_assert(ctl_mtx, LCK_MTX_ASSERT_OWNED);
1600
1601 TAILQ_FOREACH(kctl, &ctl_head, next) {
1602 if (kctl->id == id && (kctl->flags & CTL_FLAG_REG_ID_UNIT) == 0)
1603 return (kctl);
1604 else if (kctl->id == id && kctl->reg_unit == unit)
1605 return (kctl);
1606 }
1607 return (NULL);
9bccf70c
A
1608}
1609
1610/*
91447636 1611 * Must be called with kernel controller lock taken
9bccf70c 1612 */
91447636
A
1613static struct ctl_cb *
1614kcb_find(struct kctl *kctl, u_int32_t unit)
fe8ab488
A
1615{
1616 struct ctl_cb *kcb;
9bccf70c 1617
fe8ab488 1618 lck_mtx_assert(ctl_mtx, LCK_MTX_ASSERT_OWNED);
9bccf70c 1619
fe8ab488
A
1620 TAILQ_FOREACH(kcb, &kctl->kcb_head, next)
1621 if (kcb->unit == unit)
1622 return (kcb);
1623
1624 return (NULL);
9bccf70c
A
1625}
1626
6d2010ae 1627static struct socket *
3e170ce0 1628kcb_find_socket(kern_ctl_ref kctlref, u_int32_t unit, u_int32_t *kctlflags)
6d2010ae
A
1629{
1630 struct socket *so = NULL;
fe8ab488
A
1631 struct ctl_cb *kcb;
1632 void *lr_saved;
3e170ce0
A
1633 struct kctl *kctl;
1634 int i;
fe8ab488
A
1635
1636 lr_saved = __builtin_return_address(0);
1637
6d2010ae 1638 lck_mtx_lock(ctl_mtx);
3e170ce0
A
1639 /*
1640 * First validate the kctlref
1641 */
1642 if ((kctl = kctl_from_ref(kctlref)) == NULL) {
1643 kctlstat.kcs_bad_kctlref++;
1644 lck_mtx_unlock(ctl_mtx);
1645 if (ctl_debug != 0)
1646 printf("%s invalid kctlref %p\n",
1647 __func__, kctlref);
1648 return (NULL);
6d2010ae 1649 }
fe8ab488 1650
3e170ce0
A
1651 kcb = kcb_find(kctl, unit);
1652 if (kcb == NULL || kcb->kctl != kctl || (so = kcb->so) == NULL) {
1653 lck_mtx_unlock(ctl_mtx);
fe8ab488 1654 return (NULL);
6d2010ae 1655 }
3e170ce0
A
1656 /*
1657 * This prevents the socket from being closed
1658 */
1659 kcb->usecount++;
1660 /*
1661 * Respect lock ordering: socket before ctl_mtx
1662 */
1663 lck_mtx_unlock(ctl_mtx);
fe8ab488 1664
6d2010ae 1665 socket_lock(so, 1);
3e170ce0
A
1666 /*
1667 * The socket lock history is more useful if we store
1668 * the address of the caller.
1669 */
1670 i = (so->next_lock_lr + SO_LCKDBG_MAX - 1) % SO_LCKDBG_MAX;
1671 so->lock_lr[i] = lr_saved;
fe8ab488 1672
6d2010ae 1673 lck_mtx_lock(ctl_mtx);
3e170ce0
A
1674
1675 if ((kctl = kctl_from_ref(kctlref)) == NULL || kcb->kctl == NULL) {
6d2010ae
A
1676 lck_mtx_unlock(ctl_mtx);
1677 socket_unlock(so, 1);
1678 so = NULL;
1679 lck_mtx_lock(ctl_mtx);
3e170ce0
A
1680 } else if (kctlflags != NULL) {
1681 *kctlflags = kctl->flags;
6d2010ae 1682 }
3e170ce0 1683
6d2010ae
A
1684 kcb->usecount--;
1685 if (kcb->usecount == 0)
1686 wakeup((event_t)&kcb->usecount);
3e170ce0 1687
6d2010ae 1688 lck_mtx_unlock(ctl_mtx);
fe8ab488
A
1689
1690 return (so);
6d2010ae
A
1691}
1692
fe8ab488
A
1693static void
1694ctl_post_msg(u_int32_t event_code, u_int32_t id)
9bccf70c 1695{
fe8ab488
A
1696 struct ctl_event_data ctl_ev_data;
1697 struct kev_msg ev_msg;
1698
1699 lck_mtx_assert(ctl_mtx, LCK_MTX_ASSERT_NOTOWNED);
1700
1701 bzero(&ev_msg, sizeof(struct kev_msg));
1702 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1703
1704 ev_msg.kev_class = KEV_SYSTEM_CLASS;
1705 ev_msg.kev_subclass = KEV_CTL_SUBCLASS;
1706 ev_msg.event_code = event_code;
1707
1708 /* common nke subclass data */
1709 bzero(&ctl_ev_data, sizeof(ctl_ev_data));
1710 ctl_ev_data.ctl_id = id;
1711 ev_msg.dv[0].data_ptr = &ctl_ev_data;
1712 ev_msg.dv[0].data_length = sizeof(ctl_ev_data);
1713
1714 ev_msg.dv[1].data_length = 0;
1715
1716 kev_post_msg(&ev_msg);
9bccf70c
A
1717}
1718
91447636 1719static int
b0d623f7
A
1720ctl_lock(struct socket *so, int refcount, void *lr)
1721{
1722 void *lr_saved;
1723
1724 if (lr == NULL)
1725 lr_saved = __builtin_return_address(0);
1726 else
1727 lr_saved = lr;
1728
1729 if (so->so_pcb != NULL) {
91447636
A
1730 lck_mtx_lock(((struct ctl_cb *)so->so_pcb)->mtx);
1731 } else {
fe8ab488 1732 panic("ctl_lock: so=%p NO PCB! lr=%p lrh= %s\n",
b0d623f7
A
1733 so, lr_saved, solockhistory_nr(so));
1734 /* NOTREACHED */
91447636 1735 }
b0d623f7
A
1736
1737 if (so->so_usecount < 0) {
1738 panic("ctl_lock: so=%p so_pcb=%p lr=%p ref=%x lrh= %s\n",
fe8ab488
A
1739 so, so->so_pcb, lr_saved, so->so_usecount,
1740 solockhistory_nr(so));
b0d623f7
A
1741 /* NOTREACHED */
1742 }
1743
91447636
A
1744 if (refcount)
1745 so->so_usecount++;
0c530ab8 1746
2d21ac55 1747 so->lock_lr[so->next_lock_lr] = lr_saved;
0c530ab8 1748 so->next_lock_lr = (so->next_lock_lr+1) % SO_LCKDBG_MAX;
91447636
A
1749 return (0);
1750}
1751
1752static int
b0d623f7 1753ctl_unlock(struct socket *so, int refcount, void *lr)
91447636 1754{
b0d623f7
A
1755 void *lr_saved;
1756 lck_mtx_t *mutex_held;
1757
1758 if (lr == NULL)
1759 lr_saved = __builtin_return_address(0);
1760 else
1761 lr_saved = lr;
1762
91447636 1763#ifdef MORE_KCTLLOCK_DEBUG
fe8ab488
A
1764 printf("ctl_unlock: so=%llx sopcb=%x lock=%llx ref=%u lr=%llx\n",
1765 (uint64_t)VM_KERNEL_ADDRPERM(so),
1766 (uint64_t)VM_KERNEL_ADDRPERM(so->so_pcb,
1767 (uint64_t)VM_KERNEL_ADDRPERM(((struct ctl_cb *)so->so_pcb)->mtx),
1768 so->so_usecount, (uint64_t)VM_KERNEL_ADDRPERM(lr_saved));
91447636
A
1769#endif
1770 if (refcount)
1771 so->so_usecount--;
b0d623f7
A
1772
1773 if (so->so_usecount < 0) {
fe8ab488 1774 panic("ctl_unlock: so=%p usecount=%x lrh= %s\n",
b0d623f7
A
1775 so, so->so_usecount, solockhistory_nr(so));
1776 /* NOTREACHED */
1777 }
91447636 1778 if (so->so_pcb == NULL) {
fe8ab488
A
1779 panic("ctl_unlock: so=%p NO PCB usecount=%x lr=%p lrh= %s\n",
1780 so, so->so_usecount, (void *)lr_saved,
1781 solockhistory_nr(so));
b0d623f7 1782 /* NOTREACHED */
91447636 1783 }
b0d623f7
A
1784 mutex_held = ((struct ctl_cb *)so->so_pcb)->mtx;
1785
91447636 1786 lck_mtx_assert(mutex_held, LCK_MTX_ASSERT_OWNED);
2d21ac55 1787 so->unlock_lr[so->next_unlock_lr] = lr_saved;
0c530ab8 1788 so->next_unlock_lr = (so->next_unlock_lr+1) % SO_LCKDBG_MAX;
91447636 1789 lck_mtx_unlock(mutex_held);
b0d623f7 1790
91447636
A
1791 if (so->so_usecount == 0)
1792 ctl_sofreelastref(so);
b0d623f7 1793
91447636
A
1794 return (0);
1795}
1796
1797static lck_mtx_t *
fe8ab488 1798ctl_getlock(struct socket *so, int locktype)
91447636 1799{
fe8ab488 1800#pragma unused(locktype)
91447636 1801 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
fe8ab488 1802
91447636
A
1803 if (so->so_pcb) {
1804 if (so->so_usecount < 0)
fe8ab488 1805 panic("ctl_getlock: so=%p usecount=%x lrh= %s\n",
b0d623f7 1806 so, so->so_usecount, solockhistory_nr(so));
fe8ab488 1807 return (kcb->mtx);
91447636 1808 } else {
fe8ab488 1809 panic("ctl_getlock: so=%p NULL NO so_pcb %s\n",
b0d623f7 1810 so, solockhistory_nr(so));
91447636
A
1811 return (so->so_proto->pr_domain->dom_mtx);
1812 }
1813}
fe8ab488
A
1814
1815__private_extern__ int
1816kctl_reg_list SYSCTL_HANDLER_ARGS
1817{
1818#pragma unused(oidp, arg1, arg2)
1819 int error = 0;
1820 int n, i;
1821 struct xsystmgen xsg;
1822 void *buf = NULL;
1823 struct kctl *kctl;
1824 size_t item_size = ROUNDUP64(sizeof (struct xkctl_reg));
1825
1826 buf = _MALLOC(item_size, M_TEMP, M_WAITOK | M_ZERO);
1827 if (buf == NULL)
1828 return (ENOMEM);
1829
1830 lck_mtx_lock(ctl_mtx);
1831
1832 n = kctlstat.kcs_reg_count;
1833
1834 if (req->oldptr == USER_ADDR_NULL) {
1835 req->oldidx = (n + n/8) * sizeof(struct xkctl_reg);
1836 goto done;
1837 }
1838 if (req->newptr != USER_ADDR_NULL) {
1839 error = EPERM;
1840 goto done;
1841 }
1842 bzero(&xsg, sizeof (xsg));
1843 xsg.xg_len = sizeof (xsg);
1844 xsg.xg_count = n;
1845 xsg.xg_gen = kctlstat.kcs_gencnt;
1846 xsg.xg_sogen = so_gencnt;
1847 error = SYSCTL_OUT(req, &xsg, sizeof (xsg));
1848 if (error) {
1849 goto done;
1850 }
1851 /*
1852 * We are done if there is no pcb
1853 */
1854 if (n == 0) {
1855 goto done;
1856 }
1857
1858 i = 0;
1859 for (i = 0, kctl = TAILQ_FIRST(&ctl_head);
1860 i < n && kctl != NULL;
1861 i++, kctl = TAILQ_NEXT(kctl, next)) {
1862 struct xkctl_reg *xkr = (struct xkctl_reg *)buf;
1863 struct ctl_cb *kcb;
1864 u_int32_t pcbcount = 0;
1865
1866 TAILQ_FOREACH(kcb, &kctl->kcb_head, next)
1867 pcbcount++;
1868
1869 bzero(buf, item_size);
1870
1871 xkr->xkr_len = sizeof(struct xkctl_reg);
1872 xkr->xkr_kind = XSO_KCREG;
1873 xkr->xkr_id = kctl->id;
1874 xkr->xkr_reg_unit = kctl->reg_unit;
1875 xkr->xkr_flags = kctl->flags;
3e170ce0 1876 xkr->xkr_kctlref = (uint64_t)(kctl->kctlref);
fe8ab488
A
1877 xkr->xkr_recvbufsize = kctl->recvbufsize;
1878 xkr->xkr_sendbufsize = kctl->sendbufsize;
1879 xkr->xkr_lastunit = kctl->lastunit;
1880 xkr->xkr_pcbcount = pcbcount;
1881 xkr->xkr_connect = (uint64_t)VM_KERNEL_ADDRPERM(kctl->connect);
1882 xkr->xkr_disconnect =
1883 (uint64_t)VM_KERNEL_ADDRPERM(kctl->disconnect);
1884 xkr->xkr_send = (uint64_t)VM_KERNEL_ADDRPERM(kctl->send);
1885 xkr->xkr_send_list =
1886 (uint64_t)VM_KERNEL_ADDRPERM(kctl->send_list);
1887 xkr->xkr_setopt = (uint64_t)VM_KERNEL_ADDRPERM(kctl->setopt);
1888 xkr->xkr_getopt = (uint64_t)VM_KERNEL_ADDRPERM(kctl->getopt);
1889 xkr->xkr_rcvd = (uint64_t)VM_KERNEL_ADDRPERM(kctl->rcvd);
1890 strlcpy(xkr->xkr_name, kctl->name, sizeof(xkr->xkr_name));
1891
1892 error = SYSCTL_OUT(req, buf, item_size);
1893 }
1894
1895 if (error == 0) {
1896 /*
1897 * Give the user an updated idea of our state.
1898 * If the generation differs from what we told
1899 * her before, she knows that something happened
1900 * while we were processing this request, and it
1901 * might be necessary to retry.
1902 */
1903 bzero(&xsg, sizeof (xsg));
1904 xsg.xg_len = sizeof (xsg);
1905 xsg.xg_count = n;
1906 xsg.xg_gen = kctlstat.kcs_gencnt;
1907 xsg.xg_sogen = so_gencnt;
1908 error = SYSCTL_OUT(req, &xsg, sizeof (xsg));
1909 if (error) {
1910 goto done;
1911 }
1912 }
1913
1914done:
1915 lck_mtx_unlock(ctl_mtx);
1916
1917 if (buf != NULL)
1918 FREE(buf, M_TEMP);
1919
1920 return (error);
1921}
1922
1923__private_extern__ int
1924kctl_pcblist SYSCTL_HANDLER_ARGS
1925{
1926#pragma unused(oidp, arg1, arg2)
1927 int error = 0;
1928 int n, i;
1929 struct xsystmgen xsg;
1930 void *buf = NULL;
1931 struct kctl *kctl;
1932 size_t item_size = ROUNDUP64(sizeof (struct xkctlpcb)) +
1933 ROUNDUP64(sizeof (struct xsocket_n)) +
1934 2 * ROUNDUP64(sizeof (struct xsockbuf_n)) +
1935 ROUNDUP64(sizeof (struct xsockstat_n));
1936
1937 buf = _MALLOC(item_size, M_TEMP, M_WAITOK | M_ZERO);
1938 if (buf == NULL)
1939 return (ENOMEM);
1940
1941 lck_mtx_lock(ctl_mtx);
1942
1943 n = kctlstat.kcs_pcbcount;
1944
1945 if (req->oldptr == USER_ADDR_NULL) {
1946 req->oldidx = (n + n/8) * item_size;
1947 goto done;
1948 }
1949 if (req->newptr != USER_ADDR_NULL) {
1950 error = EPERM;
1951 goto done;
1952 }
1953 bzero(&xsg, sizeof (xsg));
1954 xsg.xg_len = sizeof (xsg);
1955 xsg.xg_count = n;
1956 xsg.xg_gen = kctlstat.kcs_gencnt;
1957 xsg.xg_sogen = so_gencnt;
1958 error = SYSCTL_OUT(req, &xsg, sizeof (xsg));
1959 if (error) {
1960 goto done;
1961 }
1962 /*
1963 * We are done if there is no pcb
1964 */
1965 if (n == 0) {
1966 goto done;
1967 }
1968
1969 i = 0;
1970 for (i = 0, kctl = TAILQ_FIRST(&ctl_head);
1971 i < n && kctl != NULL;
1972 kctl = TAILQ_NEXT(kctl, next)) {
1973 struct ctl_cb *kcb;
1974
1975 for (kcb = TAILQ_FIRST(&kctl->kcb_head);
1976 i < n && kcb != NULL;
1977 i++, kcb = TAILQ_NEXT(kcb, next)) {
1978 struct xkctlpcb *xk = (struct xkctlpcb *)buf;
1979 struct xsocket_n *xso = (struct xsocket_n *)
1980 ADVANCE64(xk, sizeof (*xk));
1981 struct xsockbuf_n *xsbrcv = (struct xsockbuf_n *)
1982 ADVANCE64(xso, sizeof (*xso));
1983 struct xsockbuf_n *xsbsnd = (struct xsockbuf_n *)
1984 ADVANCE64(xsbrcv, sizeof (*xsbrcv));
1985 struct xsockstat_n *xsostats = (struct xsockstat_n *)
1986 ADVANCE64(xsbsnd, sizeof (*xsbsnd));
1987
1988 bzero(buf, item_size);
1989
1990 xk->xkp_len = sizeof(struct xkctlpcb);
1991 xk->xkp_kind = XSO_KCB;
1992 xk->xkp_unit = kcb->unit;
1993 xk->xkp_kctpcb = (uint64_t)VM_KERNEL_ADDRPERM(kcb);
1994 xk->xkp_kctlref = (uint64_t)VM_KERNEL_ADDRPERM(kctl);
1995 xk->xkp_kctlid = kctl->id;
1996 strlcpy(xk->xkp_kctlname, kctl->name,
1997 sizeof(xk->xkp_kctlname));
1998
1999 sotoxsocket_n(kcb->so, xso);
2000 sbtoxsockbuf_n(kcb->so ?
2001 &kcb->so->so_rcv : NULL, xsbrcv);
2002 sbtoxsockbuf_n(kcb->so ?
2003 &kcb->so->so_snd : NULL, xsbsnd);
2004 sbtoxsockstat_n(kcb->so, xsostats);
2005
2006 error = SYSCTL_OUT(req, buf, item_size);
2007 }
2008 }
2009
2010 if (error == 0) {
2011 /*
2012 * Give the user an updated idea of our state.
2013 * If the generation differs from what we told
2014 * her before, she knows that something happened
2015 * while we were processing this request, and it
2016 * might be necessary to retry.
2017 */
2018 bzero(&xsg, sizeof (xsg));
2019 xsg.xg_len = sizeof (xsg);
2020 xsg.xg_count = n;
2021 xsg.xg_gen = kctlstat.kcs_gencnt;
2022 xsg.xg_sogen = so_gencnt;
2023 error = SYSCTL_OUT(req, &xsg, sizeof (xsg));
2024 if (error) {
2025 goto done;
2026 }
2027 }
2028
2029done:
2030 lck_mtx_unlock(ctl_mtx);
2031
2032 return (error);
2033}
2034
2035int
2036kctl_getstat SYSCTL_HANDLER_ARGS
2037{
2038#pragma unused(oidp, arg1, arg2)
2039 int error = 0;
2040
2041 lck_mtx_lock(ctl_mtx);
2042
2043 if (req->newptr != USER_ADDR_NULL) {
2044 error = EPERM;
2045 goto done;
2046 }
2047 if (req->oldptr == USER_ADDR_NULL) {
2048 req->oldidx = sizeof(struct kctlstat);
2049 goto done;
2050 }
2051
2052 error = SYSCTL_OUT(req, &kctlstat,
2053 MIN(sizeof(struct kctlstat), req->oldlen));
2054done:
2055 lck_mtx_unlock(ctl_mtx);
2056 return (error);
2057}
3e170ce0
A
2058
2059void
2060kctl_fill_socketinfo(struct socket *so, struct socket_info *si)
2061{
2062 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
2063 struct kern_ctl_info *kcsi =
2064 &si->soi_proto.pri_kern_ctl;
2065 struct kctl *kctl = kcb->kctl;
2066
2067 si->soi_kind = SOCKINFO_KERN_CTL;
2068
2069 if (kctl == 0)
2070 return;
2071
2072 kcsi->kcsi_id = kctl->id;
2073 kcsi->kcsi_reg_unit = kctl->reg_unit;
2074 kcsi->kcsi_flags = kctl->flags;
2075 kcsi->kcsi_recvbufsize = kctl->recvbufsize;
2076 kcsi->kcsi_sendbufsize = kctl->sendbufsize;
2077 kcsi->kcsi_unit = kcb->unit;
2078 strlcpy(kcsi->kcsi_name, kctl->name, MAX_KCTL_NAME);
2079}