rndctl.c revision 1.5 1 /* $NetBSD: rndctl.c,v 1.5 1999/03/30 17:32:44 mycroft Exp $ */
2
3 /*-
4 * Copyright (c) 1997 Michael Graff.
5 * All rights reserved.
6 *
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.
18 *
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.
30 */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <errno.h>
37 #include <err.h>
38 #include <string.h>
39
40 #include <sys/types.h>
41 #include <sys/ioctl.h>
42 #include <sys/rnd.h>
43
44 typedef struct {
45 char *name;
46 u_int32_t type;
47 } arg_t;
48
49 arg_t source_types[] = {
50 { "unknown", RND_TYPE_UNKNOWN },
51 { "disk", RND_TYPE_DISK },
52 { "network", RND_TYPE_NET },
53 { "net", RND_TYPE_NET },
54 { "tape", RND_TYPE_TAPE },
55 { "tty", RND_TYPE_TTY },
56 { NULL, 0 }
57 };
58
59 static void usage(void);
60 u_int32_t find_type(char *name);
61 char *find_name(u_int32_t);
62 void do_ioctl(rndctl_t *);
63 char * strflags(u_int32_t);
64 void do_list(int, u_int32_t, char *);
65
66 static void
67 usage(void)
68 {
69 fprintf(stderr, "usage: rndctl -CEce [-t devtype] [-d devname]\n");
70 fprintf(stderr, " rndctl -l [-t devtype] [-d devname]\n");
71 exit(1);
72 }
73
74 u_int32_t
75 find_type(char *name)
76 {
77 arg_t *a;
78
79 a = source_types;
80
81 while (a->name != NULL) {
82 if (strcmp(a->name, name) == 0)
83 return a->type;
84 a++;
85 }
86
87 errx(1, "Error: Device type %s unknown", name);
88 return 0;
89 }
90
91 char *
92 find_name(u_int32_t type)
93 {
94 arg_t *a;
95
96 a = source_types;
97
98 while (a->name != NULL) {
99 if (type == a->type)
100 return a->name;
101 a++;
102 }
103
104 errx(1, "Error: Device type %u unknown", type);
105 return 0;
106 }
107
108 void
109 do_ioctl(rndctl_t *rctl)
110 {
111 int fd;
112 int res;
113
114 fd = open("/dev/urandom", O_RDONLY, 0644);
115 if (fd < 0)
116 err(1, "open");
117
118 res = ioctl(fd, RNDCTL, rctl);
119 if (res < 0)
120 err(1, "ioctl(RNDCTL)");
121
122 close(fd);
123 }
124
125 char *
126 strflags(u_int32_t fl)
127 {
128 static char str[512];
129
130 str[0] = 0;
131 strcat(str, "<");
132
133 if (fl & RND_FLAG_NO_ESTIMATE)
134 strcat(str, "no");
135 strcat(str, "estimate, ");
136 if (fl & RND_FLAG_NO_COLLECT)
137 strcat(str, "no");
138 strcat(str, "collect>");
139
140 return str;
141 }
142
143 #define HEADER "Device Name Type Bits Flags\n" \
144 "---------------- -------- ---------- -----\n"
145
146 void
147 do_list(int all, u_int32_t type, char *name)
148 {
149 rndstat_t rstat;
150 rndstat_name_t rstat_name;
151 int fd;
152 int res;
153 u_int32_t start;
154
155 fd = open("/dev/urandom", O_RDONLY, 0644);
156 if (fd < 0)
157 err(1, "open");
158
159 if (all == 0 && type == 0xff) {
160 strncpy(rstat_name.name, name, 16);
161 res = ioctl(fd, RNDGETSRCNAME, &rstat_name);
162 if (res < 0)
163 err(1, "ioctl(RNDGETSRCNAME)");
164 printf(HEADER);
165 printf("%-16s %-8s %10u %s\n",
166 rstat_name.source.name,
167 find_name(rstat_name.source.type),
168 rstat_name.source.total,
169 strflags(rstat_name.source.flags));
170 close(fd);
171 return;
172 }
173
174 /*
175 * run through all the devices present in the system, and either
176 * print out ones that match, or print out all of them.
177 */
178 printf(HEADER);
179 start = 0;
180 for (;;) {
181 rstat.count = RND_MAXSTATCOUNT;
182 rstat.start = start;
183 res = ioctl(fd, RNDGETSRCNUM, &rstat);
184 if (res < 0)
185 err(1, "ioctl(RNDGETSRCNUM)");
186
187 if (rstat.count == 0)
188 break;
189
190 for (res = 0 ; res < rstat.count ; res++) {
191 if ((all != 0)
192 || (type == rstat.source[res].type))
193 printf("%-16s %-8s %10u %s\n",
194 rstat.source[res].name,
195 find_name(rstat.source[res].type),
196 rstat.source[res].total,
197 strflags(rstat.source[res].flags));
198 }
199 start += rstat.count;
200 }
201
202 close(fd);
203 }
204
205 int
206 main(int argc, char **argv)
207 {
208 rndctl_t rctl;
209 int ch;
210 int cmd;
211 int lflag;
212 int mflag;
213 u_int32_t type;
214 char name[16];
215
216 rctl.mask = 0;
217 rctl.flags = 0;
218
219 cmd = 0;
220 lflag = 0;
221 mflag = 0;
222 type = 0xff;
223
224 while ((ch = getopt(argc, argv, "CEcelt:d:")) != -1)
225 switch(ch) {
226 case 'C':
227 rctl.flags |= RND_FLAG_NO_COLLECT;
228 rctl.mask |= RND_FLAG_NO_COLLECT;
229 mflag++;
230 break;
231 case 'E':
232 rctl.flags |= RND_FLAG_NO_ESTIMATE;
233 rctl.mask |= RND_FLAG_NO_ESTIMATE;
234 mflag++;
235 break;
236 case 'c':
237 rctl.flags &= ~RND_FLAG_NO_COLLECT;
238 rctl.mask |= RND_FLAG_NO_COLLECT;
239 mflag++;
240 break;
241 case 'e':
242 rctl.flags &= ~RND_FLAG_NO_ESTIMATE;
243 rctl.mask |= RND_FLAG_NO_ESTIMATE;
244 mflag++;
245 break;
246 case 'l':
247 lflag++;
248 break;
249 case 't':
250 if (cmd != 0)
251 usage();
252 cmd = 't';
253
254 type = find_type(optarg);
255 break;
256 case 'd':
257 if (cmd != 0)
258 usage();
259 cmd = 'd';
260
261 type = 0xff;
262 strncpy(name, optarg, 16);
263 break;
264 case '?':
265 default:
266 usage();
267 }
268
269 /*
270 * cannot list and modify at the same time
271 */
272 if (lflag != 0 && mflag != 0)
273 usage();
274
275 /*
276 * bomb out on no-ops
277 */
278 if (lflag == 0 && mflag == 0)
279 usage();
280
281 /*
282 * if not listing, we need a device name or a type
283 */
284 if (lflag == 0 && cmd == 0)
285 usage();
286
287 /*
288 * modify request
289 */
290 if (mflag != 0) {
291 rctl.type = type;
292 strncpy(rctl.name, name, 16);
293 do_ioctl(&rctl);
294
295 exit(0);
296 }
297
298 /*
299 * list sources
300 */
301 if (lflag != 0)
302 do_list(cmd == 0, type, name);
303
304 return 0;
305 }
306