140090Smsmith/*- 240090Smsmith * Copyright (c) 1998 Michael Smith 340090Smsmith * All rights reserved. 440090Smsmith * 540090Smsmith * Redistribution and use in source and binary forms, with or without 640090Smsmith * modification, are permitted provided that the following conditions 740090Smsmith * are met: 840090Smsmith * 1. Redistributions of source code must retain the above copyright 940090Smsmith * notice, this list of conditions and the following disclaimer. 1040090Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1140090Smsmith * notice, this list of conditions and the following disclaimer in the 1240090Smsmith * documentation and/or other materials provided with the distribution. 1340090Smsmith * 1440090Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1540090Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1640090Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1740090Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1840090Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1940090Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2040090Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2140090Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2240090Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2340090Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2440090Smsmith * SUCH DAMAGE. 2540116Sjkh */ 2640090Smsmith 2740090Smsmith/* 2840090Smsmith * The unified bootloader passes us a pointer to a preserved copy of 2994936Smux * bootstrap/kernel environment variables. We convert them to a 3094936Smux * dynamic array of strings later when the VM subsystem is up. 3140090Smsmith * 3294936Smux * We make these available through the kenv(2) syscall for userland 3394936Smux * and through getenv()/freeenv() setenv() unsetenv() testenv() for 3494936Smux * the kernel. 3540090Smsmith */ 3640090Smsmith 37116182Sobrien#include <sys/cdefs.h> 38116182Sobrien__FBSDID("$FreeBSD$"); 39116182Sobrien 4094936Smux#include <sys/types.h> 4140090Smsmith#include <sys/param.h> 4294936Smux#include <sys/proc.h> 4394936Smux#include <sys/queue.h> 4494936Smux#include <sys/lock.h> 4594936Smux#include <sys/malloc.h> 4694936Smux#include <sys/mutex.h> 47164033Srwatson#include <sys/priv.h> 4840090Smsmith#include <sys/kernel.h> 4940090Smsmith#include <sys/systm.h> 5094936Smux#include <sys/sysent.h> 5194936Smux#include <sys/sysproto.h> 5240090Smsmith#include <sys/libkern.h> 5394936Smux#include <sys/kenv.h> 5440090Smsmith 55163606Srwatson#include <security/mac/mac_framework.h> 56163606Srwatson 57141616Sphkstatic MALLOC_DEFINE(M_KENV, "kenv", "kernel environment"); 5840090Smsmith 5994936Smux#define KENV_SIZE 512 /* Maximum number of environment strings */ 6040090Smsmith 6194936Smux/* pointer to the static environment */ 6294936Smuxchar *kern_envp; 63202050Simpstatic int env_len; 64202050Simpstatic int env_pos; 6594936Smuxstatic char *kernenv_next(char *); 6694936Smux 6794936Smux/* dynamic environment variables */ 6894936Smuxchar **kenvp; 69160217Sscottlstruct mtx kenv_lock; 7094936Smux 7185385Sjhb/* 72167232Srwatson * No need to protect this with a mutex since SYSINITS are single threaded. 7394936Smux */ 7494936Smuxint dynamic_kenv = 0; 7594936Smux 7694936Smux#define KENV_CHECK if (!dynamic_kenv) \ 7794936Smux panic("%s: called before SI_SUB_KMEM", __func__) 7894936Smux 7994936Smuxint 80225617Skmacysys_kenv(td, uap) 8194936Smux struct thread *td; 8294936Smux struct kenv_args /* { 83107850Salfred int what; 84107850Salfred const char *name; 85107850Salfred char *value; 86107850Salfred int len; 8794936Smux } */ *uap; 8894936Smux{ 89160217Sscottl char *name, *value, *buffer = NULL; 90190301Scperciva size_t len, done, needed, buflen; 9194936Smux int error, i; 9295839Speter 9394936Smux KASSERT(dynamic_kenv, ("kenv: dynamic_kenv = 0")); 9494936Smux 9594936Smux error = 0; 96107849Salfred if (uap->what == KENV_DUMP) { 97106308Srwatson#ifdef MAC 98172930Srwatson error = mac_kenv_check_dump(td->td_ucred); 99106308Srwatson if (error) 100106308Srwatson return (error); 101106308Srwatson#endif 102128697Sdas done = needed = 0; 103190301Scperciva buflen = uap->len; 104190301Scperciva if (buflen > KENV_SIZE * (KENV_MNAMELEN + KENV_MVALLEN + 2)) 105190301Scperciva buflen = KENV_SIZE * (KENV_MNAMELEN + 106190301Scperciva KENV_MVALLEN + 2); 107160217Sscottl if (uap->len > 0 && uap->value != NULL) 108190301Scperciva buffer = malloc(buflen, M_TEMP, M_WAITOK|M_ZERO); 109160217Sscottl mtx_lock(&kenv_lock); 110128697Sdas for (i = 0; kenvp[i] != NULL; i++) { 111128697Sdas len = strlen(kenvp[i]) + 1; 112128697Sdas needed += len; 113190301Scperciva len = min(len, buflen - done); 114128697Sdas /* 115128697Sdas * If called with a NULL or insufficiently large 116128697Sdas * buffer, just keep computing the required size. 117128697Sdas */ 118160217Sscottl if (uap->value != NULL && buffer != NULL && len > 0) { 119160217Sscottl bcopy(kenvp[i], buffer + done, len); 120128697Sdas done += len; 12194936Smux } 12294936Smux } 123160217Sscottl mtx_unlock(&kenv_lock); 124160217Sscottl if (buffer != NULL) { 125160217Sscottl error = copyout(buffer, uap->value, done); 126160217Sscottl free(buffer, M_TEMP); 127160217Sscottl } 128128697Sdas td->td_retval[0] = ((done == needed) ? 0 : needed); 129128697Sdas return (error); 13094936Smux } 13194936Smux 132164033Srwatson switch (uap->what) { 133164033Srwatson case KENV_SET: 134164033Srwatson error = priv_check(td, PRIV_KENV_SET); 13594936Smux if (error) 13694936Smux return (error); 137164033Srwatson break; 138164033Srwatson 139164033Srwatson case KENV_UNSET: 140164033Srwatson error = priv_check(td, PRIV_KENV_UNSET); 141164033Srwatson if (error) 142164033Srwatson return (error); 143164033Srwatson break; 14494936Smux } 14594936Smux 146241222Sjh name = malloc(KENV_MNAMELEN + 1, M_TEMP, M_WAITOK); 14794936Smux 148241222Sjh error = copyinstr(uap->name, name, KENV_MNAMELEN + 1, NULL); 14994936Smux if (error) 15094936Smux goto done; 15194936Smux 152107849Salfred switch (uap->what) { 15394936Smux case KENV_GET: 154106308Srwatson#ifdef MAC 155172930Srwatson error = mac_kenv_check_get(td->td_ucred, name); 156106308Srwatson if (error) 157106308Srwatson goto done; 158106308Srwatson#endif 15994936Smux value = getenv(name); 16094936Smux if (value == NULL) { 16194936Smux error = ENOENT; 16294936Smux goto done; 16394936Smux } 16494936Smux len = strlen(value) + 1; 165107849Salfred if (len > uap->len) 166107849Salfred len = uap->len; 167107849Salfred error = copyout(value, uap->value, len); 16894936Smux freeenv(value); 16994936Smux if (error) 17094936Smux goto done; 17194936Smux td->td_retval[0] = len; 17294936Smux break; 17394936Smux case KENV_SET: 174107849Salfred len = uap->len; 17594936Smux if (len < 1) { 17694936Smux error = EINVAL; 17794936Smux goto done; 17894936Smux } 179241222Sjh if (len > KENV_MVALLEN + 1) 180241222Sjh len = KENV_MVALLEN + 1; 181111119Simp value = malloc(len, M_TEMP, M_WAITOK); 182107849Salfred error = copyinstr(uap->value, value, len, NULL); 18394936Smux if (error) { 18494936Smux free(value, M_TEMP); 18594936Smux goto done; 18694936Smux } 187106308Srwatson#ifdef MAC 188172930Srwatson error = mac_kenv_check_set(td->td_ucred, name, value); 189106308Srwatson if (error == 0) 190106308Srwatson#endif 191106308Srwatson setenv(name, value); 19294936Smux free(value, M_TEMP); 19394936Smux break; 19494936Smux case KENV_UNSET: 195106308Srwatson#ifdef MAC 196172930Srwatson error = mac_kenv_check_unset(td->td_ucred, name); 197106308Srwatson if (error) 198106308Srwatson goto done; 199106308Srwatson#endif 20094936Smux error = unsetenv(name); 20194936Smux if (error) 20294936Smux error = ENOENT; 20394936Smux break; 20494936Smux default: 20594936Smux error = EINVAL; 20694936Smux break; 20794936Smux } 20894936Smuxdone: 20994936Smux free(name, M_TEMP); 21094936Smux return (error); 21194936Smux} 21294936Smux 213202050Simpvoid 214202050Simpinit_static_kenv(char *buf, size_t len) 215202050Simp{ 216202050Simp kern_envp = buf; 217202050Simp env_len = len; 218202050Simp env_pos = 0; 219202050Simp} 220202050Simp 22194936Smux/* 22294936Smux * Setup the dynamic kernel environment. 22394936Smux */ 22494936Smuxstatic void 22594936Smuxinit_dynamic_kenv(void *data __unused) 22694936Smux{ 22794936Smux char *cp; 228222216Sjh size_t len; 229222216Sjh int i; 23094936Smux 231148585Snetchild kenvp = malloc((KENV_SIZE + 1) * sizeof(char *), M_KENV, 232148585Snetchild M_WAITOK | M_ZERO); 23394936Smux i = 0; 23494936Smux for (cp = kern_envp; cp != NULL; cp = kernenv_next(cp)) { 23594936Smux len = strlen(cp) + 1; 236222216Sjh if (len > KENV_MNAMELEN + 1 + KENV_MVALLEN + 1) { 237222216Sjh printf("WARNING: too long kenv string, ignoring %s\n", 238222216Sjh cp); 239222216Sjh continue; 240222216Sjh } 241156748Snetchild if (i < KENV_SIZE) { 242156748Snetchild kenvp[i] = malloc(len, M_KENV, M_WAITOK); 243156482Sphk strcpy(kenvp[i++], cp); 244156748Snetchild } else 245156482Sphk printf( 246156482Sphk "WARNING: too many kenv strings, ignoring %s\n", 247156482Sphk cp); 24894936Smux } 24994936Smux kenvp[i] = NULL; 25094936Smux 251160217Sscottl mtx_init(&kenv_lock, "kernel environment", NULL, MTX_DEF); 25294936Smux dynamic_kenv = 1; 25394936Smux} 25494936SmuxSYSINIT(kenv, SI_SUB_KMEM, SI_ORDER_ANY, init_dynamic_kenv, NULL); 25594936Smux 25694936Smuxvoid 25794936Smuxfreeenv(char *env) 25894936Smux{ 25994936Smux 26094936Smux if (dynamic_kenv) 26194936Smux free(env, M_KENV); 26294936Smux} 26394936Smux 26494936Smux/* 26594936Smux * Internal functions for string lookup. 26694936Smux */ 26794936Smuxstatic char * 26894936Smux_getenv_dynamic(const char *name, int *idx) 26994936Smux{ 27094936Smux char *cp; 27194936Smux int len, i; 27294936Smux 273160217Sscottl mtx_assert(&kenv_lock, MA_OWNED); 27494936Smux len = strlen(name); 27594936Smux for (cp = kenvp[0], i = 0; cp != NULL; cp = kenvp[++i]) { 276150568Sdavidxu if ((strncmp(cp, name, len) == 0) && 277150568Sdavidxu (cp[len] == '=')) { 27894936Smux if (idx != NULL) 27994936Smux *idx = i; 28094936Smux return (cp + len + 1); 28194936Smux } 28294936Smux } 28394936Smux return (NULL); 28494936Smux} 28594936Smux 28694936Smuxstatic char * 28794936Smux_getenv_static(const char *name) 28894936Smux{ 28994936Smux char *cp, *ep; 29094936Smux int len; 29194936Smux 29294936Smux for (cp = kern_envp; cp != NULL; cp = kernenv_next(cp)) { 29394936Smux for (ep = cp; (*ep != '=') && (*ep != 0); ep++) 29494936Smux ; 29595467Sbde if (*ep != '=') 29695467Sbde continue; 29794936Smux len = ep - cp; 29895467Sbde ep++; 29995467Sbde if (!strncmp(name, cp, len) && name[len] == 0) 30094936Smux return (ep); 30194936Smux } 30294936Smux return (NULL); 30394936Smux} 30494936Smux 30594936Smux/* 30685385Sjhb * Look up an environment variable by name. 30794936Smux * Return a pointer to the string if found. 30894936Smux * The pointer has to be freed with freeenv() 30994936Smux * after use. 31085385Sjhb */ 31140090Smsmithchar * 31278247Spetergetenv(const char *name) 31340090Smsmith{ 31494959Smux char buf[KENV_MNAMELEN + 1 + KENV_MVALLEN + 1]; 31594936Smux char *ret, *cp; 31694936Smux int len; 31794936Smux 31894936Smux if (dynamic_kenv) { 319160217Sscottl mtx_lock(&kenv_lock); 32094936Smux cp = _getenv_dynamic(name, NULL); 32194936Smux if (cp != NULL) { 32294959Smux strcpy(buf, cp); 323160217Sscottl mtx_unlock(&kenv_lock); 32494959Smux len = strlen(buf) + 1; 325111119Simp ret = malloc(len, M_KENV, M_WAITOK); 32694959Smux strcpy(ret, buf); 32794959Smux } else { 328160217Sscottl mtx_unlock(&kenv_lock); 32994936Smux ret = NULL; 330221607Sjh WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 331221607Sjh "getenv"); 33294959Smux } 33394936Smux } else 33494936Smux ret = _getenv_static(name); 33594936Smux return (ret); 33640090Smsmith} 33740090Smsmith 33842706Smsmith/* 33994936Smux * Test if an environment variable is defined. 34094936Smux */ 34194936Smuxint 34294936Smuxtestenv(const char *name) 34394936Smux{ 34494936Smux char *cp; 34594936Smux 34694936Smux if (dynamic_kenv) { 347160217Sscottl mtx_lock(&kenv_lock); 34894936Smux cp = _getenv_dynamic(name, NULL); 349160217Sscottl mtx_unlock(&kenv_lock); 35094936Smux } else 35194936Smux cp = _getenv_static(name); 35294936Smux if (cp != NULL) 35394936Smux return (1); 35494936Smux return (0); 35594936Smux} 35694936Smux 357202050Simpstatic int 358202050Simpsetenv_static(const char *name, const char *value) 359202050Simp{ 360202050Simp int len; 361202050Simp 362202050Simp if (env_pos >= env_len) 363202050Simp return (-1); 364202050Simp 365202050Simp /* Check space for x=y and two nuls */ 366202050Simp len = strlen(name) + strlen(value); 367202050Simp if (len + 3 < env_len - env_pos) { 368202050Simp len = sprintf(&kern_envp[env_pos], "%s=%s", name, value); 369202050Simp env_pos += len+1; 370202050Simp kern_envp[env_pos] = '\0'; 371202050Simp return (0); 372202050Simp } else 373202050Simp return (-1); 374202050Simp 375202050Simp} 376202050Simp 37794936Smux/* 37894936Smux * Set an environment variable by name. 37994936Smux */ 38094959Smuxint 38194936Smuxsetenv(const char *name, const char *value) 38294936Smux{ 38394959Smux char *buf, *cp, *oldenv; 38494959Smux int namelen, vallen, i; 38594936Smux 386202050Simp if (dynamic_kenv == 0 && env_len > 0) 387202050Simp return (setenv_static(name, value)); 388202050Simp 38994936Smux KENV_CHECK; 39094936Smux 39194959Smux namelen = strlen(name) + 1; 392241222Sjh if (namelen > KENV_MNAMELEN + 1) 39394959Smux return (-1); 39494959Smux vallen = strlen(value) + 1; 395241222Sjh if (vallen > KENV_MVALLEN + 1) 39694959Smux return (-1); 397111119Simp buf = malloc(namelen + vallen, M_KENV, M_WAITOK); 39894936Smux sprintf(buf, "%s=%s", name, value); 39994936Smux 400160217Sscottl mtx_lock(&kenv_lock); 40194936Smux cp = _getenv_dynamic(name, &i); 40294936Smux if (cp != NULL) { 40394959Smux oldenv = kenvp[i]; 40494936Smux kenvp[i] = buf; 405160217Sscottl mtx_unlock(&kenv_lock); 40694959Smux free(oldenv, M_KENV); 40794936Smux } else { 40894936Smux /* We add the option if it wasn't found */ 40994936Smux for (i = 0; (cp = kenvp[i]) != NULL; i++) 41094936Smux ; 411148585Snetchild 412148585Snetchild /* Bounds checking */ 413148585Snetchild if (i < 0 || i >= KENV_SIZE) { 414148585Snetchild free(buf, M_KENV); 415160217Sscottl mtx_unlock(&kenv_lock); 416148585Snetchild return (-1); 417148585Snetchild } 418148585Snetchild 41994936Smux kenvp[i] = buf; 42094936Smux kenvp[i + 1] = NULL; 421160217Sscottl mtx_unlock(&kenv_lock); 42294936Smux } 42394959Smux return (0); 42494936Smux} 42594936Smux 42694936Smux/* 42794936Smux * Unset an environment variable string. 42894936Smux */ 42994936Smuxint 43094936Smuxunsetenv(const char *name) 43194936Smux{ 43294959Smux char *cp, *oldenv; 43394936Smux int i, j; 43494936Smux 43594936Smux KENV_CHECK; 43694936Smux 437160217Sscottl mtx_lock(&kenv_lock); 43894936Smux cp = _getenv_dynamic(name, &i); 43994936Smux if (cp != NULL) { 44094959Smux oldenv = kenvp[i]; 44194936Smux for (j = i + 1; kenvp[j] != NULL; j++) 44294936Smux kenvp[i++] = kenvp[j]; 44394936Smux kenvp[i] = NULL; 444160217Sscottl mtx_unlock(&kenv_lock); 44594959Smux free(oldenv, M_KENV); 44694936Smux return (0); 44794936Smux } 448160217Sscottl mtx_unlock(&kenv_lock); 44994936Smux return (-1); 45094936Smux} 45194936Smux 45294936Smux/* 45385385Sjhb * Return a string value from an environment variable. 45485385Sjhb */ 45585385Sjhbint 45685385Sjhbgetenv_string(const char *name, char *data, int size) 45785385Sjhb{ 45895839Speter char *tmp; 45985385Sjhb 46095839Speter tmp = getenv(name); 46195839Speter if (tmp != NULL) { 462105354Srobert strlcpy(data, tmp, size); 46395839Speter freeenv(tmp); 46495839Speter return (1); 46595839Speter } else 46695839Speter return (0); 46785385Sjhb} 46885385Sjhb 46985385Sjhb/* 47042706Smsmith * Return an integer value from an environment variable. 47142706Smsmith */ 47242706Smsmithint 47378247Spetergetenv_int(const char *name, int *data) 47442706Smsmith{ 47595839Speter quad_t tmp; 47695839Speter int rval; 47752947Smjacob 47895839Speter rval = getenv_quad(name, &tmp); 47995839Speter if (rval) 48095839Speter *data = (int) tmp; 48195839Speter return (rval); 48252947Smjacob} 48352947Smjacob 48452947Smjacob/* 485172612Sdes * Return an unsigned integer value from an environment variable. 486172612Sdes */ 487172612Sdesint 488172612Sdesgetenv_uint(const char *name, unsigned int *data) 489172612Sdes{ 490172612Sdes quad_t tmp; 491172612Sdes int rval; 492172612Sdes 493172612Sdes rval = getenv_quad(name, &tmp); 494172612Sdes if (rval) 495172612Sdes *data = (unsigned int) tmp; 496172612Sdes return (rval); 497172612Sdes} 498172612Sdes 499172612Sdes/* 500137099Sdes * Return a long value from an environment variable. 501137099Sdes */ 502172612Sdesint 503137099Sdesgetenv_long(const char *name, long *data) 504137099Sdes{ 505137099Sdes quad_t tmp; 506172612Sdes int rval; 507137099Sdes 508137099Sdes rval = getenv_quad(name, &tmp); 509137099Sdes if (rval) 510137099Sdes *data = (long) tmp; 511137099Sdes return (rval); 512137099Sdes} 513137099Sdes 514137099Sdes/* 515137099Sdes * Return an unsigned long value from an environment variable. 516137099Sdes */ 517172612Sdesint 518137099Sdesgetenv_ulong(const char *name, unsigned long *data) 519137099Sdes{ 520137099Sdes quad_t tmp; 521172612Sdes int rval; 522137099Sdes 523137099Sdes rval = getenv_quad(name, &tmp); 524137099Sdes if (rval) 525137099Sdes *data = (unsigned long) tmp; 526137099Sdes return (rval); 527137099Sdes} 528137099Sdes 529137099Sdes/* 53052947Smjacob * Return a quad_t value from an environment variable. 53152947Smjacob */ 53285385Sjhbint 53378247Spetergetenv_quad(const char *name, quad_t *data) 53452947Smjacob{ 53595839Speter char *value; 53695839Speter char *vtp; 53795839Speter quad_t iv; 53895839Speter 53995839Speter value = getenv(name); 54095839Speter if (value == NULL) 54195839Speter return (0); 54295839Speter iv = strtoq(value, &vtp, 0); 543143319Sdes if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) { 544143319Sdes freeenv(value); 54595839Speter return (0); 546143319Sdes } 547143151Sdes switch (vtp[0]) { 548143151Sdes case 't': case 'T': 549143151Sdes iv *= 1024; 550143151Sdes case 'g': case 'G': 551143151Sdes iv *= 1024; 552143151Sdes case 'm': case 'M': 553143151Sdes iv *= 1024; 554143151Sdes case 'k': case 'K': 555143151Sdes iv *= 1024; 556143151Sdes case '\0': 557143151Sdes break; 558143151Sdes default: 559143319Sdes freeenv(value); 560143151Sdes return (0); 56195839Speter } 56295839Speter *data = iv; 563143319Sdes freeenv(value); 56495839Speter return (1); 56542706Smsmith} 56640090Smsmith 56783744Speter/* 56840090Smsmith * Find the next entry after the one which (cp) falls within, return a 56940090Smsmith * pointer to its start or NULL if there are no more. 57040090Smsmith */ 57140090Smsmithstatic char * 57240090Smsmithkernenv_next(char *cp) 57340090Smsmith{ 57495839Speter 57595839Speter if (cp != NULL) { 57695839Speter while (*cp != 0) 57795839Speter cp++; 57895839Speter cp++; 57995839Speter if (*cp == 0) 58095839Speter cp = NULL; 58195839Speter } 58295839Speter return (cp); 58340090Smsmith} 58440090Smsmith 58577900Spetervoid 58677900Spetertunable_int_init(void *data) 58777900Speter{ 58877900Speter struct tunable_int *d = (struct tunable_int *)data; 58977900Speter 59077900Speter TUNABLE_INT_FETCH(d->path, d->var); 59177900Speter} 59277900Speter 59377900Spetervoid 594137099Sdestunable_long_init(void *data) 595137099Sdes{ 596137099Sdes struct tunable_long *d = (struct tunable_long *)data; 597137099Sdes 598137099Sdes TUNABLE_LONG_FETCH(d->path, d->var); 599137099Sdes} 600137099Sdes 601137099Sdesvoid 602137099Sdestunable_ulong_init(void *data) 603137099Sdes{ 604137099Sdes struct tunable_ulong *d = (struct tunable_ulong *)data; 605137099Sdes 606137099Sdes TUNABLE_ULONG_FETCH(d->path, d->var); 607137099Sdes} 608137099Sdes 609137099Sdesvoid 610180661Spjdtunable_quad_init(void *data) 611180661Spjd{ 612180661Spjd struct tunable_quad *d = (struct tunable_quad *)data; 613180661Spjd 614180661Spjd TUNABLE_QUAD_FETCH(d->path, d->var); 615180661Spjd} 616180661Spjd 617180661Spjdvoid 61877900Spetertunable_str_init(void *data) 61977900Speter{ 62077900Speter struct tunable_str *d = (struct tunable_str *)data; 62177900Speter 62277900Speter TUNABLE_STR_FETCH(d->path, d->var, d->size); 62377900Speter} 624