1/* 2 * Layer Two Tunnelling Protocol Daemon 3 * Copyright (C) 1998 Adtran, Inc. 4 * Copyright (C) 2002 Jeff McAdams 5 * 6 * Mark Spencer 7 * 8 * This software is distributed under the terms 9 * of the GPL, which you should have received 10 * along with this source. 11 * 12 * Miscellaneous but important functions 13 * 14 */ 15 16#include <unistd.h> 17#include <sys/types.h> 18#include <sys/stat.h> 19#include <fcntl.h> 20#include <stdarg.h> 21#include <stdio.h> 22#include <stdlib.h> 23#include <errno.h> 24#include <string.h> 25#include <syslog.h> 26#if defined(SOLARIS) 27# include <varargs.h> 28#endif 29#include <netinet/in.h> 30#include "l2tp.h" 31 32 33void log (int level, const char *fmt, ...) 34{ 35 char buf[256]; 36 va_list args; 37 va_start (args, fmt); 38 vsnprintf (buf, sizeof (buf), fmt, args); 39 va_end (args); //bk - otherwise ppc segfaults 40 va_start (args, fmt); //bk 41 vfprintf (stderr, fmt, args); 42 fflush (stderr); 43 openlog (BINARY, LOG_PID, LOG_DAEMON); 44 syslog (level, "%s", buf); 45 va_end (args); 46} 47 48void set_error (struct call *c, int error, const char *fmt, ...) 49{ 50 va_list args; 51 va_start (args, fmt); 52 c->error = error; 53 c->result = RESULT_ERROR; 54 c->needclose = -1; 55 vsnprintf (c->errormsg, sizeof (c->errormsg), fmt, args); 56 if (c->errormsg[strlen (c->errormsg) - 1] == '\n') 57 c->errormsg[strlen (c->errormsg) - 1] = 0; 58 va_end (args); 59} 60 61struct buffer *new_buf (int size) 62{ 63 struct buffer *b = malloc (sizeof (struct buffer)); 64 if (!b || !size || size < 0) 65 return NULL; 66 b->rstart = malloc (size); 67 if (!b->rstart) 68 { 69 free (b); 70 return NULL; 71 } 72 b->start = b->rstart; 73 b->rend = b->rstart + size - 1; 74 b->len = size; 75 b->maxlen = size; 76 return b; 77} 78 79inline void recycle_buf (struct buffer *b) 80{ 81 b->start = b->rstart; 82 b->len = b->maxlen; 83} 84 85#define bufferDumpWIDTH 16 86void bufferDump (char *buf, int buflen) 87{ 88 int i = 0, j = 0; 89 /* we need TWO characters to DISPLAY ONE byte */ 90 unsigned char line[2 * bufferDumpWIDTH + 1], *c; 91 92 for (i = 0; i < buflen / bufferDumpWIDTH; i++) 93 { 94 c = line; 95 for (j = 0; j < bufferDumpWIDTH; j++) 96 { 97 sprintf (c, "%02x ", (buf[i * bufferDumpWIDTH + j]) & 0xff); 98 c++; 99 c++; /* again two characters to display ONE byte */ 100 } 101 *c = '\0'; 102 log (LOG_WARN, "%s: buflen=%d, buffer[%d]: *%s*\n", __FUNCTION__, 103 buflen, i, line); 104 } 105 106 c = line; 107 for (j = 0; j < buflen % bufferDumpWIDTH; j++) 108 { 109 sprintf (c, "%02x ", 110 buf[(buflen / bufferDumpWIDTH) * bufferDumpWIDTH + 111 j] & 0xff); 112 c++; 113 c++; 114 } 115 if (c != line) 116 { 117 *c = '\0'; 118 log (LOG_WARN, "%s: buffer[%d]: *%s*\n", __FUNCTION__, i, 119 line); 120 } 121} 122 123void do_packet_dump (struct buffer *buf) 124{ 125 int x; 126 unsigned char *c = buf->start; 127 //printf ("packet dump: \nHEX: { "); 128 for (x = 0; x < buf->len; x++) 129 { 130 //printf ("%.2X ", *c); 131 c++; 132 }; 133 //printf ("}\nASCII: { "); 134 c = buf->start; 135 for (x = 0; x < buf->len; x++) 136 { 137 if (*c > 31 && *c < 127) 138 { 139 putchar (*c); 140 } 141 else 142 { 143 putchar (' '); 144 } 145 c++; 146 } 147 //printf ("}\n"); 148} 149 150inline void swaps (void *buf_v, int len) 151{ 152#ifdef __alpha 153 /* Reverse byte order alpha is little endian so lest save a step. 154 to make things work out easier */ 155 int x; 156 unsigned char t1; 157 unsigned char *tmp = (_u16 *) buf_v; 158 for (x = 0; x < len; x += 2) 159 { 160 t1 = tmp[x]; 161 tmp[x] = tmp[x + 1]; 162 tmp[x + 1] = t1; 163 } 164#else 165 166 /* Reverse byte order (if proper to do so) 167 to make things work out easier */ 168 int x; 169 _u16 *tmp = (_u16 *) buf_v; 170 for (x = 0; x < len / 2; x++) 171 tmp[x] = ntohs (tmp[x]); 172#endif 173} 174 175 176 177inline void toss (struct buffer *buf) 178{ 179 /* 180 * Toss a frame and free up the buffer that contained it 181 */ 182 183 free (buf->rstart); 184 free (buf); 185} 186 187inline void safe_copy (char *a, char *b, int size) 188{ 189 /* Copies B into A (assuming A holds MAXSTRLEN bytes) 190 safely */ 191 strncpy (a, b, MIN (size, MAXSTRLEN - 1)); 192 a[MIN (size, MAXSTRLEN - 1)] = '\000'; 193} 194 195struct ppp_opts *add_opt (struct ppp_opts *option, char *fmt, ...) 196{ 197 va_list args; 198 struct ppp_opts *new, *last; 199 new = (struct ppp_opts *) malloc (sizeof (struct ppp_opts)); 200 if (!new) 201 { 202 log (LOG_WARN, 203 "%s : Unable to allocate ppp option memory. Expect a crash\n", 204 __FUNCTION__); 205 return NULL; 206 } 207 new->next = NULL; 208 va_start (args, fmt); 209 vsnprintf (new->option, sizeof (new->option), fmt, args); 210 va_end (args); 211 if (option) 212 { 213 last = option; 214 while (last->next) 215 last = last->next; 216 last->next = new; 217 return option; 218 } 219 else 220 return new; 221} 222void opt_destroy (struct ppp_opts *option) 223{ 224 struct ppp_opts *tmp; 225 while (option) 226 { 227 tmp = option->next; 228 free (option); 229 option = tmp; 230 }; 231} 232 233int get_egd_entropy(char *buf, int count) 234{ 235 return -1; 236} 237 238int get_sys_entropy(char *buf, int count) 239{ 240 /* 241 * This way of filling buf with rand() generated data is really 242 * fairly inefficient from a function call point of view...rand() 243 * returns four bytes of data (on most systems, sizeof(int)) 244 * and we end up only using 1 byte of it (sizeof(char))...ah 245 * well...it was a *whole* lot easier to code this way...suggestions 246 * for improvements are, of course, welcome 247 */ 248 int counter; 249 for (counter = 0; counter < count; counter++) 250 { 251 buf[counter] = (char)rand(); 252 } 253#ifdef DEBUG_ENTROPY 254 bufferDump (buf, count); 255#endif 256 return count; 257} 258 259int get_dev_entropy(char *buf, int count) 260{ 261 int devrandom; 262 ssize_t entropy_amount; 263 264 devrandom = open ("/dev/urandom", O_RDONLY | O_NONBLOCK); 265 if (devrandom == -1) 266 { 267#ifdef DEBUG_ENTROPY 268 log(LOG_WARN, "%s: couldn't open /dev/urandom," 269 "falling back to rand()\n", 270 __FUNCTION__); 271#endif 272 return get_sys_entropy(buf, count); 273 } 274 entropy_amount = read(devrandom, buf, count); 275 close(devrandom); 276 return entropy_amount; 277} 278 279int get_entropy (char *buf, int count) 280{ 281 if (rand_source == RAND_SYS) 282 { 283 return get_sys_entropy(buf, count); 284 } 285 else if (rand_source == RAND_DEV) 286 { 287 return get_dev_entropy(buf, count); 288 } 289 else if (rand_source == RAND_EGD) 290 { 291 log(LOG_WARN, "%s: EGD Randomness source not yet implemented\n", 292 __FUNCTION__); 293 return -1; 294 } 295 else 296 { 297 log(LOG_WARN, "%s: Invalid Randomness source specified (%d)\n", 298 __FUNCTION__, rand_source); 299 return -1; 300 } 301} 302