Path: blob/main/share/examples/kld/dyn_sysctl/dyn_sysctl.c
39534 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2000 Andrzej Bialecki <[email protected]>4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728#include <sys/types.h>29#include <sys/param.h>30#include <sys/systm.h>31#include <sys/module.h>32#include <sys/sysctl.h>33#include <sys/kernel.h>343536/* Some example data */37static long a = 100;38static int b = 200;39static char *c = "hi there from dyn_sysctl";40static struct sysctl_oid *a_root, *a_root1, *b_root;41static struct sysctl_ctx_list clist, clist1, clist2;4243static int44sysctl_dyn_sysctl_test(SYSCTL_HANDLER_ARGS)45{46char *buf = "let's produce some text...";4748return (sysctl_handle_string(oidp, buf, strlen(buf), req));49}5051/*52* The function called at load/unload.53*/54static int55load(module_t mod, int cmd, void *arg)56{57int error;5859error = 0;60switch (cmd) {61case MOD_LOAD:62/* Initialize the contexts */63printf("Initializing contexts and creating subtrees.\n\n");64sysctl_ctx_init(&clist);65sysctl_ctx_init(&clist1);66sysctl_ctx_init(&clist2);67/*68* Create two partially overlapping subtrees, belonging69* to different contexts.70*/71printf("TREE ROOT NAME\n");72a_root = SYSCTL_ADD_ROOT_NODE(&clist,73OID_AUTO, "dyn_sysctl", CTLFLAG_RW, 0,74"dyn_sysctl root node");75a_root = SYSCTL_ADD_ROOT_NODE(&clist1,76OID_AUTO, "dyn_sysctl", CTLFLAG_RW, 0,77"dyn_sysctl root node");78if (a_root == NULL) {79printf("SYSCTL_ADD_NODE failed!\n");80return (EINVAL);81}82SYSCTL_ADD_LONG(&clist, SYSCTL_CHILDREN(a_root),83OID_AUTO, "long_a", CTLFLAG_RW, &a, "just to try");84SYSCTL_ADD_INT(&clist, SYSCTL_CHILDREN(a_root),85OID_AUTO, "int_b", CTLFLAG_RW, &b, 0, "just to try 1");86a_root1 = SYSCTL_ADD_NODE(&clist, SYSCTL_CHILDREN(a_root),87OID_AUTO, "nextlevel", CTLFLAG_RD, 0, "one level down");88SYSCTL_ADD_STRING(&clist, SYSCTL_CHILDREN(a_root1),89OID_AUTO, "string_c", CTLFLAG_RD, c, 0, "just to try 2");90printf("1. (%p) / dyn_sysctl\n", &clist);9192/* Add a subtree under already existing category */93a_root1 = SYSCTL_ADD_NODE(&clist, SYSCTL_STATIC_CHILDREN(_kern),94OID_AUTO, "dyn_sysctl", CTLFLAG_RW, 0, "dyn_sysctl root node");95if (a_root1 == NULL) {96printf("SYSCTL_ADD_NODE failed!\n");97return (EINVAL);98}99SYSCTL_ADD_PROC(&clist, SYSCTL_CHILDREN(a_root1),100OID_AUTO, "procedure", CTLTYPE_STRING | CTLFLAG_RD,101NULL, 0, sysctl_dyn_sysctl_test, "A",102"I can be here, too");103printf(" (%p) /kern dyn_sysctl\n", &clist);104105/* Overlap second tree with the first. */106b_root = SYSCTL_ADD_NODE(&clist1, SYSCTL_CHILDREN(a_root),107OID_AUTO, "nextlevel", CTLFLAG_RD, 0, "one level down");108SYSCTL_ADD_STRING(&clist1, SYSCTL_CHILDREN(b_root),109OID_AUTO, "string_c1", CTLFLAG_RD, c, 0, "just to try 2");110printf("2. (%p) / dyn_sysctl (overlapping #1)\n", &clist1);111112/*113* And now do something stupid. Connect another subtree to114* dynamic oid.115* WARNING: this is an example of WRONG use of dynamic sysctls.116*/117b_root=SYSCTL_ADD_NODE(&clist2, SYSCTL_CHILDREN(a_root1),118OID_AUTO, "bad", CTLFLAG_RW, 0, "dependent node");119SYSCTL_ADD_STRING(&clist2, SYSCTL_CHILDREN(b_root),120OID_AUTO, "string_c", CTLFLAG_RD, c, 0, "shouldn't panic");121printf("3. (%p) /kern/dyn_sysctl bad (WRONG!)\n", &clist2);122break;123case MOD_UNLOAD:124printf("1. Try to free ctx1 (%p): ", &clist);125if (sysctl_ctx_free(&clist) != 0)126printf("failed: expected. Need to remove ctx3 first.\n");127else128printf("HELP! sysctl_ctx_free(%p) succeeded. EXPECT PANIC!!!\n", &clist);129printf("2. Try to free ctx3 (%p): ", &clist2);130if (sysctl_ctx_free(&clist2) != 0) {131printf("sysctl_ctx_free(%p) failed!\n", &clist2);132/* Remove subtree forcefully... */133sysctl_remove_oid(b_root, 1, 1);134printf("sysctl_remove_oid(%p) succeeded\n", b_root);135} else136printf("Ok\n");137printf("3. Try to free ctx1 (%p) again: ", &clist);138if (sysctl_ctx_free(&clist) != 0) {139printf("sysctl_ctx_free(%p) failed!\n", &clist);140/* Remove subtree forcefully... */141sysctl_remove_oid(a_root1, 1, 1);142printf("sysctl_remove_oid(%p) succeeded\n", a_root1);143} else144printf("Ok\n");145printf("4. Try to free ctx2 (%p): ", &clist1);146if (sysctl_ctx_free(&clist1) != 0) {147printf("sysctl_ctx_free(%p) failed!\n", &clist1);148/* Remove subtree forcefully... */149sysctl_remove_oid(a_root, 1, 1);150} else151printf("Ok\n");152break;153default:154error = EOPNOTSUPP;155break;156}157return (error);158}159160static moduledata_t mod_data = {161"dyn_sysctl",162load,1630164};165166DECLARE_MODULE(dyn_sysctl, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);167168169