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 | }