1/*	$NetBSD: k_helper.c,v 1.6 2012/06/03 10:59:44 dsl Exp $	*/
2/*
3 * Copyright (c) 2008 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
16 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
24 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: k_helper.c,v 1.6 2012/06/03 10:59:44 dsl Exp $");
31
32#include <sys/param.h>
33#include <sys/kernel.h>
34#include <sys/module.h>
35#include <sys/sysctl.h>
36
37#include <prop/proplib.h>
38
39MODULE(MODULE_CLASS_MISC, k_helper, NULL);
40
41/* --------------------------------------------------------------------- */
42/* Sysctl interface to query information about the module.               */
43/* --------------------------------------------------------------------- */
44
45/* TODO: Change the integer variables below that represent booleans to
46 * bools, once sysctl(8) supports CTLTYPE_BOOL nodes. */
47
48static struct sysctllog *clogp;
49static int present = 1;
50static int prop_str_ok;
51static char prop_str_val[128];
52static int prop_int_ok;
53static int64_t prop_int_val;
54static int prop_int_load;
55
56#define K_HELPER 0x12345678
57#define K_HELPER_PRESENT 0
58#define K_HELPER_PROP_STR_OK 1
59#define K_HELPER_PROP_STR_VAL 2
60#define K_HELPER_PROP_INT_OK 3
61#define K_HELPER_PROP_INT_VAL 4
62#define K_HELPER_PROP_INT_LOAD 5
63
64SYSCTL_SETUP(sysctl_k_helper_setup, "sysctl k_helper subtree setup")
65{
66
67	sysctl_createv(clog, 0, NULL, NULL,
68	               CTLFLAG_PERMANENT,
69	               CTLTYPE_NODE, "k_helper", NULL,
70	               NULL, 0, NULL, 0,
71	               CTL_VENDOR, K_HELPER, CTL_EOL);
72
73	sysctl_createv(clog, 0, NULL, NULL,
74	               CTLFLAG_PERMANENT,
75	               CTLTYPE_INT, "present",
76		       SYSCTL_DESCR("Whether the module was loaded or not"),
77		       NULL, 0, &present, 0,
78	               CTL_VENDOR, K_HELPER, K_HELPER_PRESENT, CTL_EOL);
79
80	sysctl_createv(clog, 0, NULL, NULL,
81	               CTLFLAG_PERMANENT,
82	               CTLTYPE_INT, "prop_str_ok",
83		       SYSCTL_DESCR("String property's validity"),
84		       NULL, 0, &prop_str_ok, 0,
85	               CTL_VENDOR, K_HELPER, K_HELPER_PROP_STR_OK, CTL_EOL);
86
87	sysctl_createv(clog, 0, NULL, NULL,
88	               CTLFLAG_PERMANENT,
89	               CTLTYPE_STRING, "prop_str_val",
90		       SYSCTL_DESCR("String property's value"),
91		       NULL, 0, prop_str_val, 0,
92	               CTL_VENDOR, K_HELPER, K_HELPER_PROP_STR_VAL, CTL_EOL);
93
94	sysctl_createv(clog, 0, NULL, NULL,
95	               CTLFLAG_PERMANENT,
96	               CTLTYPE_INT, "prop_int_ok",
97		       SYSCTL_DESCR("String property's validity"),
98		       NULL, 0, &prop_int_ok, 0,
99	               CTL_VENDOR, K_HELPER, K_HELPER_PROP_INT_OK, CTL_EOL);
100
101	sysctl_createv(clog, 0, NULL, NULL,
102	               CTLFLAG_PERMANENT,
103	               CTLTYPE_QUAD, "prop_int_val",
104		       SYSCTL_DESCR("String property's value"),
105		       NULL, 0, &prop_int_val, 0,
106	               CTL_VENDOR, K_HELPER, K_HELPER_PROP_INT_VAL, CTL_EOL);
107
108	sysctl_createv(clog, 0, NULL, NULL,
109	               CTLFLAG_PERMANENT,
110	               CTLTYPE_INT, "prop_int_load",
111		       SYSCTL_DESCR("Status of recursive modload"),
112		       NULL, 0, &prop_int_load, 0,
113	               CTL_VENDOR, K_HELPER, K_HELPER_PROP_INT_LOAD, CTL_EOL);
114}
115
116/* --------------------------------------------------------------------- */
117/* Module management.                                                    */
118/* --------------------------------------------------------------------- */
119
120static
121int
122k_helper_init(prop_dictionary_t props)
123{
124	prop_object_t p;
125
126	p = prop_dictionary_get(props, "prop_str");
127	if (p == NULL)
128		prop_str_ok = 0;
129	else if (prop_object_type(p) != PROP_TYPE_STRING)
130		prop_str_ok = 0;
131	else {
132		const char *msg = prop_string_cstring_nocopy(p);
133		if (msg == NULL)
134			prop_str_ok = 0;
135		else {
136			strlcpy(prop_str_val, msg, sizeof(prop_str_val));
137			prop_str_ok = 1;
138		}
139	}
140	if (!prop_str_ok)
141		strlcpy(prop_str_val, "", sizeof(prop_str_val));
142
143	p = prop_dictionary_get(props, "prop_int");
144	if (p == NULL)
145		prop_int_ok = 0;
146	else if (prop_object_type(p) != PROP_TYPE_NUMBER)
147		prop_int_ok = 0;
148	else {
149		prop_int_val = prop_number_integer_value(p);
150		prop_int_ok = 1;
151	}
152	if (!prop_int_ok)
153		prop_int_val = -1;
154
155	p = prop_dictionary_get(props, "prop_recurse");
156	if (p != NULL && prop_object_type(p) == PROP_TYPE_STRING) {
157		const char *recurse_name = prop_string_cstring_nocopy(p);
158		if (recurse_name != NULL)
159			prop_int_load = module_load(recurse_name,
160			    MODCTL_NO_PROP, NULL, MODULE_CLASS_ANY);
161		else
162			prop_int_load = -1;
163	} else
164		prop_int_load = -2;
165
166	sysctl_k_helper_setup(&clogp);
167
168	return 0;
169}
170
171static
172int
173k_helper_fini(void *arg)
174{
175
176	sysctl_teardown(&clogp);
177
178	return 0;
179}
180
181static
182int
183k_helper_modcmd(modcmd_t cmd, void *arg)
184{
185	int ret;
186
187	switch (cmd) {
188	case MODULE_CMD_INIT:
189		ret = k_helper_init(arg);
190		break;
191
192	case MODULE_CMD_FINI:
193		ret = k_helper_fini(arg);
194		break;
195
196	case MODULE_CMD_STAT:
197	default:
198		ret = ENOTTY;
199	}
200
201	return ret;
202}
203