/* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * Copyright (C) 2005-2012, Anthony Minessale II * * Version: MPL 1.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * * The Initial Developer of the Original Code is * Anthony Minessale II * Portions created by the Initial Developer are Copyright (C) * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Anthony Minessale II * Neal Horman * * * mod_random.c -- entropy source module * */ #include /* Prototypes */ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_random_shutdown); SWITCH_MODULE_RUNTIME_FUNCTION(mod_random_runtime); SWITCH_MODULE_LOAD_FUNCTION(mod_random_load); SWITCH_MODULE_DEFINITION(mod_random, mod_random_load, mod_random_shutdown, mod_random_runtime); static int RUNNING = 0; static const char *random_device_files[] = { "/dev/hwrandom", "/dev/random", NULL }; const char *random_device_file = NULL; static void event_handler(switch_event_t *event); SWITCH_MODULE_LOAD_FUNCTION(mod_random_load) { #ifdef WIN32 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s missing window support\n", modname); return SWITCH_STATUS_NOTIMPL; #endif int i = 0; for(i = 0 ;random_device_files[i]; i++) { if (switch_file_exists(random_device_files[i], pool) == SWITCH_STATUS_SUCCESS) { random_device_file = random_device_files[i]; break; } } if (!random_device_file) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s can't locate a random device file\n", modname); return SWITCH_STATUS_FALSE; } if ((switch_event_bind(modname, SWITCH_EVENT_ALL, NULL, event_handler, NULL) != SWITCH_STATUS_SUCCESS)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_TERM; } /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); RUNNING = 1; /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; } SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_random_shutdown) { switch_event_unbind_callback(event_handler); RUNNING = 0; return SWITCH_STATUS_SUCCESS; } #if WIN32 SWITCH_MODULE_RUNTIME_FUNCTION(mod_random_runtime) { RUNNING = 0; return SWITCH_STATUS_TERM; } #else #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct { int count; int size; unsigned char *data; } entropy_t; static int random_add_entropy(int fd, void *buf, size_t size) { entropy_t e = { 0 }; int r = 0; e.count = size * 8; e.size = size; e.data = (unsigned char *) buf; if (ioctl(fd, RNDADDENTROPY, &e) != 0) { r = 1; } return r; } static int rng_read(int fd, void *buf, size_t size) { size_t off = 0; ssize_t r; unsigned char *bp = (unsigned char *) buf; while (size > 0) { do { r = read(fd, bp + off, size); } while ((r == -1) && (errno == EINTR)); if (r <= 0) { break; } off += r; size -= r; } return size; } static int rfd = 0; static void event_handler(switch_event_t *event) { char *buf; if (switch_event_serialize(event, &buf, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { random_add_entropy(rfd, buf, strlen(buf)); free(buf); } } SWITCH_MODULE_RUNTIME_FUNCTION(mod_random_runtime) { unsigned char data[1024] = {0}; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Thread starting using random_device_file %s\n", modname, random_device_file); if ((rfd = open(random_device_file, O_RDWR)) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s Error opening random_device_file %s\n", modname, random_device_file); RUNNING = 0; } rng_read(rfd, data, 4); while(RUNNING) { int16_t data[64]; int i = 0; int len = sizeof(data) / 2; switch_generate_sln_silence(data, len, 1); random_add_entropy(rfd, data, len); while(i < len && !data[i]) i++; if (i < len) { switch_yield(abs(data[i]) * 1000); } } if (rfd > -1) { close(rfd); } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Thread ending\n", modname); return SWITCH_STATUS_TERM; } #endif /* For Emacs: * Local Variables: * mode:c * indent-tabs-mode:t * tab-width:4 * c-basic-offset:4 * End: * For VIM: * vim:set softtabstop=4 shiftwidth=4 tabstop=4 */