xref: /minix3/lib/libc/gen/sysctl.c (revision e4e21ee1b2710f3d411514741ce10d80156f4b5d)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: sysctl.c,v 1.35 2015/02/05 16:05:20 christos Exp $	*/
22fe8fb19SBen Gras 
32fe8fb19SBen Gras /*-
42fe8fb19SBen Gras  * Copyright (c) 1993
52fe8fb19SBen Gras  *	The Regents of the University of California.  All rights reserved.
62fe8fb19SBen Gras  *
72fe8fb19SBen Gras  * Redistribution and use in source and binary forms, with or without
82fe8fb19SBen Gras  * modification, are permitted provided that the following conditions
92fe8fb19SBen Gras  * are met:
102fe8fb19SBen Gras  * 1. Redistributions of source code must retain the above copyright
112fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer.
122fe8fb19SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
132fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer in the
142fe8fb19SBen Gras  *    documentation and/or other materials provided with the distribution.
152fe8fb19SBen Gras  * 3. Neither the name of the University nor the names of its contributors
162fe8fb19SBen Gras  *    may be used to endorse or promote products derived from this software
172fe8fb19SBen Gras  *    without specific prior written permission.
182fe8fb19SBen Gras  *
192fe8fb19SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
202fe8fb19SBen Gras  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
212fe8fb19SBen Gras  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
222fe8fb19SBen Gras  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
232fe8fb19SBen Gras  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
242fe8fb19SBen Gras  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
252fe8fb19SBen Gras  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
262fe8fb19SBen Gras  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
272fe8fb19SBen Gras  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
282fe8fb19SBen Gras  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
292fe8fb19SBen Gras  * SUCH DAMAGE.
302fe8fb19SBen Gras  */
312fe8fb19SBen Gras 
322fe8fb19SBen Gras #include <sys/cdefs.h>
332fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
342fe8fb19SBen Gras #if 0
352fe8fb19SBen Gras static char sccsid[] = "@(#)sysctl.c	8.2 (Berkeley) 1/4/94";
362fe8fb19SBen Gras #else
37*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: sysctl.c,v 1.35 2015/02/05 16:05:20 christos Exp $");
382fe8fb19SBen Gras #endif
392fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
402fe8fb19SBen Gras 
412fe8fb19SBen Gras #include "namespace.h"
422fe8fb19SBen Gras #include <sys/param.h>
432fe8fb19SBen Gras #define __COMPAT_SYSCTL
442fe8fb19SBen Gras #include <sys/sysctl.h>
452fe8fb19SBen Gras 
46f14fb602SLionel Sambuc #include <assert.h>
472fe8fb19SBen Gras #include <errno.h>
482fe8fb19SBen Gras #include <paths.h>
492fe8fb19SBen Gras #include <stdio.h>
502fe8fb19SBen Gras #include <string.h>
512fe8fb19SBen Gras #include <unistd.h>
522fe8fb19SBen Gras #include "extern.h"
532fe8fb19SBen Gras 
542fe8fb19SBen Gras #ifdef __weak_alias
552fe8fb19SBen Gras __weak_alias(sysctl,_sysctl)
562fe8fb19SBen Gras #endif
572fe8fb19SBen Gras 
582fe8fb19SBen Gras /*
592fe8fb19SBen Gras  * handles requests off the user subtree
602fe8fb19SBen Gras  */
612fe8fb19SBen Gras static int user_sysctl(const int *, u_int, void *, size_t *,
622fe8fb19SBen Gras 			const void *, size_t);
632fe8fb19SBen Gras 
642fe8fb19SBen Gras /*
652fe8fb19SBen Gras  * copies out individual nodes taking target version into account
662fe8fb19SBen Gras  */
672fe8fb19SBen Gras static size_t __cvt_node_out(uint, const struct sysctlnode *, void **,
682fe8fb19SBen Gras 			     size_t *);
692fe8fb19SBen Gras 
702fe8fb19SBen Gras #include <stdlib.h>
712fe8fb19SBen Gras 
722fe8fb19SBen Gras int
sysctl(const int * name,unsigned int namelen,void * oldp,size_t * oldlenp,const void * newp,size_t newlen)73f14fb602SLionel Sambuc sysctl(const int *name, unsigned int namelen,
74f14fb602SLionel Sambuc 	void *oldp, size_t *oldlenp,
75f14fb602SLionel Sambuc 	const void *newp, size_t newlen)
762fe8fb19SBen Gras {
772fe8fb19SBen Gras 	size_t oldlen, savelen;
782fe8fb19SBen Gras 	int error;
792fe8fb19SBen Gras 
802fe8fb19SBen Gras 	if (name[0] != CTL_USER)
812fe8fb19SBen Gras 		return (__sysctl(name, namelen, oldp, oldlenp,
822fe8fb19SBen Gras 				 newp, newlen));
832fe8fb19SBen Gras 
842fe8fb19SBen Gras 	oldlen = (oldlenp == NULL) ? 0 : *oldlenp;
852fe8fb19SBen Gras 	savelen = oldlen;
862fe8fb19SBen Gras 	error = user_sysctl(name + 1, namelen - 1, oldp, &oldlen, newp, newlen);
872fe8fb19SBen Gras 
882fe8fb19SBen Gras 	if (error != 0) {
892fe8fb19SBen Gras 		errno = error;
902fe8fb19SBen Gras 		return (-1);
912fe8fb19SBen Gras 	}
922fe8fb19SBen Gras 
932fe8fb19SBen Gras 	if (oldlenp != NULL) {
942fe8fb19SBen Gras 		*oldlenp = oldlen;
952fe8fb19SBen Gras 		if (oldp != NULL && oldlen > savelen) {
962fe8fb19SBen Gras 			errno = ENOMEM;
972fe8fb19SBen Gras 			return (-1);
982fe8fb19SBen Gras 		}
992fe8fb19SBen Gras 	}
1002fe8fb19SBen Gras 
1012fe8fb19SBen Gras 	return (0);
1022fe8fb19SBen Gras }
1032fe8fb19SBen Gras 
1042fe8fb19SBen Gras static int
user_sysctl(const int * name,unsigned int namelen,void * oldp,size_t * oldlenp,const void * newp,size_t newlen)105f14fb602SLionel Sambuc user_sysctl(const int *name, unsigned int namelen,
106f14fb602SLionel Sambuc 	void *oldp, size_t *oldlenp,
107f14fb602SLionel Sambuc 	const void *newp, size_t newlen)
1082fe8fb19SBen Gras {
1092fe8fb19SBen Gras #define _INT(s, n, v, d) {					\
1102fe8fb19SBen Gras 	.sysctl_flags = CTLFLAG_IMMEDIATE|CTLFLAG_PERMANENT|	\
1112fe8fb19SBen Gras 			CTLTYPE_INT|SYSCTL_VERSION,		\
112*0a6a1f1dSLionel Sambuc 	.sysctl_size = sizeof(int),				\
1132fe8fb19SBen Gras 	.sysctl_name = (s),					\
1142fe8fb19SBen Gras 	.sysctl_num = (n),					\
115*0a6a1f1dSLionel Sambuc 	.sysctl_un.scu_idata = (v),				\
116*0a6a1f1dSLionel Sambuc 	.sysctl_desc = (d),					\
1172fe8fb19SBen Gras 	}
1182fe8fb19SBen Gras 
1192fe8fb19SBen Gras 	/*
1202fe8fb19SBen Gras 	 * the nodes under the "user" node
1212fe8fb19SBen Gras 	 */
1222fe8fb19SBen Gras 	static const struct sysctlnode sysctl_usermib[] = {
1232fe8fb19SBen Gras #if defined(lint)
1242fe8fb19SBen Gras 		/*
1252fe8fb19SBen Gras 		 * lint doesn't like my initializers
1262fe8fb19SBen Gras 		 */
1272fe8fb19SBen Gras 		0
1282fe8fb19SBen Gras #else /* !lint */
1292fe8fb19SBen Gras 		{
1302fe8fb19SBen Gras 			.sysctl_flags = SYSCTL_VERSION|CTLFLAG_PERMANENT|
1312fe8fb19SBen Gras 				CTLTYPE_STRING,
132*0a6a1f1dSLionel Sambuc 			.sysctl_size = sizeof(_PATH_STDPATH),
1332fe8fb19SBen Gras 			.sysctl_name = "cs_path",
1342fe8fb19SBen Gras 			.sysctl_num = USER_CS_PATH,
135*0a6a1f1dSLionel Sambuc 			.sysctl_data = __UNCONST(_PATH_STDPATH),
136*0a6a1f1dSLionel Sambuc 			.sysctl_desc = __UNCONST(
1372fe8fb19SBen Gras 				"A value for the PATH environment variable "
1382fe8fb19SBen Gras 				"that finds all the standard utilities"),
1392fe8fb19SBen Gras 		},
1402fe8fb19SBen Gras 		_INT("bc_base_max", USER_BC_BASE_MAX, BC_BASE_MAX,
1412fe8fb19SBen Gras 		     "The maximum ibase/obase values in the bc(1) utility"),
1422fe8fb19SBen Gras 		_INT("bc_dim_max", USER_BC_DIM_MAX, BC_DIM_MAX,
1432fe8fb19SBen Gras 		     "The maximum array size in the bc(1) utility"),
1442fe8fb19SBen Gras 		_INT("bc_scale_max", USER_BC_SCALE_MAX, BC_SCALE_MAX,
1452fe8fb19SBen Gras 		     "The maximum scale value in the bc(1) utility"),
1462fe8fb19SBen Gras 		_INT("bc_string_max", USER_BC_STRING_MAX, BC_STRING_MAX,
1472fe8fb19SBen Gras 		     "The maximum string length in the bc(1) utility"),
1482fe8fb19SBen Gras 		_INT("coll_weights_max", USER_COLL_WEIGHTS_MAX,
1492fe8fb19SBen Gras 		     COLL_WEIGHTS_MAX, "The maximum number of weights that can "
1502fe8fb19SBen Gras 		     "be assigned to any entry of the LC_COLLATE order keyword "
1512fe8fb19SBen Gras 		     "in the locale definition file"),
1522fe8fb19SBen Gras 		_INT("expr_nest_max", USER_EXPR_NEST_MAX, EXPR_NEST_MAX,
1532fe8fb19SBen Gras 		     "The maximum number of expressions that can be nested "
1542fe8fb19SBen Gras 		     "within parenthesis by the expr(1) utility"),
1552fe8fb19SBen Gras 		_INT("line_max", USER_LINE_MAX, LINE_MAX, "The maximum length "
1562fe8fb19SBen Gras 		     "in bytes of a text-processing utility's input line"),
1572fe8fb19SBen Gras 		_INT("re_dup_max", USER_RE_DUP_MAX, RE_DUP_MAX, "The maximum "
1582fe8fb19SBen Gras 		     "number of repeated occurrences of a regular expression "
1592fe8fb19SBen Gras 		     "permitted when using interval notation"),
1602fe8fb19SBen Gras 		_INT("posix2_version", USER_POSIX2_VERSION, _POSIX2_VERSION,
1612fe8fb19SBen Gras 		     "The version of POSIX 1003.2 with which the system "
1622fe8fb19SBen Gras 		     "attempts to comply"),
1632fe8fb19SBen Gras #ifdef _POSIX2_C_BIND
1642fe8fb19SBen Gras 		_INT("posix2_c_bind", USER_POSIX2_C_BIND, 1,
1652fe8fb19SBen Gras 		     "Whether the system's C-language development facilities "
1662fe8fb19SBen Gras 		     "support the C-Language Bindings Option"),
1672fe8fb19SBen Gras #else
1682fe8fb19SBen Gras 		_INT("posix2_c_bind", USER_POSIX2_C_BIND, 0,
1692fe8fb19SBen Gras 		     "Whether the system's C-language development facilities "
1702fe8fb19SBen Gras 		     "support the C-Language Bindings Option"),
1712fe8fb19SBen Gras #endif
1722fe8fb19SBen Gras #ifdef POSIX2_C_DEV
1732fe8fb19SBen Gras 		_INT("posix2_c_dev", USER_POSIX2_C_DEV, 1,
1742fe8fb19SBen Gras 		     "Whether the system supports the C-Language Development "
1752fe8fb19SBen Gras 		     "Utilities Option"),
1762fe8fb19SBen Gras #else
1772fe8fb19SBen Gras 		_INT("posix2_c_dev", USER_POSIX2_C_DEV, 0,
1782fe8fb19SBen Gras 		     "Whether the system supports the C-Language Development "
1792fe8fb19SBen Gras 		     "Utilities Option"),
1802fe8fb19SBen Gras #endif
1812fe8fb19SBen Gras #ifdef POSIX2_CHAR_TERM
1822fe8fb19SBen Gras 		_INT("posix2_char_term", USER_POSIX2_CHAR_TERM, 1,
1832fe8fb19SBen Gras 		     "Whether the system supports at least one terminal type "
1842fe8fb19SBen Gras 		     "capable of all operations described in POSIX 1003.2"),
1852fe8fb19SBen Gras #else
1862fe8fb19SBen Gras 		_INT("posix2_char_term", USER_POSIX2_CHAR_TERM, 0,
1872fe8fb19SBen Gras 		     "Whether the system supports at least one terminal type "
1882fe8fb19SBen Gras 		     "capable of all operations described in POSIX 1003.2"),
1892fe8fb19SBen Gras #endif
1902fe8fb19SBen Gras #ifdef POSIX2_FORT_DEV
1912fe8fb19SBen Gras 		_INT("posix2_fort_dev", USER_POSIX2_FORT_DEV, 1,
1922fe8fb19SBen Gras 		     "Whether the system supports the FORTRAN Development "
1932fe8fb19SBen Gras 		     "Utilities Option"),
1942fe8fb19SBen Gras #else
1952fe8fb19SBen Gras 		_INT("posix2_fort_dev", USER_POSIX2_FORT_DEV, 0,
1962fe8fb19SBen Gras 		     "Whether the system supports the FORTRAN Development "
1972fe8fb19SBen Gras 		     "Utilities Option"),
1982fe8fb19SBen Gras #endif
1992fe8fb19SBen Gras #ifdef POSIX2_FORT_RUN
2002fe8fb19SBen Gras 		_INT("posix2_fort_run", USER_POSIX2_FORT_RUN, 1,
2012fe8fb19SBen Gras 		     "Whether the system supports the FORTRAN Runtime "
2022fe8fb19SBen Gras 		     "Utilities Option"),
2032fe8fb19SBen Gras #else
2042fe8fb19SBen Gras 		_INT("posix2_fort_run", USER_POSIX2_FORT_RUN, 0,
2052fe8fb19SBen Gras 		     "Whether the system supports the FORTRAN Runtime "
2062fe8fb19SBen Gras 		     "Utilities Option"),
2072fe8fb19SBen Gras #endif
2082fe8fb19SBen Gras #ifdef POSIX2_LOCALEDEF
2092fe8fb19SBen Gras 		_INT("posix2_localedef", USER_POSIX2_LOCALEDEF, 1,
2102fe8fb19SBen Gras 		     "Whether the system supports the creation of locales"),
2112fe8fb19SBen Gras #else
2122fe8fb19SBen Gras 		_INT("posix2_localedef", USER_POSIX2_LOCALEDEF, 0,
2132fe8fb19SBen Gras 		     "Whether the system supports the creation of locales"),
2142fe8fb19SBen Gras #endif
2152fe8fb19SBen Gras #ifdef POSIX2_SW_DEV
2162fe8fb19SBen Gras 		_INT("posix2_sw_dev", USER_POSIX2_SW_DEV, 1,
2172fe8fb19SBen Gras 		     "Whether the system supports the Software Development "
2182fe8fb19SBen Gras 		     "Utilities Option"),
2192fe8fb19SBen Gras #else
2202fe8fb19SBen Gras 		_INT("posix2_sw_dev", USER_POSIX2_SW_DEV, 0,
2212fe8fb19SBen Gras 		     "Whether the system supports the Software Development "
2222fe8fb19SBen Gras 		     "Utilities Option"),
2232fe8fb19SBen Gras #endif
2242fe8fb19SBen Gras #ifdef POSIX2_UPE
2252fe8fb19SBen Gras 		_INT("posix2_upe", USER_POSIX2_UPE, 1,
2262fe8fb19SBen Gras 		     "Whether the system supports the User Portability "
2272fe8fb19SBen Gras 		     "Utilities Option"),
2282fe8fb19SBen Gras #else
2292fe8fb19SBen Gras 		_INT("posix2_upe", USER_POSIX2_UPE, 0,
2302fe8fb19SBen Gras 		     "Whether the system supports the User Portability "
2312fe8fb19SBen Gras 		     "Utilities Option"),
2322fe8fb19SBen Gras #endif
2332fe8fb19SBen Gras 		_INT("stream_max", USER_STREAM_MAX, FOPEN_MAX,
2342fe8fb19SBen Gras 		     "The minimum maximum number of streams that a process "
2352fe8fb19SBen Gras 		     "may have open at any one time"),
2362fe8fb19SBen Gras 		_INT("tzname_max", USER_TZNAME_MAX, NAME_MAX,
2372fe8fb19SBen Gras 		     "The minimum maximum number of types supported for the "
2382fe8fb19SBen Gras 		     "name of a timezone"),
2392fe8fb19SBen Gras 		_INT("atexit_max", USER_ATEXIT_MAX, -1,
2402fe8fb19SBen Gras 		     "The maximum number of functions that may be registered "
2412fe8fb19SBen Gras 		     "with atexit(3)"),
2422fe8fb19SBen Gras #endif /* !lint */
2432fe8fb19SBen Gras 	};
2442fe8fb19SBen Gras #undef _INT
2452fe8fb19SBen Gras 
2462fe8fb19SBen Gras 	static const int clen = sizeof(sysctl_usermib) /
2472fe8fb19SBen Gras 		sizeof(sysctl_usermib[0]);
2482fe8fb19SBen Gras 
2492fe8fb19SBen Gras 	const struct sysctlnode *node;
2502fe8fb19SBen Gras 	int ni;
2512fe8fb19SBen Gras 	size_t l, sz;
2522fe8fb19SBen Gras 
2532fe8fb19SBen Gras 	/*
2542fe8fb19SBen Gras 	 * none of these nodes are writable and they're all terminal (for now)
2552fe8fb19SBen Gras 	 */
2562fe8fb19SBen Gras 	if (namelen != 1)
2572fe8fb19SBen Gras 		return (EINVAL);
2582fe8fb19SBen Gras 
2592fe8fb19SBen Gras 	l = *oldlenp;
2602fe8fb19SBen Gras 	if (name[0] == CTL_QUERY) {
2612fe8fb19SBen Gras 		uint v;
2622fe8fb19SBen Gras 		node = newp;
2632fe8fb19SBen Gras 		if (node == NULL)
2642fe8fb19SBen Gras 			return (EINVAL);
2652fe8fb19SBen Gras 		else if (SYSCTL_VERS(node->sysctl_flags) == SYSCTL_VERS_1 &&
2662fe8fb19SBen Gras 			 newlen == sizeof(struct sysctlnode))
2672fe8fb19SBen Gras 			v = SYSCTL_VERS_1;
2682fe8fb19SBen Gras 		else
2692fe8fb19SBen Gras 			return (EINVAL);
2702fe8fb19SBen Gras 
2712fe8fb19SBen Gras 		sz = 0;
2722fe8fb19SBen Gras 		for (ni = 0; ni < clen; ni++)
2732fe8fb19SBen Gras 			sz += __cvt_node_out(v, &sysctl_usermib[ni], &oldp, &l);
2742fe8fb19SBen Gras 		*oldlenp = sz;
2752fe8fb19SBen Gras 		return (0);
2762fe8fb19SBen Gras 	}
2772fe8fb19SBen Gras 
2782fe8fb19SBen Gras 	if (name[0] == CTL_DESCRIBE) {
2792fe8fb19SBen Gras 		/*
2802fe8fb19SBen Gras 		 * XXX make sure this is larger than the largest
2812fe8fb19SBen Gras 		 * "user" description
2822fe8fb19SBen Gras 		 */
2832fe8fb19SBen Gras 		char buf[192];
2842fe8fb19SBen Gras 		struct sysctldesc *d1 = (void *)&buf[0], *d2 = oldp;
2852fe8fb19SBen Gras 		size_t d;
2862fe8fb19SBen Gras 
2872fe8fb19SBen Gras 		node = newp;
2882fe8fb19SBen Gras 		if (node != NULL &&
2892fe8fb19SBen Gras 		    (SYSCTL_VERS(node->sysctl_flags) < SYSCTL_VERS_1 ||
2902fe8fb19SBen Gras 		     newlen != sizeof(struct sysctlnode)))
2912fe8fb19SBen Gras 			return (EINVAL);
2922fe8fb19SBen Gras 
2932fe8fb19SBen Gras 		sz = 0;
2942fe8fb19SBen Gras 		for (ni = 0; ni < clen; ni++) {
2952fe8fb19SBen Gras 			memset(&buf[0], 0, sizeof(buf));
2962fe8fb19SBen Gras 			if (node != NULL &&
2972fe8fb19SBen Gras 			    node->sysctl_num != sysctl_usermib[ni].sysctl_num)
2982fe8fb19SBen Gras 				continue;
2992fe8fb19SBen Gras 			d1->descr_num = sysctl_usermib[ni].sysctl_num;
3002fe8fb19SBen Gras 			d1->descr_ver = sysctl_usermib[ni].sysctl_ver;
3012fe8fb19SBen Gras 			if (sysctl_usermib[ni].sysctl_desc == NULL)
3022fe8fb19SBen Gras 				d1->descr_len = 1;
3032fe8fb19SBen Gras 			else {
304f14fb602SLionel Sambuc 				size_t dlen;
3052fe8fb19SBen Gras 				(void)strlcpy(d1->descr_str,
3062fe8fb19SBen Gras 					sysctl_usermib[ni].sysctl_desc,
3072fe8fb19SBen Gras 					sizeof(buf) - sizeof(*d1));
308f14fb602SLionel Sambuc 				dlen = strlen(d1->descr_str) + 1;
309f14fb602SLionel Sambuc 				_DIAGASSERT(__type_fit(uint32_t, dlen));
310f14fb602SLionel Sambuc 				d1->descr_len = (uint32_t)dlen;
3112fe8fb19SBen Gras 			}
3122fe8fb19SBen Gras 			d = (size_t)__sysc_desc_adv(NULL, d1->descr_len);
3132fe8fb19SBen Gras 			if (d2 != NULL)
3142fe8fb19SBen Gras 				memcpy(d2, d1, d);
3152fe8fb19SBen Gras 			sz += d;
316*0a6a1f1dSLionel Sambuc 			d2 = (struct sysctldesc *)(void *)((char *)d2 + d);
3172fe8fb19SBen Gras 			if (node != NULL)
3182fe8fb19SBen Gras 				break;
3192fe8fb19SBen Gras 		}
3202fe8fb19SBen Gras 		*oldlenp = sz;
3212fe8fb19SBen Gras 		if (sz == 0 && node != NULL)
3222fe8fb19SBen Gras 			return (ENOENT);
3232fe8fb19SBen Gras 		return (0);
3242fe8fb19SBen Gras 
3252fe8fb19SBen Gras 	}
3262fe8fb19SBen Gras 
3272fe8fb19SBen Gras 	/*
3282fe8fb19SBen Gras 	 * none of these nodes are writable
3292fe8fb19SBen Gras 	 */
3302fe8fb19SBen Gras 	if (newp != NULL || newlen != 0)
3312fe8fb19SBen Gras 		return (EPERM);
3322fe8fb19SBen Gras 
3332fe8fb19SBen Gras 	node = &sysctl_usermib[0];
3342fe8fb19SBen Gras 	for (ni = 0; ni	< clen; ni++)
3352fe8fb19SBen Gras 		if (name[0] == node[ni].sysctl_num)
3362fe8fb19SBen Gras 			break;
3372fe8fb19SBen Gras 	if (ni == clen)
3382fe8fb19SBen Gras 		return (EOPNOTSUPP);
3392fe8fb19SBen Gras 
3402fe8fb19SBen Gras 	node = &node[ni];
3412fe8fb19SBen Gras 	if (node->sysctl_flags & CTLFLAG_IMMEDIATE) {
3422fe8fb19SBen Gras 		switch (SYSCTL_TYPE(node->sysctl_flags)) {
3432fe8fb19SBen Gras 		case CTLTYPE_INT:
3442fe8fb19SBen Gras 			newp = &node->sysctl_idata;
3452fe8fb19SBen Gras 			break;
3462fe8fb19SBen Gras 		case CTLTYPE_QUAD:
3472fe8fb19SBen Gras 			newp = &node->sysctl_qdata;
3482fe8fb19SBen Gras 			break;
3492fe8fb19SBen Gras 		default:
3502fe8fb19SBen Gras 			return (EINVAL);
3512fe8fb19SBen Gras 		}
3522fe8fb19SBen Gras 	}
3532fe8fb19SBen Gras 	else
3542fe8fb19SBen Gras 		newp = node->sysctl_data;
3552fe8fb19SBen Gras 
3562fe8fb19SBen Gras 	l = MIN(l, node->sysctl_size);
3572fe8fb19SBen Gras 	if (oldp != NULL)
3582fe8fb19SBen Gras 		memcpy(oldp, newp, l);
3592fe8fb19SBen Gras 	*oldlenp = node->sysctl_size;
3602fe8fb19SBen Gras 
3612fe8fb19SBen Gras 	return (0);
3622fe8fb19SBen Gras }
3632fe8fb19SBen Gras 
3642fe8fb19SBen Gras static size_t
__cvt_node_out(uint v,const struct sysctlnode * n,void ** o,size_t * l)3652fe8fb19SBen Gras __cvt_node_out(uint v, const struct sysctlnode *n, void **o, size_t *l)
3662fe8fb19SBen Gras {
3672fe8fb19SBen Gras 	const void *src = n;
3682fe8fb19SBen Gras 	size_t sz;
3692fe8fb19SBen Gras 
3702fe8fb19SBen Gras 	switch (v) {
3712fe8fb19SBen Gras #if (SYSCTL_VERSION != SYSCTL_VERS_1)
3722fe8fb19SBen Gras #error __cvt_node_out: no support for SYSCTL_VERSION
3732fe8fb19SBen Gras #endif /* (SYSCTL_VERSION != SYSCTL_VERS_1) */
3742fe8fb19SBen Gras 
3752fe8fb19SBen Gras 	case SYSCTL_VERSION:
3762fe8fb19SBen Gras 		sz = sizeof(struct sysctlnode);
3772fe8fb19SBen Gras 		break;
3782fe8fb19SBen Gras 
3792fe8fb19SBen Gras 	default:
3802fe8fb19SBen Gras 		sz = 0;
3812fe8fb19SBen Gras 		break;
3822fe8fb19SBen Gras 	}
3832fe8fb19SBen Gras 
3842fe8fb19SBen Gras 	if (sz > 0 && *o != NULL && *l >= sz) {
3852fe8fb19SBen Gras 		memcpy(*o, src, sz);
3862fe8fb19SBen Gras 		*o = sz + (caddr_t)*o;
3872fe8fb19SBen Gras 		*l -= sz;
3882fe8fb19SBen Gras 	}
3892fe8fb19SBen Gras 
3902fe8fb19SBen Gras 	return(sz);
3912fe8fb19SBen Gras }
392