1/*********************************************************************** 2* 3* utils.c 4* 5* Utility functions for l2tp 6* 7* Copyright (C) 2002 Roaring Penguin Software Inc. 8* 9* This software may be distributed under the terms of the GNU General 10* Public License, Version 2, or (at your option) any later version. 11* 12* LIC: GPL 13* 14***********************************************************************/ 15 16static char const RCSID[] = 17"$Id: utils.c,v 1.1.1.1 2008/10/15 03:31:00 james26_jang Exp $"; 18 19#include <sys/types.h> 20#include <sys/stat.h> 21#include <fcntl.h> 22#include <stdlib.h> 23#include <unistd.h> 24#include <time.h> 25#include <stdarg.h> 26#include <stdio.h> 27#include <dlfcn.h> 28#include <string.h> 29#include <errno.h> 30#include <syslog.h> 31 32#include "l2tp.h" 33 34#define MAX_ERRMSG_LEN 512 35 36static int random_fd = -1; 37static char errmsg[MAX_ERRMSG_LEN]; 38 39struct sd_handler { 40 l2tp_shutdown_func f; 41 void *data; 42}; 43 44static struct sd_handler shutdown_handlers[16]; 45 46static int n_shutdown_handlers = 0; 47 48int 49l2tp_register_shutdown_handler(l2tp_shutdown_func f, void *data) 50{ 51 if (n_shutdown_handlers == 16) return -1; 52 shutdown_handlers[n_shutdown_handlers].f = f; 53 shutdown_handlers[n_shutdown_handlers].data = data; 54 n_shutdown_handlers++; 55 return n_shutdown_handlers; 56} 57 58void 59l2tp_cleanup(void) 60{ 61 int i; 62 for (i=0; i<n_shutdown_handlers; i++) { 63 shutdown_handlers[i].f(shutdown_handlers[i].data); 64 } 65} 66 67char const * 68l2tp_get_errmsg(void) 69{ 70 return errmsg; 71} 72 73/********************************************************************** 74* %FUNCTION: set_errmsg 75* %ARGUMENTS: 76* fmt -- printf format 77* ... -- format args 78* %RETURNS: 79* Nothing 80* %DESCRIPTION: 81* Sets static errmsg string 82***********************************************************************/ 83void 84l2tp_set_errmsg(char const *fmt, ...) 85{ 86 va_list ap; 87 va_start(ap, fmt); 88 vsnprintf(errmsg, MAX_ERRMSG_LEN, fmt, ap); 89 va_end(ap); 90 errmsg[MAX_ERRMSG_LEN-1] = 0; 91 fprintf(stderr, "Error: %s\n", errmsg); 92 93 vsyslog(LOG_ERR, fmt, ap); 94} 95 96/********************************************************************** 97* %FUNCTION: random_init 98* %ARGUMENTS: 99* None 100* %RETURNS: 101* Nothing 102* %DESCRIPTION: 103* Sets up random-number generator 104***********************************************************************/ 105void 106l2tp_random_init(void) 107{ 108 /* Prefer /dev/urandom; fall back on rand() */ 109 random_fd = open("/dev/urandom", O_RDONLY); 110 if (random_fd < 0) { 111 srand(time(NULL) + getpid()*getppid()); 112 } 113 114} 115 116/********************************************************************** 117* %FUNCTION: bad random_fill 118* %ARGUMENTS: 119* ptr -- pointer to a buffer 120* size -- size of buffer 121* %RETURNS: 122* Nothing 123* %DESCRIPTION: 124* Fills buffer with "size" random bytes. This function is not 125* cryptographically strong; it's used as a fallback for systems 126* without /dev/urandom. 127***********************************************************************/ 128static void 129bad_random_fill(void *ptr, size_t size) 130{ 131 unsigned char *buf = ptr; 132 while(size--) { 133 *buf++ = rand() & 0xFF; 134 } 135} 136 137/********************************************************************** 138* %FUNCTION: random_fill 139* %ARGUMENTS: 140* ptr -- pointer to a buffer 141* size -- size of buffer 142* %RETURNS: 143* Nothing 144* %DESCRIPTION: 145* Fills buffer with "size" random bytes. 146***********************************************************************/ 147void 148l2tp_random_fill(void *ptr, size_t size) 149{ 150 int n; 151 int ndone = 0; 152 int nleft = size; 153 unsigned char *buf = ptr; 154 155 if (random_fd < 0) { 156 bad_random_fill(ptr, size); 157 return; 158 } 159 160 while(nleft) { 161 n = read(random_fd, buf+ndone, nleft); 162 if (n <= 0) { 163 close(random_fd); 164 random_fd = -1; 165 bad_random_fill(buf+ndone, nleft); 166 return; 167 } 168 nleft -= n; 169 ndone += n; 170 } 171} 172 173void l2tp_die(void) 174{ 175 fprintf(stderr, "FATAL: %s\n", errmsg); 176 l2tp_cleanup(); 177 exit(1); 178} 179 180/********************************************************************** 181* %FUNCTION: load_handler 182* %ARGUMENTS: 183* fname -- filename to load 184* %RETURNS: 185* -1 on error, 0 if OK 186* %DESCRIPTION: 187* Dynamically-loads a handler and initializes it. If fname is not 188* an absolute path name, we load the handler from /usr/lib/l2tp/plugins 189***********************************************************************/ 190int 191l2tp_load_handler(EventSelector *es, 192 char const *fname) 193{ 194 char buf[1024]; 195 void *handle; 196 void *init; 197 void (*init_fn)(EventSelector *); 198 199 if (*fname == '/') { 200 handle = dlopen(fname, RTLD_NOW); 201 } else { 202 snprintf(buf, sizeof(buf), "%s/lib/l2tp/plugins/%s", PREFIX, fname); 203 buf[sizeof(buf)-1] = 0; 204 handle = dlopen(buf, RTLD_NOW); 205 } 206 207 if (!handle) { 208 l2tp_set_errmsg("Could not dload %s: %s", 209 fname, dlerror()); 210 return -1; 211 } 212 213 init = dlsym(handle, "handler_init"); 214 if (!init) { 215 dlclose(handle); 216 l2tp_set_errmsg("No handler_init found in %s", fname); 217 return -1; 218 } 219 init_fn = (void (*)(EventSelector *)) init; 220 init_fn(es); 221 return 0; 222} 223