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