xref: /freebsd/sys/compat/linux/linux_mib.c (revision b62f75cf4406c25c5910775e81241f19ccc77e99)
1c6dfea0eSMarcel Moolenaar /*-
2c6dfea0eSMarcel Moolenaar  * Copyright (c) 1999 Marcel Moolenaar
3c6dfea0eSMarcel Moolenaar  * All rights reserved.
4c6dfea0eSMarcel Moolenaar  *
5c6dfea0eSMarcel Moolenaar  * Redistribution and use in source and binary forms, with or without
6c6dfea0eSMarcel Moolenaar  * modification, are permitted provided that the following conditions
7c6dfea0eSMarcel Moolenaar  * are met:
8c6dfea0eSMarcel Moolenaar  * 1. Redistributions of source code must retain the above copyright
9c6dfea0eSMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer
10c6dfea0eSMarcel Moolenaar  *    in this position and unchanged.
11c6dfea0eSMarcel Moolenaar  * 2. Redistributions in binary form must reproduce the above copyright
12c6dfea0eSMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer in the
13c6dfea0eSMarcel Moolenaar  *    documentation and/or other materials provided with the distribution.
14c6dfea0eSMarcel Moolenaar  * 3. The name of the author may not be used to endorse or promote products
15bc34729cSMarcel Moolenaar  *    derived from this software without specific prior written permission.
16c6dfea0eSMarcel Moolenaar  *
17c6dfea0eSMarcel Moolenaar  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18c6dfea0eSMarcel Moolenaar  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19c6dfea0eSMarcel Moolenaar  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20c6dfea0eSMarcel Moolenaar  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21c6dfea0eSMarcel Moolenaar  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22c6dfea0eSMarcel Moolenaar  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23c6dfea0eSMarcel Moolenaar  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24c6dfea0eSMarcel Moolenaar  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25c6dfea0eSMarcel Moolenaar  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26c6dfea0eSMarcel Moolenaar  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27c6dfea0eSMarcel Moolenaar  *
2828065282SPeter Wemm  * $FreeBSD$
29c6dfea0eSMarcel Moolenaar  */
30c6dfea0eSMarcel Moolenaar 
31c6dfea0eSMarcel Moolenaar #include <sys/param.h>
32c6dfea0eSMarcel Moolenaar #include <sys/kernel.h>
33c6dfea0eSMarcel Moolenaar #include <sys/systm.h>
34c6dfea0eSMarcel Moolenaar #include <sys/sysctl.h>
35c6dfea0eSMarcel Moolenaar #include <sys/proc.h>
36c6dfea0eSMarcel Moolenaar #include <sys/malloc.h>
37c6dfea0eSMarcel Moolenaar #include <sys/jail.h>
3801137630SRobert Watson #include <sys/lock.h>
3901137630SRobert Watson #include <sys/mutex.h>
40c6dfea0eSMarcel Moolenaar 
41607d46efSMarcel Moolenaar #include <machine/../linux/linux.h>
42607d46efSMarcel Moolenaar #include <compat/linux/linux_mib.h>
43c6dfea0eSMarcel Moolenaar 
44c6dfea0eSMarcel Moolenaar struct linux_prison {
45c6dfea0eSMarcel Moolenaar 	char	pr_osname[LINUX_MAX_UTSNAME];
46c6dfea0eSMarcel Moolenaar 	char	pr_osrelease[LINUX_MAX_UTSNAME];
47c6dfea0eSMarcel Moolenaar 	int	pr_oss_version;
48c6dfea0eSMarcel Moolenaar };
49c6dfea0eSMarcel Moolenaar 
50c6dfea0eSMarcel Moolenaar SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0,
51c6dfea0eSMarcel Moolenaar 	    "Linux mode");
52c6dfea0eSMarcel Moolenaar 
53b62f75cfSJohn Baldwin static struct mtx osname_lock;
54b62f75cfSJohn Baldwin MTX_SYSINIT(linux_osname, &osname_lock, "linux osname", MTX_DEF);
55b62f75cfSJohn Baldwin 
56c6dfea0eSMarcel Moolenaar static char	linux_osname[LINUX_MAX_UTSNAME] = "Linux";
57c6dfea0eSMarcel Moolenaar 
58c6dfea0eSMarcel Moolenaar static int
5982d9ae4eSPoul-Henning Kamp linux_sysctl_osname(SYSCTL_HANDLER_ARGS)
60c6dfea0eSMarcel Moolenaar {
61c6dfea0eSMarcel Moolenaar 	char osname[LINUX_MAX_UTSNAME];
62c6dfea0eSMarcel Moolenaar 	int error;
63c6dfea0eSMarcel Moolenaar 
64b62f75cfSJohn Baldwin 	linux_get_osname(req->td, osname);
65c6dfea0eSMarcel Moolenaar 	error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req);
66c6dfea0eSMarcel Moolenaar 	if (error || req->newptr == NULL)
67c6dfea0eSMarcel Moolenaar 		return (error);
68b62f75cfSJohn Baldwin 	error = linux_set_osname(req->td, osname);
69c6dfea0eSMarcel Moolenaar 	return (error);
70c6dfea0eSMarcel Moolenaar }
71c6dfea0eSMarcel Moolenaar 
72c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, osname,
73c6dfea0eSMarcel Moolenaar 	    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON,
74c6dfea0eSMarcel Moolenaar 	    0, 0, linux_sysctl_osname, "A",
75c6dfea0eSMarcel Moolenaar 	    "Linux kernel OS name");
76c6dfea0eSMarcel Moolenaar 
775002a60fSMarcel Moolenaar static char	linux_osrelease[LINUX_MAX_UTSNAME] = "2.4.2";
78c6dfea0eSMarcel Moolenaar 
79c6dfea0eSMarcel Moolenaar static int
8082d9ae4eSPoul-Henning Kamp linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS)
81c6dfea0eSMarcel Moolenaar {
82c6dfea0eSMarcel Moolenaar 	char osrelease[LINUX_MAX_UTSNAME];
83c6dfea0eSMarcel Moolenaar 	int error;
84c6dfea0eSMarcel Moolenaar 
85b62f75cfSJohn Baldwin 	linux_get_osrelease(req->td, osrelease);
86c6dfea0eSMarcel Moolenaar 	error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req);
87c6dfea0eSMarcel Moolenaar 	if (error || req->newptr == NULL)
88c6dfea0eSMarcel Moolenaar 		return (error);
89b62f75cfSJohn Baldwin 	error = linux_set_osrelease(req->td, osrelease);
90c6dfea0eSMarcel Moolenaar 	return (error);
91c6dfea0eSMarcel Moolenaar }
92c6dfea0eSMarcel Moolenaar 
93c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, osrelease,
94c6dfea0eSMarcel Moolenaar 	    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON,
95c6dfea0eSMarcel Moolenaar 	    0, 0, linux_sysctl_osrelease, "A",
96c6dfea0eSMarcel Moolenaar 	    "Linux kernel OS release");
97c6dfea0eSMarcel Moolenaar 
98c6dfea0eSMarcel Moolenaar static int	linux_oss_version = 0x030600;
99c6dfea0eSMarcel Moolenaar 
100c6dfea0eSMarcel Moolenaar static int
10182d9ae4eSPoul-Henning Kamp linux_sysctl_oss_version(SYSCTL_HANDLER_ARGS)
102c6dfea0eSMarcel Moolenaar {
103c6dfea0eSMarcel Moolenaar 	int oss_version;
104c6dfea0eSMarcel Moolenaar 	int error;
105c6dfea0eSMarcel Moolenaar 
106b62f75cfSJohn Baldwin 	oss_version = linux_get_oss_version(req->td);
107c6dfea0eSMarcel Moolenaar 	error = sysctl_handle_int(oidp, &oss_version, 0, req);
108c6dfea0eSMarcel Moolenaar 	if (error || req->newptr == NULL)
109c6dfea0eSMarcel Moolenaar 		return (error);
110b62f75cfSJohn Baldwin 	error = linux_set_oss_version(req->td, oss_version);
111c6dfea0eSMarcel Moolenaar 	return (error);
112c6dfea0eSMarcel Moolenaar }
113c6dfea0eSMarcel Moolenaar 
114c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, oss_version,
115c6dfea0eSMarcel Moolenaar 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON,
116c6dfea0eSMarcel Moolenaar 	    0, 0, linux_sysctl_oss_version, "I",
117c6dfea0eSMarcel Moolenaar 	    "Linux OSS version");
118c6dfea0eSMarcel Moolenaar 
11901137630SRobert Watson /*
12001137630SRobert Watson  * Returns holding the prison mutex if return non-NULL.
12101137630SRobert Watson  */
122b62f75cfSJohn Baldwin static struct prison *
123b62f75cfSJohn Baldwin linux_get_prison(struct thread *td)
124c6dfea0eSMarcel Moolenaar {
125c6dfea0eSMarcel Moolenaar 	register struct prison *pr;
126c6dfea0eSMarcel Moolenaar 	register struct linux_prison *lpr;
127c6dfea0eSMarcel Moolenaar 
128b62f75cfSJohn Baldwin 	KASSERT(td == curthread, ("linux_get_prison() called on !curthread"));
129b62f75cfSJohn Baldwin 	if (!jailed(td->td_ucred))
130c6dfea0eSMarcel Moolenaar 		return (NULL);
131b62f75cfSJohn Baldwin 	pr = td->td_ucred->cr_prison;
132b62f75cfSJohn Baldwin 	mtx_lock(&pr->pr_mtx);
133b62f75cfSJohn Baldwin 	if (pr->pr_linux == NULL) {
13401137630SRobert Watson 		/*
135b62f75cfSJohn Baldwin 		 * If we don't have a linux prison structure yet, allocate
136b62f75cfSJohn Baldwin 		 * one.  We have to handle the race where another thread
137b62f75cfSJohn Baldwin 		 * could be adding a linux prison to this process already.
13801137630SRobert Watson 		 */
13901137630SRobert Watson 		mtx_unlock(&pr->pr_mtx);
140b62f75cfSJohn Baldwin 		lpr = malloc(sizeof(struct linux_prison), M_PRISON,
141b62f75cfSJohn Baldwin 		    M_WAITOK | M_ZERO);
14201137630SRobert Watson 		mtx_lock(&pr->pr_mtx);
143b62f75cfSJohn Baldwin 		if (pr->pr_linux == NULL)
144c6dfea0eSMarcel Moolenaar 			pr->pr_linux = lpr;
145b62f75cfSJohn Baldwin 		else
146b62f75cfSJohn Baldwin 			free(lpr, M_PRISON);
14701137630SRobert Watson 	}
148b62f75cfSJohn Baldwin 	return (pr);
149c6dfea0eSMarcel Moolenaar }
150c6dfea0eSMarcel Moolenaar 
15101137630SRobert Watson void
152b62f75cfSJohn Baldwin linux_get_osname(struct thread *td, char *dst)
153c6dfea0eSMarcel Moolenaar {
154c6dfea0eSMarcel Moolenaar 	register struct prison *pr;
155c6dfea0eSMarcel Moolenaar 	register struct linux_prison *lpr;
156c6dfea0eSMarcel Moolenaar 
157b62f75cfSJohn Baldwin 	pr = td->td_ucred->cr_prison;
158b62f75cfSJohn Baldwin 	if (pr != NULL) {
15901137630SRobert Watson 		mtx_lock(&pr->pr_mtx);
16001137630SRobert Watson 		if (pr->pr_linux != NULL) {
16101137630SRobert Watson 			lpr = (struct linux_prison *)pr->pr_linux;
16201137630SRobert Watson 			if (lpr->pr_osname[0]) {
16301137630SRobert Watson 				bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME);
16401137630SRobert Watson 				mtx_unlock(&pr->pr_mtx);
16501137630SRobert Watson 				return;
16601137630SRobert Watson 			}
16701137630SRobert Watson 		}
16801137630SRobert Watson 		mtx_unlock(&pr->pr_mtx);
169b62f75cfSJohn Baldwin 	}
170b62f75cfSJohn Baldwin 
171b62f75cfSJohn Baldwin 	mtx_lock(&osname_lock);
17201137630SRobert Watson 	bcopy(linux_osname, dst, LINUX_MAX_UTSNAME);
173b62f75cfSJohn Baldwin 	mtx_unlock(&osname_lock);
174c6dfea0eSMarcel Moolenaar }
175c6dfea0eSMarcel Moolenaar 
176c6dfea0eSMarcel Moolenaar int
177b62f75cfSJohn Baldwin linux_set_osname(struct thread *td, char *osname)
178c6dfea0eSMarcel Moolenaar {
179b62f75cfSJohn Baldwin 	struct prison *pr;
180b62f75cfSJohn Baldwin 	struct linux_prison *lpr;
181c6dfea0eSMarcel Moolenaar 
182b62f75cfSJohn Baldwin 	pr = linux_get_prison(td);
183b62f75cfSJohn Baldwin 	if (pr != NULL) {
184b62f75cfSJohn Baldwin 		lpr = (struct linux_prison *)pr->pr_linux;
185c6dfea0eSMarcel Moolenaar 		strcpy(lpr->pr_osname, osname);
186b62f75cfSJohn Baldwin 		mtx_unlock(&pr->pr_mtx);
18701137630SRobert Watson 	} else {
188b62f75cfSJohn Baldwin 		mtx_lock(&osname_lock);
189c6dfea0eSMarcel Moolenaar 		strcpy(linux_osname, osname);
190b62f75cfSJohn Baldwin 		mtx_unlock(&osname_lock);
19101137630SRobert Watson 	}
192c6dfea0eSMarcel Moolenaar 
193c6dfea0eSMarcel Moolenaar 	return (0);
194c6dfea0eSMarcel Moolenaar }
195c6dfea0eSMarcel Moolenaar 
19601137630SRobert Watson void
197b62f75cfSJohn Baldwin linux_get_osrelease(struct thread *td, char *dst)
198c6dfea0eSMarcel Moolenaar {
199c6dfea0eSMarcel Moolenaar 	register struct prison *pr;
20001137630SRobert Watson 	struct linux_prison *lpr;
201c6dfea0eSMarcel Moolenaar 
202b62f75cfSJohn Baldwin 	pr = td->td_ucred->cr_prison;
203b62f75cfSJohn Baldwin 	if (pr != NULL) {
20401137630SRobert Watson 		mtx_lock(&pr->pr_mtx);
20501137630SRobert Watson 		if (pr->pr_linux != NULL) {
20601137630SRobert Watson 			lpr = (struct linux_prison *)pr->pr_linux;
20701137630SRobert Watson 			if (lpr->pr_osrelease[0]) {
208b62f75cfSJohn Baldwin 				bcopy(lpr->pr_osrelease, dst,
209b62f75cfSJohn Baldwin 				    LINUX_MAX_UTSNAME);
21001137630SRobert Watson 				mtx_unlock(&pr->pr_mtx);
21101137630SRobert Watson 				return;
21201137630SRobert Watson 			}
21301137630SRobert Watson 		}
21401137630SRobert Watson 		mtx_unlock(&pr->pr_mtx);
215b62f75cfSJohn Baldwin 	}
216b62f75cfSJohn Baldwin 
217b62f75cfSJohn Baldwin 	mtx_lock(&osname_lock);
21801137630SRobert Watson 	bcopy(linux_osrelease, dst, LINUX_MAX_UTSNAME);
219b62f75cfSJohn Baldwin 	mtx_unlock(&osname_lock);
220c6dfea0eSMarcel Moolenaar }
221c6dfea0eSMarcel Moolenaar 
222c6dfea0eSMarcel Moolenaar int
223b62f75cfSJohn Baldwin linux_set_osrelease(struct thread *td, char *osrelease)
224c6dfea0eSMarcel Moolenaar {
225b62f75cfSJohn Baldwin 	struct prison *pr;
226b62f75cfSJohn Baldwin 	struct linux_prison *lpr;
227c6dfea0eSMarcel Moolenaar 
228b62f75cfSJohn Baldwin 	pr = linux_get_prison(td);
229b62f75cfSJohn Baldwin 	if (pr != NULL) {
230b62f75cfSJohn Baldwin 		lpr = (struct linux_prison *)pr->pr_linux;
231c6dfea0eSMarcel Moolenaar 		strcpy(lpr->pr_osrelease, osrelease);
232b62f75cfSJohn Baldwin 		mtx_unlock(&pr->pr_mtx);
23301137630SRobert Watson 	} else {
234b62f75cfSJohn Baldwin 		mtx_lock(&osname_lock);
235c6dfea0eSMarcel Moolenaar 		strcpy(linux_osrelease, osrelease);
236b62f75cfSJohn Baldwin 		mtx_unlock(&osname_lock);
23701137630SRobert Watson 	}
238c6dfea0eSMarcel Moolenaar 
239c6dfea0eSMarcel Moolenaar 	return (0);
240c6dfea0eSMarcel Moolenaar }
241c6dfea0eSMarcel Moolenaar 
242c6dfea0eSMarcel Moolenaar int
243b62f75cfSJohn Baldwin linux_get_oss_version(struct thread *td)
244c6dfea0eSMarcel Moolenaar {
245c6dfea0eSMarcel Moolenaar 	register struct prison *pr;
246c6dfea0eSMarcel Moolenaar 	register struct linux_prison *lpr;
24701137630SRobert Watson 	int version;
24801137630SRobert Watson 
249b62f75cfSJohn Baldwin 	pr = td->td_ucred->cr_prison;
250b62f75cfSJohn Baldwin 	if (pr != NULL) {
25101137630SRobert Watson 		mtx_lock(&pr->pr_mtx);
25201137630SRobert Watson 		if (pr->pr_linux != NULL) {
25301137630SRobert Watson 			lpr = (struct linux_prison *)pr->pr_linux;
25401137630SRobert Watson 			if (lpr->pr_oss_version) {
25501137630SRobert Watson 				version = lpr->pr_oss_version;
256b62f75cfSJohn Baldwin 				mtx_unlock(&pr->pr_mtx);
257b62f75cfSJohn Baldwin 				return (version);
25801137630SRobert Watson 			}
25901137630SRobert Watson 		}
26001137630SRobert Watson 		mtx_unlock(&pr->pr_mtx);
261b62f75cfSJohn Baldwin 	}
26201137630SRobert Watson 
263b62f75cfSJohn Baldwin 	mtx_lock(&osname_lock);
264b62f75cfSJohn Baldwin 	version = linux_oss_version;
265b62f75cfSJohn Baldwin 	mtx_unlock(&osname_lock);
26601137630SRobert Watson 	return (version);
267c6dfea0eSMarcel Moolenaar }
268c6dfea0eSMarcel Moolenaar 
269c6dfea0eSMarcel Moolenaar int
270b62f75cfSJohn Baldwin linux_set_oss_version(struct thread *td, int oss_version)
271c6dfea0eSMarcel Moolenaar {
272b62f75cfSJohn Baldwin 	struct prison *pr;
273b62f75cfSJohn Baldwin 	struct linux_prison *lpr;
274c6dfea0eSMarcel Moolenaar 
275b62f75cfSJohn Baldwin 	pr = linux_get_prison(td);
276b62f75cfSJohn Baldwin 	if (pr != NULL) {
277b62f75cfSJohn Baldwin 		lpr = (struct linux_prison *)pr->pr_linux;
278c6dfea0eSMarcel Moolenaar 		lpr->pr_oss_version = oss_version;
279b62f75cfSJohn Baldwin 		mtx_unlock(&pr->pr_mtx);
28001137630SRobert Watson 	} else {
281b62f75cfSJohn Baldwin 		mtx_lock(&osname_lock);
282c6dfea0eSMarcel Moolenaar 		linux_oss_version = oss_version;
283b62f75cfSJohn Baldwin 		mtx_unlock(&osname_lock);
28401137630SRobert Watson 	}
285c6dfea0eSMarcel Moolenaar 
286c6dfea0eSMarcel Moolenaar 	return (0);
287c6dfea0eSMarcel Moolenaar }
28824593369SJonathan Lemon 
28924593369SJonathan Lemon #ifdef DEBUG
29024593369SJonathan Lemon 
29167b60513SPeter Wemm u_char linux_debug_map[howmany(LINUX_SYS_MAXSYSCALL, sizeof(u_char))];
29224593369SJonathan Lemon 
293ec0b1e67SPeter Wemm static int
29424593369SJonathan Lemon linux_debug(int syscall, int toggle, int global)
29524593369SJonathan Lemon {
29624593369SJonathan Lemon 
29724593369SJonathan Lemon 	if (global) {
29824593369SJonathan Lemon 		char c = toggle ? 0 : 0xff;
29924593369SJonathan Lemon 
30024593369SJonathan Lemon 		memset(linux_debug_map, c, sizeof(linux_debug_map));
30124593369SJonathan Lemon 		return (0);
30224593369SJonathan Lemon 	}
30324593369SJonathan Lemon 	if (syscall < 0 || syscall >= LINUX_SYS_MAXSYSCALL)
30424593369SJonathan Lemon 		return (EINVAL);
30524593369SJonathan Lemon 	if (toggle)
30624593369SJonathan Lemon 		clrbit(linux_debug_map, syscall);
30724593369SJonathan Lemon 	else
30824593369SJonathan Lemon 		setbit(linux_debug_map, syscall);
30924593369SJonathan Lemon 	return (0);
31024593369SJonathan Lemon }
31124593369SJonathan Lemon 
31224593369SJonathan Lemon /*
313b90faaf3SDima Dorfman  * Usage: sysctl linux.debug=<syscall_nr>.<0/1>
31424593369SJonathan Lemon  *
315b90faaf3SDima Dorfman  *    E.g.: sysctl linux.debug=21.0
31624593369SJonathan Lemon  *
31724593369SJonathan Lemon  * As a special case, syscall "all" will apply to all syscalls globally.
31824593369SJonathan Lemon  */
31924593369SJonathan Lemon #define LINUX_MAX_DEBUGSTR	16
32024593369SJonathan Lemon static int
32124593369SJonathan Lemon linux_sysctl_debug(SYSCTL_HANDLER_ARGS)
32224593369SJonathan Lemon {
32324593369SJonathan Lemon 	char value[LINUX_MAX_DEBUGSTR], *p;
32424593369SJonathan Lemon 	int error, sysc, toggle;
32524593369SJonathan Lemon 	int global = 0;
32624593369SJonathan Lemon 
32724593369SJonathan Lemon 	value[0] = '\0';
32824593369SJonathan Lemon 	error = sysctl_handle_string(oidp, value, LINUX_MAX_DEBUGSTR, req);
32924593369SJonathan Lemon 	if (error || req->newptr == NULL)
33024593369SJonathan Lemon 		return (error);
33124593369SJonathan Lemon 	for (p = value; *p != '\0' && *p != '.'; p++);
33224593369SJonathan Lemon 	if (*p == '\0')
33324593369SJonathan Lemon 		return (EINVAL);
33424593369SJonathan Lemon 	*p++ = '\0';
33524593369SJonathan Lemon 	sysc = strtol(value, NULL, 0);
33624593369SJonathan Lemon 	toggle = strtol(p, NULL, 0);
33724593369SJonathan Lemon 	if (strcmp(value, "all") == 0)
33824593369SJonathan Lemon 		global = 1;
33924593369SJonathan Lemon 	error = linux_debug(sysc, toggle, global);
34024593369SJonathan Lemon 	return (error);
34124593369SJonathan Lemon }
34224593369SJonathan Lemon 
34324593369SJonathan Lemon SYSCTL_PROC(_compat_linux, OID_AUTO, debug,
34424593369SJonathan Lemon             CTLTYPE_STRING | CTLFLAG_RW,
34524593369SJonathan Lemon             0, 0, linux_sysctl_debug, "A",
34624593369SJonathan Lemon             "Linux debugging control");
34724593369SJonathan Lemon 
34824593369SJonathan Lemon #endif /* DEBUG */
349