- int error = 0;
- int n, i;
- struct xsystmgen xsg;
- void *buf = NULL;
- struct kctl *kctl;
- size_t item_size = ROUNDUP64(sizeof (struct xkctl_reg));
-
- buf = _MALLOC(item_size, M_TEMP, M_WAITOK | M_ZERO);
- if (buf == NULL)
- return (ENOMEM);
-
- lck_mtx_lock(ctl_mtx);
-
- n = kctlstat.kcs_reg_count;
-
- if (req->oldptr == USER_ADDR_NULL) {
- req->oldidx = (n + n/8) * sizeof(struct xkctl_reg);
- goto done;
- }
- if (req->newptr != USER_ADDR_NULL) {
- error = EPERM;
- goto done;
- }
- bzero(&xsg, sizeof (xsg));
- xsg.xg_len = sizeof (xsg);
- xsg.xg_count = n;
- xsg.xg_gen = kctlstat.kcs_gencnt;
- xsg.xg_sogen = so_gencnt;
- error = SYSCTL_OUT(req, &xsg, sizeof (xsg));
- if (error) {
- goto done;
- }
- /*
- * We are done if there is no pcb
- */
- if (n == 0) {
- goto done;
- }
-
- i = 0;
- for (i = 0, kctl = TAILQ_FIRST(&ctl_head);
- i < n && kctl != NULL;
- i++, kctl = TAILQ_NEXT(kctl, next)) {
- struct xkctl_reg *xkr = (struct xkctl_reg *)buf;
- struct ctl_cb *kcb;
- u_int32_t pcbcount = 0;
-
- TAILQ_FOREACH(kcb, &kctl->kcb_head, next)
- pcbcount++;
-
- bzero(buf, item_size);
-
- xkr->xkr_len = sizeof(struct xkctl_reg);
- xkr->xkr_kind = XSO_KCREG;
- xkr->xkr_id = kctl->id;
- xkr->xkr_reg_unit = kctl->reg_unit;
- xkr->xkr_flags = kctl->flags;
- xkr->xkr_kctlref = (uint64_t)(kctl->kctlref);
- xkr->xkr_recvbufsize = kctl->recvbufsize;
- xkr->xkr_sendbufsize = kctl->sendbufsize;
- xkr->xkr_lastunit = kctl->lastunit;
- xkr->xkr_pcbcount = pcbcount;
- xkr->xkr_connect = (uint64_t)VM_KERNEL_UNSLIDE(kctl->connect);
- xkr->xkr_disconnect =
- (uint64_t)VM_KERNEL_UNSLIDE(kctl->disconnect);
- xkr->xkr_send = (uint64_t)VM_KERNEL_UNSLIDE(kctl->send);
- xkr->xkr_send_list =
- (uint64_t)VM_KERNEL_UNSLIDE(kctl->send_list);
- xkr->xkr_setopt = (uint64_t)VM_KERNEL_UNSLIDE(kctl->setopt);
- xkr->xkr_getopt = (uint64_t)VM_KERNEL_UNSLIDE(kctl->getopt);
- xkr->xkr_rcvd = (uint64_t)VM_KERNEL_UNSLIDE(kctl->rcvd);
- strlcpy(xkr->xkr_name, kctl->name, sizeof(xkr->xkr_name));
-
- error = SYSCTL_OUT(req, buf, item_size);
- }
-
- if (error == 0) {
- /*
- * Give the user an updated idea of our state.
- * If the generation differs from what we told
- * her before, she knows that something happened
- * while we were processing this request, and it
- * might be necessary to retry.
- */
- bzero(&xsg, sizeof (xsg));
- xsg.xg_len = sizeof (xsg);
- xsg.xg_count = n;
- xsg.xg_gen = kctlstat.kcs_gencnt;
- xsg.xg_sogen = so_gencnt;
- error = SYSCTL_OUT(req, &xsg, sizeof (xsg));
- if (error) {
- goto done;
+ int error = 0;
+ u_int64_t i, n;
+ struct xsystmgen xsg;
+ void *buf = NULL;
+ struct kctl *kctl;
+ size_t item_size = ROUNDUP64(sizeof(struct xkctl_reg));
+
+ buf = kheap_alloc(KHEAP_TEMP, item_size, Z_WAITOK | Z_ZERO);
+ if (buf == NULL) {
+ return ENOMEM;
+ }
+
+ lck_mtx_lock(&ctl_mtx);
+
+ n = kctlstat.kcs_reg_count;
+
+ if (req->oldptr == USER_ADDR_NULL) {
+ req->oldidx = (size_t)(n + n / 8) * sizeof(struct xkctl_reg);
+ goto done;
+ }
+ if (req->newptr != USER_ADDR_NULL) {
+ error = EPERM;
+ goto done;
+ }
+ bzero(&xsg, sizeof(xsg));
+ xsg.xg_len = sizeof(xsg);
+ xsg.xg_count = n;
+ xsg.xg_gen = kctlstat.kcs_gencnt;
+ xsg.xg_sogen = so_gencnt;
+ error = SYSCTL_OUT(req, &xsg, sizeof(xsg));
+ if (error) {
+ goto done;
+ }
+ /*
+ * We are done if there is no pcb
+ */
+ if (n == 0) {
+ goto done;
+ }
+
+ for (i = 0, kctl = TAILQ_FIRST(&ctl_head);
+ i < n && kctl != NULL;
+ i++, kctl = TAILQ_NEXT(kctl, next)) {
+ struct xkctl_reg *xkr = (struct xkctl_reg *)buf;
+ struct ctl_cb *kcb;
+ u_int32_t pcbcount = 0;
+
+ TAILQ_FOREACH(kcb, &kctl->kcb_head, next)
+ pcbcount++;
+
+ bzero(buf, item_size);
+
+ xkr->xkr_len = sizeof(struct xkctl_reg);
+ xkr->xkr_kind = XSO_KCREG;
+ xkr->xkr_id = kctl->id;
+ xkr->xkr_reg_unit = kctl->reg_unit;
+ xkr->xkr_flags = kctl->flags;
+ xkr->xkr_kctlref = (uint64_t)(kctl->kctlref);
+ xkr->xkr_recvbufsize = kctl->recvbufsize;
+ xkr->xkr_sendbufsize = kctl->sendbufsize;
+ xkr->xkr_lastunit = kctl->lastunit;
+ xkr->xkr_pcbcount = pcbcount;
+ xkr->xkr_connect = (uint64_t)VM_KERNEL_UNSLIDE(kctl->connect);
+ xkr->xkr_disconnect =
+ (uint64_t)VM_KERNEL_UNSLIDE(kctl->disconnect);
+ xkr->xkr_send = (uint64_t)VM_KERNEL_UNSLIDE(kctl->send);
+ xkr->xkr_send_list =
+ (uint64_t)VM_KERNEL_UNSLIDE(kctl->send_list);
+ xkr->xkr_setopt = (uint64_t)VM_KERNEL_UNSLIDE(kctl->setopt);
+ xkr->xkr_getopt = (uint64_t)VM_KERNEL_UNSLIDE(kctl->getopt);
+ xkr->xkr_rcvd = (uint64_t)VM_KERNEL_UNSLIDE(kctl->rcvd);
+ strlcpy(xkr->xkr_name, kctl->name, sizeof(xkr->xkr_name));
+
+ error = SYSCTL_OUT(req, buf, item_size);
+ }
+
+ if (error == 0) {
+ /*
+ * Give the user an updated idea of our state.
+ * If the generation differs from what we told
+ * her before, she knows that something happened
+ * while we were processing this request, and it
+ * might be necessary to retry.
+ */
+ bzero(&xsg, sizeof(xsg));
+ xsg.xg_len = sizeof(xsg);
+ xsg.xg_count = n;
+ xsg.xg_gen = kctlstat.kcs_gencnt;
+ xsg.xg_sogen = so_gencnt;
+ error = SYSCTL_OUT(req, &xsg, sizeof(xsg));
+ if (error) {
+ goto done;