xref: /netbsd-src/external/bsd/iscsi/dist/src/initiator/libkmod.c (revision 5e01dafb5c1f3a68ee2f80136c3b6043ad89a0f3)
1*5e01dafbSagc /*	$NetBSD: libkmod.c,v 1.2 2009/06/30 02:44:52 agc Exp $	*/
2b6364952Sagc 
3b6364952Sagc /*-
4b6364952Sagc  * Copyright (c) 2008 The NetBSD Foundation, Inc.
5b6364952Sagc  * All rights reserved.
6b6364952Sagc  *
7b6364952Sagc  * Redistribution and use in source and binary forms, with or without
8b6364952Sagc  * modification, are permitted provided that the following conditions
9b6364952Sagc  * are met:
10b6364952Sagc  * 1. Redistributions of source code must retain the above copyright
11b6364952Sagc  *    notice, this list of conditions and the following disclaimer.
12b6364952Sagc  * 2. Redistributions in binary form must reproduce the above copyright
13b6364952Sagc  *    notice, this list of conditions and the following disclaimer in the
14b6364952Sagc  *    documentation and/or other materials provided with the distribution.
15b6364952Sagc  *
16b6364952Sagc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17b6364952Sagc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18b6364952Sagc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19b6364952Sagc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20b6364952Sagc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21b6364952Sagc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22b6364952Sagc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23b6364952Sagc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24b6364952Sagc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25b6364952Sagc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26b6364952Sagc  * POSSIBILITY OF SUCH DAMAGE.
27b6364952Sagc  */
28b6364952Sagc 
29b6364952Sagc #include <sys/cdefs.h>
30b6364952Sagc #ifndef lint
31*5e01dafbSagc __RCSID("$NetBSD: libkmod.c,v 1.2 2009/06/30 02:44:52 agc Exp $");
32b6364952Sagc #endif /* !lint */
33b6364952Sagc 
34b6364952Sagc #include <sys/module.h>
35b6364952Sagc 
36b6364952Sagc #include <prop/proplib.h>
37b6364952Sagc 
38b6364952Sagc #include <assert.h>
39b6364952Sagc #include <err.h>
40b6364952Sagc #include <stdbool.h>
41b6364952Sagc #include <stdio.h>
42b6364952Sagc #include <stdlib.h>
43b6364952Sagc #include <string.h>
44b6364952Sagc #include <unistd.h>
45b6364952Sagc 
46b6364952Sagc #include "libkmod.h"
47b6364952Sagc 
48b6364952Sagc #ifdef USE_LIBKMOD
49b6364952Sagc 
50b6364952Sagc static const char *classes[] = {
51b6364952Sagc 	"any",
52b6364952Sagc 	"misc",
53b6364952Sagc 	"vfs",
54b6364952Sagc 	"driver",
55b6364952Sagc 	"exec",
56b6364952Sagc };
57b6364952Sagc 
58b6364952Sagc static const char *sources[] = {
59b6364952Sagc 	"builtin",
60b6364952Sagc 	"boot",
61b6364952Sagc 	"filesys",
62b6364952Sagc };
63b6364952Sagc 
64b6364952Sagc /* comparison routine for qsort */
65b6364952Sagc static int
modcmp(const void * a,const void * b)66b6364952Sagc modcmp(const void *a, const void *b)
67b6364952Sagc {
68b6364952Sagc 	const modstat_t *msa, *msb;
69b6364952Sagc 
70b6364952Sagc 	msa = a;
71b6364952Sagc 	msb = b;
72b6364952Sagc 	return strcmp(msa->ms_name, msb->ms_name);
73b6364952Sagc }
74b6364952Sagc 
75b6364952Sagc /* function which "opens" a module */
76b6364952Sagc int
openkmod(kernel_t * kernel)77b6364952Sagc openkmod(kernel_t *kernel)
78b6364952Sagc {
79b6364952Sagc 	kernel->size = 4096;
80b6364952Sagc 	for (;;) {
81b6364952Sagc 		kernel->iov.iov_base = malloc(kernel->size);
82b6364952Sagc 		kernel->iov.iov_len = kernel->size;
83b6364952Sagc 		if (modctl(MODCTL_STAT, &kernel->iov)) {
84b6364952Sagc 			warn("modctl(MODCTL_STAT)");
85b6364952Sagc 			return 0;
86b6364952Sagc 		}
87b6364952Sagc 		if (kernel->size >= kernel->iov.iov_len) {
88b6364952Sagc 			break;
89b6364952Sagc 		}
90b6364952Sagc 		free(kernel->iov.iov_base);
91b6364952Sagc 		kernel->size = kernel->iov.iov_len;
92b6364952Sagc 	}
93b6364952Sagc 	kernel->size = kernel->iov.iov_len / sizeof(modstat_t);
94b6364952Sagc 	qsort(kernel->iov.iov_base, kernel->size, sizeof(modstat_t), modcmp);
95b6364952Sagc 	return 1;
96b6364952Sagc }
97b6364952Sagc 
98b6364952Sagc /* return details on the module */
99b6364952Sagc int
readkmod(kernel_t * kernel,kmod_t * module)100b6364952Sagc readkmod(kernel_t *kernel, kmod_t *module)
101b6364952Sagc {
102b6364952Sagc 	modstat_t *ms;
103b6364952Sagc 
104b6364952Sagc 	if (kernel->c * sizeof(*ms) >= kernel->iov.iov_len) {
105b6364952Sagc 		return 0;
106b6364952Sagc 	}
107b6364952Sagc 	ms = kernel->iov.iov_base;
108b6364952Sagc 	ms += kernel->c++;
109b6364952Sagc 	(void) memset(module, 0x0, sizeof(*module));
110b6364952Sagc 	module->name = strdup(ms->ms_name);
111b6364952Sagc 	module->class = strdup(classes[ms->ms_class]);
112b6364952Sagc 	module->source = strdup(sources[ms->ms_source]);
113b6364952Sagc 	module->refcnt = ms->ms_refcnt;
114b6364952Sagc 	module->size = ms->ms_size;
115b6364952Sagc 	if (ms->ms_required[0]) {
116b6364952Sagc 		module->required = strdup(ms->ms_required);
117b6364952Sagc 	}
118b6364952Sagc 	return 1;
119b6364952Sagc }
120b6364952Sagc 
121b6364952Sagc /* free up all resources allocated in a module read */
122b6364952Sagc void
freekmod(kmod_t * module)123b6364952Sagc freekmod(kmod_t *module)
124b6364952Sagc {
125b6364952Sagc 	(void) free(module->name);
126b6364952Sagc 	(void) free(module->class);
127b6364952Sagc 	(void) free(module->source);
128b6364952Sagc 	if (module->required) {
129b6364952Sagc 		(void) free(module->required);
130b6364952Sagc 	}
131b6364952Sagc }
132b6364952Sagc 
133b6364952Sagc /* "close" the module */
134b6364952Sagc int
closekmod(kernel_t * kernel)135b6364952Sagc closekmod(kernel_t *kernel)
136b6364952Sagc {
137b6364952Sagc 	(void) free(kernel->iov.iov_base);
138b6364952Sagc 	return 1;
139b6364952Sagc }
140b6364952Sagc 
141b6364952Sagc /* do the modstat operation */
142b6364952Sagc int
kmodstat(const char * modname,FILE * fp)143b6364952Sagc kmodstat(const char *modname, FILE *fp)
144b6364952Sagc {
145b6364952Sagc 	kernel_t	kernel;
146b6364952Sagc 	kmod_t		module;
147b6364952Sagc 	int		modc;
148b6364952Sagc 
149b6364952Sagc 	(void) memset(&kernel, 0x0, sizeof(kernel));
150b6364952Sagc 	(void) memset(&module, 0x0, sizeof(module));
151b6364952Sagc 	if (!openkmod(&kernel)) {
152b6364952Sagc 		(void) fprintf(stderr, "can't read kernel modules\n");
153b6364952Sagc 		return 0;
154b6364952Sagc 	}
155b6364952Sagc 	for (modc = 0 ; readkmod(&kernel, &module) ; ) {
156b6364952Sagc 		if (modname == NULL || strcmp(modname, module.name) == 0) {
157b6364952Sagc 			if (modc++ == 0) {
158b6364952Sagc 				if (fp) {
159b6364952Sagc 					(void) fprintf(fp,
160b6364952Sagc 						"NAME\t\tCLASS\tSOURCE\tREFS"
161b6364952Sagc 						"\tSIZE\tREQUIRES\n");
162b6364952Sagc 				}
163b6364952Sagc 			}
164b6364952Sagc 			if (fp) {
165b6364952Sagc 				(void) fprintf(fp, "%-16s%s\t%s\t%d\t%u\t%s\n",
166b6364952Sagc 				module.name,
167b6364952Sagc 				module.class,
168b6364952Sagc 				module.source,
169b6364952Sagc 				module.refcnt,
170b6364952Sagc 				module.size,
171b6364952Sagc 				(module.required) ? module.required : "-");
172b6364952Sagc 			}
173b6364952Sagc 			freekmod(&module);
174b6364952Sagc 		}
175b6364952Sagc 	}
176b6364952Sagc 	(void) closekmod(&kernel);
177b6364952Sagc 	return modc;
178b6364952Sagc }
179b6364952Sagc 
180b6364952Sagc /* load the named module into the kernel */
181b6364952Sagc int
kmodload(const char * module)182b6364952Sagc kmodload(const char *module)
183b6364952Sagc {
184b6364952Sagc 	prop_dictionary_t	 props;
185b6364952Sagc 	modctl_load_t		 cmdargs;
186b6364952Sagc 	char			*propsstr;
187b6364952Sagc 
188b6364952Sagc 	props = prop_dictionary_create();
189b6364952Sagc 
190b6364952Sagc 	propsstr = prop_dictionary_externalize(props);
191b6364952Sagc 	if (propsstr == NULL) {
192b6364952Sagc 		(void) fprintf(stderr, "Failed to process properties");
193b6364952Sagc 		return 0;
194b6364952Sagc 	}
195b6364952Sagc 
196b6364952Sagc 	cmdargs.ml_filename = module;
197b6364952Sagc 	cmdargs.ml_flags = 0;
198b6364952Sagc 	cmdargs.ml_props = propsstr;
199b6364952Sagc 	cmdargs.ml_propslen = strlen(propsstr);
200b6364952Sagc 
201b6364952Sagc 	if (modctl(MODCTL_LOAD, &cmdargs)) {
202b6364952Sagc 		(void) fprintf(stderr, "modctl failure\n");
203b6364952Sagc 		return 0;
204b6364952Sagc 	}
205b6364952Sagc 
206b6364952Sagc 	(void) free(propsstr);
207b6364952Sagc 	prop_object_release(props);
208b6364952Sagc 
209b6364952Sagc 	return 1;
210b6364952Sagc }
211b6364952Sagc 
212b6364952Sagc /* and unload the module from the kernel */
213b6364952Sagc int
kmodunload(const char * name)214b6364952Sagc kmodunload(const char *name)
215b6364952Sagc {
216b6364952Sagc 	return modctl(MODCTL_UNLOAD, __UNCONST(name)) == 0;
217b6364952Sagc }
218b6364952Sagc 
219b6364952Sagc #endif /* USE_LIBKMOD */
220