Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sbin / rndctl / rndctl.c
blobe7b4dd079d265e3439f4a3e7723c2d92420678d1
1 /* $NetBSD: rndctl.c,v 1.18 2008/11/06 16:01:54 apb Exp $ */
3 /*-
4 * Copyright (c) 1997 Michael Graff.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the author nor the names of other contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
31 #include <sys/cdefs.h>
33 #ifndef lint
34 __RCSID("$NetBSD: rndctl.c,v 1.18 2008/11/06 16:01:54 apb Exp $");
35 #endif
38 #include <sys/types.h>
39 #include <sys/ioctl.h>
40 #include <sys/rnd.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include <fcntl.h>
46 #include <errno.h>
47 #include <err.h>
48 #include <string.h>
50 typedef struct {
51 const char *a_name;
52 u_int32_t a_type;
53 } arg_t;
55 arg_t source_types[] = {
56 { "???", RND_TYPE_UNKNOWN },
57 { "disk", RND_TYPE_DISK },
58 { "net", RND_TYPE_NET },
59 { "tape", RND_TYPE_TAPE },
60 { "tty", RND_TYPE_TTY },
61 { "rng", RND_TYPE_RNG },
62 { NULL, 0 }
65 static void usage(void);
66 u_int32_t find_type(char *name);
67 const char *find_name(u_int32_t);
68 void do_ioctl(rndctl_t *);
69 char * strflags(u_int32_t);
70 void do_list(int, u_int32_t, char *);
71 void do_stats(void);
73 static void
74 usage(void)
77 fprintf(stderr, "usage: %s -CEce [-d devname | -t devtype]\n",
78 getprogname());
79 fprintf(stderr, " %s -ls [-d devname | -t devtype]\n",
80 getprogname());
81 exit(1);
84 u_int32_t
85 find_type(char *name)
87 arg_t *a;
89 a = source_types;
91 while (a->a_name != NULL) {
92 if (strcmp(a->a_name, name) == 0)
93 return (a->a_type);
94 a++;
97 errx(1, "device name %s unknown", name);
98 return (0);
101 const char *
102 find_name(u_int32_t type)
104 arg_t *a;
106 a = source_types;
108 while (a->a_name != NULL) {
109 if (type == a->a_type)
110 return (a->a_name);
111 a++;
114 warnx("device type %u unknown", type);
115 return ("???");
118 void
119 do_ioctl(rndctl_t *rctl)
121 int fd;
122 int res;
124 fd = open("/dev/urandom", O_RDONLY, 0644);
125 if (fd < 0)
126 err(1, "open");
128 res = ioctl(fd, RNDCTL, rctl);
129 if (res < 0)
130 err(1, "ioctl(RNDCTL)");
132 close(fd);
135 char *
136 strflags(u_int32_t fl)
138 static char str[512];
140 str[0] = 0;
141 if (fl & RND_FLAG_NO_ESTIMATE)
143 else
144 strlcat(str, "estimate", sizeof(str));
146 if (fl & RND_FLAG_NO_COLLECT)
148 else {
149 if (str[0])
150 strlcat(str, ", ", sizeof(str));
151 strlcat(str, "collect", sizeof(str));
154 return (str);
157 #define HEADER "Source Bits Type Flags\n"
159 void
160 do_list(int all, u_int32_t type, char *name)
162 rndstat_t rstat;
163 rndstat_name_t rstat_name;
164 int fd;
165 int res;
166 uint32_t i;
167 u_int32_t start;
169 fd = open("/dev/urandom", O_RDONLY, 0644);
170 if (fd < 0)
171 err(1, "open");
173 if (all == 0 && type == 0xff) {
174 strncpy(rstat_name.name, name, sizeof(rstat_name.name));
175 res = ioctl(fd, RNDGETSRCNAME, &rstat_name);
176 if (res < 0)
177 err(1, "ioctl(RNDGETSRCNAME)");
178 printf(HEADER);
179 printf("%-16s %10u %-4s %s\n",
180 rstat_name.source.name,
181 rstat_name.source.total,
182 find_name(rstat_name.source.type),
183 strflags(rstat_name.source.flags));
184 close(fd);
185 return;
189 * Run through all the devices present in the system, and either
190 * print out ones that match, or print out all of them.
192 printf(HEADER);
193 start = 0;
194 for (;;) {
195 rstat.count = RND_MAXSTATCOUNT;
196 rstat.start = start;
197 res = ioctl(fd, RNDGETSRCNUM, &rstat);
198 if (res < 0)
199 err(1, "ioctl(RNDGETSRCNUM)");
201 if (rstat.count == 0)
202 break;
204 for (i = 0; i < rstat.count; i++) {
205 if (all != 0 ||
206 type == rstat.source[i].type)
207 printf("%-16s %10u %-4s %s\n",
208 rstat.source[i].name,
209 rstat.source[i].total,
210 find_name(rstat.source[i].type),
211 strflags(rstat.source[i].flags));
213 start += rstat.count;
216 close(fd);
219 void
220 do_stats()
222 rndpoolstat_t rs;
223 int fd;
225 fd = open("/dev/urandom", O_RDONLY, 0644);
226 if (fd < 0)
227 err(1, "open");
229 if (ioctl(fd, RNDGETPOOLSTAT, &rs) < 0)
230 err(1, "ioctl(RNDGETPOOLSTAT)");
232 printf("\t%9u bits mixed into pool\n", rs.added);
233 printf("\t%9u bits currently stored in pool (max %u)\n",
234 rs.curentropy, rs.maxentropy);
235 printf("\t%9u bits of entropy discarded due to full pool\n",
236 rs.discarded);
237 printf("\t%9u hard-random bits generated\n", rs.removed);
238 printf("\t%9u pseudo-random bits generated\n", rs.generated);
240 close(fd);
244 main(int argc, char **argv)
246 rndctl_t rctl;
247 int ch, cmd, lflag, mflag, sflag;
248 u_int32_t type;
249 char name[16];
251 rctl.mask = 0;
252 rctl.flags = 0;
254 cmd = 0;
255 lflag = 0;
256 mflag = 0;
257 sflag = 0;
258 type = 0xff;
260 while ((ch = getopt(argc, argv, "CEcelt:d:s")) != -1) {
261 switch (ch) {
262 case 'C':
263 rctl.flags |= RND_FLAG_NO_COLLECT;
264 rctl.mask |= RND_FLAG_NO_COLLECT;
265 mflag++;
266 break;
267 case 'E':
268 rctl.flags |= RND_FLAG_NO_ESTIMATE;
269 rctl.mask |= RND_FLAG_NO_ESTIMATE;
270 mflag++;
271 break;
272 case 'c':
273 rctl.flags &= ~RND_FLAG_NO_COLLECT;
274 rctl.mask |= RND_FLAG_NO_COLLECT;
275 mflag++;
276 break;
277 case 'e':
278 rctl.flags &= ~RND_FLAG_NO_ESTIMATE;
279 rctl.mask |= RND_FLAG_NO_ESTIMATE;
280 mflag++;
281 break;
282 case 'l':
283 lflag++;
284 break;
285 case 't':
286 if (cmd != 0)
287 usage();
288 cmd = 't';
290 type = find_type(optarg);
291 break;
292 case 'd':
293 if (cmd != 0)
294 usage();
295 cmd = 'd';
297 type = 0xff;
298 strlcpy(name, optarg, sizeof(name));
299 break;
300 case 's':
301 sflag++;
302 break;
303 case '?':
304 default:
305 usage();
308 argc -= optind;
309 argv += optind;
312 * No leftover non-option arguments.
314 if (argc > 0)
315 usage();
318 * Cannot list and modify at the same time.
320 if ((lflag != 0 || sflag != 0) && mflag != 0)
321 usage();
324 * Bomb out on no-ops.
326 if (lflag == 0 && mflag == 0 && sflag == 0)
327 usage();
330 * If not listing, we need a device name or a type.
332 if (lflag == 0 && cmd == 0 && sflag == 0)
333 usage();
336 * Modify request.
338 if (mflag != 0) {
339 rctl.type = type;
340 strncpy(rctl.name, name, sizeof(rctl.name));
341 do_ioctl(&rctl);
343 exit(0);
347 * List sources.
349 if (lflag != 0)
350 do_list(cmd == 0, type, name);
352 if (sflag != 0)
353 do_stats();
355 exit(0);