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