1276789Sdim/*- 2276789Sdim * Copyright (c) 2000 Andrzej Bialecki <abial@freebsd.org> 3276789Sdim * All rights reserved. 4276789Sdim * 5276789Sdim * Redistribution and use in source and binary forms, with or without 6276789Sdim * modification, are permitted provided that the following conditions 7276789Sdim * are met: 8276789Sdim * 1. Redistributions of source code must retain the above copyright 9276789Sdim * notice, this list of conditions and the following disclaimer. 10276789Sdim * 2. Redistributions in binary form must reproduce the above copyright 11276789Sdim * notice, this list of conditions and the following disclaimer in the 12276789Sdim * documentation and/or other materials provided with the distribution. 13276789Sdim * 14276789Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15276789Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16276789Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17276789Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18276789Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19276789Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20276789Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21276789Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22276789Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23296417Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24296417Sdim * SUCH DAMAGE. 25296417Sdim * 26296417Sdim * $FreeBSD: releng/11.0/share/examples/kld/dyn_sysctl/dyn_sysctl.c 241394 2012-10-10 08:36:38Z kevlo $ 27276789Sdim */ 28276789Sdim 29276789Sdim#include <sys/types.h> 30276789Sdim#include <sys/param.h> 31276789Sdim#include <sys/systm.h> 32276789Sdim#include <sys/module.h> 33276789Sdim#include <sys/sysctl.h> 34276789Sdim#include <sys/kernel.h> 35276789Sdim 36276789Sdim 37276789Sdim/* Some example data */ 38276789Sdimstatic long a = 100; 39276789Sdimstatic int b = 200; 40276789Sdimstatic char *c = "hi there from dyn_sysctl"; 41276789Sdimstatic struct sysctl_oid *a_root, *a_root1, *b_root; 42276789Sdimstatic struct sysctl_ctx_list clist, clist1, clist2; 43276789Sdim 44276789Sdimstatic int 45276789Sdimsysctl_dyn_sysctl_test(SYSCTL_HANDLER_ARGS) 46276789Sdim{ 47276789Sdim char *buf = "let's produce some text..."; 48276789Sdim 49276789Sdim return (sysctl_handle_string(oidp, buf, strlen(buf), req)); 50276789Sdim} 51276789Sdim 52276789Sdim/* 53276789Sdim * The function called at load/unload. 54276789Sdim */ 55276789Sdimstatic int 56276789Sdimload(module_t mod, int cmd, void *arg) 57276789Sdim{ 58276789Sdim int error; 59276789Sdim 60276789Sdim error = 0; 61276789Sdim switch (cmd) { 62276789Sdim case MOD_LOAD: 63280031Sdim /* Initialize the contexts */ 64296417Sdim printf("Initializing contexts and creating subtrees.\n\n"); 65296417Sdim sysctl_ctx_init(&clist); 66276789Sdim sysctl_ctx_init(&clist1); 67276789Sdim sysctl_ctx_init(&clist2); 68276789Sdim /* 69276789Sdim * Create two partially overlapping subtrees, belonging 70276789Sdim * to different contexts. 71276789Sdim */ 72276789Sdim printf("TREE ROOT NAME\n"); 73276789Sdim a_root = SYSCTL_ADD_NODE(&clist, 74276789Sdim SYSCTL_STATIC_CHILDREN(/* top of sysctl tree */), 75276789Sdim OID_AUTO, "dyn_sysctl", CTLFLAG_RW, 0, 76276789Sdim "dyn_sysctl root node"); 77276789Sdim a_root = SYSCTL_ADD_NODE(&clist1, 78276789Sdim SYSCTL_STATIC_CHILDREN(/* top of sysctl tree */), 79276789Sdim OID_AUTO, "dyn_sysctl", CTLFLAG_RW, 0, 80276789Sdim "dyn_sysctl root node"); 81276789Sdim if (a_root == NULL) { 82276789Sdim printf("SYSCTL_ADD_NODE failed!\n"); 83276789Sdim return (EINVAL); 84276789Sdim } 85276789Sdim SYSCTL_ADD_LONG(&clist, SYSCTL_CHILDREN(a_root), 86276789Sdim OID_AUTO, "long_a", CTLFLAG_RW, &a, "just to try"); 87276789Sdim SYSCTL_ADD_INT(&clist, SYSCTL_CHILDREN(a_root), 88276789Sdim OID_AUTO, "int_b", CTLFLAG_RW, &b, 0, "just to try 1"); 89276789Sdim a_root1 = SYSCTL_ADD_NODE(&clist, SYSCTL_CHILDREN(a_root), 90276789Sdim OID_AUTO, "nextlevel", CTLFLAG_RD, 0, "one level down"); 91276789Sdim SYSCTL_ADD_STRING(&clist, SYSCTL_CHILDREN(a_root1), 92276789Sdim OID_AUTO, "string_c", CTLFLAG_RD, c, 0, "just to try 2"); 93276789Sdim printf("1. (%p) / dyn_sysctl\n", &clist); 94276789Sdim 95276789Sdim /* Add a subtree under already existing category */ 96276789Sdim a_root1 = SYSCTL_ADD_NODE(&clist, SYSCTL_STATIC_CHILDREN(_kern), 97276789Sdim OID_AUTO, "dyn_sysctl", CTLFLAG_RW, 0, "dyn_sysctl root node"); 98276789Sdim if (a_root1 == NULL) { 99276789Sdim printf("SYSCTL_ADD_NODE failed!\n"); 100276789Sdim return (EINVAL); 101276789Sdim } 102276789Sdim SYSCTL_ADD_PROC(&clist, SYSCTL_CHILDREN(a_root1), 103296417Sdim OID_AUTO, "procedure", CTLTYPE_STRING | CTLFLAG_RD, 104276789Sdim NULL, 0, sysctl_dyn_sysctl_test, "A", 105276789Sdim "I can be here, too"); 106276789Sdim printf(" (%p) /kern dyn_sysctl\n", &clist); 107276789Sdim 108276789Sdim /* Overlap second tree with the first. */ 109276789Sdim b_root = SYSCTL_ADD_NODE(&clist1, SYSCTL_CHILDREN(a_root), 110296417Sdim OID_AUTO, "nextlevel", CTLFLAG_RD, 0, "one level down"); 111276789Sdim SYSCTL_ADD_STRING(&clist1, SYSCTL_CHILDREN(b_root), 112276789Sdim OID_AUTO, "string_c1", CTLFLAG_RD, c, 0, "just to try 2"); 113276789Sdim printf("2. (%p) / dyn_sysctl (overlapping #1)\n", &clist1); 114276789Sdim 115276789Sdim /* 116276789Sdim * And now do something stupid. Connect another subtree to 117276789Sdim * dynamic oid. 118276789Sdim * WARNING: this is an example of WRONG use of dynamic sysctls. 119276789Sdim */ 120276789Sdim b_root=SYSCTL_ADD_NODE(&clist2, SYSCTL_CHILDREN(a_root1), 121276789Sdim OID_AUTO, "bad", CTLFLAG_RW, 0, "dependent node"); 122276789Sdim SYSCTL_ADD_STRING(&clist2, SYSCTL_CHILDREN(b_root), 123276789Sdim OID_AUTO, "string_c", CTLFLAG_RD, c, 0, "shouldn't panic"); 124276789Sdim printf("3. (%p) /kern/dyn_sysctl bad (WRONG!)\n", &clist2); 125276789Sdim break; 126276789Sdim case MOD_UNLOAD: 127276789Sdim printf("1. Try to free ctx1 (%p): ", &clist); 128276789Sdim if (sysctl_ctx_free(&clist) != 0) 129276789Sdim printf("failed: expected. Need to remove ctx3 first.\n"); 130276789Sdim else 131276789Sdim printf("HELP! sysctl_ctx_free(%p) succeeded. EXPECT PANIC!!!\n", &clist); 132276789Sdim printf("2. Try to free ctx3 (%p): ", &clist2); 133276789Sdim if (sysctl_ctx_free(&clist2) != 0) { 134276789Sdim printf("sysctl_ctx_free(%p) failed!\n", &clist2); 135276789Sdim /* Remove subtree forcefully... */ 136276789Sdim sysctl_remove_oid(b_root, 1, 1); 137276789Sdim printf("sysctl_remove_oid(%p) succeeded\n", b_root); 138276789Sdim } else 139276789Sdim printf("Ok\n"); 140276789Sdim printf("3. Try to free ctx1 (%p) again: ", &clist); 141276789Sdim if (sysctl_ctx_free(&clist) != 0) { 142276789Sdim printf("sysctl_ctx_free(%p) failed!\n", &clist); 143276789Sdim /* Remove subtree forcefully... */ 144276789Sdim sysctl_remove_oid(a_root1, 1, 1); 145276789Sdim printf("sysctl_remove_oid(%p) succeeded\n", a_root1); 146276789Sdim } else 147276789Sdim printf("Ok\n"); 148296417Sdim printf("4. Try to free ctx2 (%p): ", &clist1); 149296417Sdim if (sysctl_ctx_free(&clist1) != 0) { 150296417Sdim printf("sysctl_ctx_free(%p) failed!\n", &clist1); 151296417Sdim /* Remove subtree forcefully... */ 152296417Sdim sysctl_remove_oid(a_root, 1, 1); 153296417Sdim } else 154296417Sdim printf("Ok\n"); 155296417Sdim break; 156296417Sdim default: 157296417Sdim error = EOPNOTSUPP; 158296417Sdim break; 159296417Sdim } 160296417Sdim return (error); 161296417Sdim} 162296417Sdim 163296417Sdimstatic moduledata_t mod_data = { 164296417Sdim "dyn_sysctl", 165276789Sdim load, 166276789Sdim 0 167}; 168 169DECLARE_MODULE(dyn_sysctl, mod_data, SI_SUB_EXEC, SI_ORDER_ANY); 170