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