163212Sabial/*- 263212Sabial * Copyright (c) 2000 Andrzej Bialecki <abial@freebsd.org> 363212Sabial * All rights reserved. 463212Sabial * 563212Sabial * Redistribution and use in source and binary forms, with or without 663212Sabial * modification, are permitted provided that the following conditions 763212Sabial * are met: 863212Sabial * 1. Redistributions of source code must retain the above copyright 963212Sabial * notice, this list of conditions and the following disclaimer. 1063212Sabial * 2. Redistributions in binary form must reproduce the above copyright 1163212Sabial * notice, this list of conditions and the following disclaimer in the 1263212Sabial * documentation and/or other materials provided with the distribution. 1363212Sabial * 1463212Sabial * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1563212Sabial * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1663212Sabial * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1763212Sabial * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1863212Sabial * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1963212Sabial * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2063212Sabial * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2163212Sabial * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2263212Sabial * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2363212Sabial * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2463212Sabial * SUCH DAMAGE. 2563212Sabial * 2663212Sabial * $FreeBSD$ 2763212Sabial */ 2863212Sabial 2963212Sabial#include <sys/types.h> 3063212Sabial#include <sys/param.h> 3163212Sabial#include <sys/systm.h> 3263212Sabial#include <sys/module.h> 3363212Sabial#include <sys/sysctl.h> 3463212Sabial#include <sys/kernel.h> 3563212Sabial 3663212Sabial 3763212Sabial/* Some example data */ 3863212Sabialstatic long a = 100; 3963212Sabialstatic int b = 200; 4063212Sabialstatic char *c = "hi there from dyn_sysctl"; 4163212Sabialstatic struct sysctl_oid *a_root, *a_root1, *b_root; 4263212Sabialstatic struct sysctl_ctx_list clist, clist1, clist2; 4363212Sabial 4463212Sabialstatic int 45193374Spjdsysctl_dyn_sysctl_test(SYSCTL_HANDLER_ARGS) 4663212Sabial{ 4763212Sabial char *buf = "let's produce some text..."; 4863212Sabial 4963212Sabial return (sysctl_handle_string(oidp, buf, strlen(buf), req)); 5063212Sabial} 5163212Sabial 5263212Sabial/* 5363212Sabial * The function called at load/unload. 5463212Sabial */ 5563212Sabialstatic int 56193374Spjdload(module_t mod, int cmd, void *arg) 5763212Sabial{ 5863212Sabial int error; 5963212Sabial 6063212Sabial error = 0; 6163212Sabial switch (cmd) { 62239130Semaste case MOD_LOAD: 6363212Sabial /* Initialize the contexts */ 6463212Sabial printf("Initializing contexts and creating subtrees.\n\n"); 6563212Sabial sysctl_ctx_init(&clist); 6663212Sabial sysctl_ctx_init(&clist1); 6763212Sabial sysctl_ctx_init(&clist2); 6863212Sabial /* 6963212Sabial * Create two partially overlapping subtrees, belonging 7063212Sabial * to different contexts. 7163212Sabial */ 7263212Sabial printf("TREE ROOT NAME\n"); 7363212Sabial a_root = SYSCTL_ADD_NODE(&clist, 7463212Sabial SYSCTL_STATIC_CHILDREN(/* top of sysctl tree */), 7572336Sabial OID_AUTO, "dyn_sysctl", CTLFLAG_RW, 0, 7663212Sabial "dyn_sysctl root node"); 7763212Sabial a_root = SYSCTL_ADD_NODE(&clist1, 7863212Sabial SYSCTL_STATIC_CHILDREN(/* top of sysctl tree */), 7972336Sabial OID_AUTO, "dyn_sysctl", CTLFLAG_RW, 0, 8063212Sabial "dyn_sysctl root node"); 81193374Spjd if (a_root == NULL) { 8263212Sabial printf("SYSCTL_ADD_NODE failed!\n"); 8363212Sabial return (EINVAL); 8463212Sabial } 8563212Sabial SYSCTL_ADD_LONG(&clist, SYSCTL_CHILDREN(a_root), 86193374Spjd OID_AUTO, "long_a", CTLFLAG_RW, &a, "just to try"); 8763212Sabial SYSCTL_ADD_INT(&clist, SYSCTL_CHILDREN(a_root), 88193374Spjd OID_AUTO, "int_b", CTLFLAG_RW, &b, 0, "just to try 1"); 89193374Spjd a_root1 = SYSCTL_ADD_NODE(&clist, SYSCTL_CHILDREN(a_root), 90193374Spjd OID_AUTO, "nextlevel", CTLFLAG_RD, 0, "one level down"); 9163212Sabial SYSCTL_ADD_STRING(&clist, SYSCTL_CHILDREN(a_root1), 92193374Spjd OID_AUTO, "string_c", CTLFLAG_RD, c, 0, "just to try 2"); 9363212Sabial printf("1. (%p) / dyn_sysctl\n", &clist); 9463212Sabial 9563212Sabial /* Add a subtree under already existing category */ 9663212Sabial a_root1 = SYSCTL_ADD_NODE(&clist, SYSCTL_STATIC_CHILDREN(_kern), 97193374Spjd OID_AUTO, "dyn_sysctl", CTLFLAG_RW, 0, "dyn_sysctl root node"); 98193374Spjd if (a_root1 == NULL) { 9963212Sabial printf("SYSCTL_ADD_NODE failed!\n"); 10063212Sabial return (EINVAL); 10163212Sabial } 10263212Sabial SYSCTL_ADD_PROC(&clist, SYSCTL_CHILDREN(a_root1), 103217566Smdf OID_AUTO, "procedure", CTLTYPE_STRING | CTLFLAG_RD, 104217566Smdf NULL, 0, sysctl_dyn_sysctl_test, "A", 105217566Smdf "I can be here, too"); 10663212Sabial printf(" (%p) /kern dyn_sysctl\n", &clist); 10763212Sabial 10863212Sabial /* Overlap second tree with the first. */ 10963212Sabial b_root = SYSCTL_ADD_NODE(&clist1, SYSCTL_CHILDREN(a_root), 110193374Spjd OID_AUTO, "nextlevel", CTLFLAG_RD, 0, "one level down"); 11163212Sabial SYSCTL_ADD_STRING(&clist1, SYSCTL_CHILDREN(b_root), 112193374Spjd OID_AUTO, "string_c1", CTLFLAG_RD, c, 0, "just to try 2"); 11363212Sabial printf("2. (%p) / dyn_sysctl (overlapping #1)\n", &clist1); 11463212Sabial 11563212Sabial /* 11663212Sabial * And now do something stupid. Connect another subtree to 11763212Sabial * dynamic oid. 11863212Sabial * WARNING: this is an example of WRONG use of dynamic sysctls. 11963212Sabial */ 12063212Sabial b_root=SYSCTL_ADD_NODE(&clist2, SYSCTL_CHILDREN(a_root1), 121193374Spjd OID_AUTO, "bad", CTLFLAG_RW, 0, "dependent node"); 12263212Sabial SYSCTL_ADD_STRING(&clist2, SYSCTL_CHILDREN(b_root), 123193374Spjd OID_AUTO, "string_c", CTLFLAG_RD, c, 0, "shouldn't panic"); 12463212Sabial printf("3. (%p) /kern/dyn_sysctl bad (WRONG!)\n", &clist2); 12563212Sabial break; 126239130Semaste case MOD_UNLOAD: 12763212Sabial printf("1. Try to free ctx1 (%p): ", &clist); 128193374Spjd if (sysctl_ctx_free(&clist) != 0) 12963212Sabial printf("failed: expected. Need to remove ctx3 first.\n"); 13063212Sabial else 13163212Sabial printf("HELP! sysctl_ctx_free(%p) succeeded. EXPECT PANIC!!!\n", &clist); 13263212Sabial printf("2. Try to free ctx3 (%p): ", &clist2); 133193374Spjd if (sysctl_ctx_free(&clist2) != 0) { 13463212Sabial printf("sysctl_ctx_free(%p) failed!\n", &clist2); 13563212Sabial /* Remove subtree forcefully... */ 13663212Sabial sysctl_remove_oid(b_root, 1, 1); 13763212Sabial printf("sysctl_remove_oid(%p) succeeded\n", b_root); 13863212Sabial } else 13963212Sabial printf("Ok\n"); 14063212Sabial printf("3. Try to free ctx1 (%p) again: ", &clist); 141193374Spjd if (sysctl_ctx_free(&clist) != 0) { 14263212Sabial printf("sysctl_ctx_free(%p) failed!\n", &clist); 14363212Sabial /* Remove subtree forcefully... */ 14463212Sabial sysctl_remove_oid(a_root1, 1, 1); 14563212Sabial printf("sysctl_remove_oid(%p) succeeded\n", a_root1); 14663212Sabial } else 14763212Sabial printf("Ok\n"); 14863212Sabial printf("4. Try to free ctx2 (%p): ", &clist1); 149193374Spjd if (sysctl_ctx_free(&clist1) != 0) { 15063212Sabial printf("sysctl_ctx_free(%p) failed!\n", &clist1); 15163212Sabial /* Remove subtree forcefully... */ 15263212Sabial sysctl_remove_oid(a_root, 1, 1); 15363212Sabial } else 15463212Sabial printf("Ok\n"); 15563212Sabial break; 156239130Semaste default: 157134520Spjd error = EOPNOTSUPP; 15863212Sabial break; 15963212Sabial } 160193374Spjd return (error); 16163212Sabial} 16263212Sabial 163193374Spjdstatic moduledata_t mod_data = { 16463212Sabial "dyn_sysctl", 16563212Sabial load, 166241394Skevlo 0 16763212Sabial}; 16863212Sabial 16963212SabialDECLARE_MODULE(dyn_sysctl, mod_data, SI_SUB_EXEC, SI_ORDER_ANY); 170