1 |
|
|
/* $OpenBSD: l2tp_ctrl.c,v 1.21 2015/12/05 18:43:36 mmcc Exp $ */ |
2 |
|
|
|
3 |
|
|
/*- |
4 |
|
|
* Copyright (c) 2009 Internet Initiative Japan Inc. |
5 |
|
|
* All rights reserved. |
6 |
|
|
* |
7 |
|
|
* Redistribution and use in source and binary forms, with or without |
8 |
|
|
* modification, are permitted provided that the following conditions |
9 |
|
|
* are met: |
10 |
|
|
* 1. Redistributions of source code must retain the above copyright |
11 |
|
|
* notice, this list of conditions and the following disclaimer. |
12 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
13 |
|
|
* notice, this list of conditions and the following disclaimer in the |
14 |
|
|
* documentation and/or other materials provided with the distribution. |
15 |
|
|
* |
16 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
17 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
18 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
19 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
20 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
21 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
22 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
23 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
24 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
25 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
26 |
|
|
* SUCH DAMAGE. |
27 |
|
|
*/ |
28 |
|
|
/**@file Control connection processing functions for L2TP LNS */ |
29 |
|
|
/* $Id: l2tp_ctrl.c,v 1.21 2015/12/05 18:43:36 mmcc Exp $ */ |
30 |
|
|
#include <sys/types.h> |
31 |
|
|
#include <sys/time.h> |
32 |
|
|
#include <sys/socket.h> |
33 |
|
|
#include <netinet/in.h> |
34 |
|
|
#include <net/if.h> |
35 |
|
|
#include <arpa/inet.h> |
36 |
|
|
#include <endian.h> |
37 |
|
|
#include <errno.h> |
38 |
|
|
#include <event.h> |
39 |
|
|
#include <ifaddrs.h> |
40 |
|
|
#include <netdb.h> |
41 |
|
|
#include <stdarg.h> |
42 |
|
|
#include <stddef.h> |
43 |
|
|
#include <stdio.h> |
44 |
|
|
#include <stdlib.h> |
45 |
|
|
#include <string.h> |
46 |
|
|
#include <syslog.h> |
47 |
|
|
#include <time.h> |
48 |
|
|
#include <unistd.h> |
49 |
|
|
#include <limits.h> |
50 |
|
|
|
51 |
|
|
#ifdef USE_LIBSOCKUTIL |
52 |
|
|
#include <seil/sockfromto.h> |
53 |
|
|
#endif |
54 |
|
|
|
55 |
|
|
#include "time_utils.h" |
56 |
|
|
#include "ipsec_util.h" |
57 |
|
|
#include "bytebuf.h" |
58 |
|
|
#include "hash.h" |
59 |
|
|
#include "debugutil.h" |
60 |
|
|
#include "slist.h" |
61 |
|
|
#include "l2tp.h" |
62 |
|
|
#include "l2tp_local.h" |
63 |
|
|
#include "l2tp_subr.h" |
64 |
|
|
#include "net_utils.h" |
65 |
|
|
#include "version.h" |
66 |
|
|
#include "recvfromto.h" |
67 |
|
|
|
68 |
|
|
#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) |
69 |
|
|
|
70 |
|
|
static int l2tp_ctrl_init (l2tp_ctrl *, l2tpd *, struct sockaddr *, struct sockaddr *, void *); |
71 |
|
|
static void l2tp_ctrl_reload (l2tp_ctrl *); |
72 |
|
|
static int l2tp_ctrl_send_disconnect_notify (l2tp_ctrl *); |
73 |
|
|
#if 0 |
74 |
|
|
static void l2tp_ctrl_purge_ipsec_sa (l2tp_ctrl *); |
75 |
|
|
#endif |
76 |
|
|
static void l2tp_ctrl_timeout (int, short, void *); |
77 |
|
|
static int l2tp_ctrl_resend_una_packets (l2tp_ctrl *); |
78 |
|
|
static void l2tp_ctrl_destroy_all_calls (l2tp_ctrl *); |
79 |
|
|
static int l2tp_ctrl_disconnect_all_calls (l2tp_ctrl *, int); |
80 |
|
|
static void l2tp_ctrl_reset_timeout (l2tp_ctrl *); |
81 |
|
|
static inline int l2tp_ctrl_txwin_size (l2tp_ctrl *); |
82 |
|
|
static inline int l2tp_ctrl_txwin_is_full (l2tp_ctrl *); |
83 |
|
|
static int l2tp_ctrl_recv_SCCRQ (l2tp_ctrl *, u_char *, int, l2tpd *, struct sockaddr *); |
84 |
|
|
static int l2tp_ctrl_send_StopCCN (l2tp_ctrl *, int); |
85 |
|
|
static int l2tp_ctrl_recv_StopCCN (l2tp_ctrl *, u_char *, int); |
86 |
|
|
static void l2tp_ctrl_send_SCCRP (l2tp_ctrl *); |
87 |
|
|
static int l2tp_ctrl_send_HELLO (l2tp_ctrl *); |
88 |
|
|
static int l2tp_ctrl_send_ZLB (l2tp_ctrl *); |
89 |
|
|
static inline const char *l2tp_ctrl_state_string (l2tp_ctrl *); |
90 |
|
|
|
91 |
|
|
#ifdef L2TP_CTRL_DEBUG |
92 |
|
|
#define L2TP_CTRL_ASSERT(x) ASSERT(x) |
93 |
|
|
#define L2TP_CTRL_DBG(x) l2tp_ctrl_log x |
94 |
|
|
#else |
95 |
|
|
#define L2TP_CTRL_ASSERT(x) |
96 |
|
|
#define L2TP_CTRL_DBG(x) |
97 |
|
|
#endif |
98 |
|
|
|
99 |
|
|
/* Sequence # of l2tp_ctrl ID */ |
100 |
|
|
static u_int l2tp_ctrl_id_seq = 0; |
101 |
|
|
|
102 |
|
|
#define SEQ_LT(a,b) ((int16_t)((a) - (b)) < 0) |
103 |
|
|
#define SEQ_GT(a,b) ((int16_t)((a) - (b)) > 0) |
104 |
|
|
|
105 |
|
|
/** |
106 |
|
|
* Build instance of {@link ::_l2tp_ctrl L2TP LNS control connection} |
107 |
|
|
*/ |
108 |
|
|
l2tp_ctrl * |
109 |
|
|
l2tp_ctrl_create(void) |
110 |
|
|
{ |
111 |
|
|
|
112 |
|
|
return calloc(1, sizeof(l2tp_ctrl)); |
113 |
|
|
} |
114 |
|
|
|
115 |
|
|
/** |
116 |
|
|
* initialize and startup of {@link ::_l2tp_ctrl L2TP LNS control connection} |
117 |
|
|
* instance |
118 |
|
|
*/ |
119 |
|
|
static int |
120 |
|
|
l2tp_ctrl_init(l2tp_ctrl *_this, l2tpd *_l2tpd, struct sockaddr *peer, |
121 |
|
|
struct sockaddr *sock, void *nat_t_ctx) |
122 |
|
|
{ |
123 |
|
|
int tunid, i; |
124 |
|
|
bytebuffer *bytebuf; |
125 |
|
|
time_t curr_time; |
126 |
|
|
|
127 |
|
|
memset(_this, 0, sizeof(l2tp_ctrl)); |
128 |
|
|
|
129 |
|
|
curr_time = get_monosec(); |
130 |
|
|
_this->l2tpd = _l2tpd; |
131 |
|
|
_this->state = L2TP_CTRL_STATE_IDLE; |
132 |
|
|
_this->last_snd_ctrl = curr_time; |
133 |
|
|
|
134 |
|
|
slist_init(&_this->call_list); |
135 |
|
|
|
136 |
|
|
/* seek a free tunnel ID */ |
137 |
|
|
i = 0; |
138 |
|
|
_this->id = ++l2tp_ctrl_id_seq; |
139 |
|
|
for (i = 0, tunid = _this->id; ; i++, tunid++) { |
140 |
|
|
tunid &= 0xffff; |
141 |
|
|
_this->tunnel_id = l2tp_ctrl_id_seq & 0xffff; |
142 |
|
|
if (tunid == 0) |
143 |
|
|
continue; |
144 |
|
|
if (l2tpd_get_ctrl(_l2tpd, tunid) == NULL) |
145 |
|
|
break; |
146 |
|
|
if (i > 80000) { |
147 |
|
|
/* this must be happen, just log it. */ |
148 |
|
|
l2tpd_log(_l2tpd, LOG_ERR, "Too many l2tp controls"); |
149 |
|
|
return -1; |
150 |
|
|
} |
151 |
|
|
} |
152 |
|
|
|
153 |
|
|
_this->tunnel_id = tunid; |
154 |
|
|
|
155 |
|
|
L2TP_CTRL_ASSERT(peer != NULL); |
156 |
|
|
L2TP_CTRL_ASSERT(sock != NULL); |
157 |
|
|
memcpy(&_this->peer, peer, peer->sa_len); |
158 |
|
|
memcpy(&_this->sock, sock, sock->sa_len); |
159 |
|
|
|
160 |
|
|
/* prepare send buffer */ |
161 |
|
|
_this->winsz = L2TPD_DEFAULT_SEND_WINSZ; |
162 |
|
|
if ((_this->snd_buffers = calloc(_this->winsz, sizeof(bytebuffer *))) |
163 |
|
|
== NULL) { |
164 |
|
|
l2tpd_log(_l2tpd, LOG_ERR, |
165 |
|
|
"calloc() failed in %s(): %m", __func__); |
166 |
|
|
goto fail; |
167 |
|
|
} |
168 |
|
|
for (i = 0; i < _this->winsz; i++) { |
169 |
|
|
if ((bytebuf = bytebuffer_create(L2TPD_SND_BUFSIZ)) == NULL) { |
170 |
|
|
l2tpd_log(_l2tpd, LOG_ERR, |
171 |
|
|
"bytebuffer_create() failed in %s(): %m", __func__); |
172 |
|
|
goto fail; |
173 |
|
|
} |
174 |
|
|
_this->snd_buffers[i] = bytebuf; |
175 |
|
|
} |
176 |
|
|
if ((_this->zlb_buffer = bytebuffer_create(sizeof(struct l2tp_header) |
177 |
|
|
+ 128)) == NULL) { |
178 |
|
|
l2tpd_log(_l2tpd, LOG_ERR, |
179 |
|
|
"bytebuffer_create() failed in %s(): %m", __func__); |
180 |
|
|
goto fail; |
181 |
|
|
} |
182 |
|
|
#if defined(USE_LIBSOCKUTIL) || defined(USE_SA_COOKIE) |
183 |
|
|
if (nat_t_ctx != NULL) { |
184 |
|
|
if ((_this->sa_cookie = malloc( |
185 |
|
|
sizeof(struct in_ipsec_sa_cookie))) != NULL) { |
186 |
|
|
*(struct in_ipsec_sa_cookie *)_this->sa_cookie = |
187 |
|
|
*(struct in_ipsec_sa_cookie *)nat_t_ctx; |
188 |
|
|
} else { |
189 |
|
|
l2tpd_log(_l2tpd, LOG_ERR, |
190 |
|
|
"creating sa_cookie failed: %m"); |
191 |
|
|
goto fail; |
192 |
|
|
} |
193 |
|
|
} |
194 |
|
|
#endif |
195 |
|
|
_this->hello_interval = L2TP_CTRL_DEFAULT_HELLO_INTERVAL; |
196 |
|
|
_this->hello_timeout = L2TP_CTRL_DEFAULT_HELLO_TIMEOUT; |
197 |
|
|
_this->hello_io_time = curr_time; |
198 |
|
|
|
199 |
|
|
/* initialize timeout timer */ |
200 |
|
|
l2tp_ctrl_reset_timeout(_this); |
201 |
|
|
|
202 |
|
|
/* register l2tp context */ |
203 |
|
|
l2tpd_add_ctrl(_l2tpd, _this); |
204 |
|
|
return 0; |
205 |
|
|
fail: |
206 |
|
|
l2tp_ctrl_stop(_this, 0); |
207 |
|
|
return -1; |
208 |
|
|
} |
209 |
|
|
|
210 |
|
|
/* |
211 |
|
|
* setup {@link ::_l2tp_ctrl L2TP LNS control connection} instance |
212 |
|
|
*/ |
213 |
|
|
static void |
214 |
|
|
l2tp_ctrl_reload(l2tp_ctrl *_this) |
215 |
|
|
{ |
216 |
|
|
_this->data_use_seq = L2TP_CTRL_CONF(_this)->data_use_seq; |
217 |
|
|
if (L2TP_CTRL_CONF(_this)->hello_interval != 0) |
218 |
|
|
_this->hello_interval = L2TP_CTRL_CONF(_this)->hello_interval; |
219 |
|
|
if (L2TP_CTRL_CONF(_this)->hello_timeout != 0) |
220 |
|
|
_this->hello_timeout = L2TP_CTRL_CONF(_this)->hello_timeout; |
221 |
|
|
} |
222 |
|
|
|
223 |
|
|
/* |
224 |
|
|
* free {@link ::_l2tp_ctrl L2TP LNS control connection} instance |
225 |
|
|
*/ |
226 |
|
|
void |
227 |
|
|
l2tp_ctrl_destroy(l2tp_ctrl *_this) |
228 |
|
|
{ |
229 |
|
|
L2TP_CTRL_ASSERT(_this != NULL); |
230 |
|
|
#if defined(USE_LIBSOCKUTIL) || defined(USE_SA_COOKIE) |
231 |
|
|
free(_this->sa_cookie); |
232 |
|
|
#endif |
233 |
|
|
free(_this); |
234 |
|
|
} |
235 |
|
|
|
236 |
|
|
/* |
237 |
|
|
* nortify disconnection to peer |
238 |
|
|
* |
239 |
|
|
* @return 0: all CDN and StopCCN have been sent. |
240 |
|
|
* N: if the remaining calls which still not sent CDN exist, |
241 |
|
|
* return # of the calls. |
242 |
|
|
* -1: when try to send of StopCCN failed. |
243 |
|
|
*/ |
244 |
|
|
static int |
245 |
|
|
l2tp_ctrl_send_disconnect_notify(l2tp_ctrl *_this) |
246 |
|
|
{ |
247 |
|
|
int ncalls; |
248 |
|
|
|
249 |
|
|
L2TP_CTRL_ASSERT(_this != NULL) |
250 |
|
|
L2TP_CTRL_ASSERT(_this->state == L2TP_CTRL_STATE_ESTABLISHED || |
251 |
|
|
_this->state == L2TP_CTRL_STATE_CLEANUP_WAIT); |
252 |
|
|
|
253 |
|
|
/* this control is not actively closing or StopCCN have been sent */ |
254 |
|
|
if (_this->active_closing == 0) |
255 |
|
|
return 0; |
256 |
|
|
|
257 |
|
|
/* Send CDN all Calls */ |
258 |
|
|
ncalls = 0; |
259 |
|
|
if (slist_length(&_this->call_list) != 0) { |
260 |
|
|
ncalls = l2tp_ctrl_disconnect_all_calls(_this, 0); |
261 |
|
|
if (ncalls > 0) { |
262 |
|
|
/* |
263 |
|
|
* Call the function again to check whether the |
264 |
|
|
* sending window is fulled. In case ncalls == 0, |
265 |
|
|
* it means we've sent CDN for all calls. |
266 |
|
|
*/ |
267 |
|
|
ncalls = l2tp_ctrl_disconnect_all_calls(_this, 0); |
268 |
|
|
} |
269 |
|
|
} |
270 |
|
|
if (ncalls > 0) |
271 |
|
|
return ncalls; |
272 |
|
|
|
273 |
|
|
if (l2tp_ctrl_send_StopCCN(_this, _this->active_closing) != 0) |
274 |
|
|
return -1; |
275 |
|
|
_this->active_closing = 0; |
276 |
|
|
|
277 |
|
|
return 0; |
278 |
|
|
} |
279 |
|
|
|
280 |
|
|
/* |
281 |
|
|
* Terminate the control connection |
282 |
|
|
* |
283 |
|
|
* <p> |
284 |
|
|
* please specify an appropriate value to result( >0 ) for |
285 |
|
|
* StopCCN ResultCode AVP, when to sent Active Close (which |
286 |
|
|
* require StopCCN sent).</p> |
287 |
|
|
* <p> |
288 |
|
|
* When the return value of this function is zero, the _this |
289 |
|
|
* is already released. The lt2p_ctrl process that was bound to it |
290 |
|
|
* could not contine. |
291 |
|
|
* When the return value of this function is one, the timer |
292 |
|
|
* is reset.</p> |
293 |
|
|
* |
294 |
|
|
* @return return 0 if terminate process was completed. |
295 |
|
|
*/ |
296 |
|
|
int |
297 |
|
|
l2tp_ctrl_stop(l2tp_ctrl *_this, int result) |
298 |
|
|
{ |
299 |
|
|
int i; |
300 |
|
|
l2tpd *_l2tpd; |
301 |
|
|
|
302 |
|
|
L2TP_CTRL_ASSERT(_this != NULL); |
303 |
|
|
|
304 |
|
|
switch (_this->state) { |
305 |
|
|
case L2TP_CTRL_STATE_ESTABLISHED: |
306 |
|
|
_this->state = L2TP_CTRL_STATE_CLEANUP_WAIT; |
307 |
|
|
if (result > 0) { |
308 |
|
|
_this->active_closing = result; |
309 |
|
|
l2tp_ctrl_send_disconnect_notify(_this); |
310 |
|
|
break; |
311 |
|
|
} |
312 |
|
|
goto cleanup; |
313 |
|
|
default: |
314 |
|
|
l2tp_ctrl_log(_this, LOG_DEBUG, "%s() unexpected state=%s", |
315 |
|
|
__func__, l2tp_ctrl_state_string(_this)); |
316 |
|
|
/* FALLTHROUGH */ |
317 |
|
|
case L2TP_CTRL_STATE_WAIT_CTL_CONN: |
318 |
|
|
/* FALLTHROUGH */ |
319 |
|
|
case L2TP_CTRL_STATE_CLEANUP_WAIT: |
320 |
|
|
cleanup: |
321 |
|
|
if (slist_length(&_this->call_list) != 0) { |
322 |
|
|
if (l2tp_ctrl_disconnect_all_calls(_this, 1) > 0) |
323 |
|
|
break; |
324 |
|
|
} |
325 |
|
|
#if 0 |
326 |
|
|
if (L2TP_CTRL_CONF(_this)e_ipsec_sa != 0) |
327 |
|
|
l2tp_ctrl_purge_ipsec_sa(_this); |
328 |
|
|
#endif |
329 |
|
|
|
330 |
|
|
l2tp_ctrl_log(_this, LOG_NOTICE, "logtype=Finished"); |
331 |
|
|
|
332 |
|
|
evtimer_del(&_this->ev_timeout); |
333 |
|
|
|
334 |
|
|
/* free send buffer */ |
335 |
|
|
if (_this->snd_buffers != NULL) { |
336 |
|
|
for (i = 0; i < _this->winsz; i++) |
337 |
|
|
bytebuffer_destroy(_this->snd_buffers[i]); |
338 |
|
|
free(_this->snd_buffers); |
339 |
|
|
_this->snd_buffers = NULL; |
340 |
|
|
} |
341 |
|
|
if (_this->zlb_buffer != NULL) { |
342 |
|
|
bytebuffer_destroy(_this->zlb_buffer); |
343 |
|
|
_this->zlb_buffer = NULL; |
344 |
|
|
} |
345 |
|
|
|
346 |
|
|
/* free l2tp_call */ |
347 |
|
|
l2tp_ctrl_destroy_all_calls(_this); |
348 |
|
|
slist_fini(&_this->call_list); |
349 |
|
|
|
350 |
|
|
l2tpd_remove_ctrl(_this->l2tpd, _this->tunnel_id); |
351 |
|
|
|
352 |
|
|
_l2tpd = _this->l2tpd; |
353 |
|
|
l2tp_ctrl_destroy(_this); |
354 |
|
|
|
355 |
|
|
l2tpd_ctrl_finished_notify(_l2tpd); |
356 |
|
|
return 0; /* stopped */ |
357 |
|
|
} |
358 |
|
|
l2tp_ctrl_reset_timeout(_this); |
359 |
|
|
|
360 |
|
|
return 1; |
361 |
|
|
} |
362 |
|
|
|
363 |
|
|
#if 0 |
364 |
|
|
/** Delete the IPsec SA for disconnection */ |
365 |
|
|
static void |
366 |
|
|
l2tp_ctrl_purge_ipsec_sa(l2tp_ctrl *_this) |
367 |
|
|
{ |
368 |
|
|
int is_natt, proto; |
369 |
|
|
struct sockaddr_storage peer, sock; |
370 |
|
|
hash_link *hl; |
371 |
|
|
#ifdef USE_LIBSOCKUTIL |
372 |
|
|
struct in_ipsec_sa_cookie *ipsec_sa_cookie; |
373 |
|
|
#endif |
374 |
|
|
l2tp_ctrl *anot; |
375 |
|
|
|
376 |
|
|
/* |
377 |
|
|
* Search another tunnel that uses the same IPsec SA |
378 |
|
|
* by lineer. |
379 |
|
|
*/ |
380 |
|
|
for (hl = hash_first(_this->l2tpd->ctrl_map); |
381 |
|
|
hl != NULL; hl = hash_next(_this->l2tpd->ctrl_map)) { |
382 |
|
|
anot = hl->item; |
383 |
|
|
if (anot == _this) |
384 |
|
|
continue; |
385 |
|
|
|
386 |
|
|
if (_this->peer.ss_family != anot->peer.ss_family) |
387 |
|
|
continue; |
388 |
|
|
if (_this->peer.ss_family == AF_INET) { |
389 |
|
|
if (SIN(&_this->peer)->sin_addr.s_addr != |
390 |
|
|
SIN(&anot->peer)->sin_addr.s_addr) |
391 |
|
|
continue; |
392 |
|
|
} else if (_this->peer.ss_family == AF_INET6) { |
393 |
|
|
if (!IN6_ARE_ADDR_EQUAL( |
394 |
|
|
&(SIN6(&_this->peer)->sin6_addr), |
395 |
|
|
&(SIN6(&anot->peer)->sin6_addr))) |
396 |
|
|
continue; |
397 |
|
|
} |
398 |
|
|
#ifdef USE_LIBSOCKUTIL |
399 |
|
|
if (_this->sa_cookie != NULL && anot->sa_cookie != NULL) { |
400 |
|
|
/* Both tunnels belong the same NAT box. */ |
401 |
|
|
|
402 |
|
|
if (memcmp(_this->sa_cookie, anot->sa_cookie, |
403 |
|
|
sizeof(struct in_ipsec_sa_cookie)) != 0) |
404 |
|
|
/* Different hosts behind the NAT box. */ |
405 |
|
|
continue; |
406 |
|
|
|
407 |
|
|
/* The SA is shared by another tunnels by one host. */ |
408 |
|
|
return; /* don't purge the sa */ |
409 |
|
|
|
410 |
|
|
} else if (_this->sa_cookie != NULL || anot->sa_cookie != NULL) |
411 |
|
|
/* Only one is behind the NAT */ |
412 |
|
|
continue; |
413 |
|
|
#endif |
414 |
|
|
return; /* don't purge the sa */ |
415 |
|
|
} |
416 |
|
|
|
417 |
|
|
#if defined(USE_LIBSOCKUTIL) && defined(IP_IPSEC_SA_COOKIE) |
418 |
|
|
is_natt = (_this->sa_cookie != NULL)? 1 : 0; |
419 |
|
|
#else |
420 |
|
|
is_natt = 0; |
421 |
|
|
#endif |
422 |
|
|
proto = 0; |
423 |
|
|
memcpy(&peer, &_this->peer, _this->peer.ss_len); |
424 |
|
|
memcpy(&sock, &_this->sock, _this->sock.ss_len); |
425 |
|
|
if (!is_natt) |
426 |
|
|
SIN(&peer)->sin_port = SIN(&sock)->sin_port = 0; |
427 |
|
|
#if defined(USE_LIBSOCKUTIL) && defined(IP_IPSEC_SA_COOKIE) |
428 |
|
|
else { |
429 |
|
|
ipsec_sa_cookie = _this->sa_cookie; |
430 |
|
|
SIN(&peer)->sin_port = ipsec_sa_cookie->remote_port; |
431 |
|
|
SIN(&sock)->sin_port = ipsec_sa_cookie->local_port; |
432 |
|
|
#if 1 |
433 |
|
|
/* |
434 |
|
|
* XXX: As RFC 2367, protocol sould be specified if the port |
435 |
|
|
* XXX: number is non-zero. |
436 |
|
|
*/ |
437 |
|
|
proto = 0; |
438 |
|
|
#else |
439 |
|
|
proto = IPPROTO_UDP; |
440 |
|
|
#endif |
441 |
|
|
} |
442 |
|
|
#endif |
443 |
|
|
if (ipsec_util_purge_transport_sa((struct sockaddr *)&peer, |
444 |
|
|
(struct sockaddr *)&sock, proto, IPSEC_UTIL_DIRECTION_BOTH) != 0) |
445 |
|
|
l2tp_ctrl_log(_this, LOG_NOTICE, "failed to purge IPSec SA"); |
446 |
|
|
} |
447 |
|
|
#endif |
448 |
|
|
|
449 |
|
|
/* timeout processing */ |
450 |
|
|
static void |
451 |
|
|
l2tp_ctrl_timeout(int fd, short evtype, void *ctx) |
452 |
|
|
{ |
453 |
|
|
int next_timeout, need_resend; |
454 |
|
|
time_t curr_time; |
455 |
|
|
l2tp_ctrl *_this; |
456 |
|
|
l2tp_call *call; |
457 |
|
|
|
458 |
|
|
/* |
459 |
|
|
* the timer must be reset, when leave this function. |
460 |
|
|
* MEMO: l2tp_ctrl_stop() will reset the timer in it. |
461 |
|
|
* and please remember that the l2tp_ctrl_stop() may free _this. |
462 |
|
|
*/ |
463 |
|
|
_this = ctx; |
464 |
|
|
L2TP_CTRL_ASSERT(_this != NULL); |
465 |
|
|
|
466 |
|
|
curr_time = get_monosec(); |
467 |
|
|
|
468 |
|
|
next_timeout = 2; |
469 |
|
|
need_resend = 0; |
470 |
|
|
|
471 |
|
|
if (l2tp_ctrl_txwin_size(_this) > 0) { |
472 |
|
|
if (_this->state == L2TP_CTRL_STATE_ESTABLISHED) { |
473 |
|
|
if (_this->hello_wait_ack != 0) { |
474 |
|
|
/* wait Hello reply */ |
475 |
|
|
if (curr_time - _this->hello_io_time >= |
476 |
|
|
_this->hello_timeout) { |
477 |
|
|
l2tp_ctrl_log(_this, LOG_NOTICE, |
478 |
|
|
"timeout waiting ack for hello " |
479 |
|
|
"packets."); |
480 |
|
|
l2tp_ctrl_stop(_this, |
481 |
|
|
L2TP_STOP_CCN_RCODE_GENERAL); |
482 |
|
|
return; |
483 |
|
|
} |
484 |
|
|
} |
485 |
|
|
} else if (curr_time - _this->last_snd_ctrl >= |
486 |
|
|
L2TP_CTRL_CTRL_PKT_TIMEOUT) { |
487 |
|
|
l2tp_ctrl_log(_this, LOG_NOTICE, |
488 |
|
|
"timeout waiting ack for ctrl packets."); |
489 |
|
|
l2tp_ctrl_stop(_this, |
490 |
|
|
L2TP_STOP_CCN_RCODE_GENERAL); |
491 |
|
|
return; |
492 |
|
|
} |
493 |
|
|
need_resend = 1; |
494 |
|
|
} else { |
495 |
|
|
for (slist_itr_first(&_this->call_list); |
496 |
|
|
slist_itr_has_next(&_this->call_list);) { |
497 |
|
|
call = slist_itr_next(&_this->call_list); |
498 |
|
|
if (call->state == L2TP_CALL_STATE_CLEANUP_WAIT) { |
499 |
|
|
l2tp_call_destroy(call, 1); |
500 |
|
|
slist_itr_remove(&_this->call_list); |
501 |
|
|
} |
502 |
|
|
} |
503 |
|
|
} |
504 |
|
|
|
505 |
|
|
switch (_this->state) { |
506 |
|
|
case L2TP_CTRL_STATE_IDLE: |
507 |
|
|
/* |
508 |
|
|
* idle: |
509 |
|
|
* XXX: never happen in current implementation |
510 |
|
|
*/ |
511 |
|
|
l2tp_ctrl_log(_this, LOG_ERR, |
512 |
|
|
"Internal error, timeout on illegal state=idle"); |
513 |
|
|
l2tp_ctrl_stop(_this, L2TP_STOP_CCN_RCODE_GENERAL); |
514 |
|
|
break; |
515 |
|
|
case L2TP_CTRL_STATE_WAIT_CTL_CONN: |
516 |
|
|
/* |
517 |
|
|
* wait-ctrl-conn: |
518 |
|
|
* if there is no ack for SCCRP, the peer will |
519 |
|
|
* resend SCCRQ. however this implementation can |
520 |
|
|
* not recognize that the SCCRQ was resent or not. |
521 |
|
|
* Therefore, never resent from this side. |
522 |
|
|
*/ |
523 |
|
|
need_resend = 0; |
524 |
|
|
break; |
525 |
|
|
case L2TP_CTRL_STATE_ESTABLISHED: |
526 |
|
|
if (slist_length(&_this->call_list) == 0 && |
527 |
|
|
curr_time - _this->last_snd_ctrl >= |
528 |
|
|
L2TP_CTRL_WAIT_CALL_TIMEOUT) { |
529 |
|
|
if (_this->ncalls == 0) |
530 |
|
|
/* fail to receive first call */ |
531 |
|
|
l2tp_ctrl_log(_this, LOG_WARNING, |
532 |
|
|
"timeout waiting call"); |
533 |
|
|
l2tp_ctrl_stop(_this, |
534 |
|
|
L2TP_STOP_CCN_RCODE_GENERAL); |
535 |
|
|
return; |
536 |
|
|
} |
537 |
|
|
if (_this->hello_wait_ack == 0 && _this->hello_interval > 0) { |
538 |
|
|
/* send Hello */ |
539 |
|
|
if (curr_time - _this->hello_interval >= |
540 |
|
|
_this->hello_io_time) { |
541 |
|
|
if (l2tp_ctrl_send_HELLO(_this) == 0) |
542 |
|
|
/* success */ |
543 |
|
|
_this->hello_wait_ack = 1; |
544 |
|
|
_this->hello_io_time = curr_time; |
545 |
|
|
need_resend = 0; |
546 |
|
|
} |
547 |
|
|
} |
548 |
|
|
break; |
549 |
|
|
case L2TP_CTRL_STATE_CLEANUP_WAIT: |
550 |
|
|
if (curr_time - _this->last_snd_ctrl >= |
551 |
|
|
L2TP_CTRL_CLEANUP_WAIT_TIME) { |
552 |
|
|
l2tp_ctrl_log(_this, LOG_NOTICE, |
553 |
|
|
"Cleanup timeout state=%d", _this->state); |
554 |
|
|
l2tp_ctrl_stop(_this, 0); |
555 |
|
|
return; |
556 |
|
|
} |
557 |
|
|
if (_this->active_closing != 0) |
558 |
|
|
l2tp_ctrl_send_disconnect_notify(_this); |
559 |
|
|
break; |
560 |
|
|
default: |
561 |
|
|
l2tp_ctrl_log(_this, LOG_ERR, |
562 |
|
|
"Internal error, timeout on illegal state=%d", |
563 |
|
|
_this->state); |
564 |
|
|
l2tp_ctrl_stop(_this, L2TP_STOP_CCN_RCODE_GENERAL); |
565 |
|
|
return; |
566 |
|
|
} |
567 |
|
|
/* resend if required */ |
568 |
|
|
if (need_resend) |
569 |
|
|
l2tp_ctrl_resend_una_packets(_this); |
570 |
|
|
l2tp_ctrl_reset_timeout(_this); |
571 |
|
|
} |
572 |
|
|
|
573 |
|
|
int |
574 |
|
|
l2tp_ctrl_send(l2tp_ctrl *_this, const void *msg, int len) |
575 |
|
|
{ |
576 |
|
|
int rval; |
577 |
|
|
|
578 |
|
|
#ifdef USE_LIBSOCKUTIL |
579 |
|
|
if (_this->sa_cookie != NULL) |
580 |
|
|
rval = sendfromto_nat_t(LISTENER_SOCK(_this), msg, len, 0, |
581 |
|
|
(struct sockaddr *)&_this->sock, |
582 |
|
|
(struct sockaddr *)&_this->peer, _this->sa_cookie); |
583 |
|
|
else |
584 |
|
|
rval = sendfromto(LISTENER_SOCK(_this), msg, len, 0, |
585 |
|
|
(struct sockaddr *)&_this->sock, |
586 |
|
|
(struct sockaddr *)&_this->peer); |
587 |
|
|
#else |
588 |
|
|
#ifdef USE_SA_COOKIE |
589 |
|
|
if (_this->sa_cookie != NULL) |
590 |
|
|
rval = sendto_nat_t(LISTENER_SOCK(_this), msg, len, 0, |
591 |
|
|
(struct sockaddr *)&_this->peer, _this->peer.ss_len, |
592 |
|
|
_this->sa_cookie); |
593 |
|
|
else |
594 |
|
|
#endif |
595 |
|
|
rval = sendto(LISTENER_SOCK(_this), msg, len, 0, |
596 |
|
|
(struct sockaddr *)&_this->peer, _this->peer.ss_len); |
597 |
|
|
#endif |
598 |
|
|
return rval; |
599 |
|
|
} |
600 |
|
|
|
601 |
|
|
/* resend una packets */ |
602 |
|
|
static int |
603 |
|
|
l2tp_ctrl_resend_una_packets(l2tp_ctrl *_this) |
604 |
|
|
{ |
605 |
|
|
uint16_t seq; |
606 |
|
|
bytebuffer *bytebuf; |
607 |
|
|
struct l2tp_header *header; |
608 |
|
|
int nsend; |
609 |
|
|
|
610 |
|
|
nsend = 0; |
611 |
|
|
for (seq = _this->snd_una; SEQ_LT(seq, _this->snd_nxt); seq++) { |
612 |
|
|
bytebuf = _this->snd_buffers[seq % _this->winsz]; |
613 |
|
|
header = bytebuffer_pointer(bytebuf); |
614 |
|
|
header->nr = htons(_this->rcv_nxt); |
615 |
|
|
#ifdef L2TP_CTRL_DEBUG |
616 |
|
|
if (debuglevel >= 3) { |
617 |
|
|
l2tp_ctrl_log(_this, DEBUG_LEVEL_3, "RESEND seq=%u", |
618 |
|
|
ntohs(header->ns)); |
619 |
|
|
show_hd(debug_get_debugfp(), |
620 |
|
|
bytebuffer_pointer(bytebuf), |
621 |
|
|
bytebuffer_remaining(bytebuf)); |
622 |
|
|
} |
623 |
|
|
#endif |
624 |
|
|
if (l2tp_ctrl_send(_this, bytebuffer_pointer(bytebuf), |
625 |
|
|
bytebuffer_remaining(bytebuf)) < 0) { |
626 |
|
|
l2tp_ctrl_log(_this, LOG_ERR, |
627 |
|
|
"sendto() failed in %s: %m", __func__); |
628 |
|
|
return -1; |
629 |
|
|
} |
630 |
|
|
nsend++; |
631 |
|
|
} |
632 |
|
|
return nsend; |
633 |
|
|
} |
634 |
|
|
|
635 |
|
|
/* free all calls */ |
636 |
|
|
static void |
637 |
|
|
l2tp_ctrl_destroy_all_calls(l2tp_ctrl *_this) |
638 |
|
|
{ |
639 |
|
|
l2tp_call *call; |
640 |
|
|
|
641 |
|
|
L2TP_CTRL_ASSERT(_this != NULL); |
642 |
|
|
|
643 |
|
|
while ((call = slist_remove_first(&_this->call_list)) != NULL) |
644 |
|
|
l2tp_call_destroy(call, 1); |
645 |
|
|
} |
646 |
|
|
|
647 |
|
|
|
648 |
|
|
/* disconnect all calls on the control context |
649 |
|
|
* @return return # of calls that is not waiting cleanup. |
650 |
|
|
*/ |
651 |
|
|
static int |
652 |
|
|
l2tp_ctrl_disconnect_all_calls(l2tp_ctrl *_this, int drop) |
653 |
|
|
{ |
654 |
|
|
int i, len, ncalls; |
655 |
|
|
l2tp_call *call; |
656 |
|
|
|
657 |
|
|
L2TP_CTRL_ASSERT(_this != NULL); |
658 |
|
|
|
659 |
|
|
ncalls = 0; |
660 |
|
|
len = slist_length(&_this->call_list); |
661 |
|
|
for (i = 0; i < len; i++) { |
662 |
|
|
call = slist_get(&_this->call_list, i); |
663 |
|
|
if (call->state != L2TP_CALL_STATE_CLEANUP_WAIT) { |
664 |
|
|
ncalls++; |
665 |
|
|
if (l2tp_ctrl_txwin_is_full(_this)) { |
666 |
|
|
L2TP_CTRL_DBG((_this, LOG_INFO, |
667 |
|
|
"Too many calls. Sending window is not " |
668 |
|
|
"enough to send CDN to all clients.")); |
669 |
|
|
if (drop) |
670 |
|
|
l2tp_call_drop(call); |
671 |
|
|
} else |
672 |
|
|
l2tp_call_admin_disconnect(call); |
673 |
|
|
} |
674 |
|
|
} |
675 |
|
|
return ncalls; |
676 |
|
|
} |
677 |
|
|
|
678 |
|
|
/* reset timeout */ |
679 |
|
|
static void |
680 |
|
|
l2tp_ctrl_reset_timeout(l2tp_ctrl *_this) |
681 |
|
|
{ |
682 |
|
|
int intvl; |
683 |
|
|
struct timeval tv0; |
684 |
|
|
|
685 |
|
|
L2TP_CTRL_ASSERT(_this != NULL); |
686 |
|
|
|
687 |
|
|
if (evtimer_initialized(&_this->ev_timeout)) |
688 |
|
|
evtimer_del(&_this->ev_timeout); |
689 |
|
|
|
690 |
|
|
switch (_this->state) { |
691 |
|
|
case L2TP_CTRL_STATE_CLEANUP_WAIT: |
692 |
|
|
intvl = 1; |
693 |
|
|
break; |
694 |
|
|
default: |
695 |
|
|
intvl = 2; |
696 |
|
|
break; |
697 |
|
|
} |
698 |
|
|
tv0.tv_usec = 0; |
699 |
|
|
tv0.tv_sec = intvl; |
700 |
|
|
if (!evtimer_initialized(&_this->ev_timeout)) |
701 |
|
|
evtimer_set(&_this->ev_timeout, l2tp_ctrl_timeout, _this); |
702 |
|
|
evtimer_add(&_this->ev_timeout, &tv0); |
703 |
|
|
} |
704 |
|
|
|
705 |
|
|
/* |
706 |
|
|
* protocols / send and receive |
707 |
|
|
*/ |
708 |
|
|
/* Receive packet */ |
709 |
|
|
void |
710 |
|
|
l2tp_ctrl_input(l2tpd *_this, int listener_index, struct sockaddr *peer, |
711 |
|
|
struct sockaddr *sock, void *nat_t_ctx, u_char *pkt, int pktlen) |
712 |
|
|
{ |
713 |
|
|
int i, len, offsiz, reqlen, is_ctrl; |
714 |
|
|
uint16_t mestype; |
715 |
|
|
struct l2tp_avp *avp, *avp0; |
716 |
|
|
l2tp_ctrl *ctrl; |
717 |
|
|
l2tp_call *call; |
718 |
|
|
char buf[L2TP_AVP_MAXSIZ], errmsg[256]; |
719 |
|
|
time_t curr_time; |
720 |
|
|
u_char *pkt0; |
721 |
|
|
struct l2tp_header hdr; |
722 |
|
|
char hbuf[NI_MAXHOST + NI_MAXSERV + 16]; |
723 |
|
|
|
724 |
|
|
ctrl = NULL; |
725 |
|
|
curr_time = get_monosec(); |
726 |
|
|
pkt0 = pkt; |
727 |
|
|
|
728 |
|
|
L2TP_CTRL_ASSERT(peer->sa_family == sock->sa_family); |
729 |
|
|
L2TP_CTRL_ASSERT(peer->sa_family == AF_INET || |
730 |
|
|
peer->sa_family == AF_INET6) |
731 |
|
|
/* |
732 |
|
|
* Parse L2TP Header |
733 |
|
|
*/ |
734 |
|
|
memset(&hdr, 0, sizeof(hdr)); |
735 |
|
|
if (pktlen < 2) { |
736 |
|
|
snprintf(errmsg, sizeof(errmsg), "a short packet. " |
737 |
|
|
"length=%d", pktlen); |
738 |
|
|
goto bad_packet; |
739 |
|
|
} |
740 |
|
|
memcpy(&hdr, pkt, 2); |
741 |
|
|
pkt += 2; |
742 |
|
|
if (hdr.ver != L2TP_HEADER_VERSION_RFC2661) { |
743 |
|
|
/* XXX: only RFC2661 is supported */ |
744 |
|
|
snprintf(errmsg, sizeof(errmsg), |
745 |
|
|
"Unsupported version at header = %d", hdr.ver); |
746 |
|
|
goto bad_packet; |
747 |
|
|
} |
748 |
|
|
is_ctrl = (hdr.t != 0)? 1 : 0; |
749 |
|
|
|
750 |
|
|
/* calc required length */ |
751 |
|
|
reqlen = 6; /* for Flags, Tunnel-Id, Session-Id field */ |
752 |
|
|
if (hdr.l) reqlen += 2; /* for Length field (opt) */ |
753 |
|
|
if (hdr.s) reqlen += 4; /* for Ns, Nr field (opt) */ |
754 |
|
|
if (hdr.o) reqlen += 2; /* for Offset Size field (opt) */ |
755 |
|
|
if (reqlen > pktlen) { |
756 |
|
|
snprintf(errmsg, sizeof(errmsg), |
757 |
|
|
"a short packet. length=%d", pktlen); |
758 |
|
|
goto bad_packet; |
759 |
|
|
} |
760 |
|
|
|
761 |
|
|
if (hdr.l != 0) { |
762 |
|
|
GETSHORT(hdr.length, pkt); |
763 |
|
|
if (hdr.length > pktlen) { |
764 |
|
|
snprintf(errmsg, sizeof(errmsg), |
765 |
|
|
"Actual packet size is smaller than the length " |
766 |
|
|
"field %d < %d", pktlen, hdr.length); |
767 |
|
|
goto bad_packet; |
768 |
|
|
} |
769 |
|
|
pktlen = hdr.length; /* remove trailing trash */ |
770 |
|
|
} |
771 |
|
|
GETSHORT(hdr.tunnel_id, pkt); |
772 |
|
|
GETSHORT(hdr.session_id, pkt); |
773 |
|
|
if (hdr.s != 0) { |
774 |
|
|
GETSHORT(hdr.ns, pkt); |
775 |
|
|
GETSHORT(hdr.nr, pkt); |
776 |
|
|
} |
777 |
|
|
if (hdr.o != 0) { |
778 |
|
|
GETSHORT(offsiz, pkt); |
779 |
|
|
if (pktlen < offsiz) { |
780 |
|
|
snprintf(errmsg, sizeof(errmsg), |
781 |
|
|
"offset field is bigger than remaining packet " |
782 |
|
|
"length %d > %d", offsiz, pktlen); |
783 |
|
|
goto bad_packet; |
784 |
|
|
} |
785 |
|
|
pkt += offsiz; |
786 |
|
|
} |
787 |
|
|
L2TP_CTRL_ASSERT(pkt - pkt0 == reqlen); |
788 |
|
|
pktlen -= (pkt - pkt0); /* cut down the length of header */ |
789 |
|
|
|
790 |
|
|
ctrl = NULL; |
791 |
|
|
memset(buf, 0, sizeof(buf)); |
792 |
|
|
mestype = 0; |
793 |
|
|
avp = NULL; |
794 |
|
|
|
795 |
|
|
if (is_ctrl) { |
796 |
|
|
avp0 = (struct l2tp_avp *)buf; |
797 |
|
|
avp = avp_find_message_type_avp(avp0, pkt, pktlen); |
798 |
|
|
if (avp != NULL) |
799 |
|
|
mestype = avp->attr_value[0] << 8 | avp->attr_value[1]; |
800 |
|
|
} |
801 |
|
|
ctrl = l2tpd_get_ctrl(_this, hdr.tunnel_id); |
802 |
|
|
|
803 |
|
|
if (ctrl == NULL) { |
804 |
|
|
/* new control */ |
805 |
|
|
if (!is_ctrl) { |
806 |
|
|
snprintf(errmsg, sizeof(errmsg), |
807 |
|
|
"bad data message: tunnelId=%d is not " |
808 |
|
|
"found.", hdr.tunnel_id); |
809 |
|
|
goto bad_packet; |
810 |
|
|
} |
811 |
|
|
if (mestype != L2TP_AVP_MESSAGE_TYPE_SCCRQ) { |
812 |
|
|
snprintf(errmsg, sizeof(errmsg), |
813 |
|
|
"bad control message: tunnelId=%d is not " |
814 |
|
|
"found. mestype=%s", hdr.tunnel_id, |
815 |
|
|
avp_mes_type_string(mestype)); |
816 |
|
|
goto bad_packet; |
817 |
|
|
} |
818 |
|
|
|
819 |
|
|
if ((ctrl = l2tp_ctrl_create()) == NULL) { |
820 |
|
|
l2tp_ctrl_log(ctrl, LOG_ERR, |
821 |
|
|
"l2tp_ctrl_create() failed: %m"); |
822 |
|
|
goto fail; |
823 |
|
|
} |
824 |
|
|
|
825 |
|
|
if (l2tp_ctrl_init(ctrl, _this, peer, sock, nat_t_ctx) != 0) { |
826 |
|
|
l2tp_ctrl_log(ctrl, LOG_ERR, |
827 |
|
|
"l2tp_ctrl_start() failed: %m"); |
828 |
|
|
goto fail; |
829 |
|
|
} |
830 |
|
|
|
831 |
|
|
ctrl->listener_index = listener_index; |
832 |
|
|
l2tp_ctrl_reload(ctrl); |
833 |
|
|
} else { |
834 |
|
|
/* |
835 |
|
|
* treat as an error if src address and port is not |
836 |
|
|
* match. (because it is potentially DoS attach) |
837 |
|
|
*/ |
838 |
|
|
int notmatch = 0; |
839 |
|
|
|
840 |
|
|
if (ctrl->peer.ss_family != peer->sa_family) |
841 |
|
|
notmatch = 1; |
842 |
|
|
else if (peer->sa_family == AF_INET) { |
843 |
|
|
if (SIN(peer)->sin_addr.s_addr != |
844 |
|
|
SIN(&ctrl->peer)->sin_addr.s_addr || |
845 |
|
|
SIN(peer)->sin_port != SIN(&ctrl->peer)->sin_port) |
846 |
|
|
notmatch = 1; |
847 |
|
|
} else if (peer->sa_family == AF_INET6) { |
848 |
|
|
if (!IN6_ARE_ADDR_EQUAL(&(SIN6(peer)->sin6_addr), |
849 |
|
|
&(SIN6(&ctrl->peer)->sin6_addr)) || |
850 |
|
|
SIN6(peer)->sin6_port != |
851 |
|
|
SIN6(&ctrl->peer)->sin6_port) |
852 |
|
|
notmatch = 1; |
853 |
|
|
} |
854 |
|
|
if (notmatch) { |
855 |
|
|
snprintf(errmsg, sizeof(errmsg), |
856 |
|
|
"tunnelId=%u is already assigned for %s", |
857 |
|
|
hdr.tunnel_id, addrport_tostring( |
858 |
|
|
(struct sockaddr *)&ctrl->peer, |
859 |
|
|
ctrl->peer.ss_len, hbuf, sizeof(hbuf))); |
860 |
|
|
goto bad_packet; |
861 |
|
|
} |
862 |
|
|
} |
863 |
|
|
ctrl->last_rcv = curr_time; |
864 |
|
|
call = NULL; |
865 |
|
|
if (hdr.session_id != 0) { |
866 |
|
|
/* search l2tp_call by Session ID */ |
867 |
|
|
/* linear search is enough for this purpose */ |
868 |
|
|
len = slist_length(&ctrl->call_list); |
869 |
|
|
for (i = 0; i < len; i++) { |
870 |
|
|
call = slist_get(&ctrl->call_list, i); |
871 |
|
|
if (call->session_id == hdr.session_id) |
872 |
|
|
break; |
873 |
|
|
call = NULL; |
874 |
|
|
} |
875 |
|
|
} |
876 |
|
|
if (!is_ctrl) { |
877 |
|
|
int delayed = 0; |
878 |
|
|
|
879 |
|
|
/* L2TP data */ |
880 |
|
|
if (ctrl->state != L2TP_CTRL_STATE_ESTABLISHED) { |
881 |
|
|
l2tp_ctrl_log(ctrl, LOG_WARNING, |
882 |
|
|
"Received Data packet in '%s'", |
883 |
|
|
l2tp_ctrl_state_string(ctrl)); |
884 |
|
|
goto fail; |
885 |
|
|
} |
886 |
|
|
if (call == NULL) { |
887 |
|
|
l2tp_ctrl_log(ctrl, LOG_WARNING, |
888 |
|
|
"Received a data packet but it has no call. " |
889 |
|
|
"session_id=%u", hdr.session_id); |
890 |
|
|
goto fail; |
891 |
|
|
} |
892 |
|
|
L2TP_CTRL_DBG((ctrl, DEBUG_LEVEL_2, |
893 |
|
|
"call=%u RECV ns=%u nr=%u snd_nxt=%u rcv_nxt=%u len=%d", |
894 |
|
|
call->id, hdr.ns, hdr.nr, call->snd_nxt, call->rcv_nxt, |
895 |
|
|
pktlen)); |
896 |
|
|
if (call->state != L2TP_CALL_STATE_ESTABLISHED){ |
897 |
|
|
l2tp_ctrl_log(ctrl, LOG_WARNING, |
898 |
|
|
"Received a data packet but call is not " |
899 |
|
|
"established"); |
900 |
|
|
goto fail; |
901 |
|
|
} |
902 |
|
|
|
903 |
|
|
if (hdr.s != 0) { |
904 |
|
|
if (SEQ_LT(hdr.ns, call->rcv_nxt)) { |
905 |
|
|
if (SEQ_LT(hdr.ns, |
906 |
|
|
call->rcv_nxt - L2TP_CALL_DELAY_LIMIT)) { |
907 |
|
|
/* sequence number seems to be delayed */ |
908 |
|
|
/* XXX: need to log? */ |
909 |
|
|
L2TP_CTRL_DBG((ctrl, LOG_DEBUG, |
910 |
|
|
"receive a out of sequence " |
911 |
|
|
"data packet: %u < %u.", |
912 |
|
|
hdr.ns, call->rcv_nxt)); |
913 |
|
|
return; |
914 |
|
|
} |
915 |
|
|
delayed = 1; |
916 |
|
|
} else { |
917 |
|
|
call->rcv_nxt = hdr.ns + 1; |
918 |
|
|
} |
919 |
|
|
} |
920 |
|
|
|
921 |
|
|
l2tp_call_ppp_input(call, pkt, pktlen, delayed); |
922 |
|
|
|
923 |
|
|
return; |
924 |
|
|
} |
925 |
|
|
if (hdr.s != 0) { |
926 |
|
|
L2TP_CTRL_DBG((ctrl, DEBUG_LEVEL_2, |
927 |
|
|
"RECV %s ns=%u nr=%u snd_nxt=%u snd_una=%u rcv_nxt=%u " |
928 |
|
|
"len=%d", (is_ctrl)? "C" : "", hdr.ns, hdr.nr, |
929 |
|
|
ctrl->snd_nxt, ctrl->snd_una, ctrl->rcv_nxt, pktlen)); |
930 |
|
|
|
931 |
|
|
if (pktlen <= 0) |
932 |
|
|
l2tp_ctrl_log(ctrl, LOG_INFO, "RecvZLB"); |
933 |
|
|
|
934 |
|
|
if (SEQ_GT(hdr.nr, ctrl->snd_una)) { |
935 |
|
|
if (hdr.nr == ctrl->snd_nxt || |
936 |
|
|
SEQ_LT(hdr.nr, ctrl->snd_nxt)) |
937 |
|
|
ctrl->snd_una = hdr.nr; |
938 |
|
|
else { |
939 |
|
|
l2tp_ctrl_log(ctrl, LOG_INFO, |
940 |
|
|
"Received message has bad Nr field: " |
941 |
|
|
"%u < %u.", hdr.ns, ctrl->snd_nxt); |
942 |
|
|
/* XXX Drop with ZLB? */ |
943 |
|
|
goto fail; |
944 |
|
|
} |
945 |
|
|
} |
946 |
|
|
if (l2tp_ctrl_txwin_size(ctrl) <= 0) { |
947 |
|
|
/* no waiting ack */ |
948 |
|
|
if (ctrl->hello_wait_ack != 0) { |
949 |
|
|
/* |
950 |
|
|
* Reset Hello state, as an ack for the Hello |
951 |
|
|
* is recived. |
952 |
|
|
*/ |
953 |
|
|
ctrl->hello_wait_ack = 0; |
954 |
|
|
ctrl->hello_io_time = curr_time; |
955 |
|
|
} |
956 |
|
|
switch (ctrl->state) { |
957 |
|
|
case L2TP_CTRL_STATE_CLEANUP_WAIT: |
958 |
|
|
l2tp_ctrl_stop(ctrl, 0); |
959 |
|
|
return; |
960 |
|
|
} |
961 |
|
|
} |
962 |
|
|
if (hdr.ns != ctrl->rcv_nxt) { |
963 |
|
|
/* there are remaining packet */ |
964 |
|
|
if (l2tp_ctrl_resend_una_packets(ctrl) <= 0) { |
965 |
|
|
/* resend or sent ZLB */ |
966 |
|
|
l2tp_ctrl_send_ZLB(ctrl); |
967 |
|
|
} |
968 |
|
|
#ifdef L2TP_CTRL_DEBUG |
969 |
|
|
if (pktlen != 0) { /* not ZLB */ |
970 |
|
|
L2TP_CTRL_DBG((ctrl, LOG_DEBUG, |
971 |
|
|
"receive out of sequence %u must be %u. " |
972 |
|
|
"mestype=%s", hdr.ns, ctrl->rcv_nxt, |
973 |
|
|
avp_mes_type_string(mestype))); |
974 |
|
|
} |
975 |
|
|
#endif |
976 |
|
|
return; |
977 |
|
|
} |
978 |
|
|
if (pktlen <= 0) |
979 |
|
|
return; /* ZLB */ |
980 |
|
|
|
981 |
|
|
if (l2tp_ctrl_txwin_is_full(ctrl)) { |
982 |
|
|
L2TP_CTRL_DBG((ctrl, LOG_DEBUG, |
983 |
|
|
"Received message cannot be handled. " |
984 |
|
|
"Transmission window is full.")); |
985 |
|
|
l2tp_ctrl_send_ZLB(ctrl); |
986 |
|
|
return; |
987 |
|
|
} |
988 |
|
|
|
989 |
|
|
ctrl->rcv_nxt++; |
990 |
|
|
if (avp == NULL) { |
991 |
|
|
l2tpd_log(_this, LOG_WARNING, |
992 |
|
|
"bad control message: no message-type AVP."); |
993 |
|
|
goto fail; |
994 |
|
|
} |
995 |
|
|
} |
996 |
|
|
|
997 |
|
|
/* |
998 |
|
|
* state machine (RFC2661 pp. 56-57) |
999 |
|
|
*/ |
1000 |
|
|
switch (ctrl->state) { |
1001 |
|
|
case L2TP_CTRL_STATE_IDLE: |
1002 |
|
|
switch (mestype) { |
1003 |
|
|
case L2TP_AVP_MESSAGE_TYPE_SCCRQ: |
1004 |
|
|
if (l2tp_ctrl_recv_SCCRQ(ctrl, pkt, pktlen, _this, |
1005 |
|
|
peer) == 0) { |
1006 |
|
|
/* acceptable */ |
1007 |
|
|
l2tp_ctrl_send_SCCRP(ctrl); |
1008 |
|
|
ctrl->state = L2TP_CTRL_STATE_WAIT_CTL_CONN; |
1009 |
|
|
return; |
1010 |
|
|
} |
1011 |
|
|
/* |
1012 |
|
|
* in case un-acceptable, it was already processed |
1013 |
|
|
* at l2tcp_ctrl_recv_SCCRQ |
1014 |
|
|
*/ |
1015 |
|
|
return; |
1016 |
|
|
case L2TP_AVP_MESSAGE_TYPE_SCCRP: |
1017 |
|
|
/* |
1018 |
|
|
* RFC specifies that sent of StopCCN in the state, |
1019 |
|
|
* However as this implementation only support Passive |
1020 |
|
|
* open, this packet will not received. |
1021 |
|
|
*/ |
1022 |
|
|
/* FALLTHROUGH */ |
1023 |
|
|
case L2TP_AVP_MESSAGE_TYPE_SCCCN: |
1024 |
|
|
default: |
1025 |
|
|
break; |
1026 |
|
|
} |
1027 |
|
|
goto fsm_fail; |
1028 |
|
|
|
1029 |
|
|
case L2TP_CTRL_STATE_WAIT_CTL_CONN: |
1030 |
|
|
/* Wait-Ctl-Conn */ |
1031 |
|
|
switch (mestype) { |
1032 |
|
|
case L2TP_AVP_MESSAGE_TYPE_SCCCN: |
1033 |
|
|
l2tp_ctrl_log(ctrl, LOG_INFO, "RecvSCCN"); |
1034 |
|
|
if (l2tp_ctrl_send_ZLB(ctrl) == 0) { |
1035 |
|
|
ctrl->state = L2TP_CTRL_STATE_ESTABLISHED; |
1036 |
|
|
} |
1037 |
|
|
return; |
1038 |
|
|
case L2TP_AVP_MESSAGE_TYPE_StopCCN: |
1039 |
|
|
goto receive_stop_ccn; |
1040 |
|
|
case L2TP_AVP_MESSAGE_TYPE_SCCRQ: |
1041 |
|
|
case L2TP_AVP_MESSAGE_TYPE_SCCRP: |
1042 |
|
|
default: |
1043 |
|
|
break; |
1044 |
|
|
} |
1045 |
|
|
break; /* fsm_fail */ |
1046 |
|
|
case L2TP_CTRL_STATE_ESTABLISHED: |
1047 |
|
|
/* Established */ |
1048 |
|
|
switch (mestype) { |
1049 |
|
|
case L2TP_AVP_MESSAGE_TYPE_SCCCN: |
1050 |
|
|
case L2TP_AVP_MESSAGE_TYPE_SCCRQ: |
1051 |
|
|
case L2TP_AVP_MESSAGE_TYPE_SCCRP: |
1052 |
|
|
break; |
1053 |
|
|
receive_stop_ccn: |
1054 |
|
|
case L2TP_AVP_MESSAGE_TYPE_StopCCN: |
1055 |
|
|
if (l2tp_ctrl_recv_StopCCN(ctrl, pkt, pktlen) == 0) { |
1056 |
|
|
if (l2tp_ctrl_resend_una_packets(ctrl) <= 0) |
1057 |
|
|
l2tp_ctrl_send_ZLB(ctrl); |
1058 |
|
|
l2tp_ctrl_stop(ctrl, 0); |
1059 |
|
|
return; |
1060 |
|
|
} |
1061 |
|
|
l2tp_ctrl_log(ctrl, LOG_ERR, "Received bad StopCCN"); |
1062 |
|
|
l2tp_ctrl_send_ZLB(ctrl); |
1063 |
|
|
l2tp_ctrl_stop(ctrl, 0); |
1064 |
|
|
return; |
1065 |
|
|
|
1066 |
|
|
case L2TP_AVP_MESSAGE_TYPE_HELLO: |
1067 |
|
|
if (l2tp_ctrl_resend_una_packets(ctrl) <= 0) |
1068 |
|
|
l2tp_ctrl_send_ZLB(ctrl); |
1069 |
|
|
return; |
1070 |
|
|
case L2TP_AVP_MESSAGE_TYPE_CDN: |
1071 |
|
|
case L2TP_AVP_MESSAGE_TYPE_ICRP: |
1072 |
|
|
case L2TP_AVP_MESSAGE_TYPE_ICCN: |
1073 |
|
|
if (call == NULL) { |
1074 |
|
|
l2tp_ctrl_log(ctrl, LOG_INFO, |
1075 |
|
|
"Unknown call message: %s", |
1076 |
|
|
avp_mes_type_string(mestype)); |
1077 |
|
|
goto fail; |
1078 |
|
|
} |
1079 |
|
|
/* FALLTHROUGH */ |
1080 |
|
|
case L2TP_AVP_MESSAGE_TYPE_ICRQ: |
1081 |
|
|
l2tp_call_recv_packet(ctrl, call, mestype, pkt, |
1082 |
|
|
pktlen); |
1083 |
|
|
return; |
1084 |
|
|
default: |
1085 |
|
|
break; |
1086 |
|
|
} |
1087 |
|
|
break; /* fsm_fail */ |
1088 |
|
|
case L2TP_CTRL_STATE_CLEANUP_WAIT: |
1089 |
|
|
if (mestype == L2TP_AVP_MESSAGE_TYPE_StopCCN) { |
1090 |
|
|
/* |
1091 |
|
|
* We left ESTABLISHED state, but the peer sent StopCCN. |
1092 |
|
|
*/ |
1093 |
|
|
goto receive_stop_ccn; |
1094 |
|
|
} |
1095 |
|
|
break; /* fsm_fail */ |
1096 |
|
|
} |
1097 |
|
|
|
1098 |
|
|
fsm_fail: |
1099 |
|
|
/* state machine error */ |
1100 |
|
|
l2tp_ctrl_log(ctrl, LOG_WARNING, "Received %s in '%s' state", |
1101 |
|
|
avp_mes_type_string(mestype), l2tp_ctrl_state_string(ctrl)); |
1102 |
|
|
l2tp_ctrl_stop(ctrl, L2TP_STOP_CCN_RCODE_FSM_ERROR); |
1103 |
|
|
|
1104 |
|
|
return; |
1105 |
|
|
fail: |
1106 |
|
|
if (ctrl != NULL && mestype != 0) { |
1107 |
|
|
l2tp_ctrl_log(ctrl, LOG_WARNING, "Received %s in '%s' state", |
1108 |
|
|
avp_mes_type_string(mestype), l2tp_ctrl_state_string(ctrl)); |
1109 |
|
|
l2tp_ctrl_stop(ctrl, L2TP_STOP_CCN_RCODE_GENERAL_ERROR); |
1110 |
|
|
} |
1111 |
|
|
return; |
1112 |
|
|
|
1113 |
|
|
bad_packet: |
1114 |
|
|
l2tpd_log(_this, LOG_INFO, "Received from=%s: %s", |
1115 |
|
|
addrport_tostring(peer, peer->sa_len, hbuf, sizeof(hbuf)), errmsg); |
1116 |
|
|
|
1117 |
|
|
return; |
1118 |
|
|
} |
1119 |
|
|
|
1120 |
|
|
static inline int |
1121 |
|
|
l2tp_ctrl_txwin_size(l2tp_ctrl *_this) |
1122 |
|
|
{ |
1123 |
|
|
uint16_t sz; |
1124 |
|
|
|
1125 |
|
|
sz = _this->snd_nxt - _this->snd_una; |
1126 |
|
|
|
1127 |
|
|
L2TP_CTRL_ASSERT(sz <= _this->winsz); |
1128 |
|
|
|
1129 |
|
|
return sz; |
1130 |
|
|
} |
1131 |
|
|
|
1132 |
|
|
static inline int |
1133 |
|
|
l2tp_ctrl_txwin_is_full(l2tp_ctrl *_this) |
1134 |
|
|
{ |
1135 |
|
|
return (l2tp_ctrl_txwin_size(_this) >= _this->winsz)? 1 : 0; |
1136 |
|
|
} |
1137 |
|
|
|
1138 |
|
|
/* send control packet */ |
1139 |
|
|
int |
1140 |
|
|
l2tp_ctrl_send_packet(l2tp_ctrl *_this, int call_id, bytebuffer *bytebuf) |
1141 |
|
|
{ |
1142 |
|
|
struct l2tp_header *hdr; |
1143 |
|
|
int rval; |
1144 |
|
|
time_t curr_time; |
1145 |
|
|
|
1146 |
|
|
curr_time = get_monosec(); |
1147 |
|
|
|
1148 |
|
|
bytebuffer_flip(bytebuf); |
1149 |
|
|
hdr = (struct l2tp_header *)bytebuffer_pointer(bytebuf); |
1150 |
|
|
memset(hdr, 0, sizeof(*hdr)); |
1151 |
|
|
|
1152 |
|
|
hdr->t = 1; |
1153 |
|
|
hdr->ver = L2TP_HEADER_VERSION_RFC2661; |
1154 |
|
|
hdr->l = 1; |
1155 |
|
|
hdr->length = htons(bytebuffer_remaining(bytebuf)); |
1156 |
|
|
hdr->tunnel_id = htons(_this->peer_tunnel_id); |
1157 |
|
|
hdr->session_id = htons(call_id); |
1158 |
|
|
|
1159 |
|
|
hdr->s = 1; |
1160 |
|
|
hdr->ns = htons(_this->snd_nxt); |
1161 |
|
|
hdr->nr = htons(_this->rcv_nxt); |
1162 |
|
|
|
1163 |
|
|
if (bytebuffer_remaining(bytebuf) > sizeof(struct l2tp_header)) |
1164 |
|
|
/* Not ZLB */ |
1165 |
|
|
_this->snd_nxt++; |
1166 |
|
|
|
1167 |
|
|
L2TP_CTRL_DBG((_this, DEBUG_LEVEL_2, |
1168 |
|
|
"SEND C ns=%u nr=%u snd_nxt=%u snd_una=%u rcv_nxt=%u ", |
1169 |
|
|
ntohs(hdr->ns), htons(hdr->nr), |
1170 |
|
|
_this->snd_nxt, _this->snd_una, _this->rcv_nxt)); |
1171 |
|
|
|
1172 |
|
|
if (L2TP_CTRL_CONF(_this)->ctrl_out_pktdump != 0) { |
1173 |
|
|
l2tpd_log(_this->l2tpd, LOG_DEBUG, |
1174 |
|
|
"L2TP Control output packet dump"); |
1175 |
|
|
show_hd(debug_get_debugfp(), bytebuffer_pointer(bytebuf), |
1176 |
|
|
bytebuffer_remaining(bytebuf)); |
1177 |
|
|
} |
1178 |
|
|
|
1179 |
|
|
if ((rval = l2tp_ctrl_send(_this, bytebuffer_pointer(bytebuf), |
1180 |
|
|
bytebuffer_remaining(bytebuf))) < 0) { |
1181 |
|
|
L2TP_CTRL_DBG((_this, LOG_DEBUG, "sendto() failed: %m")); |
1182 |
|
|
} |
1183 |
|
|
|
1184 |
|
|
_this->last_snd_ctrl = curr_time; |
1185 |
|
|
|
1186 |
|
|
return (rval == bytebuffer_remaining(bytebuf))? 0 : 1; |
1187 |
|
|
} |
1188 |
|
|
|
1189 |
|
|
/* |
1190 |
|
|
* receiver SCCRQ |
1191 |
|
|
*/ |
1192 |
|
|
static int |
1193 |
|
|
l2tp_ctrl_recv_SCCRQ(l2tp_ctrl *_this, u_char *pkt, int pktlen, l2tpd *_l2tpd, |
1194 |
|
|
struct sockaddr *peer) |
1195 |
|
|
{ |
1196 |
|
|
int avpsz, len, protover, protorev, firmrev, result; |
1197 |
|
|
struct l2tp_avp *avp; |
1198 |
|
|
char host[NI_MAXHOST], serv[NI_MAXSERV]; |
1199 |
|
|
char buf[L2TP_AVP_MAXSIZ], emes[256], hostname[256], vendorname[256]; |
1200 |
|
|
|
1201 |
|
|
result = L2TP_STOP_CCN_RCODE_GENERAL_ERROR; |
1202 |
|
|
strlcpy(hostname, "(no hostname)", sizeof(hostname)); |
1203 |
|
|
strlcpy(vendorname, "(no vendorname)", sizeof(vendorname)); |
1204 |
|
|
|
1205 |
|
|
firmrev = 0; |
1206 |
|
|
protover = 0; |
1207 |
|
|
protorev = 0; |
1208 |
|
|
avp = (struct l2tp_avp *)buf; |
1209 |
|
|
while (pktlen >= 6 && (avpsz = avp_enum(avp, pkt, pktlen, 1)) > 0) { |
1210 |
|
|
pkt += avpsz; |
1211 |
|
|
pktlen -= avpsz; |
1212 |
|
|
if (avp->vendor_id != 0) { |
1213 |
|
|
L2TP_CTRL_DBG((_this, LOG_DEBUG, |
1214 |
|
|
"Received a Vendor-specific AVP vendor-id=%d " |
1215 |
|
|
"type=%d", avp->vendor_id, avp->attr_type)); |
1216 |
|
|
continue; |
1217 |
|
|
} |
1218 |
|
|
switch (avp->attr_type) { |
1219 |
|
|
case L2TP_AVP_TYPE_MESSAGE_TYPE: |
1220 |
|
|
AVP_SIZE_CHECK(avp, ==, 8); |
1221 |
|
|
continue; |
1222 |
|
|
case L2TP_AVP_TYPE_PROTOCOL_VERSION: |
1223 |
|
|
AVP_SIZE_CHECK(avp, ==, 8); |
1224 |
|
|
protover = avp->attr_value[0]; |
1225 |
|
|
protorev = avp->attr_value[1]; |
1226 |
|
|
|
1227 |
|
|
if (protover != L2TP_RFC2661_VERSION || |
1228 |
|
|
protorev != L2TP_RFC2661_REVISION) { |
1229 |
|
|
result = L2TP_STOP_CCN_RCODE_GENERAL_ERROR; |
1230 |
|
|
snprintf(emes, sizeof(emes), |
1231 |
|
|
"Peer's protocol version is not supported:" |
1232 |
|
|
" %d.%d", protover, protorev); |
1233 |
|
|
goto not_acceptable; |
1234 |
|
|
} |
1235 |
|
|
continue; |
1236 |
|
|
case L2TP_AVP_TYPE_FRAMING_CAPABILITIES: |
1237 |
|
|
AVP_SIZE_CHECK(avp, ==, 10); |
1238 |
|
|
if ((avp_get_val32(avp) & L2TP_FRAMING_CAP_FLAGS_SYNC) |
1239 |
|
|
== 0) { |
1240 |
|
|
L2TP_CTRL_DBG((_this, LOG_DEBUG, "Peer doesn't " |
1241 |
|
|
"support synchronous framing")); |
1242 |
|
|
} |
1243 |
|
|
continue; |
1244 |
|
|
case L2TP_AVP_TYPE_BEARER_CAPABILITIES: |
1245 |
|
|
AVP_SIZE_CHECK(avp, ==, 10); |
1246 |
|
|
continue; |
1247 |
|
|
case L2TP_AVP_TYPE_TIE_BREAKER: |
1248 |
|
|
AVP_SIZE_CHECK(avp, ==, 14); |
1249 |
|
|
/* |
1250 |
|
|
* As the implementation never send SCCRQ, |
1251 |
|
|
* the peer is always winner |
1252 |
|
|
*/ |
1253 |
|
|
continue; |
1254 |
|
|
case L2TP_AVP_TYPE_FIRMWARE_REVISION: |
1255 |
|
|
AVP_SIZE_CHECK(avp, >=, 6); |
1256 |
|
|
firmrev = avp_get_val16(avp); |
1257 |
|
|
continue; |
1258 |
|
|
case L2TP_AVP_TYPE_HOST_NAME: |
1259 |
|
|
AVP_SIZE_CHECK(avp, >, 4); |
1260 |
|
|
len = MINIMUM(sizeof(hostname) - 1, avp->length - 6); |
1261 |
|
|
memcpy(hostname, avp->attr_value, len); |
1262 |
|
|
hostname[len] = '\0'; |
1263 |
|
|
continue; |
1264 |
|
|
case L2TP_AVP_TYPE_VENDOR_NAME: |
1265 |
|
|
AVP_SIZE_CHECK(avp, >, 4); |
1266 |
|
|
len = MINIMUM(sizeof(vendorname) - 1, avp->length - 6); |
1267 |
|
|
memcpy(vendorname, avp->attr_value, len); |
1268 |
|
|
vendorname[len] = '\0'; |
1269 |
|
|
continue; |
1270 |
|
|
case L2TP_AVP_TYPE_ASSINGED_TUNNEL_ID: |
1271 |
|
|
AVP_SIZE_CHECK(avp, ==, 8); |
1272 |
|
|
_this->peer_tunnel_id = avp_get_val16(avp); |
1273 |
|
|
continue; |
1274 |
|
|
case L2TP_AVP_TYPE_RECV_WINDOW_SIZE: |
1275 |
|
|
AVP_SIZE_CHECK(avp, ==, 8); |
1276 |
|
|
_this->peer_winsz = avp_get_val16(avp); |
1277 |
|
|
continue; |
1278 |
|
|
} |
1279 |
|
|
if (avp->is_mandatory) { |
1280 |
|
|
l2tp_ctrl_log(_this, LOG_WARNING, |
1281 |
|
|
"Received AVP (%s/%d) is not supported, but it's " |
1282 |
|
|
"mandatory", avp_attr_type_string(avp->attr_type), |
1283 |
|
|
avp->attr_type); |
1284 |
|
|
#ifdef L2TP_CTRL_DEBUG |
1285 |
|
|
} else { |
1286 |
|
|
L2TP_CTRL_DBG((_this, LOG_DEBUG, |
1287 |
|
|
"AVP (%s/%d) is not handled", |
1288 |
|
|
avp_attr_type_string(avp->attr_type), |
1289 |
|
|
avp->attr_type)); |
1290 |
|
|
#endif |
1291 |
|
|
} |
1292 |
|
|
} |
1293 |
|
|
if (getnameinfo((struct sockaddr *)&_this->peer, _this->peer.ss_len, |
1294 |
|
|
host, sizeof(host), serv, sizeof(serv), |
1295 |
|
|
NI_NUMERICHOST | NI_NUMERICSERV | NI_DGRAM) != 0) { |
1296 |
|
|
l2tp_ctrl_log(_this, LOG_ERR, |
1297 |
|
|
"getnameinfo() failed at %s(): %m", __func__); |
1298 |
|
|
strlcpy(host, "error", sizeof(host)); |
1299 |
|
|
strlcpy(serv, "error", sizeof(serv)); |
1300 |
|
|
} |
1301 |
|
|
l2tp_ctrl_log(_this, LOG_NOTICE, "logtype=Started RecvSCCRQ " |
1302 |
|
|
"from=%s:%s/udp tunnel_id=%u/%u protocol=%d.%d winsize=%d " |
1303 |
|
|
"hostname=%s vendor=%s firm=%04X", host, serv, _this->tunnel_id, |
1304 |
|
|
_this->peer_tunnel_id, protover, protorev, _this->peer_winsz, |
1305 |
|
|
hostname, vendorname, firmrev); |
1306 |
|
|
|
1307 |
|
|
return 0; |
1308 |
|
|
not_acceptable: |
1309 |
|
|
size_check_failed: |
1310 |
|
|
l2tp_ctrl_log(_this, LOG_ERR, "Received bad SCCRQ: %s", emes); |
1311 |
|
|
l2tp_ctrl_stop(_this, result); |
1312 |
|
|
|
1313 |
|
|
return 1; |
1314 |
|
|
} |
1315 |
|
|
|
1316 |
|
|
/* |
1317 |
|
|
* send StopCCN |
1318 |
|
|
*/ |
1319 |
|
|
static int |
1320 |
|
|
l2tp_ctrl_send_StopCCN(l2tp_ctrl *_this, int result) |
1321 |
|
|
{ |
1322 |
|
|
struct l2tp_avp *avp; |
1323 |
|
|
char buf[L2TP_AVP_MAXSIZ]; |
1324 |
|
|
bytebuffer *bytebuf; |
1325 |
|
|
|
1326 |
|
|
if ((bytebuf = l2tp_ctrl_prepare_snd_buffer(_this, 1)) == NULL) { |
1327 |
|
|
l2tp_ctrl_log(_this, LOG_ERR, |
1328 |
|
|
"sending StopCCN failed: no buffer."); |
1329 |
|
|
return -1; |
1330 |
|
|
} |
1331 |
|
|
avp = (struct l2tp_avp *)buf; |
1332 |
|
|
|
1333 |
|
|
/* Message Type = StopCCN */ |
1334 |
|
|
memset(avp, 0, sizeof(*avp)); |
1335 |
|
|
avp->is_mandatory = 1; |
1336 |
|
|
avp->attr_type = L2TP_AVP_TYPE_MESSAGE_TYPE; |
1337 |
|
|
avp_set_val16(avp, L2TP_AVP_MESSAGE_TYPE_StopCCN); |
1338 |
|
|
bytebuf_add_avp(bytebuf, avp, 2); |
1339 |
|
|
|
1340 |
|
|
/* Assigned Tunnel Id */ |
1341 |
|
|
memset(avp, 0, sizeof(*avp)); |
1342 |
|
|
avp->is_mandatory = 1; |
1343 |
|
|
avp->attr_type = L2TP_AVP_TYPE_ASSINGED_TUNNEL_ID; |
1344 |
|
|
avp_set_val16(avp, _this->tunnel_id); |
1345 |
|
|
bytebuf_add_avp(bytebuf, avp, 2); |
1346 |
|
|
|
1347 |
|
|
/* Result Code */ |
1348 |
|
|
memset(avp, 0, sizeof(*avp)); |
1349 |
|
|
avp->is_mandatory = 1; |
1350 |
|
|
avp->attr_type = L2TP_AVP_TYPE_RESULT_CODE; |
1351 |
|
|
avp_set_val16(avp, result); |
1352 |
|
|
bytebuf_add_avp(bytebuf, avp, 2); |
1353 |
|
|
|
1354 |
|
|
if (l2tp_ctrl_send_packet(_this, 0, bytebuf) != 0) { |
1355 |
|
|
l2tp_ctrl_log(_this, LOG_ERR, "sending StopCCN failed"); |
1356 |
|
|
return - 1; |
1357 |
|
|
} |
1358 |
|
|
l2tp_ctrl_log(_this, LOG_INFO, "SendStopCCN result=%d", result); |
1359 |
|
|
|
1360 |
|
|
return 0; |
1361 |
|
|
} |
1362 |
|
|
|
1363 |
|
|
/* |
1364 |
|
|
* Receiver StopCCN |
1365 |
|
|
*/ |
1366 |
|
|
static int |
1367 |
|
|
l2tp_ctrl_recv_StopCCN(l2tp_ctrl *_this, u_char *pkt, int pktlen) |
1368 |
|
|
{ |
1369 |
|
|
int result, error, avpsz, len; |
1370 |
|
|
uint16_t tunid; |
1371 |
|
|
struct l2tp_avp *avp; |
1372 |
|
|
char buf[L2TP_AVP_MAXSIZ + 16], emes[256], pmes[256]; |
1373 |
|
|
|
1374 |
|
|
result = 0; |
1375 |
|
|
error = 0; |
1376 |
|
|
tunid = 0; |
1377 |
|
|
pmes[0] = '\0'; |
1378 |
|
|
avp = (struct l2tp_avp *)buf; |
1379 |
|
|
while (pktlen >= 6 && (avpsz = avp_enum(avp, pkt, pktlen, 1)) > 0) { |
1380 |
|
|
pkt += avpsz; |
1381 |
|
|
pktlen -= avpsz; |
1382 |
|
|
if (avp->vendor_id != 0) { |
1383 |
|
|
L2TP_CTRL_DBG((_this, LOG_DEBUG, |
1384 |
|
|
"Received a Vendor-specific AVP vendor-id=%d " |
1385 |
|
|
"type=%d", avp->vendor_id, avp->attr_type)); |
1386 |
|
|
continue; |
1387 |
|
|
} |
1388 |
|
|
if (avp->is_hidden != 0) { |
1389 |
|
|
l2tp_ctrl_log(_this, LOG_WARNING, |
1390 |
|
|
"Received AVP (%s/%d) is hidden. But we don't " |
1391 |
|
|
"share secret.", |
1392 |
|
|
avp_attr_type_string(avp->attr_type), |
1393 |
|
|
avp->attr_type); |
1394 |
|
|
if (avp->is_mandatory != 0) { |
1395 |
|
|
l2tp_ctrl_stop(_this, |
1396 |
|
|
L2TP_STOP_CCN_RCODE_GENERAL_ERROR | |
1397 |
|
|
L2TP_ECODE_UNKNOWN_MANDATORY_AVP); |
1398 |
|
|
return 1; |
1399 |
|
|
} |
1400 |
|
|
continue; |
1401 |
|
|
} |
1402 |
|
|
switch (avp->attr_type) { |
1403 |
|
|
case L2TP_AVP_TYPE_MESSAGE_TYPE: |
1404 |
|
|
AVP_SIZE_CHECK(avp, ==, 8); |
1405 |
|
|
continue; |
1406 |
|
|
case L2TP_AVP_TYPE_RESULT_CODE: |
1407 |
|
|
AVP_SIZE_CHECK(avp, >=, 8); |
1408 |
|
|
result = avp->attr_value[0] << 8 | avp->attr_value[1]; |
1409 |
|
|
if (avp->length >= 10) { |
1410 |
|
|
error = avp->attr_value[2] << 8 | |
1411 |
|
|
avp->attr_value[3]; |
1412 |
|
|
len = avp->length - 12; |
1413 |
|
|
if (len > 0) { |
1414 |
|
|
len = MINIMUM(len, sizeof(pmes) - 1); |
1415 |
|
|
memcpy(pmes, &avp->attr_value[4], len); |
1416 |
|
|
pmes[len] = '\0'; |
1417 |
|
|
} |
1418 |
|
|
} |
1419 |
|
|
continue; |
1420 |
|
|
case L2TP_AVP_TYPE_ASSINGED_TUNNEL_ID: |
1421 |
|
|
AVP_SIZE_CHECK(avp, ==, 8); |
1422 |
|
|
tunid = avp_get_val16(avp); |
1423 |
|
|
continue; |
1424 |
|
|
default: |
1425 |
|
|
if (avp->is_mandatory != 0) { |
1426 |
|
|
l2tp_ctrl_log(_this, LOG_WARNING, |
1427 |
|
|
"Received AVP (%s/%d) is not supported, " |
1428 |
|
|
"but it's mandatory", |
1429 |
|
|
avp_attr_type_string(avp->attr_type), |
1430 |
|
|
avp->attr_type); |
1431 |
|
|
#ifdef L2TP_CTRL_DEBUG |
1432 |
|
|
} else { |
1433 |
|
|
L2TP_CTRL_DBG((_this, LOG_DEBUG, |
1434 |
|
|
"AVP (%s/%d) is not handled", |
1435 |
|
|
avp_attr_type_string(avp->attr_type), |
1436 |
|
|
avp->attr_type)); |
1437 |
|
|
#endif |
1438 |
|
|
} |
1439 |
|
|
} |
1440 |
|
|
} |
1441 |
|
|
|
1442 |
|
|
if (result == L2TP_CDN_RCODE_ERROR_CODE && |
1443 |
|
|
error == L2TP_ECODE_NO_RESOURCE) { |
1444 |
|
|
/* |
1445 |
|
|
* Memo: |
1446 |
|
|
* This state may be happen in following state. |
1447 |
|
|
* - lots of connect/disconect by long-running |
1448 |
|
|
* windows2000, sometimes it fall to this state. |
1449 |
|
|
* Once it fall to here, connection will fail till |
1450 |
|
|
* the windows rebooted |
1451 |
|
|
*/ |
1452 |
|
|
l2tp_ctrl_log(_this, LOG_WARNING, |
1453 |
|
|
"Peer indicates \"No Resource\" error."); |
1454 |
|
|
} |
1455 |
|
|
|
1456 |
|
|
l2tp_ctrl_log(_this, LOG_INFO, "RecvStopCCN result=%s/%u " |
1457 |
|
|
"error=%s/%u tunnel_id=%u message=\"%s\"", |
1458 |
|
|
l2tp_stopccn_rcode_string(result), result, |
1459 |
|
|
l2tp_ecode_string(error), error, tunid, pmes); |
1460 |
|
|
|
1461 |
|
|
return 0; |
1462 |
|
|
|
1463 |
|
|
size_check_failed: |
1464 |
|
|
l2tp_ctrl_log(_this, LOG_ERR, "Received bad StopCCN: %s", emes); |
1465 |
|
|
|
1466 |
|
|
return -1; |
1467 |
|
|
} |
1468 |
|
|
|
1469 |
|
|
/* |
1470 |
|
|
* send SCCRP |
1471 |
|
|
*/ |
1472 |
|
|
static void |
1473 |
|
|
l2tp_ctrl_send_SCCRP(l2tp_ctrl *_this) |
1474 |
|
|
{ |
1475 |
|
|
int len; |
1476 |
|
|
struct l2tp_avp *avp; |
1477 |
|
|
char buf[L2TP_AVP_MAXSIZ], hbuf[HOST_NAME_MAX+1]; |
1478 |
|
|
const char *val; |
1479 |
|
|
bytebuffer *bytebuf; |
1480 |
|
|
|
1481 |
|
|
if ((bytebuf = l2tp_ctrl_prepare_snd_buffer(_this, 1)) == NULL) { |
1482 |
|
|
l2tp_ctrl_log(_this, LOG_ERR, |
1483 |
|
|
"sending SCCRP failed: no buffer."); |
1484 |
|
|
return; |
1485 |
|
|
} |
1486 |
|
|
avp = (struct l2tp_avp *)buf; |
1487 |
|
|
|
1488 |
|
|
/* Message Type = SCCRP */ |
1489 |
|
|
memset(avp, 0, sizeof(*avp)); |
1490 |
|
|
avp->is_mandatory = 1; |
1491 |
|
|
avp->attr_type = L2TP_AVP_TYPE_MESSAGE_TYPE; |
1492 |
|
|
avp_set_val16(avp, L2TP_AVP_MESSAGE_TYPE_SCCRP); |
1493 |
|
|
bytebuf_add_avp(bytebuf, avp, 2); |
1494 |
|
|
|
1495 |
|
|
/* Protocol Version = 1.0 */ |
1496 |
|
|
memset(avp, 0, sizeof(*avp)); |
1497 |
|
|
avp->is_mandatory = 1; |
1498 |
|
|
avp->attr_type = L2TP_AVP_TYPE_PROTOCOL_VERSION; |
1499 |
|
|
avp->attr_value[0] = L2TP_RFC2661_VERSION; |
1500 |
|
|
avp->attr_value[1] = L2TP_RFC2661_REVISION; |
1501 |
|
|
bytebuf_add_avp(bytebuf, avp, 2); |
1502 |
|
|
|
1503 |
|
|
/* Framing Capability = Async */ |
1504 |
|
|
memset(avp, 0, sizeof(*avp)); |
1505 |
|
|
avp->is_mandatory = 1; |
1506 |
|
|
avp->attr_type = L2TP_AVP_TYPE_FRAMING_CAPABILITIES; |
1507 |
|
|
avp_set_val32(avp, L2TP_FRAMING_CAP_FLAGS_SYNC); |
1508 |
|
|
bytebuf_add_avp(bytebuf, avp, 4); |
1509 |
|
|
|
1510 |
|
|
/* Host Name */ |
1511 |
|
|
memset(avp, 0, sizeof(*avp)); |
1512 |
|
|
avp->is_mandatory = 1; |
1513 |
|
|
avp->attr_type = L2TP_AVP_TYPE_HOST_NAME; |
1514 |
|
|
if ((val = L2TP_CTRL_CONF(_this)->hostname) == NULL) { |
1515 |
|
|
gethostname(hbuf, sizeof(hbuf)); |
1516 |
|
|
val = hbuf; |
1517 |
|
|
} |
1518 |
|
|
len = strlen(val); |
1519 |
|
|
memcpy(avp->attr_value, val, len); |
1520 |
|
|
bytebuf_add_avp(bytebuf, avp, len); |
1521 |
|
|
|
1522 |
|
|
/* Assigned Tunnel Id */ |
1523 |
|
|
memset(avp, 0, sizeof(*avp)); |
1524 |
|
|
avp->is_mandatory = 1; |
1525 |
|
|
avp->attr_type = L2TP_AVP_TYPE_ASSINGED_TUNNEL_ID; |
1526 |
|
|
avp_set_val16(avp, _this->tunnel_id); |
1527 |
|
|
bytebuf_add_avp(bytebuf, avp, 2); |
1528 |
|
|
|
1529 |
|
|
/* Bearer Capability |
1530 |
|
|
* This implementation never act as LAC. |
1531 |
|
|
* |
1532 |
|
|
memset(avp, 0, sizeof(*avp)); |
1533 |
|
|
avp->is_mandatory = 1; |
1534 |
|
|
avp->attr_type = L2TP_AVP_TYPE_BEARER_CAPABILITIES; |
1535 |
|
|
avp_set_val32(avp, 0); |
1536 |
|
|
bytebuf_add_avp(bytebuf, avp, 4); |
1537 |
|
|
*/ |
1538 |
|
|
|
1539 |
|
|
/* Firmware Revision */ |
1540 |
|
|
memset(avp, 0, sizeof(*avp)); |
1541 |
|
|
avp->is_mandatory = 0; |
1542 |
|
|
avp->attr_type = L2TP_AVP_TYPE_FIRMWARE_REVISION; |
1543 |
|
|
avp->attr_value[0] = MAJOR_VERSION; |
1544 |
|
|
avp->attr_value[1] = MINOR_VERSION; |
1545 |
|
|
bytebuf_add_avp(bytebuf, avp, 2); |
1546 |
|
|
|
1547 |
|
|
/* Vendor Name */ |
1548 |
|
|
if ((val = L2TP_CTRL_CONF(_this)->vendor_name) != NULL) { |
1549 |
|
|
memset(avp, 0, sizeof(*avp)); |
1550 |
|
|
avp->is_mandatory = 0; |
1551 |
|
|
avp->attr_type = L2TP_AVP_TYPE_VENDOR_NAME; |
1552 |
|
|
|
1553 |
|
|
len = strlen(val); |
1554 |
|
|
memcpy(avp->attr_value, val, len); |
1555 |
|
|
bytebuf_add_avp(bytebuf, avp, len); |
1556 |
|
|
} |
1557 |
|
|
|
1558 |
|
|
/* Window Size */ |
1559 |
|
|
memset(avp, 0, sizeof(*avp)); |
1560 |
|
|
avp->is_mandatory = 1; |
1561 |
|
|
avp->attr_type = L2TP_AVP_TYPE_RECV_WINDOW_SIZE; |
1562 |
|
|
avp_set_val16(avp, _this->winsz); |
1563 |
|
|
bytebuf_add_avp(bytebuf, avp, 2); |
1564 |
|
|
|
1565 |
|
|
if ((l2tp_ctrl_send_packet(_this, 0, bytebuf)) != 0) { |
1566 |
|
|
l2tp_ctrl_log(_this, LOG_ERR, "sending SCCRP failed"); |
1567 |
|
|
l2tp_ctrl_stop(_this, L2TP_STOP_CCN_RCODE_GENERAL); |
1568 |
|
|
return; |
1569 |
|
|
} |
1570 |
|
|
l2tp_ctrl_log(_this, LOG_INFO, "SendSCCRP"); |
1571 |
|
|
} |
1572 |
|
|
|
1573 |
|
|
static int |
1574 |
|
|
l2tp_ctrl_send_HELLO(l2tp_ctrl *_this) |
1575 |
|
|
{ |
1576 |
|
|
struct l2tp_avp *avp; |
1577 |
|
|
char buf[L2TP_AVP_MAXSIZ]; |
1578 |
|
|
bytebuffer *bytebuf; |
1579 |
|
|
|
1580 |
|
|
if ((bytebuf = l2tp_ctrl_prepare_snd_buffer(_this, 1)) == NULL) { |
1581 |
|
|
l2tp_ctrl_log(_this, LOG_ERR, |
1582 |
|
|
"sending SCCRP failed: no buffer."); |
1583 |
|
|
return 1; |
1584 |
|
|
} |
1585 |
|
|
avp = (struct l2tp_avp *)buf; |
1586 |
|
|
|
1587 |
|
|
/* Message Type = HELLO */ |
1588 |
|
|
memset(avp, 0, sizeof(*avp)); |
1589 |
|
|
avp->is_mandatory = 1; |
1590 |
|
|
avp->attr_type = L2TP_AVP_TYPE_MESSAGE_TYPE; |
1591 |
|
|
avp_set_val16(avp, L2TP_AVP_MESSAGE_TYPE_HELLO); |
1592 |
|
|
bytebuf_add_avp(bytebuf, avp, 2); |
1593 |
|
|
|
1594 |
|
|
if ((l2tp_ctrl_send_packet(_this, 0, bytebuf)) != 0) { |
1595 |
|
|
l2tp_ctrl_log(_this, LOG_ERR, "sending HELLO failed"); |
1596 |
|
|
l2tp_ctrl_stop(_this, L2TP_STOP_CCN_RCODE_GENERAL); |
1597 |
|
|
return 1; |
1598 |
|
|
} |
1599 |
|
|
l2tp_ctrl_log(_this, LOG_DEBUG, "SendHELLO"); |
1600 |
|
|
|
1601 |
|
|
return 0; |
1602 |
|
|
} |
1603 |
|
|
|
1604 |
|
|
/* Send ZLB */ |
1605 |
|
|
static int |
1606 |
|
|
l2tp_ctrl_send_ZLB(l2tp_ctrl *_this) |
1607 |
|
|
{ |
1608 |
|
|
int loglevel; |
1609 |
|
|
|
1610 |
|
|
loglevel = (_this->state == L2TP_CTRL_STATE_ESTABLISHED) |
1611 |
|
|
? LOG_DEBUG : LOG_INFO; |
1612 |
|
|
l2tp_ctrl_log(_this, loglevel, "SendZLB"); |
1613 |
|
|
bytebuffer_clear(_this->zlb_buffer); |
1614 |
|
|
bytebuffer_put(_this->zlb_buffer, BYTEBUFFER_PUT_DIRECT, |
1615 |
|
|
sizeof(struct l2tp_header)); |
1616 |
|
|
|
1617 |
|
|
return l2tp_ctrl_send_packet(_this, 0, _this->zlb_buffer); |
1618 |
|
|
} |
1619 |
|
|
|
1620 |
|
|
/* |
1621 |
|
|
* Utitlity |
1622 |
|
|
*/ |
1623 |
|
|
|
1624 |
|
|
/** |
1625 |
|
|
* Prepare send buffer |
1626 |
|
|
* @return return Null when the send buffer exceed Window. |
1627 |
|
|
*/ |
1628 |
|
|
bytebuffer * |
1629 |
|
|
l2tp_ctrl_prepare_snd_buffer(l2tp_ctrl *_this, int with_seq) |
1630 |
|
|
{ |
1631 |
|
|
bytebuffer *bytebuf; |
1632 |
|
|
|
1633 |
|
|
L2TP_CTRL_ASSERT(_this != NULL); |
1634 |
|
|
|
1635 |
|
|
if (l2tp_ctrl_txwin_is_full(_this)) { |
1636 |
|
|
l2tp_ctrl_log(_this, LOG_INFO, "sending buffer is full."); |
1637 |
|
|
return NULL; |
1638 |
|
|
} |
1639 |
|
|
bytebuf = _this->snd_buffers[_this->snd_nxt % _this->winsz]; |
1640 |
|
|
bytebuffer_clear(bytebuf); |
1641 |
|
|
if (with_seq) |
1642 |
|
|
bytebuffer_put(bytebuf, BYTEBUFFER_PUT_DIRECT, |
1643 |
|
|
sizeof(struct l2tp_header)); |
1644 |
|
|
else |
1645 |
|
|
bytebuffer_put(bytebuf, BYTEBUFFER_PUT_DIRECT, |
1646 |
|
|
offsetof(struct l2tp_header, ns)); |
1647 |
|
|
|
1648 |
|
|
return bytebuf; |
1649 |
|
|
} |
1650 |
|
|
|
1651 |
|
|
/** |
1652 |
|
|
* return current state as strings |
1653 |
|
|
*/ |
1654 |
|
|
static inline const char * |
1655 |
|
|
l2tp_ctrl_state_string(l2tp_ctrl *_this) |
1656 |
|
|
{ |
1657 |
|
|
switch (_this->state) { |
1658 |
|
|
case L2TP_CTRL_STATE_IDLE: return "idle"; |
1659 |
|
|
case L2TP_CTRL_STATE_WAIT_CTL_CONN: return "wait-ctl-conn"; |
1660 |
|
|
case L2TP_CTRL_STATE_WAIT_CTL_REPLY: return "wait-ctl-reply"; |
1661 |
|
|
case L2TP_CTRL_STATE_ESTABLISHED: return "established"; |
1662 |
|
|
case L2TP_CTRL_STATE_CLEANUP_WAIT: return "cleanup-wait"; |
1663 |
|
|
} |
1664 |
|
|
return "unknown"; |
1665 |
|
|
} |
1666 |
|
|
|
1667 |
|
|
/* logging with the label of the l2tp instance. */ |
1668 |
|
|
void |
1669 |
|
|
l2tp_ctrl_log(l2tp_ctrl *_this, int prio, const char *fmt, ...) |
1670 |
|
|
{ |
1671 |
|
|
char logbuf[BUFSIZ]; |
1672 |
|
|
va_list ap; |
1673 |
|
|
|
1674 |
|
|
va_start(ap, fmt); |
1675 |
|
|
#ifdef L2TPD_MULTIPLE |
1676 |
|
|
snprintf(logbuf, sizeof(logbuf), "l2tpd id=%u ctrl=%u %s", |
1677 |
|
|
_this->l2tpd->id, _this->id, fmt); |
1678 |
|
|
#else |
1679 |
|
|
snprintf(logbuf, sizeof(logbuf), "l2tpd ctrl=%u %s", _this->id, fmt); |
1680 |
|
|
#endif |
1681 |
|
|
vlog_printf(prio, logbuf, ap); |
1682 |
|
|
va_end(ap); |
1683 |
|
|
} |