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