rndctl.c revision 1.6.2.2 1 1.6.2.2 itojun /* $NetBSD: rndctl.c,v 1.6.2.2 2002/09/18 15:56:19 itojun Exp $ */
2 1.6.2.2 itojun
3 1.6.2.2 itojun /*-
4 1.6.2.2 itojun * Copyright (c) 1997 Michael Graff.
5 1.6.2.2 itojun * All rights reserved.
6 1.6.2.2 itojun *
7 1.6.2.2 itojun * Redistribution and use in source and binary forms, with or without
8 1.6.2.2 itojun * modification, are permitted provided that the following conditions
9 1.6.2.2 itojun * are met:
10 1.6.2.2 itojun * 1. Redistributions of source code must retain the above copyright
11 1.6.2.2 itojun * notice, this list of conditions and the following disclaimer.
12 1.6.2.2 itojun * 2. Redistributions in binary form must reproduce the above copyright
13 1.6.2.2 itojun * notice, this list of conditions and the following disclaimer in the
14 1.6.2.2 itojun * documentation and/or other materials provided with the distribution.
15 1.6.2.2 itojun * 3. Neither the name of the author nor the names of other contributors
16 1.6.2.2 itojun * may be used to endorse or promote products derived from this software
17 1.6.2.2 itojun * without specific prior written permission.
18 1.6.2.2 itojun *
19 1.6.2.2 itojun * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 1.6.2.2 itojun * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 1.6.2.2 itojun * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 1.6.2.2 itojun * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 1.6.2.2 itojun * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 1.6.2.2 itojun * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 1.6.2.2 itojun * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 1.6.2.2 itojun * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 1.6.2.2 itojun * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 1.6.2.2 itojun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 1.6.2.2 itojun * SUCH DAMAGE.
30 1.6.2.2 itojun */
31 1.6.2.2 itojun
32 1.6.2.2 itojun #include <stdio.h>
33 1.6.2.2 itojun #include <stdlib.h>
34 1.6.2.2 itojun #include <unistd.h>
35 1.6.2.2 itojun #include <fcntl.h>
36 1.6.2.2 itojun #include <errno.h>
37 1.6.2.2 itojun #include <err.h>
38 1.6.2.2 itojun #include <string.h>
39 1.6.2.2 itojun
40 1.6.2.2 itojun #include <sys/types.h>
41 1.6.2.2 itojun #include <sys/ioctl.h>
42 1.6.2.2 itojun #include <sys/rnd.h>
43 1.6.2.2 itojun
44 1.6.2.2 itojun typedef struct {
45 1.6.2.2 itojun char *name;
46 1.6.2.2 itojun u_int32_t type;
47 1.6.2.2 itojun } arg_t;
48 1.6.2.2 itojun
49 1.6.2.2 itojun arg_t source_types[] = {
50 1.6.2.2 itojun { "???", RND_TYPE_UNKNOWN },
51 1.6.2.2 itojun { "disk", RND_TYPE_DISK },
52 1.6.2.2 itojun { "net", RND_TYPE_NET },
53 1.6.2.2 itojun { "net", RND_TYPE_NET },
54 1.6.2.2 itojun { "tape", RND_TYPE_TAPE },
55 1.6.2.2 itojun { "tty", RND_TYPE_TTY },
56 1.6.2.2 itojun { NULL, 0 }
57 1.6.2.2 itojun };
58 1.6.2.2 itojun
59 1.6.2.2 itojun static void usage(void);
60 1.6.2.2 itojun u_int32_t find_type(char *name);
61 1.6.2.2 itojun char *find_name(u_int32_t);
62 1.6.2.2 itojun void do_ioctl(rndctl_t *);
63 1.6.2.2 itojun char * strflags(u_int32_t);
64 1.6.2.2 itojun void do_list(int, u_int32_t, char *);
65 1.6.2.2 itojun void do_stats(void);
66 1.6.2.2 itojun
67 1.6.2.2 itojun static void
68 1.6.2.2 itojun usage(void)
69 1.6.2.2 itojun {
70 1.6.2.2 itojun fprintf(stderr, "usage: rndctl -CEce [-t devtype] [-d devname]\n");
71 1.6.2.2 itojun fprintf(stderr, " rndctl -l [-t devtype] [-d devname]\n");
72 1.6.2.2 itojun exit(1);
73 1.6.2.2 itojun }
74 1.6.2.2 itojun
75 1.6.2.2 itojun u_int32_t
76 1.6.2.2 itojun find_type(char *name)
77 1.6.2.2 itojun {
78 1.6.2.2 itojun arg_t *a;
79 1.6.2.2 itojun
80 1.6.2.2 itojun a = source_types;
81 1.6.2.2 itojun
82 1.6.2.2 itojun while (a->name != NULL) {
83 1.6.2.2 itojun if (strcmp(a->name, name) == 0)
84 1.6.2.2 itojun return a->type;
85 1.6.2.2 itojun a++;
86 1.6.2.2 itojun }
87 1.6.2.2 itojun
88 1.6.2.2 itojun errx(1, "Error: Device type %s unknown", name);
89 1.6.2.2 itojun return 0;
90 1.6.2.2 itojun }
91 1.6.2.2 itojun
92 1.6.2.2 itojun char *
93 1.6.2.2 itojun find_name(u_int32_t type)
94 1.6.2.2 itojun {
95 1.6.2.2 itojun arg_t *a;
96 1.6.2.2 itojun
97 1.6.2.2 itojun a = source_types;
98 1.6.2.2 itojun
99 1.6.2.2 itojun while (a->name != NULL) {
100 1.6.2.2 itojun if (type == a->type)
101 1.6.2.2 itojun return a->name;
102 1.6.2.2 itojun a++;
103 1.6.2.2 itojun }
104 1.6.2.2 itojun
105 1.6.2.2 itojun errx(1, "Error: Device type %u unknown", type);
106 1.6.2.2 itojun return 0;
107 1.6.2.2 itojun }
108 1.6.2.2 itojun
109 1.6.2.2 itojun void
110 1.6.2.2 itojun do_ioctl(rndctl_t *rctl)
111 1.6.2.2 itojun {
112 1.6.2.2 itojun int fd;
113 1.6.2.2 itojun int res;
114 1.6.2.2 itojun
115 1.6.2.2 itojun fd = open("/dev/urandom", O_RDONLY, 0644);
116 1.6.2.2 itojun if (fd < 0)
117 1.6.2.2 itojun err(1, "open");
118 1.6.2.2 itojun
119 1.6.2.2 itojun res = ioctl(fd, RNDCTL, rctl);
120 1.6.2.2 itojun if (res < 0)
121 1.6.2.2 itojun err(1, "ioctl(RNDCTL)");
122 1.6.2.2 itojun
123 1.6.2.2 itojun close(fd);
124 1.6.2.2 itojun }
125 1.6.2.2 itojun
126 1.6.2.2 itojun char *
127 1.6.2.2 itojun strflags(u_int32_t fl)
128 1.6.2.2 itojun {
129 1.6.2.2 itojun static char str[512];
130 1.6.2.2 itojun
131 1.6.2.2 itojun str[0] = 0;
132 1.6.2.2 itojun if (fl & RND_FLAG_NO_ESTIMATE)
133 1.6.2.2 itojun ;
134 1.6.2.2 itojun else
135 1.6.2.2 itojun strcat(str, "estimate");
136 1.6.2.2 itojun
137 1.6.2.2 itojun if (fl & RND_FLAG_NO_COLLECT)
138 1.6.2.2 itojun ;
139 1.6.2.2 itojun else {
140 1.6.2.2 itojun if (str[0])
141 1.6.2.2 itojun strcat(str, ", ");
142 1.6.2.2 itojun strcat(str, "collect");
143 1.6.2.2 itojun }
144 1.6.2.2 itojun
145 1.6.2.2 itojun return str;
146 1.6.2.2 itojun }
147 1.6.2.2 itojun
148 1.6.2.2 itojun #define HEADER "Source Bits Type Flags\n"
149 1.6.2.2 itojun
150 1.6.2.2 itojun void
151 1.6.2.2 itojun do_list(int all, u_int32_t type, char *name)
152 1.6.2.2 itojun {
153 1.6.2.2 itojun rndstat_t rstat;
154 1.6.2.2 itojun rndstat_name_t rstat_name;
155 1.6.2.2 itojun int fd;
156 1.6.2.2 itojun int res;
157 1.6.2.2 itojun u_int32_t start;
158 1.6.2.2 itojun
159 1.6.2.2 itojun fd = open("/dev/urandom", O_RDONLY, 0644);
160 1.6.2.2 itojun if (fd < 0)
161 1.6.2.2 itojun err(1, "open");
162 1.6.2.2 itojun
163 1.6.2.2 itojun if (all == 0 && type == 0xff) {
164 1.6.2.2 itojun strncpy(rstat_name.name, name, 16);
165 1.6.2.2 itojun res = ioctl(fd, RNDGETSRCNAME, &rstat_name);
166 1.6.2.2 itojun if (res < 0)
167 1.6.2.2 itojun err(1, "ioctl(RNDGETSRCNAME)");
168 1.6.2.2 itojun printf(HEADER);
169 1.6.2.2 itojun printf("%-16s %10u %-4s %s\n",
170 1.6.2.2 itojun rstat_name.source.name,
171 1.6.2.2 itojun rstat_name.source.total,
172 1.6.2.2 itojun find_name(rstat_name.source.type),
173 1.6.2.2 itojun strflags(rstat_name.source.flags));
174 1.6.2.2 itojun close(fd);
175 1.6.2.2 itojun return;
176 1.6.2.2 itojun }
177 1.6.2.2 itojun
178 1.6.2.2 itojun /*
179 1.6.2.2 itojun * run through all the devices present in the system, and either
180 1.6.2.2 itojun * print out ones that match, or print out all of them.
181 1.6.2.2 itojun */
182 1.6.2.2 itojun printf(HEADER);
183 1.6.2.2 itojun start = 0;
184 1.6.2.2 itojun for (;;) {
185 1.6.2.2 itojun rstat.count = RND_MAXSTATCOUNT;
186 1.6.2.2 itojun rstat.start = start;
187 1.6.2.2 itojun res = ioctl(fd, RNDGETSRCNUM, &rstat);
188 1.6.2.2 itojun if (res < 0)
189 1.6.2.2 itojun err(1, "ioctl(RNDGETSRCNUM)");
190 1.6.2.2 itojun
191 1.6.2.2 itojun if (rstat.count == 0)
192 1.6.2.2 itojun break;
193 1.6.2.2 itojun
194 1.6.2.2 itojun for (res = 0 ; res < rstat.count ; res++) {
195 1.6.2.2 itojun if ((all != 0)
196 1.6.2.2 itojun || (type == rstat.source[res].type))
197 1.6.2.2 itojun printf("%-16s %10u %-4s %s\n",
198 1.6.2.2 itojun rstat.source[res].name,
199 1.6.2.2 itojun rstat.source[res].total,
200 1.6.2.2 itojun find_name(rstat.source[res].type),
201 1.6.2.2 itojun strflags(rstat.source[res].flags));
202 1.6.2.2 itojun }
203 1.6.2.2 itojun start += rstat.count;
204 1.6.2.2 itojun }
205 1.6.2.2 itojun
206 1.6.2.2 itojun close(fd);
207 1.6.2.2 itojun }
208 1.6.2.2 itojun
209 1.6.2.2 itojun void
210 1.6.2.2 itojun do_stats()
211 1.6.2.2 itojun {
212 1.6.2.2 itojun rndpoolstat_t rs;
213 1.6.2.2 itojun int fd;
214 1.6.2.2 itojun
215 1.6.2.2 itojun fd = open("/dev/urandom", O_RDONLY, 0644);
216 1.6.2.2 itojun if (fd < 0)
217 1.6.2.2 itojun err(1, "open");
218 1.6.2.2 itojun
219 1.6.2.2 itojun if (ioctl(fd, RNDGETPOOLSTAT, &rs) < 0)
220 1.6.2.2 itojun err(1, "ioctl(RNDGETPOOLSTAT)");
221 1.6.2.2 itojun
222 1.6.2.2 itojun printf("\t%9d bits mixed into pool\n", rs.added);
223 1.6.2.2 itojun printf("\t%9d bits currently stored in pool (max %d)\n",
224 1.6.2.2 itojun rs.curentropy, rs.maxentropy);
225 1.6.2.2 itojun printf("\t%9d bits of entropy discarded due to full pool\n",
226 1.6.2.2 itojun rs.discarded);
227 1.6.2.2 itojun printf("\t%9d hard-random bits generated\n", rs.removed);
228 1.6.2.2 itojun printf("\t%9d pseudo-random bits generated\n", rs.generated);
229 1.6.2.2 itojun
230 1.6.2.2 itojun close(fd);
231 1.6.2.2 itojun }
232 1.6.2.2 itojun
233 1.6.2.2 itojun
234 1.6.2.2 itojun int
235 1.6.2.2 itojun main(int argc, char **argv)
236 1.6.2.2 itojun {
237 1.6.2.2 itojun rndctl_t rctl;
238 1.6.2.2 itojun int ch;
239 1.6.2.2 itojun int cmd;
240 1.6.2.2 itojun int lflag;
241 1.6.2.2 itojun int mflag;
242 1.6.2.2 itojun int sflag;
243 1.6.2.2 itojun u_int32_t type;
244 1.6.2.2 itojun char name[16];
245 1.6.2.2 itojun
246 1.6.2.2 itojun rctl.mask = 0;
247 1.6.2.2 itojun rctl.flags = 0;
248 1.6.2.2 itojun
249 1.6.2.2 itojun cmd = 0;
250 1.6.2.2 itojun lflag = 0;
251 1.6.2.2 itojun mflag = 0;
252 1.6.2.2 itojun sflag = 0;
253 1.6.2.2 itojun type = 0xff;
254 1.6.2.2 itojun
255 1.6.2.2 itojun while ((ch = getopt(argc, argv, "CEcelt:d:s")) != -1)
256 1.6.2.2 itojun switch(ch) {
257 1.6.2.2 itojun case 'C':
258 1.6.2.2 itojun rctl.flags |= RND_FLAG_NO_COLLECT;
259 1.6.2.2 itojun rctl.mask |= RND_FLAG_NO_COLLECT;
260 1.6.2.2 itojun mflag++;
261 1.6.2.2 itojun break;
262 1.6.2.2 itojun case 'E':
263 1.6.2.2 itojun rctl.flags |= RND_FLAG_NO_ESTIMATE;
264 1.6.2.2 itojun rctl.mask |= RND_FLAG_NO_ESTIMATE;
265 1.6.2.2 itojun mflag++;
266 1.6.2.2 itojun break;
267 1.6.2.2 itojun case 'c':
268 1.6.2.2 itojun rctl.flags &= ~RND_FLAG_NO_COLLECT;
269 1.6.2.2 itojun rctl.mask |= RND_FLAG_NO_COLLECT;
270 1.6.2.2 itojun mflag++;
271 1.6.2.2 itojun break;
272 1.6.2.2 itojun case 'e':
273 1.6.2.2 itojun rctl.flags &= ~RND_FLAG_NO_ESTIMATE;
274 1.6.2.2 itojun rctl.mask |= RND_FLAG_NO_ESTIMATE;
275 1.6.2.2 itojun mflag++;
276 1.6.2.2 itojun break;
277 1.6.2.2 itojun case 'l':
278 1.6.2.2 itojun lflag++;
279 1.6.2.2 itojun break;
280 1.6.2.2 itojun case 't':
281 1.6.2.2 itojun if (cmd != 0)
282 1.6.2.2 itojun usage();
283 1.6.2.2 itojun cmd = 't';
284 1.6.2.2 itojun
285 1.6.2.2 itojun type = find_type(optarg);
286 1.6.2.2 itojun break;
287 1.6.2.2 itojun case 'd':
288 1.6.2.2 itojun if (cmd != 0)
289 1.6.2.2 itojun usage();
290 1.6.2.2 itojun cmd = 'd';
291 1.6.2.2 itojun
292 1.6.2.2 itojun type = 0xff;
293 1.6.2.2 itojun strncpy(name, optarg, 16);
294 1.6.2.2 itojun break;
295 1.6.2.2 itojun case 's':
296 1.6.2.2 itojun sflag++;
297 1.6.2.2 itojun break;
298 1.6.2.2 itojun case '?':
299 1.6.2.2 itojun default:
300 1.6.2.2 itojun usage();
301 1.6.2.2 itojun }
302 1.6.2.2 itojun
303 1.6.2.2 itojun /*
304 1.6.2.2 itojun * cannot list and modify at the same time
305 1.6.2.2 itojun */
306 1.6.2.2 itojun if ((lflag != 0 || sflag != 0) && mflag != 0)
307 1.6.2.2 itojun usage();
308 1.6.2.2 itojun
309 1.6.2.2 itojun /*
310 1.6.2.2 itojun * bomb out on no-ops
311 1.6.2.2 itojun */
312 1.6.2.2 itojun if (lflag == 0 && mflag == 0 && sflag == 0)
313 1.6.2.2 itojun usage();
314 1.6.2.2 itojun
315 1.6.2.2 itojun /*
316 1.6.2.2 itojun * if not listing, we need a device name or a type
317 1.6.2.2 itojun */
318 1.6.2.2 itojun if (lflag == 0 && cmd == 0 && sflag == 0)
319 1.6.2.2 itojun usage();
320 1.6.2.2 itojun
321 1.6.2.2 itojun /*
322 1.6.2.2 itojun * modify request
323 1.6.2.2 itojun */
324 1.6.2.2 itojun if (mflag != 0) {
325 1.6.2.2 itojun rctl.type = type;
326 1.6.2.2 itojun strncpy(rctl.name, name, 16);
327 1.6.2.2 itojun do_ioctl(&rctl);
328 1.6.2.2 itojun
329 1.6.2.2 itojun exit(0);
330 1.6.2.2 itojun }
331 1.6.2.2 itojun
332 1.6.2.2 itojun /*
333 1.6.2.2 itojun * list sources
334 1.6.2.2 itojun */
335 1.6.2.2 itojun if (lflag != 0)
336 1.6.2.2 itojun do_list(cmd == 0, type, name);
337 1.6.2.2 itojun
338 1.6.2.2 itojun if (sflag != 0)
339 1.6.2.2 itojun do_stats();
340 1.6.2.2 itojun
341 1.6.2.2 itojun return 0;
342 1.6.2.2 itojun }
343