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