1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Neal Horman <neal at wanlink dot com>
28  *
29  *
30  * mod_random.c -- entropy source module
31  *
32  */
33 #include <switch.h>
34 
35 /* Prototypes */
36 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_random_shutdown);
37 SWITCH_MODULE_RUNTIME_FUNCTION(mod_random_runtime);
38 SWITCH_MODULE_LOAD_FUNCTION(mod_random_load);
39 
40 SWITCH_MODULE_DEFINITION(mod_random, mod_random_load, mod_random_shutdown, mod_random_runtime);
41 
42 static int RUNNING = 0;
43 static const char *random_device_files[] = { "/dev/hwrandom", "/dev/random", NULL };
44 const char *random_device_file = NULL;
45 
46 static void event_handler(switch_event_t *event);
47 
48 
SWITCH_MODULE_LOAD_FUNCTION(mod_random_load)49 SWITCH_MODULE_LOAD_FUNCTION(mod_random_load)
50 {
51 
52 #ifdef WIN32
53 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s missing window support\n", modname);
54 	return SWITCH_STATUS_NOTIMPL;
55 #endif
56 
57 	int i = 0;
58 
59 
60 	for(i = 0 ;random_device_files[i]; i++) {
61 		if (switch_file_exists(random_device_files[i], pool) == SWITCH_STATUS_SUCCESS) {
62 			random_device_file = random_device_files[i];
63 			break;
64 		}
65 	}
66 
67 
68 	if (!random_device_file) {
69 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s can't locate a random device file\n", modname);
70 		return SWITCH_STATUS_FALSE;
71 	}
72 
73 
74 	if ((switch_event_bind(modname, SWITCH_EVENT_ALL, NULL, event_handler, NULL) != SWITCH_STATUS_SUCCESS)) {
75 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
76 		return SWITCH_STATUS_TERM;
77 	}
78 
79 	/* connect my internal structure to the blank pointer passed to me */
80 	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
81 
82 	RUNNING = 1;
83 
84 	/* indicate that the module should continue to be loaded */
85 	return SWITCH_STATUS_SUCCESS;
86 }
87 
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_random_shutdown)88 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_random_shutdown)
89 {
90 
91 	switch_event_unbind_callback(event_handler);
92 
93 	RUNNING = 0;
94 
95 	return SWITCH_STATUS_SUCCESS;
96 }
97 
98 #if WIN32
SWITCH_MODULE_RUNTIME_FUNCTION(mod_random_runtime)99 SWITCH_MODULE_RUNTIME_FUNCTION(mod_random_runtime)
100 {
101 	RUNNING = 0;
102 	return SWITCH_STATUS_TERM;
103 }
104 #else
105 
106 #include <unistd.h>
107 #include <stdint.h>
108 #include <stdlib.h>
109 #include <stdio.h>
110 #include <errno.h>
111 #include <syslog.h>
112 #include <sys/ioctl.h>
113 #include <sys/poll.h>
114 #include <sys/types.h>
115 #include <sys/stat.h>
116 #include <fcntl.h>
117 #include <sys/time.h>
118 #include <time.h>
119 #include <linux/types.h>
120 #include <linux/random.h>
121 #include <string.h>
122 
123 
124 
125 typedef struct {
126 	int count;
127 	int size;
128 	unsigned char *data;
129 } entropy_t;
130 
131 
random_add_entropy(int fd,void * buf,size_t size)132 static int random_add_entropy(int fd, void *buf, size_t size)
133 {
134 	entropy_t e = { 0 };
135 	int r = 0;
136 
137 	e.count = size * 8;
138 	e.size = size;
139 	e.data = (unsigned char *) buf;
140 
141 	if (ioctl(fd, RNDADDENTROPY, &e) != 0) {
142 		r = 1;
143 	}
144 
145 	return r;
146 }
147 
rng_read(int fd,void * buf,size_t size)148 static int rng_read(int fd, void *buf, size_t size)
149 {
150 	size_t off = 0;
151 	ssize_t r;
152 	unsigned char *bp = (unsigned char *) buf;
153 
154 	while (size > 0) {
155 		do {
156 			r = read(fd, bp + off, size);
157 		} while ((r == -1) && (errno == EINTR));
158 
159 		if (r <= 0) {
160 			break;
161 		}
162 
163 		off += r;
164 		size -= r;
165 	}
166 
167 	return size;
168 }
169 
170 static int rfd = 0;
171 
event_handler(switch_event_t * event)172 static void event_handler(switch_event_t *event)
173 {
174 	char *buf;
175 
176 	if (switch_event_serialize(event, &buf, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
177 		random_add_entropy(rfd, buf, strlen(buf));
178 		free(buf);
179 	}
180 
181 }
182 
SWITCH_MODULE_RUNTIME_FUNCTION(mod_random_runtime)183 SWITCH_MODULE_RUNTIME_FUNCTION(mod_random_runtime)
184 {
185 
186 	unsigned char data[1024] = {0};
187 
188 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Thread starting using random_device_file %s\n", modname, random_device_file);
189 
190 	if ((rfd = open(random_device_file, O_RDWR)) < 0) {
191 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s Error opening random_device_file %s\n", modname, random_device_file);
192 		RUNNING = 0;
193 	}
194 
195 	rng_read(rfd, data, 4);
196 
197 	while(RUNNING) {
198 		int16_t data[64];
199 		int i = 0;
200 		int len = sizeof(data) / 2;
201 
202 		switch_generate_sln_silence(data, len, 1, 1);
203 		random_add_entropy(rfd, data, len);
204 
205 		while(i < len && !data[i]) i++;
206 
207 		if (i < len) {
208 			switch_yield(abs(data[i]) * 1000);
209 		}
210 
211 	}
212 
213 	if (rfd > -1) {
214 		close(rfd);
215 	}
216 
217 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Thread ending\n", modname);
218 
219 	return SWITCH_STATUS_TERM;
220 }
221 
222 #endif
223 
224 
225 /* For Emacs:
226  * Local Variables:
227  * mode:c
228  * indent-tabs-mode:t
229  * tab-width:4
230  * c-basic-offset:4
231  * End:
232  * For VIM:
233  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet
234  */
235