1*bbb1b6f9SApple OSS Distributions /*
2*bbb1b6f9SApple OSS Distributions * Copyright (c) 2023 Apple Computer, Inc. All rights reserved.
3*bbb1b6f9SApple OSS Distributions *
4*bbb1b6f9SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*bbb1b6f9SApple OSS Distributions *
6*bbb1b6f9SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*bbb1b6f9SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*bbb1b6f9SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*bbb1b6f9SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*bbb1b6f9SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*bbb1b6f9SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*bbb1b6f9SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*bbb1b6f9SApple OSS Distributions * terms of an Apple operating system software license agreement.
14*bbb1b6f9SApple OSS Distributions *
15*bbb1b6f9SApple OSS Distributions * Please obtain a copy of the License at
16*bbb1b6f9SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*bbb1b6f9SApple OSS Distributions *
18*bbb1b6f9SApple OSS Distributions * The Original Code and all software distributed under the License are
19*bbb1b6f9SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*bbb1b6f9SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*bbb1b6f9SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*bbb1b6f9SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*bbb1b6f9SApple OSS Distributions * Please see the License for the specific language governing rights and
24*bbb1b6f9SApple OSS Distributions * limitations under the License.
25*bbb1b6f9SApple OSS Distributions *
26*bbb1b6f9SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*bbb1b6f9SApple OSS Distributions */
28*bbb1b6f9SApple OSS Distributions
29*bbb1b6f9SApple OSS Distributions #include <mach/vm_types.h>
30*bbb1b6f9SApple OSS Distributions #include <mach/kmod.h>
31*bbb1b6f9SApple OSS Distributions #include <sys/socket.h>
32*bbb1b6f9SApple OSS Distributions #include <sys/syslog.h>
33*bbb1b6f9SApple OSS Distributions #include <sys/errno.h>
34*bbb1b6f9SApple OSS Distributions #include <netinet/in.h>
35*bbb1b6f9SApple OSS Distributions
36*bbb1b6f9SApple OSS Distributions #include <sys/kern_control.h>
37*bbb1b6f9SApple OSS Distributions #include <libkern/libkern.h>
38*bbb1b6f9SApple OSS Distributions #include <os/log.h>
39*bbb1b6f9SApple OSS Distributions
40*bbb1b6f9SApple OSS Distributions #include <net/kctl_test.h>
41*bbb1b6f9SApple OSS Distributions
42*bbb1b6f9SApple OSS Distributions static errno_t kctl_test_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, void **unitinfo);
43*bbb1b6f9SApple OSS Distributions static errno_t kctl_test_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo);
44*bbb1b6f9SApple OSS Distributions static errno_t kctl_test_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, mbuf_t m, int flags);
45*bbb1b6f9SApple OSS Distributions static errno_t kctl_test_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt, void *data, size_t len);
46*bbb1b6f9SApple OSS Distributions static errno_t kctl_test_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt, void *data, size_t *len);
47*bbb1b6f9SApple OSS Distributions static errno_t kctl_test_send_list(kern_ctl_ref kctlref, u_int32_t unit,
48*bbb1b6f9SApple OSS Distributions void *unitinfo, mbuf_t m, int flags);
49*bbb1b6f9SApple OSS Distributions
50*bbb1b6f9SApple OSS Distributions static struct kern_ctl_reg kctl_test_reg = {
51*bbb1b6f9SApple OSS Distributions .ctl_name = KCTL_TEST_CONTROL_NAME,
52*bbb1b6f9SApple OSS Distributions .ctl_id = 0,
53*bbb1b6f9SApple OSS Distributions .ctl_unit = 0,
54*bbb1b6f9SApple OSS Distributions .ctl_flags = CTL_FLAG_PRIVILEGED | CTL_FLAG_REG_EXTENDED,
55*bbb1b6f9SApple OSS Distributions .ctl_sendsize = 256 * 1024, /* 256 KiB */
56*bbb1b6f9SApple OSS Distributions .ctl_recvsize = 2 * 1024 * 1024, /* 2 MiB */
57*bbb1b6f9SApple OSS Distributions .ctl_connect = kctl_test_connect,
58*bbb1b6f9SApple OSS Distributions .ctl_disconnect = kctl_test_disconnect,
59*bbb1b6f9SApple OSS Distributions .ctl_send = kctl_test_send,
60*bbb1b6f9SApple OSS Distributions .ctl_setopt = kctl_test_setopt,
61*bbb1b6f9SApple OSS Distributions .ctl_getopt = kctl_test_getopt,
62*bbb1b6f9SApple OSS Distributions .ctl_send_list = kctl_test_send_list
63*bbb1b6f9SApple OSS Distributions };
64*bbb1b6f9SApple OSS Distributions static kern_ctl_ref kctl_test_ref;
65*bbb1b6f9SApple OSS Distributions static u_int32_t kctl_test_id;
66*bbb1b6f9SApple OSS Distributions
67*bbb1b6f9SApple OSS Distributions
68*bbb1b6f9SApple OSS Distributions static errno_t
kctl_test_connect(kern_ctl_ref kctlref,struct sockaddr_ctl * sac,void ** unitinfo)69*bbb1b6f9SApple OSS Distributions kctl_test_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, void **unitinfo)
70*bbb1b6f9SApple OSS Distributions {
71*bbb1b6f9SApple OSS Distributions #pragma unused(unitinfo)
72*bbb1b6f9SApple OSS Distributions errno_t error = 0;
73*bbb1b6f9SApple OSS Distributions size_t space;
74*bbb1b6f9SApple OSS Distributions
75*bbb1b6f9SApple OSS Distributions os_log(OS_LOG_DEFAULT, "kctl_test_connect: ref %p id %u port %u",
76*bbb1b6f9SApple OSS Distributions kctlref, sac->sc_id, sac->sc_unit);
77*bbb1b6f9SApple OSS Distributions
78*bbb1b6f9SApple OSS Distributions error = ctl_getenqueuespace(kctlref, sac->sc_unit, &space);
79*bbb1b6f9SApple OSS Distributions if (error != 0) {
80*bbb1b6f9SApple OSS Distributions os_log(OS_LOG_DEFAULT, "kctl_test_connect; ctl_getenqueuespace failed %d", error);
81*bbb1b6f9SApple OSS Distributions goto out;
82*bbb1b6f9SApple OSS Distributions }
83*bbb1b6f9SApple OSS Distributions os_log(OS_LOG_DEFAULT, "kctl_test_connect: ctl_getenqueuespace %ld", space);
84*bbb1b6f9SApple OSS Distributions out:
85*bbb1b6f9SApple OSS Distributions return error;
86*bbb1b6f9SApple OSS Distributions }
87*bbb1b6f9SApple OSS Distributions
88*bbb1b6f9SApple OSS Distributions static errno_t
kctl_test_disconnect(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo)89*bbb1b6f9SApple OSS Distributions kctl_test_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo)
90*bbb1b6f9SApple OSS Distributions {
91*bbb1b6f9SApple OSS Distributions #pragma unused(unitinfo)
92*bbb1b6f9SApple OSS Distributions errno_t error = 0;
93*bbb1b6f9SApple OSS Distributions size_t space;
94*bbb1b6f9SApple OSS Distributions
95*bbb1b6f9SApple OSS Distributions os_log(OS_LOG_DEFAULT, "kctl_test_disconnect: ref %p", kctlref);
96*bbb1b6f9SApple OSS Distributions
97*bbb1b6f9SApple OSS Distributions error = ctl_getenqueuespace(kctlref, unit, &space);
98*bbb1b6f9SApple OSS Distributions if (error != 0) {
99*bbb1b6f9SApple OSS Distributions os_log(OS_LOG_DEFAULT, "kctl_test_disconnect; ctl_getenqueuespace failed %d", error);
100*bbb1b6f9SApple OSS Distributions goto out;
101*bbb1b6f9SApple OSS Distributions }
102*bbb1b6f9SApple OSS Distributions os_log(OS_LOG_DEFAULT, "kctl_test_disconnect: ctl_getenqueuespace %ld", space);
103*bbb1b6f9SApple OSS Distributions out:
104*bbb1b6f9SApple OSS Distributions
105*bbb1b6f9SApple OSS Distributions return error;
106*bbb1b6f9SApple OSS Distributions }
107*bbb1b6f9SApple OSS Distributions
108*bbb1b6f9SApple OSS Distributions static errno_t
kctl_test_send(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo,mbuf_t m,int flags)109*bbb1b6f9SApple OSS Distributions kctl_test_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, mbuf_t m, int flags)
110*bbb1b6f9SApple OSS Distributions {
111*bbb1b6f9SApple OSS Distributions #pragma unused(unitinfo, flags)
112*bbb1b6f9SApple OSS Distributions errno_t error = 0;
113*bbb1b6f9SApple OSS Distributions
114*bbb1b6f9SApple OSS Distributions error = ctl_enqueuembuf(kctlref, unit, m, CTL_DATA_EOR);
115*bbb1b6f9SApple OSS Distributions if (error != 0) {
116*bbb1b6f9SApple OSS Distributions os_log(OS_LOG_DEFAULT, "kctl_test_send: ctl_enqueuembuf() failed %d", error);
117*bbb1b6f9SApple OSS Distributions mbuf_freem(m);
118*bbb1b6f9SApple OSS Distributions }
119*bbb1b6f9SApple OSS Distributions
120*bbb1b6f9SApple OSS Distributions return error;
121*bbb1b6f9SApple OSS Distributions }
122*bbb1b6f9SApple OSS Distributions
123*bbb1b6f9SApple OSS Distributions static int optval = 0;
124*bbb1b6f9SApple OSS Distributions
125*bbb1b6f9SApple OSS Distributions static errno_t
kctl_test_setopt(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo,int opt,void * data,size_t len)126*bbb1b6f9SApple OSS Distributions kctl_test_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt, void *data, size_t len)
127*bbb1b6f9SApple OSS Distributions {
128*bbb1b6f9SApple OSS Distributions #pragma unused(unit, unitinfo)
129*bbb1b6f9SApple OSS Distributions errno_t error = 0;
130*bbb1b6f9SApple OSS Distributions
131*bbb1b6f9SApple OSS Distributions os_log(OS_LOG_DEFAULT, "kctl_test_setopt: ref %p", kctlref);
132*bbb1b6f9SApple OSS Distributions
133*bbb1b6f9SApple OSS Distributions switch (opt) {
134*bbb1b6f9SApple OSS Distributions case 0:
135*bbb1b6f9SApple OSS Distributions if (len < sizeof(int)) {
136*bbb1b6f9SApple OSS Distributions error = EINVAL;
137*bbb1b6f9SApple OSS Distributions } else {
138*bbb1b6f9SApple OSS Distributions optval = *(int*)data;
139*bbb1b6f9SApple OSS Distributions }
140*bbb1b6f9SApple OSS Distributions break;
141*bbb1b6f9SApple OSS Distributions default:
142*bbb1b6f9SApple OSS Distributions error = ENOPROTOOPT;
143*bbb1b6f9SApple OSS Distributions break;
144*bbb1b6f9SApple OSS Distributions }
145*bbb1b6f9SApple OSS Distributions
146*bbb1b6f9SApple OSS Distributions return error;
147*bbb1b6f9SApple OSS Distributions }
148*bbb1b6f9SApple OSS Distributions
149*bbb1b6f9SApple OSS Distributions static errno_t
kctl_test_getopt(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo,int opt,void * data,size_t * len)150*bbb1b6f9SApple OSS Distributions kctl_test_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt, void *data, size_t *len)
151*bbb1b6f9SApple OSS Distributions {
152*bbb1b6f9SApple OSS Distributions #pragma unused(unitinfo, unit)
153*bbb1b6f9SApple OSS Distributions errno_t error = 0;
154*bbb1b6f9SApple OSS Distributions
155*bbb1b6f9SApple OSS Distributions os_log(OS_LOG_DEFAULT, "kctl_test_getopt: ref %p", kctlref);
156*bbb1b6f9SApple OSS Distributions
157*bbb1b6f9SApple OSS Distributions switch (opt) {
158*bbb1b6f9SApple OSS Distributions case 0:
159*bbb1b6f9SApple OSS Distributions if (*len < sizeof(int)) {
160*bbb1b6f9SApple OSS Distributions error = EINVAL;
161*bbb1b6f9SApple OSS Distributions } else {
162*bbb1b6f9SApple OSS Distributions *(int*)data = optval;
163*bbb1b6f9SApple OSS Distributions *len = sizeof(int);
164*bbb1b6f9SApple OSS Distributions }
165*bbb1b6f9SApple OSS Distributions break;
166*bbb1b6f9SApple OSS Distributions default:
167*bbb1b6f9SApple OSS Distributions error = ENOPROTOOPT;
168*bbb1b6f9SApple OSS Distributions break;
169*bbb1b6f9SApple OSS Distributions }
170*bbb1b6f9SApple OSS Distributions
171*bbb1b6f9SApple OSS Distributions return error;
172*bbb1b6f9SApple OSS Distributions }
173*bbb1b6f9SApple OSS Distributions
174*bbb1b6f9SApple OSS Distributions static errno_t
kctl_test_send_list(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo,mbuf_t m,int flags)175*bbb1b6f9SApple OSS Distributions kctl_test_send_list(kern_ctl_ref kctlref, u_int32_t unit,
176*bbb1b6f9SApple OSS Distributions void *unitinfo, mbuf_t m, int flags)
177*bbb1b6f9SApple OSS Distributions {
178*bbb1b6f9SApple OSS Distributions #pragma unused(unitinfo)
179*bbb1b6f9SApple OSS Distributions errno_t error = 0;
180*bbb1b6f9SApple OSS Distributions mbuf_ref_t m_remain = NULL;
181*bbb1b6f9SApple OSS Distributions uint32_t unsent_count = 0;
182*bbb1b6f9SApple OSS Distributions
183*bbb1b6f9SApple OSS Distributions error = ctl_enqueuembuf_list(kctlref, unit, m, flags, &m_remain);
184*bbb1b6f9SApple OSS Distributions if (m_remain != NULL) {
185*bbb1b6f9SApple OSS Distributions mbuf_ref_t tmp = m_remain;
186*bbb1b6f9SApple OSS Distributions
187*bbb1b6f9SApple OSS Distributions while (tmp != NULL) {
188*bbb1b6f9SApple OSS Distributions unsent_count += 1;
189*bbb1b6f9SApple OSS Distributions tmp = mbuf_next(tmp);
190*bbb1b6f9SApple OSS Distributions }
191*bbb1b6f9SApple OSS Distributions
192*bbb1b6f9SApple OSS Distributions mbuf_freem_list(m_remain);
193*bbb1b6f9SApple OSS Distributions }
194*bbb1b6f9SApple OSS Distributions if (error != 0) {
195*bbb1b6f9SApple OSS Distributions os_log(OS_LOG_DEFAULT, "kctl_test_send_list: ctl_enqueuembuf_list() error %d unsent packets %u",
196*bbb1b6f9SApple OSS Distributions error, unsent_count);
197*bbb1b6f9SApple OSS Distributions }
198*bbb1b6f9SApple OSS Distributions return error;
199*bbb1b6f9SApple OSS Distributions }
200*bbb1b6f9SApple OSS Distributions
201*bbb1b6f9SApple OSS Distributions int
kctl_test_init(void)202*bbb1b6f9SApple OSS Distributions kctl_test_init(void)
203*bbb1b6f9SApple OSS Distributions {
204*bbb1b6f9SApple OSS Distributions errno_t error = 0;
205*bbb1b6f9SApple OSS Distributions struct kern_ctl_reg kern_ctl_reg = kctl_test_reg;
206*bbb1b6f9SApple OSS Distributions
207*bbb1b6f9SApple OSS Distributions os_log(OS_LOG_DEFAULT, "kctl_test_init ctl_sendsize %u ctl_recvsize %u",
208*bbb1b6f9SApple OSS Distributions kctl_test_reg.ctl_sendsize, kctl_test_reg.ctl_recvsize);
209*bbb1b6f9SApple OSS Distributions
210*bbb1b6f9SApple OSS Distributions error = ctl_register(&kern_ctl_reg, &kctl_test_ref);
211*bbb1b6f9SApple OSS Distributions if (error == 0) {
212*bbb1b6f9SApple OSS Distributions kctl_test_id = kern_ctl_reg.ctl_id;
213*bbb1b6f9SApple OSS Distributions os_log(OS_LOG_DEFAULT, "kctl_test_register: OK kctlref %p kctlid %x ctl_sendsize %u ctl_recvsize %u",
214*bbb1b6f9SApple OSS Distributions kctl_test_ref, kctl_test_id, kern_ctl_reg.ctl_sendsize, kern_ctl_reg.ctl_recvsize);
215*bbb1b6f9SApple OSS Distributions } else {
216*bbb1b6f9SApple OSS Distributions os_log(OS_LOG_DEFAULT, "kctl_test_register: error %d", error);
217*bbb1b6f9SApple OSS Distributions }
218*bbb1b6f9SApple OSS Distributions return (error == 0) ? KERN_SUCCESS : KERN_FAILURE;
219*bbb1b6f9SApple OSS Distributions }
220