• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * kmod-insmod - insert modules into linux kernel using libkmod.
3  *
4  * Copyright (C) 2011-2013  ProFUSION embedded systems
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <errno.h>
21 #include <getopt.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include <shared/util.h>
27 
28 #include <libkmod/libkmod.h>
29 
30 #include "kmod.h"
31 
32 static const char cmdopts_s[] = "psfVh";
33 static const struct option cmdopts[] = {
34 	{"version", no_argument, 0, 'V'},
35 	{"help", no_argument, 0, 'h'},
36 	{NULL, 0, 0, 0}
37 };
38 
help(void)39 static void help(void)
40 {
41 	printf("Usage:\n"
42 		"\t%s [options] filename [args]\n"
43 		"Options:\n"
44 		"\t-V, --version     show version\n"
45 		"\t-h, --help        show this help\n",
46 		program_invocation_short_name);
47 }
48 
mod_strerror(int err)49 static const char *mod_strerror(int err)
50 {
51 	switch (err) {
52 	case ENOEXEC:
53 		return "Invalid module format";
54 	case ENOENT:
55 		return "Unknown symbol in module";
56 	case ESRCH:
57 		return "Module has wrong symbol version";
58 	case EINVAL:
59 		return "Invalid parameters";
60 	default:
61 		return strerror(err);
62 	}
63 }
64 
do_insmod(int argc,char * argv[])65 static int do_insmod(int argc, char *argv[])
66 {
67 	struct kmod_ctx *ctx;
68 	struct kmod_module *mod;
69 	const char *filename;
70 	char *opts = NULL;
71 	size_t optslen = 0;
72 	int i, err;
73 	const char *null_config = NULL;
74 	unsigned int flags = 0;
75 
76 	for (;;) {
77 		int c, idx = 0;
78 		c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
79 		if (c == -1)
80 			break;
81 		switch (c) {
82 		case 'p':
83 		case 's':
84 			/* ignored, for compatibility only */
85 			break;
86 		case 'f':
87 			flags |= KMOD_PROBE_FORCE_MODVERSION;
88 			flags |= KMOD_PROBE_FORCE_VERMAGIC;
89 			break;
90 		case 'h':
91 			help();
92 			return EXIT_SUCCESS;
93 		case 'V':
94 			puts(PACKAGE " version " VERSION);
95 			puts(KMOD_FEATURES);
96 			return EXIT_SUCCESS;
97 		case '?':
98 			return EXIT_FAILURE;
99 		default:
100 			ERR("unexpected getopt_long() value '%c'.\n",
101 				c);
102 			return EXIT_FAILURE;
103 		}
104 	}
105 
106 	if (optind >= argc) {
107 		ERR("missing filename.\n");
108 		return EXIT_FAILURE;
109 	}
110 
111 	filename = argv[optind];
112 	if (streq(filename, "-")) {
113 		ERR("this tool does not support loading from stdin!\n");
114 		return EXIT_FAILURE;
115 	}
116 
117 	for (i = optind + 1; i < argc; i++) {
118 		size_t len = strlen(argv[i]);
119 		void *tmp = realloc(opts, optslen + len + 2);
120 		if (tmp == NULL) {
121 			ERR("out of memory\n");
122 			free(opts);
123 			return EXIT_FAILURE;
124 		}
125 		opts = tmp;
126 		if (optslen > 0) {
127 			opts[optslen] = ' ';
128 			optslen++;
129 		}
130 		memcpy(opts + optslen, argv[i], len);
131 		optslen += len;
132 		opts[optslen] = '\0';
133 	}
134 
135 	ctx = kmod_new(NULL, &null_config);
136 	if (!ctx) {
137 		ERR("kmod_new() failed!\n");
138 		free(opts);
139 		return EXIT_FAILURE;
140 	}
141 
142 	err = kmod_module_new_from_path(ctx, filename, &mod);
143 	if (err < 0) {
144 		ERR("could not load module %s: %s\n", filename,
145 		    strerror(-err));
146 		goto end;
147 	}
148 
149 	err = kmod_module_insert_module(mod, flags, opts);
150 	if (err < 0) {
151 		ERR("could not insert module %s: %s\n", filename,
152 		    mod_strerror(-err));
153 	}
154 	kmod_module_unref(mod);
155 
156 end:
157 	kmod_unref(ctx);
158 	free(opts);
159 	return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
160 }
161 
162 const struct kmod_cmd kmod_cmd_compat_insmod = {
163 	.name = "insmod",
164 	.cmd = do_insmod,
165 	.help = "compat insmod command",
166 };
167