dyn_sysctl.c revision 256281
1178479Sjb/*- 2178479Sjb * Copyright (c) 2000 Andrzej Bialecki <abial@freebsd.org> 3178479Sjb * All rights reserved. 4178479Sjb * 5178479Sjb * Redistribution and use in source and binary forms, with or without 6178479Sjb * modification, are permitted provided that the following conditions 7178479Sjb * are met: 8178479Sjb * 1. Redistributions of source code must retain the above copyright 9178479Sjb * notice, this list of conditions and the following disclaimer. 10178479Sjb * 2. Redistributions in binary form must reproduce the above copyright 11178479Sjb * notice, this list of conditions and the following disclaimer in the 12178479Sjb * documentation and/or other materials provided with the distribution. 13178479Sjb * 14178479Sjb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15178479Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16178479Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17178479Sjb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18178479Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19178479Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20178479Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21178479Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22178479Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23178573Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24178479Sjb * SUCH DAMAGE. 25178479Sjb * 26178479Sjb * $FreeBSD: stable/10/share/examples/kld/dyn_sysctl/dyn_sysctl.c 241394 2012-10-10 08:36:38Z kevlo $ 27178479Sjb */ 28178479Sjb 29178479Sjb#include <sys/types.h> 30178479Sjb#include <sys/param.h> 31178479Sjb#include <sys/systm.h> 32178479Sjb#include <sys/module.h> 33178573Sjb#include <sys/sysctl.h> 34178479Sjb#include <sys/kernel.h> 35178573Sjb 36178573Sjb 37178573Sjb/* Some example data */ 38178479Sjbstatic long a = 100; 39178479Sjbstatic int b = 200; 40178479Sjbstatic char *c = "hi there from dyn_sysctl"; 41178573Sjbstatic struct sysctl_oid *a_root, *a_root1, *b_root; 42178479Sjbstatic struct sysctl_ctx_list clist, clist1, clist2; 43178573Sjb 44178479Sjbstatic int 45178479Sjbsysctl_dyn_sysctl_test(SYSCTL_HANDLER_ARGS) 46178479Sjb{ 47178479Sjb char *buf = "let's produce some text..."; 48178479Sjb 49178479Sjb return (sysctl_handle_string(oidp, buf, strlen(buf), req)); 50178573Sjb} 51178479Sjb 52178573Sjb/* 53178573Sjb * The function called at load/unload. 54211554Srpaulo */ 55211554Srpaulostatic int 56211554Srpauloload(module_t mod, int cmd, void *arg) 57178573Sjb{ 58178479Sjb int error; 59178479Sjb 60178479Sjb error = 0; 61178479Sjb switch (cmd) { 62178479Sjb case MOD_LOAD: 63178479Sjb /* Initialize the contexts */ 64178479Sjb printf("Initializing contexts and creating subtrees.\n\n"); 65178479Sjb sysctl_ctx_init(&clist); 66178479Sjb sysctl_ctx_init(&clist1); 67178479Sjb sysctl_ctx_init(&clist2); 68178479Sjb /* 69178479Sjb * Create two partially overlapping subtrees, belonging 70178479Sjb * to different contexts. 71178479Sjb */ 72178479Sjb printf("TREE ROOT NAME\n"); 73178479Sjb a_root = SYSCTL_ADD_NODE(&clist, 74178479Sjb SYSCTL_STATIC_CHILDREN(/* top of sysctl tree */), 75178479Sjb OID_AUTO, "dyn_sysctl", CTLFLAG_RW, 0, 76178479Sjb "dyn_sysctl root node"); 77178479Sjb a_root = SYSCTL_ADD_NODE(&clist1, 78178479Sjb SYSCTL_STATIC_CHILDREN(/* top of sysctl tree */), 79178479Sjb OID_AUTO, "dyn_sysctl", CTLFLAG_RW, 0, 80178479Sjb "dyn_sysctl root node"); 81178479Sjb if (a_root == NULL) { 82178479Sjb printf("SYSCTL_ADD_NODE failed!\n"); 83178479Sjb return (EINVAL); 84178479Sjb } 85178479Sjb SYSCTL_ADD_LONG(&clist, SYSCTL_CHILDREN(a_root), 86178479Sjb OID_AUTO, "long_a", CTLFLAG_RW, &a, "just to try"); 87178479Sjb SYSCTL_ADD_INT(&clist, SYSCTL_CHILDREN(a_root), 88178479Sjb OID_AUTO, "int_b", CTLFLAG_RW, &b, 0, "just to try 1"); 89178479Sjb a_root1 = SYSCTL_ADD_NODE(&clist, SYSCTL_CHILDREN(a_root), 90178479Sjb OID_AUTO, "nextlevel", CTLFLAG_RD, 0, "one level down"); 91178479Sjb SYSCTL_ADD_STRING(&clist, SYSCTL_CHILDREN(a_root1), 92178479Sjb OID_AUTO, "string_c", CTLFLAG_RD, c, 0, "just to try 2"); 93178479Sjb printf("1. (%p) / dyn_sysctl\n", &clist); 94178479Sjb 95178479Sjb /* Add a subtree under already existing category */ 96178479Sjb a_root1 = SYSCTL_ADD_NODE(&clist, SYSCTL_STATIC_CHILDREN(_kern), 97178479Sjb OID_AUTO, "dyn_sysctl", CTLFLAG_RW, 0, "dyn_sysctl root node"); 98178479Sjb if (a_root1 == NULL) { 99178479Sjb printf("SYSCTL_ADD_NODE failed!\n"); 100178479Sjb return (EINVAL); 101178479Sjb } 102178479Sjb SYSCTL_ADD_PROC(&clist, SYSCTL_CHILDREN(a_root1), 103178479Sjb OID_AUTO, "procedure", CTLTYPE_STRING | CTLFLAG_RD, 104178479Sjb NULL, 0, sysctl_dyn_sysctl_test, "A", 105178479Sjb "I can be here, too"); 106178479Sjb printf(" (%p) /kern dyn_sysctl\n", &clist); 107178479Sjb 108178479Sjb /* Overlap second tree with the first. */ 109178479Sjb b_root = SYSCTL_ADD_NODE(&clist1, SYSCTL_CHILDREN(a_root), 110178479Sjb OID_AUTO, "nextlevel", CTLFLAG_RD, 0, "one level down"); 111178479Sjb SYSCTL_ADD_STRING(&clist1, SYSCTL_CHILDREN(b_root), 112178479Sjb OID_AUTO, "string_c1", CTLFLAG_RD, c, 0, "just to try 2"); 113178479Sjb printf("2. (%p) / dyn_sysctl (overlapping #1)\n", &clist1); 114178479Sjb 115178479Sjb /* 116178479Sjb * And now do something stupid. Connect another subtree to 117178479Sjb * dynamic oid. 118178479Sjb * WARNING: this is an example of WRONG use of dynamic sysctls. 119178479Sjb */ 120178479Sjb b_root=SYSCTL_ADD_NODE(&clist2, SYSCTL_CHILDREN(a_root1), 121178479Sjb OID_AUTO, "bad", CTLFLAG_RW, 0, "dependent node"); 122178479Sjb SYSCTL_ADD_STRING(&clist2, SYSCTL_CHILDREN(b_root), 123178479Sjb OID_AUTO, "string_c", CTLFLAG_RD, c, 0, "shouldn't panic"); 124178479Sjb printf("3. (%p) /kern/dyn_sysctl bad (WRONG!)\n", &clist2); 125178479Sjb break; 126178479Sjb case MOD_UNLOAD: 127178479Sjb printf("1. Try to free ctx1 (%p): ", &clist); 128178479Sjb if (sysctl_ctx_free(&clist) != 0) 129178479Sjb printf("failed: expected. Need to remove ctx3 first.\n"); 130178479Sjb else 131178479Sjb printf("HELP! sysctl_ctx_free(%p) succeeded. EXPECT PANIC!!!\n", &clist); 132178479Sjb printf("2. Try to free ctx3 (%p): ", &clist2); 133178479Sjb if (sysctl_ctx_free(&clist2) != 0) { 134178479Sjb printf("sysctl_ctx_free(%p) failed!\n", &clist2); 135178479Sjb /* Remove subtree forcefully... */ 136178479Sjb sysctl_remove_oid(b_root, 1, 1); 137178479Sjb printf("sysctl_remove_oid(%p) succeeded\n", b_root); 138178479Sjb } else 139178479Sjb printf("Ok\n"); 140178479Sjb printf("3. Try to free ctx1 (%p) again: ", &clist); 141178479Sjb if (sysctl_ctx_free(&clist) != 0) { 142178479Sjb printf("sysctl_ctx_free(%p) failed!\n", &clist); 143178479Sjb /* Remove subtree forcefully... */ 144178479Sjb sysctl_remove_oid(a_root1, 1, 1); 145178479Sjb printf("sysctl_remove_oid(%p) succeeded\n", a_root1); 146178479Sjb } else 147178479Sjb printf("Ok\n"); 148178479Sjb printf("4. Try to free ctx2 (%p): ", &clist1); 149178479Sjb if (sysctl_ctx_free(&clist1) != 0) { 150178479Sjb printf("sysctl_ctx_free(%p) failed!\n", &clist1); 151178479Sjb /* Remove subtree forcefully... */ 152178479Sjb sysctl_remove_oid(a_root, 1, 1); 153178479Sjb } else 154178479Sjb printf("Ok\n"); 155178479Sjb break; 156178479Sjb default: 157178479Sjb error = EOPNOTSUPP; 158178479Sjb break; 159178479Sjb } 160178479Sjb return (error); 161178479Sjb} 162178479Sjb 163178479Sjbstatic moduledata_t mod_data = { 164178479Sjb "dyn_sysctl", 165178479Sjb load, 166178479Sjb 0 167178479Sjb}; 168178479Sjb 169178479SjbDECLARE_MODULE(dyn_sysctl, mod_data, SI_SUB_EXEC, SI_ORDER_ANY); 170178479Sjb