xref: /f-stack/lib/ff_kern_environment.c (revision 2317ada5)
1a9643ea8Slogwang /*
2a9643ea8Slogwang  * Copyright (c) 1998 Michael Smith. All rights reserved.
3a9643ea8Slogwang  * Copyright (c) 2013 Patrick Kelsey. All rights reserved.
4*2317ada5Sfengbojiang  * Copyright (C) 2017-2021 THL A29 Limited, a Tencent company.
5a9643ea8Slogwang  * All rights reserved.
6a9643ea8Slogwang  *
7a9643ea8Slogwang  * Redistribution and use in source and binary forms, with or without
8a9643ea8Slogwang  * modification, are permitted provided that the following conditions are met:
9a9643ea8Slogwang  *
10a9643ea8Slogwang  * 1. Redistributions of source code must retain the above copyright notice, this
11a9643ea8Slogwang  *   list of conditions and the following disclaimer.
12a9643ea8Slogwang  * 2. Redistributions in binary form must reproduce the above copyright notice,
13a9643ea8Slogwang  *   this list of conditions and the following disclaimer in the documentation
14a9643ea8Slogwang  *   and/or other materials provided with the distribution.
15a9643ea8Slogwang  *
16a9643ea8Slogwang  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17a9643ea8Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18a9643ea8Slogwang  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19a9643ea8Slogwang  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20a9643ea8Slogwang  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21a9643ea8Slogwang  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22a9643ea8Slogwang  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23a9643ea8Slogwang  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24a9643ea8Slogwang  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25a9643ea8Slogwang  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26a9643ea8Slogwang  *
27a9643ea8Slogwang  * Derived from libuinet's uinet_kern_environment.c.
28a9643ea8Slogwang  */
29a9643ea8Slogwang 
30a9643ea8Slogwang /*
31a9643ea8Slogwang  * This is an override of ken_environment.c so that get/set/put/unsetenv()
32a9643ea8Slogwang  * from libc will be used, and the extended kernel environment API will
33a9643ea8Slogwang  * still be available.
34a9643ea8Slogwang  */
35a9643ea8Slogwang 
36a9643ea8Slogwang #include <sys/cdefs.h>
37a9643ea8Slogwang __FBSDID("$FreeBSD: release/9.1.0/sys/kern/kern_environment.c 225617 2011-09-16 13:58:51Z kmacy $");
38a9643ea8Slogwang 
39a9643ea8Slogwang #include <sys/types.h>
40a9643ea8Slogwang #include <sys/param.h>
41a9643ea8Slogwang #include <sys/proc.h>
42a9643ea8Slogwang #include <sys/queue.h>
43a9643ea8Slogwang #include <sys/lock.h>
44a9643ea8Slogwang #include <sys/malloc.h>
45a9643ea8Slogwang #include <sys/mutex.h>
46a9643ea8Slogwang #include <sys/priv.h>
47a9643ea8Slogwang #include <sys/kernel.h>
48a9643ea8Slogwang #include <sys/systm.h>
49a9643ea8Slogwang #include <sys/sysent.h>
50a9643ea8Slogwang #include <sys/sysproto.h>
51a9643ea8Slogwang #include <sys/libkern.h>
52a9643ea8Slogwang #include <sys/kenv.h>
5322ce4affSfengbojiang #include <sys/limits.h>
54a9643ea8Slogwang 
55a9643ea8Slogwang #include "ff_host_interface.h"
56a9643ea8Slogwang 
57a9643ea8Slogwang static MALLOC_DEFINE(M_KENV, "kenv", "kernel environment");
58a9643ea8Slogwang 
59a9643ea8Slogwang #define KENV_SIZE    512    /* Maximum number of environment strings */
60a9643ea8Slogwang 
6122ce4affSfengbojiang /* pointer to the config-generated static environment */
6222ce4affSfengbojiang char *kern_envp;
6322ce4affSfengbojiang 
6422ce4affSfengbojiang /* pointer to the md-static environment */
6522ce4affSfengbojiang char *md_envp;
66a9643ea8Slogwang 
67a9643ea8Slogwang /* dynamic environment variables */
68a9643ea8Slogwang char **kenvp = &kern_envp; /* points to a pointer to NULL */
69a9643ea8Slogwang struct mtx kenv_lock;  /* does not need initialization - it will not be used as dynamic_kenv == 0 */
70a9643ea8Slogwang 
71a9643ea8Slogwang /*
72a9643ea8Slogwang  * No need to protect this with a mutex since SYSINITS are single threaded.
73a9643ea8Slogwang  */
7422ce4affSfengbojiang bool dynamic_kenv = 0;
75a9643ea8Slogwang 
76a9643ea8Slogwang char *
kern_getenv(const char * name)77a9643ea8Slogwang kern_getenv(const char *name)
78a9643ea8Slogwang {
79a9643ea8Slogwang     return ff_getenv(name);
80a9643ea8Slogwang }
81a9643ea8Slogwang 
82a9643ea8Slogwang int
kern_setenv(const char * name,const char * value)83a9643ea8Slogwang kern_setenv(const char *name, const char *value)
84a9643ea8Slogwang {
85a9643ea8Slogwang     return ff_setenv(name, value);
86a9643ea8Slogwang }
87a9643ea8Slogwang 
88a9643ea8Slogwang void
freeenv(char * env)89a9643ea8Slogwang freeenv(char *env)
90a9643ea8Slogwang {
91a9643ea8Slogwang     ;
92a9643ea8Slogwang }
93a9643ea8Slogwang 
94a9643ea8Slogwang 
95a9643ea8Slogwang /*
96a9643ea8Slogwang  * Test if an environment variable is defined.
97a9643ea8Slogwang  */
98a9643ea8Slogwang int
testenv(const char * name)99a9643ea8Slogwang testenv(const char *name)
100a9643ea8Slogwang {
101a9643ea8Slogwang     return (kern_getenv(name) != NULL);
102a9643ea8Slogwang }
103a9643ea8Slogwang 
104a9643ea8Slogwang 
105a9643ea8Slogwang 
106a9643ea8Slogwang /*
107a9643ea8Slogwang  * Return a string value from an environment variable.
108a9643ea8Slogwang  */
109a9643ea8Slogwang int
getenv_string(const char * name,char * data,int size)110a9643ea8Slogwang getenv_string(const char *name, char *data, int size)
111a9643ea8Slogwang {
112a9643ea8Slogwang     char *tmp;
113a9643ea8Slogwang 
114a9643ea8Slogwang     tmp = kern_getenv(name);
115a9643ea8Slogwang     if (tmp != NULL) {
116a9643ea8Slogwang         strlcpy(data, tmp, size);
117a9643ea8Slogwang         freeenv(tmp);
118a9643ea8Slogwang         return (1);
119a9643ea8Slogwang     } else
120a9643ea8Slogwang         return (0);
121a9643ea8Slogwang }
122a9643ea8Slogwang 
123a9643ea8Slogwang /*
124a9643ea8Slogwang  * Return an integer value from an environment variable.
125a9643ea8Slogwang  */
126a9643ea8Slogwang int
getenv_int(const char * name,int * data)127a9643ea8Slogwang getenv_int(const char *name, int *data)
128a9643ea8Slogwang {
129a9643ea8Slogwang     quad_t tmp;
130a9643ea8Slogwang     int rval;
131a9643ea8Slogwang 
132a9643ea8Slogwang     rval = getenv_quad(name, &tmp);
133a9643ea8Slogwang     if (rval)
134a9643ea8Slogwang         *data = (int) tmp;
135a9643ea8Slogwang     return (rval);
136a9643ea8Slogwang }
137a9643ea8Slogwang 
138a9643ea8Slogwang /*
139a9643ea8Slogwang  * Return an unsigned integer value from an environment variable.
140a9643ea8Slogwang  */
141a9643ea8Slogwang int
getenv_uint(const char * name,unsigned int * data)142a9643ea8Slogwang getenv_uint(const char *name, unsigned int *data)
143a9643ea8Slogwang {
144a9643ea8Slogwang     quad_t tmp;
145a9643ea8Slogwang     int rval;
146a9643ea8Slogwang 
147a9643ea8Slogwang     rval = getenv_quad(name, &tmp);
148a9643ea8Slogwang     if (rval)
149a9643ea8Slogwang         *data = (unsigned int) tmp;
150a9643ea8Slogwang     return (rval);
151a9643ea8Slogwang }
152a9643ea8Slogwang 
153a9643ea8Slogwang /*
154a9643ea8Slogwang  * Return a long value from an environment variable.
155a9643ea8Slogwang  */
156a9643ea8Slogwang int
getenv_long(const char * name,long * data)157a9643ea8Slogwang getenv_long(const char *name, long *data)
158a9643ea8Slogwang {
159a9643ea8Slogwang     quad_t tmp;
160a9643ea8Slogwang     int rval;
161a9643ea8Slogwang 
162a9643ea8Slogwang     rval = getenv_quad(name, &tmp);
163a9643ea8Slogwang     if (rval)
164a9643ea8Slogwang         *data = (long) tmp;
165a9643ea8Slogwang     return (rval);
166a9643ea8Slogwang }
167a9643ea8Slogwang 
168a9643ea8Slogwang /*
169a9643ea8Slogwang  * Return an unsigned long value from an environment variable.
170a9643ea8Slogwang  */
171a9643ea8Slogwang int
getenv_ulong(const char * name,unsigned long * data)172a9643ea8Slogwang getenv_ulong(const char *name, unsigned long *data)
173a9643ea8Slogwang {
174a9643ea8Slogwang     quad_t tmp;
175a9643ea8Slogwang     int rval;
176a9643ea8Slogwang 
177a9643ea8Slogwang     rval = getenv_quad(name, &tmp);
178a9643ea8Slogwang     if (rval)
179a9643ea8Slogwang         *data = (unsigned long) tmp;
180a9643ea8Slogwang     return (rval);
181a9643ea8Slogwang }
182a9643ea8Slogwang 
183a9643ea8Slogwang /*
184a9643ea8Slogwang  * Return a quad_t value from an environment variable.
185a9643ea8Slogwang  */
186a9643ea8Slogwang int
getenv_quad(const char * name,quad_t * data)187a9643ea8Slogwang getenv_quad(const char *name, quad_t *data)
188a9643ea8Slogwang {
189a9643ea8Slogwang     char *value;
190a9643ea8Slogwang     char *vtp;
191a9643ea8Slogwang     quad_t iv;
192a9643ea8Slogwang 
193a9643ea8Slogwang     value = kern_getenv(name);
194a9643ea8Slogwang     if (value == NULL)
195a9643ea8Slogwang         return (0);
196a9643ea8Slogwang     iv = strtoq(value, &vtp, 0);
197a9643ea8Slogwang     if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) {
198a9643ea8Slogwang         freeenv(value);
199a9643ea8Slogwang         return (0);
200a9643ea8Slogwang     }
201a9643ea8Slogwang     switch (vtp[0]) {
202a9643ea8Slogwang     case 't': case 'T':
203a9643ea8Slogwang         iv *= 1024;
204a9643ea8Slogwang     case 'g': case 'G':
205a9643ea8Slogwang         iv *= 1024;
206a9643ea8Slogwang     case 'm': case 'M':
207a9643ea8Slogwang         iv *= 1024;
208a9643ea8Slogwang     case 'k': case 'K':
209a9643ea8Slogwang         iv *= 1024;
210a9643ea8Slogwang     case '\0':
211a9643ea8Slogwang         break;
212a9643ea8Slogwang     default:
213a9643ea8Slogwang         freeenv(value);
214a9643ea8Slogwang         return (0);
215a9643ea8Slogwang     }
216a9643ea8Slogwang     *data = iv;
217a9643ea8Slogwang     freeenv(value);
218a9643ea8Slogwang     return (1);
219a9643ea8Slogwang }
220a9643ea8Slogwang 
22122ce4affSfengbojiang /*
22222ce4affSfengbojiang  * Internal functions for string lookup.
22322ce4affSfengbojiang  */
22422ce4affSfengbojiang static char *
_getenv_dynamic_locked(const char * name,int * idx)22522ce4affSfengbojiang _getenv_dynamic_locked(const char *name, int *idx)
22622ce4affSfengbojiang {
22722ce4affSfengbojiang 	char *cp;
22822ce4affSfengbojiang 	int len, i;
22922ce4affSfengbojiang 
23022ce4affSfengbojiang 	len = strlen(name);
23122ce4affSfengbojiang 	for (cp = kenvp[0], i = 0; cp != NULL; cp = kenvp[++i]) {
23222ce4affSfengbojiang 		if ((strncmp(cp, name, len) == 0) &&
23322ce4affSfengbojiang 		    (cp[len] == '=')) {
23422ce4affSfengbojiang 			if (idx != NULL)
23522ce4affSfengbojiang 				*idx = i;
23622ce4affSfengbojiang 			return (cp + len + 1);
23722ce4affSfengbojiang 		}
23822ce4affSfengbojiang 	}
23922ce4affSfengbojiang 	return (NULL);
24022ce4affSfengbojiang }
24122ce4affSfengbojiang 
24222ce4affSfengbojiang static char *
_getenv_dynamic(const char * name,int * idx)24322ce4affSfengbojiang _getenv_dynamic(const char *name, int *idx)
24422ce4affSfengbojiang {
24522ce4affSfengbojiang 
24622ce4affSfengbojiang 	mtx_assert(&kenv_lock, MA_OWNED);
24722ce4affSfengbojiang 	return (_getenv_dynamic_locked(name, idx));
24822ce4affSfengbojiang }
24922ce4affSfengbojiang 
25022ce4affSfengbojiang /*
25122ce4affSfengbojiang  * Find the next entry after the one which (cp) falls within, return a
25222ce4affSfengbojiang  * pointer to its start or NULL if there are no more.
25322ce4affSfengbojiang  */
25422ce4affSfengbojiang static char *
kernenv_next(char * cp)25522ce4affSfengbojiang kernenv_next(char *cp)
25622ce4affSfengbojiang {
25722ce4affSfengbojiang 
25822ce4affSfengbojiang 	if (cp != NULL) {
25922ce4affSfengbojiang 		while (*cp != 0)
26022ce4affSfengbojiang 			cp++;
26122ce4affSfengbojiang 		cp++;
26222ce4affSfengbojiang 		if (*cp == 0)
26322ce4affSfengbojiang 			cp = NULL;
26422ce4affSfengbojiang 	}
26522ce4affSfengbojiang 	return (cp);
26622ce4affSfengbojiang }
26722ce4affSfengbojiang 
26822ce4affSfengbojiang static char *
_getenv_static_from(char * chkenv,const char * name)26922ce4affSfengbojiang _getenv_static_from(char *chkenv, const char *name)
27022ce4affSfengbojiang {
27122ce4affSfengbojiang 	char *cp, *ep;
27222ce4affSfengbojiang 	int len;
27322ce4affSfengbojiang 
27422ce4affSfengbojiang 	for (cp = chkenv; cp != NULL; cp = kernenv_next(cp)) {
27522ce4affSfengbojiang 		for (ep = cp; (*ep != '=') && (*ep != 0); ep++)
27622ce4affSfengbojiang 			;
27722ce4affSfengbojiang 		if (*ep != '=')
27822ce4affSfengbojiang 			continue;
27922ce4affSfengbojiang 		len = ep - cp;
28022ce4affSfengbojiang 		ep++;
28122ce4affSfengbojiang 		if (!strncmp(name, cp, len) && name[len] == 0)
28222ce4affSfengbojiang 			return (ep);
28322ce4affSfengbojiang 	}
28422ce4affSfengbojiang 	return (NULL);
28522ce4affSfengbojiang }
28622ce4affSfengbojiang 
28722ce4affSfengbojiang static char *
_getenv_static(const char * name)28822ce4affSfengbojiang _getenv_static(const char *name)
28922ce4affSfengbojiang {
29022ce4affSfengbojiang 	char *val;
29122ce4affSfengbojiang 
29222ce4affSfengbojiang 	val = _getenv_static_from(md_envp, name);
29322ce4affSfengbojiang 	if (val != NULL)
29422ce4affSfengbojiang 		return (val);
29522ce4affSfengbojiang 	val = _getenv_static_from(kern_envp, name);
29622ce4affSfengbojiang 	if (val != NULL)
29722ce4affSfengbojiang 		return (val);
29822ce4affSfengbojiang 	return (NULL);
29922ce4affSfengbojiang }
30022ce4affSfengbojiang 
30122ce4affSfengbojiang /*
30222ce4affSfengbojiang  * Return the internal kenv buffer for the variable name, if it exists.
30322ce4affSfengbojiang  * If the dynamic kenv is initialized and the name is present, return
30422ce4affSfengbojiang  * with kenv_lock held.
30522ce4affSfengbojiang  */
30622ce4affSfengbojiang static char *
kenv_acquire(const char * name)30722ce4affSfengbojiang kenv_acquire(const char *name)
30822ce4affSfengbojiang {
30922ce4affSfengbojiang 	char *value;
31022ce4affSfengbojiang 
31122ce4affSfengbojiang 	if (dynamic_kenv) {
31222ce4affSfengbojiang 		mtx_lock(&kenv_lock);
31322ce4affSfengbojiang 		value = _getenv_dynamic(name, NULL);
31422ce4affSfengbojiang 		if (value == NULL)
31522ce4affSfengbojiang 			mtx_unlock(&kenv_lock);
31622ce4affSfengbojiang 		return (value);
31722ce4affSfengbojiang 	} else
31822ce4affSfengbojiang 		return (_getenv_static(name));
31922ce4affSfengbojiang }
32022ce4affSfengbojiang 
32122ce4affSfengbojiang /*
32222ce4affSfengbojiang  * Undo a previous kenv_acquire() operation
32322ce4affSfengbojiang  */
32422ce4affSfengbojiang static void
kenv_release(const char * buf)32522ce4affSfengbojiang kenv_release(const char *buf)
32622ce4affSfengbojiang {
32722ce4affSfengbojiang 	if ((buf != NULL) && dynamic_kenv)
32822ce4affSfengbojiang 		mtx_unlock(&kenv_lock);
32922ce4affSfengbojiang }
33022ce4affSfengbojiang 
33122ce4affSfengbojiang /*
33222ce4affSfengbojiang  * Return an array of integers at the given type size and signedness.
33322ce4affSfengbojiang  */
33422ce4affSfengbojiang int
getenv_array(const char * name,void * pdata,int size,int * psize,int type_size,bool allow_signed)33522ce4affSfengbojiang getenv_array(const char *name, void *pdata, int size, int *psize,
33622ce4affSfengbojiang     int type_size, bool allow_signed)
33722ce4affSfengbojiang {
33822ce4affSfengbojiang     uint8_t shift;
33922ce4affSfengbojiang     int64_t value;
34022ce4affSfengbojiang     int64_t old;
34122ce4affSfengbojiang     const char *buf;
34222ce4affSfengbojiang     char *end;
34322ce4affSfengbojiang     const char *ptr;
34422ce4affSfengbojiang     int n;
34522ce4affSfengbojiang     int rc;
34622ce4affSfengbojiang 
34722ce4affSfengbojiang     rc = 0;              /* assume failure */
34822ce4affSfengbojiang 
34922ce4affSfengbojiang     buf = kenv_acquire(name);
35022ce4affSfengbojiang     if (buf == NULL)
35122ce4affSfengbojiang         goto error;
35222ce4affSfengbojiang 
35322ce4affSfengbojiang     /* get maximum number of elements */
35422ce4affSfengbojiang     size /= type_size;
35522ce4affSfengbojiang 
35622ce4affSfengbojiang     n = 0;
35722ce4affSfengbojiang 
35822ce4affSfengbojiang     for (ptr = buf; *ptr != 0; ) {
35922ce4affSfengbojiang         value = strtoq(ptr, &end, 0);
36022ce4affSfengbojiang 
36122ce4affSfengbojiang         /* check if signed numbers are allowed */
36222ce4affSfengbojiang         if (value < 0 && !allow_signed)
36322ce4affSfengbojiang             goto error;
36422ce4affSfengbojiang 
36522ce4affSfengbojiang         /* check for invalid value */
36622ce4affSfengbojiang         if (ptr == end)
36722ce4affSfengbojiang             goto error;
36822ce4affSfengbojiang 
36922ce4affSfengbojiang         /* check for valid suffix */
37022ce4affSfengbojiang         switch (*end) {
37122ce4affSfengbojiang         case 't':
37222ce4affSfengbojiang         case 'T':
37322ce4affSfengbojiang             shift = 40;
37422ce4affSfengbojiang             end++;
37522ce4affSfengbojiang             break;
37622ce4affSfengbojiang         case 'g':
37722ce4affSfengbojiang         case 'G':
37822ce4affSfengbojiang             shift = 30;
37922ce4affSfengbojiang             end++;
38022ce4affSfengbojiang             break;
38122ce4affSfengbojiang         case 'm':
38222ce4affSfengbojiang         case 'M':
38322ce4affSfengbojiang             shift = 20;
38422ce4affSfengbojiang             end++;
38522ce4affSfengbojiang             break;
38622ce4affSfengbojiang         case 'k':
38722ce4affSfengbojiang         case 'K':
38822ce4affSfengbojiang             shift = 10;
38922ce4affSfengbojiang             end++;
39022ce4affSfengbojiang             break;
39122ce4affSfengbojiang         case ' ':
39222ce4affSfengbojiang         case '\t':
39322ce4affSfengbojiang         case ',':
39422ce4affSfengbojiang         case 0:
39522ce4affSfengbojiang             shift = 0;
39622ce4affSfengbojiang             break;
39722ce4affSfengbojiang         default:
39822ce4affSfengbojiang             /* garbage after numeric value */
39922ce4affSfengbojiang             goto error;
40022ce4affSfengbojiang         }
40122ce4affSfengbojiang 
40222ce4affSfengbojiang         /* skip till next value, if any */
40322ce4affSfengbojiang         while (*end == '\t' || *end == ',' || *end == ' ')
40422ce4affSfengbojiang             end++;
40522ce4affSfengbojiang 
40622ce4affSfengbojiang         /* update pointer */
40722ce4affSfengbojiang         ptr = end;
40822ce4affSfengbojiang 
40922ce4affSfengbojiang         /* apply shift */
41022ce4affSfengbojiang         old = value;
41122ce4affSfengbojiang         value <<= shift;
41222ce4affSfengbojiang 
41322ce4affSfengbojiang         /* overflow check */
41422ce4affSfengbojiang         if ((value >> shift) != old)
41522ce4affSfengbojiang             goto error;
41622ce4affSfengbojiang 
41722ce4affSfengbojiang         /* check for buffer overflow */
41822ce4affSfengbojiang         if (n >= size)
41922ce4affSfengbojiang             goto error;
42022ce4affSfengbojiang 
42122ce4affSfengbojiang         /* store value according to type size */
42222ce4affSfengbojiang         switch (type_size) {
42322ce4affSfengbojiang         case 1:
42422ce4affSfengbojiang             if (allow_signed) {
42522ce4affSfengbojiang                 if (value < SCHAR_MIN || value > SCHAR_MAX)
42622ce4affSfengbojiang                     goto error;
42722ce4affSfengbojiang             } else {
42822ce4affSfengbojiang                 if (value < 0 || value > UCHAR_MAX)
42922ce4affSfengbojiang                     goto error;
43022ce4affSfengbojiang             }
43122ce4affSfengbojiang             ((uint8_t *)pdata)[n] = (uint8_t)value;
43222ce4affSfengbojiang             break;
43322ce4affSfengbojiang         case 2:
43422ce4affSfengbojiang             if (allow_signed) {
43522ce4affSfengbojiang                 if (value < SHRT_MIN || value > SHRT_MAX)
43622ce4affSfengbojiang                     goto error;
43722ce4affSfengbojiang             } else {
43822ce4affSfengbojiang                 if (value < 0 || value > USHRT_MAX)
43922ce4affSfengbojiang                     goto error;
44022ce4affSfengbojiang             }
44122ce4affSfengbojiang             ((uint16_t *)pdata)[n] = (uint16_t)value;
44222ce4affSfengbojiang             break;
44322ce4affSfengbojiang         case 4:
44422ce4affSfengbojiang             if (allow_signed) {
44522ce4affSfengbojiang                 if (value < INT_MIN || value > INT_MAX)
44622ce4affSfengbojiang                     goto error;
44722ce4affSfengbojiang             } else {
44822ce4affSfengbojiang                 if (value > UINT_MAX)
44922ce4affSfengbojiang                     goto error;
45022ce4affSfengbojiang             }
45122ce4affSfengbojiang             ((uint32_t *)pdata)[n] = (uint32_t)value;
45222ce4affSfengbojiang             break;
45322ce4affSfengbojiang         case 8:
45422ce4affSfengbojiang             ((uint64_t *)pdata)[n] = (uint64_t)value;
45522ce4affSfengbojiang             break;
45622ce4affSfengbojiang         default:
45722ce4affSfengbojiang             goto error;
45822ce4affSfengbojiang         }
45922ce4affSfengbojiang         n++;
46022ce4affSfengbojiang     }
46122ce4affSfengbojiang     *psize = n * type_size;
46222ce4affSfengbojiang 
46322ce4affSfengbojiang     if (n != 0)
46422ce4affSfengbojiang         rc = 1;    /* success */
46522ce4affSfengbojiang error:
46622ce4affSfengbojiang     kenv_release(buf);
46722ce4affSfengbojiang     return (rc);
46822ce4affSfengbojiang }
469a9643ea8Slogwang 
470a9643ea8Slogwang void
tunable_int_init(void * data)471a9643ea8Slogwang tunable_int_init(void *data)
472a9643ea8Slogwang {
473a9643ea8Slogwang     struct tunable_int *d = (struct tunable_int *)data;
474a9643ea8Slogwang 
475a9643ea8Slogwang     TUNABLE_INT_FETCH(d->path, d->var);
476a9643ea8Slogwang }
477a9643ea8Slogwang 
478a9643ea8Slogwang void
tunable_long_init(void * data)479a9643ea8Slogwang tunable_long_init(void *data)
480a9643ea8Slogwang {
481a9643ea8Slogwang     struct tunable_long *d = (struct tunable_long *)data;
482a9643ea8Slogwang 
483a9643ea8Slogwang     TUNABLE_LONG_FETCH(d->path, d->var);
484a9643ea8Slogwang }
485a9643ea8Slogwang 
486a9643ea8Slogwang void
tunable_ulong_init(void * data)487a9643ea8Slogwang tunable_ulong_init(void *data)
488a9643ea8Slogwang {
489a9643ea8Slogwang     struct tunable_ulong *d = (struct tunable_ulong *)data;
490a9643ea8Slogwang 
491a9643ea8Slogwang     TUNABLE_ULONG_FETCH(d->path, d->var);
492a9643ea8Slogwang }
493a9643ea8Slogwang 
494a9643ea8Slogwang void
tunable_quad_init(void * data)495a9643ea8Slogwang tunable_quad_init(void *data)
496a9643ea8Slogwang {
497a9643ea8Slogwang     struct tunable_quad *d = (struct tunable_quad *)data;
498a9643ea8Slogwang 
499a9643ea8Slogwang     TUNABLE_QUAD_FETCH(d->path, d->var);
500a9643ea8Slogwang }
501a9643ea8Slogwang 
502a9643ea8Slogwang void
tunable_str_init(void * data)503a9643ea8Slogwang tunable_str_init(void *data)
504a9643ea8Slogwang {
505a9643ea8Slogwang     struct tunable_str *d = (struct tunable_str *)data;
506a9643ea8Slogwang 
507a9643ea8Slogwang     TUNABLE_STR_FETCH(d->path, d->var, d->size);
508a9643ea8Slogwang }
509a9643ea8Slogwang 
510