1 | /* 2 | * Layer Two Tunnelling Protocol Daemon 3 | * Copyright (C) 1998 Adtran, Inc. 4 | * 5 | * Mark Spencer 6 | * 7 | * This software is distributed under the terms 8 | * of the GPL, which you should have received 9 | * along with this source. 10 | * 11 | * Miscellaneous but important functions 12 | * 13 | */ 14 | #include <stdarg.h> 15 | #include <stdio.h> 16 | #include <stdlib.h> 17 | #include <errno.h> 18 | #include <string.h> 19 | #include <syslog.h> 20 | #if defined(SOLARIS) 21 | # include <varargs.h> 22 | #endif 23 | #include <netinet/in.h> 24 | #include "l2tp.h" 25 | 26 | void log (int level, const char *fmt, ...) 27 | { 28 | char buf[256]; 29 | va_list args; 30 | va_start (args, fmt); 31 | vsnprintf (buf, sizeof (buf), fmt, args); 32 | va_end (args); //bk - otherwise ppc segfaults 33 | va_start (args, fmt); //bk 34 | vfprintf (stderr, fmt, args); 35 | fflush (stderr); 36 | openlog (BINARY, LOG_PID, LOG_DAEMON); 37 | syslog (level, "%s", buf); 38 | va_end (args); 39 | } 40 | 41 | void set_error (struct call *c, int error, const char *fmt, ...) 42 | { 43 | va_list args; 44 | va_start (args, fmt); 45 | c->error = error; 46 | c->result = RESULT_ERROR; 47 | c->needclose = -1; 48 | vsnprintf (c->errormsg, sizeof (c->errormsg), fmt, args); 49 | if (c->errormsg[strlen (c->errormsg) - 1] == '\n') 50 | c->errormsg[strlen (c->errormsg) - 1] = 0; 51 | va_end (args); 52 | } 53 | 54 | struct buffer *new_buf (int size) 55 | { 56 | struct buffer *b = malloc (sizeof (struct buffer)); 57 | if (!b || !size || size < 0) 58 | return NULL; 59 | b->rstart = malloc (size); 60 | if (!b->rstart) 61 | { 62 | free (b); 63 | return NULL; 64 | } 65 | b->start = b->rstart; 66 | b->rend = b->rstart + size - 1; 67 | b->len = size; 68 | b->maxlen = size; 69 | return b; 70 | } 71 | 72 | inline void recycle_buf (struct buffer *b) 73 | { 74 | b->start = b->rstart; 75 | b->len = b->maxlen; 76 | } 77 | 78 | #define bufferDumpWIDTH 16 79 | void bufferDump (buf, buflen) 80 | char *buf; 81 | int buflen; 82 | { 83 | int i = 0, j = 0; 84 | unsigned char line[2 * bufferDumpWIDTH + 1], *c; /* we need TWO characters to DISPLAY ONE byte */ 85 | 86 | for (i = 0; i < buflen / bufferDumpWIDTH; i++) 87 | { 88 | c = line; 89 | for (j = 0; j < bufferDumpWIDTH; j++) 90 | { 91 | sprintf (c, "%02x ", (buf[i * bufferDumpWIDTH + j]) & 0xff); 92 | c++; 93 | c++; /* again two characters to display ONE byte */ 94 | } 95 | *c = '\0'; 96 | log (LOG_WARN, "%s: buflen=%d, buffer[%d]: *%s*\n", __FUNCTION__, 97 | buflen, i, line); 98 | } 99 | 100 | c = line; 101 | for (j = 0; j < buflen % bufferDumpWIDTH; j++) 102 | { 103 | sprintf (c, "%02x ", 104 | buf[(buflen / bufferDumpWIDTH) * bufferDumpWIDTH + 105 | j] & 0xff); 106 | c++; 107 | c++; 108 | } 109 | if (c != line) 110 | { 111 | *c = '\0'; 112 | log (LOG_WARN, "%s: buffer[%d]: *%s*\n", __FUNCTION__, i, 113 | line); 114 | } 115 | } 116 | 117 | void do_packet_dump (struct buffer *buf) 118 | { 119 | int x; 120 | unsigned char *c = buf->start; 121 | printf ("packet dump: \nHEX: { "); 122 | for (x = 0; x < buf->len; x++) 123 | { 124 | printf ("%.2X ", *c); 125 | c++; 126 | }; 127 | printf ("}\nASCII: { "); 128 | c = buf->start; 129 | for (x = 0; x < buf->len; x++) 130 | { 131 | if (*c > 31 && *c < 127) 132 | { 133 | putchar (*c); 134 | } 135 | else 136 | { 137 | putchar (' '); 138 | } 139 | c++; 140 | } 141 | printf ("}\n"); 142 | } 143 | 144 | inline void swaps (void *buf_v, int len) 145 | { 146 | #ifdef __alpha 147 | /* Reverse byte order alpha is little endian so lest save a step. 148 | to make things work out easier */ 149 | int x; 150 | unsigned char t1; 151 | unsigned char *tmp = (_u16 *) buf_v; 152 | for (x = 0; x < len; x += 2) 153 | { 154 | t1 = tmp[x]; 155 | tmp[x] = tmp[x + 1]; 156 | tmp[x + 1] = t1; 157 | } 158 | #else 159 | 160 | /* Reverse byte order (if proper to do so) 161 | to make things work out easier */ 162 | int x; 163 | _u16 *tmp = (_u16 *) buf_v; 164 | for (x = 0; x < len / 2; x++) 165 | tmp[x] = ntohs (tmp[x]); 166 | #endif 167 | } 168 | 169 | 170 | 171 | inline void toss (struct buffer *buf) 172 | { 173 | /* 174 | * Toss a frame and free up the buffer that contained it 175 | */ 176 | 177 | free (buf->rstart); 178 | free (buf); 179 | } 180 | 181 | inline void safe_copy (char *a, char *b, int size) 182 | { 183 | /* Copies B into A (assuming A holds MAXSTRLEN bytes) 184 | safely */ 185 | strncpy (a, b, MIN (size, MAXSTRLEN - 1)); 186 | a[MIN (size, MAXSTRLEN - 1)] = '\000'; 187 | } 188 | 189 | struct ppp_opts *add_opt (struct ppp_opts *option, char *fmt, ...) 190 | { 191 | va_list args; 192 | struct ppp_opts *new, *last; 193 | new = (struct ppp_opts *) malloc (sizeof (struct ppp_opts)); 194 | if (!new) 195 | { 196 | log (LOG_WARN, 197 | "%s : Unable to allocate ppp option memory. Expect a crash\n", 198 | __FUNCTION__); 199 | return NULL; 200 | } 201 | new->next = NULL; 202 | va_start (args, fmt); 203 | vsnprintf (new->option, sizeof (new->option), fmt, args); 204 | va_end (args); 205 | if (option) 206 | { 207 | last = option; 208 | while (last->next) 209 | last = last->next; 210 | last->next = new; 211 | return option; 212 | } 213 | else 214 | return new; 215 | } 216 | void opt_destroy (struct ppp_opts *option) 217 | { 218 | struct ppp_opts *tmp; 219 | while (option) 220 | { 221 | tmp = option->next; 222 | free (option); 223 | option = tmp; 224 | }; 225 | }