File: | src/usr.sbin/npppd/npppd/../l2tp/l2tp_call.c |
Warning: | line 687, column 4 Value stored to 'sessid' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: l2tp_call.c,v 1.20 2021/03/29 03:54:39 yasuoka 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 | /* $Id: l2tp_call.c,v 1.20 2021/03/29 03:54:39 yasuoka Exp $ */ |
29 | /**@file L2TP LNS call */ |
30 | #include <sys/types.h> |
31 | #include <sys/socket.h> |
32 | #include <sys/time.h> |
33 | #include <stdlib.h> |
34 | #include <stddef.h> |
35 | #include <netinet/in.h> |
36 | #include <stdio.h> |
37 | #include <string.h> |
38 | #include <syslog.h> |
39 | #include <stdarg.h> |
40 | #include <unistd.h> |
41 | #include <event.h> |
42 | #include <net/if_dl.h> |
43 | |
44 | #include "debugutil.h" |
45 | #include "bytebuf.h" |
46 | #include "hash.h" |
47 | #include "slist.h" |
48 | #include "l2tp.h" |
49 | #include "l2tp_subr.h" |
50 | |
51 | #include "npppd.h" |
52 | #include "l2tp_local.h" |
53 | |
54 | #ifdef L2TP_CALL_DEBUG |
55 | #define L2TP_CALL_DBG(m) l2tp_call_log m |
56 | #define L2TP_CALL_ASSERT(x) ASSERT(x)((void)0); |
57 | #else |
58 | #define L2TP_CALL_DBG(m) |
59 | #define L2TP_CALL_ASSERT(x) |
60 | #endif |
61 | |
62 | static void l2tp_call_log (l2tp_call *, int, const char *, ...) __printflike(3,4)__attribute__((__format__ (__printf__, 3, 4))); |
63 | static void l2tp_call_disconnect (l2tp_call *, int, int, const char *, struct l2tp_avp *[], int); |
64 | static int l2tp_call_recv_ICRQ (l2tp_call *, u_char *, int); |
65 | static int l2tp_call_send_ICRP (l2tp_call *); |
66 | static int l2tp_call_recv_ICCN (l2tp_call *, u_char *, int, dialin_proxy_info *); |
67 | static int l2tp_recv_CDN (l2tp_call *, u_char *, int); |
68 | static int l2tp_call_send_CDN (l2tp_call *, int, int, const char *, struct l2tp_avp *[], int); |
69 | static int l2tp_call_send_ZLB (l2tp_call *); |
70 | static inline const char *l2tp_call_state_string (l2tp_call *); |
71 | static int l2tp_call_bind_ppp (l2tp_call *, dialin_proxy_info *); |
72 | static void l2tp_call_notify_down (l2tp_call *); |
73 | static int l2tp_call_send_data_packet (l2tp_call *, bytebuffer *); |
74 | |
75 | static int l2tp_call_ppp_output (npppd_ppp *, unsigned char *, int, int); |
76 | static void l2tp_call_closed_by_ppp (npppd_ppp *); |
77 | |
78 | /* create {@link ::_l2tp_call L2TP call} instance */ |
79 | l2tp_call * |
80 | l2tp_call_create(void) |
81 | { |
82 | l2tp_call *_this; |
83 | |
84 | if ((_this = malloc(sizeof(l2tp_call))) == NULL((void*)0)) |
85 | return NULL((void*)0); |
86 | |
87 | return _this; |
88 | } |
89 | |
90 | /* initialize {@link ::_l2tp_call L2TP call} instance */ |
91 | int |
92 | l2tp_call_init(l2tp_call *_this, l2tp_ctrl *ctrl) |
93 | { |
94 | memset(_this, 0, sizeof(l2tp_call)); |
95 | |
96 | _this->ctrl = ctrl; |
97 | if (l2tpd_assign_call(ctrl->l2tpd, _this) != 0) |
98 | return -1; |
99 | |
100 | _this->use_seq = ctrl->data_use_seq; |
101 | |
102 | return 0; |
103 | } |
104 | |
105 | /* free {@link ::_l2tp_call L2TP call} instance */ |
106 | void |
107 | l2tp_call_destroy(l2tp_call *_this, int from_l2tp_ctrl) |
108 | { |
109 | l2tpd_release_call(_this->ctrl->l2tpd, _this); |
110 | free(_this); |
111 | } |
112 | |
113 | /* |
114 | * l2tp disconnect will occur when |
115 | * 1) disconnect request issued from nppdctl command |
116 | * 2) npppd is terminated |
117 | * in case 1) ppp_stop() is used to terminal. (PPP LCP TermReq) |
118 | * and in case 2) l2tp_call_disconnect() is used (L2TP CDN) |
119 | */ |
120 | /* administrative reason disconnection */ |
121 | void |
122 | l2tp_call_admin_disconnect(l2tp_call *_this) |
123 | { |
124 | l2tp_call_disconnect(_this, L2TP_CDN_RCODE_ADMINISTRATIVE_REASON3, 0, |
125 | NULL((void*)0), NULL((void*)0), 0); |
126 | } |
127 | |
128 | void |
129 | l2tp_call_drop(l2tp_call *_this) |
130 | { |
131 | l2tp_call_disconnect(_this, 0, 0, NULL((void*)0), NULL((void*)0), 0); |
132 | } |
133 | |
134 | /* |
135 | * disconnect l2tp connection |
136 | * @param result_code disconnect without CDN, specify zero |
137 | */ |
138 | static void |
139 | l2tp_call_disconnect(l2tp_call *_this, int result_code, int error_code, |
140 | const char *errmes, struct l2tp_avp *addavp[], int naddavp) |
141 | { |
142 | L2TP_CALL_ASSERT(_this != NULL); |
143 | |
144 | if (_this->state == L2TP_CALL_STATE_CLEANUP_WAIT3) { |
145 | /* CDN received, or have been sent */ |
146 | l2tp_call_notify_down(_this); /* just in case */ |
147 | return; |
148 | } |
149 | if (result_code > 0) { |
150 | if (l2tp_call_send_CDN(_this, result_code, error_code, errmes, |
151 | addavp, naddavp) |
152 | != 0) |
153 | l2tp_call_log(_this, LOG_ERR3, "Error sending CDN: %m"); |
154 | } |
155 | _this->state = L2TP_CALL_STATE_CLEANUP_WAIT3; |
156 | l2tp_call_notify_down(_this); |
157 | } |
158 | |
159 | /* |
160 | * control packet |
161 | */ |
162 | |
163 | /* call it when control packet is received */ |
164 | int |
165 | l2tp_call_recv_packet(l2tp_ctrl *ctrl, l2tp_call *_this, int mestype, |
166 | u_char *pkt, int pktlen) |
167 | { |
168 | int i, len, session_id, send_cdn; |
169 | l2tp_call *call; |
170 | dialin_proxy_info dpi; |
171 | |
172 | /* when ICRQ, this will be NULL */ |
173 | L2TP_CALL_ASSERT(_this != NULL || |
174 | mestype == L2TP_AVP_MESSAGE_TYPE_ICRQ); |
175 | |
176 | if (_this == NULL((void*)0)) { |
177 | if (mestype != L2TP_AVP_MESSAGE_TYPE_ICRQ10) |
178 | return 1; |
179 | if ((_this = l2tp_call_create()) == NULL((void*)0)) { |
180 | l2tp_ctrl_log(ctrl, LOG_ERR3, |
181 | "l2tp_call_create failed in %s(): %m", __func__); |
182 | return 1; |
183 | } |
184 | l2tp_call_init(_this, ctrl); |
185 | |
186 | if (l2tp_call_recv_ICRQ(_this, pkt, pktlen) != 0) |
187 | return 1; |
188 | |
189 | len = slist_length(&ctrl->call_list); |
190 | session_id = _this->id; |
191 | again: |
192 | /* assign a session ID */ |
193 | session_id &= 0xffff; |
194 | if (session_id == 0) |
195 | session_id = 1; |
196 | for (i = 0; i < len; i++) { |
197 | call = slist_get(&ctrl->call_list, i); |
198 | if (call->session_id == session_id) { |
199 | session_id++; |
200 | goto again; |
201 | } |
202 | } |
203 | _this->session_id = session_id; |
204 | |
205 | /* add the l2tp_call to call list */ |
206 | slist_add(&_this->ctrl->call_list, _this); |
207 | |
208 | if (l2tp_call_send_ICRP(_this) != 0) |
209 | return 1; |
210 | _this->state = L2TP_CALL_STATE_WAIT_CONN1; |
211 | return 0; |
212 | } |
213 | |
214 | /* state machine */ |
215 | send_cdn = 0; |
216 | switch (_this->state) { |
217 | default: |
218 | break; |
219 | case L2TP_CALL_STATE_WAIT_CONN1: |
220 | switch (mestype) { |
221 | case L2TP_AVP_MESSAGE_TYPE_ICCN12: |
222 | memset(&dpi, 0, sizeof(dpi)); |
223 | if (l2tp_call_recv_ICCN(_this, pkt, pktlen, &dpi) != 0) |
224 | return 1; |
225 | l2tp_call_bind_ppp(_this, &dpi); |
226 | l2tp_call_send_ZLB(_this); |
227 | _this->state = L2TP_CALL_STATE_ESTABLISHED2; |
228 | _this->ctrl->ncalls++; |
229 | return 0; |
230 | case L2TP_AVP_MESSAGE_TYPE_ICRQ10: |
231 | case L2TP_AVP_MESSAGE_TYPE_ICRP11: |
232 | send_cdn = 1; |
233 | /* FALLTHROUGH */ |
234 | default: |
235 | l2tp_call_log(_this, LOG_ERR3, |
236 | "Waiting ICCN. But received %s", |
237 | avp_mes_type_string(mestype)); |
238 | if (send_cdn) { |
239 | l2tp_call_disconnect(_this, |
240 | L2TP_CDN_RCODE_ERROR_CODE2, |
241 | L2TP_ECODE_GENERIC_ERROR6, "Illegal state.", |
242 | NULL((void*)0), 0); |
243 | return 0; |
244 | } |
245 | } |
246 | break; |
247 | case L2TP_CALL_STATE_ESTABLISHED2: |
248 | switch (mestype) { |
249 | case L2TP_AVP_MESSAGE_TYPE_CDN14: |
250 | /* disconnect from peer. log it */ |
251 | l2tp_recv_CDN(_this, pkt, pktlen); |
252 | _this->state = L2TP_CALL_STATE_CLEANUP_WAIT3; |
253 | l2tp_call_notify_down(_this); |
254 | l2tp_call_send_ZLB(_this); |
255 | return 0; |
256 | case L2TP_AVP_MESSAGE_TYPE_ICRQ10: |
257 | case L2TP_AVP_MESSAGE_TYPE_ICRP11: |
258 | case L2TP_AVP_MESSAGE_TYPE_ICCN12: |
259 | send_cdn = 1; |
260 | break; |
261 | default: |
262 | break; |
263 | } |
264 | l2tp_call_log(_this, LOG_ERR3, |
265 | "Call established. But received %s", |
266 | avp_mes_type_string(mestype)); |
267 | if (send_cdn) { |
268 | l2tp_call_disconnect(_this, |
269 | L2TP_CDN_RCODE_ERROR_CODE2, |
270 | L2TP_ECODE_GENERIC_ERROR6, "Illegal state.", |
271 | NULL((void*)0), 0); |
272 | return 0; |
273 | } |
274 | l2tp_call_disconnect(_this, 0, 0, NULL((void*)0), NULL((void*)0), 0); |
275 | return 1; |
276 | } |
277 | l2tp_call_log(_this, LOG_INFO6, "Received %s in unexpected state=%s", |
278 | avp_mes_type_string(mestype), l2tp_call_state_string(_this)); |
279 | l2tp_call_disconnect(_this, 0, 0, NULL((void*)0), NULL((void*)0), 0); |
280 | return 1; |
281 | } |
282 | /* |
283 | * receive ICRQ |
284 | * @return return 0 if the ICRQ is acceptable. |
285 | * other values means fail to receive, and |
286 | * CDN was sent and status was updated. |
287 | */ |
288 | static int |
289 | l2tp_call_recv_ICRQ(l2tp_call *_this, u_char *pkt, int pktlen) |
290 | { |
291 | int avpsz, slen; |
292 | struct l2tp_avp *avp; |
293 | char buf[L2TP_AVP_MAXSIZ1024], emes[256]; |
294 | |
295 | avp = (struct l2tp_avp *)buf; |
296 | while (pktlen >= 6 && (avpsz = avp_enum(avp, pkt, pktlen, 1)) > 0) { |
297 | pkt += avpsz; |
298 | pktlen -= avpsz; |
299 | if (avp->vendor_id != 0) { |
300 | L2TP_CALL_DBG((_this, LOG_DEBUG, |
301 | "Received a Vendor-specific AVP vendor-id=%d " |
302 | "type=%d", avp->vendor_id, avp->attr_type)); |
303 | continue; |
304 | } |
305 | if (avp->is_hidden != 0) { |
306 | l2tp_call_log(_this, LOG_WARNING4, |
307 | "Received AVP (%s/%d) is hidden. But we don't " |
308 | "share secret.", |
309 | avp_attr_type_string(avp->attr_type), |
310 | avp->attr_type); |
311 | if (avp->is_mandatory != 0) { |
312 | l2tp_call_disconnect(_this, |
313 | L2TP_CDN_RCODE_ERROR_CODE2, |
314 | L2TP_ECODE_UNKNOWN_MANDATORY_AVP8, NULL((void*)0), |
315 | NULL((void*)0), 0); |
316 | return 1; |
317 | } |
318 | continue; |
319 | } |
320 | switch (avp->attr_type) { |
321 | case L2TP_AVP_TYPE_MESSAGE_TYPE0: |
322 | AVP_SIZE_CHECK(avp, ==, 8)do { if (!((avp)->length == (8))) { snprintf(emes, sizeof( emes), "invalid packet size %s %d" "==" "%d)", avp_attr_type_string ((avp)->attr_type), (avp)->length, (8)); goto size_check_failed ; } } while ( 0); |
323 | continue; |
324 | case L2TP_AVP_TYPE_ASSIGNED_SESSION_ID14: |
325 | AVP_SIZE_CHECK(avp, ==, 8)do { if (!((avp)->length == (8))) { snprintf(emes, sizeof( emes), "invalid packet size %s %d" "==" "%d)", avp_attr_type_string ((avp)->attr_type), (avp)->length, (8)); goto size_check_failed ; } } while ( 0); |
326 | _this->peer_session_id = avp_get_val16(avp); |
327 | continue; |
328 | case L2TP_AVP_TYPE_CALL_SERIAL_NUMBER15: |
329 | case L2TP_AVP_TYPE_BEARER_TYPE18: |
330 | case L2TP_AVP_TYPE_PHYSICAL_CHANNEL_ID25: |
331 | /* |
332 | * Memo: |
333 | * Microsoft "L2TP/IPsec VPN Client" for |
334 | * Windows 98/Me/NT asserts mandatory bit in |
335 | * Physical Channel Id |
336 | */ |
337 | break; |
338 | case L2TP_AVP_TYPE_CALLING_NUMBER22: |
339 | slen = MINIMUM(sizeof(_this->calling_number) - 1,(((sizeof(_this->calling_number) - 1) < (((avp)->length - 6))) ? (sizeof(_this->calling_number) - 1) : (((avp)-> length - 6))) |
340 | avp_attr_length(avp))(((sizeof(_this->calling_number) - 1) < (((avp)->length - 6))) ? (sizeof(_this->calling_number) - 1) : (((avp)-> length - 6))); |
341 | memcpy(_this->calling_number, avp->attr_value, slen); |
342 | _this->calling_number[slen] = '\0'; |
343 | break; |
344 | case L2TP_AVP_TYPE_CALLED_NUMBER21: |
345 | case L2TP_AVP_TYPE_SUB_ADDRESS23: |
346 | continue; |
347 | default: |
348 | if (avp->is_mandatory) { |
349 | l2tp_call_log(_this, LOG_WARNING4, |
350 | "AVP (%s/%d) is not supported, but it's " |
351 | "mandatory", |
352 | avp_attr_type_string(avp->attr_type), |
353 | avp->attr_type); |
354 | if (avp->is_mandatory != 0) { |
355 | l2tp_call_disconnect(_this, |
356 | L2TP_CDN_RCODE_ERROR_CODE2, |
357 | L2TP_ECODE_UNKNOWN_MANDATORY_AVP8, |
358 | NULL((void*)0), NULL((void*)0), 0); |
359 | return 1; |
360 | } |
361 | #ifdef L2TP_CALL_DEBUG |
362 | } else { |
363 | L2TP_CALL_DBG((_this, LOG_DEBUG, |
364 | "AVP (%s/%d) is not handled", |
365 | avp_attr_type_string(avp->attr_type), |
366 | avp->attr_type)); |
367 | #endif |
368 | } |
369 | } |
370 | } |
371 | if (_this->peer_session_id == 0) { |
372 | l2tp_call_log(_this, LOG_ERR3, |
373 | "Received a bad ICRP: SessionId = 0"); |
374 | l2tp_call_disconnect(_this, L2TP_CDN_RCODE_ERROR_CODE2, |
375 | L2TP_ECODE_INVALID_MESSAGE3, "Session Id must not be 0", |
376 | NULL((void*)0), 0); |
377 | return 1; |
378 | } |
379 | l2tp_call_log(_this, LOG_INFO6, "RecvICRQ session_id=%u", |
380 | _this->peer_session_id); |
381 | |
382 | return 0; |
383 | size_check_failed: |
384 | l2tp_call_log(_this, LOG_ERR3, "Received bad ICRQ: %s", emes); |
385 | l2tp_call_disconnect(_this, L2TP_CDN_RCODE_ERROR_CODE2, |
386 | L2TP_ECODE_WRONG_LENGTH2, NULL((void*)0), NULL((void*)0), 0); |
387 | |
388 | return 1; |
389 | } |
390 | |
391 | /* send ICRP */ |
392 | static int |
393 | l2tp_call_send_ICRP(l2tp_call *_this) |
394 | { |
395 | int rval; |
396 | struct l2tp_avp *avp; |
397 | char buf[L2TP_AVP_MAXSIZ1024]; |
398 | bytebuffer *bytebuf; |
399 | |
400 | bytebuf = l2tp_ctrl_prepare_snd_buffer(_this->ctrl, 1); |
401 | if (bytebuf == NULL((void*)0)) { |
402 | l2tp_call_log(_this, LOG_ERR3, "sending ICRP failed: no buffer"); |
403 | return 1; |
404 | } |
405 | avp = (struct l2tp_avp *)buf; |
406 | |
407 | /* Message Type = ICRP */ |
408 | memset(avp, 0, sizeof(*avp)); |
409 | avp->is_mandatory = 1; |
410 | avp->attr_type = L2TP_AVP_TYPE_MESSAGE_TYPE0; |
411 | avp_set_val16(avp, L2TP_AVP_MESSAGE_TYPE_ICRP11); |
412 | bytebuf_add_avp(bytebuf, avp, 2); |
413 | |
414 | memset(avp, 0, sizeof(*avp)); |
415 | avp->is_mandatory = 1; |
416 | avp->attr_type = L2TP_AVP_TYPE_ASSIGNED_SESSION_ID14; |
417 | avp_set_val16(avp, _this->session_id); |
418 | bytebuf_add_avp(bytebuf, avp, 2); |
419 | |
420 | if ((rval = l2tp_ctrl_send_packet(_this->ctrl, _this->peer_session_id, |
421 | bytebuf)) != 0) { |
422 | l2tp_call_log(_this, LOG_ERR3, "failed to SendICRP: %m"); |
423 | return 1; |
424 | } |
425 | l2tp_call_log(_this, LOG_INFO6, "SendICRP session_id=%u", |
426 | _this->session_id); |
427 | return 0; |
428 | } |
429 | |
430 | /* send L2TP data message */ |
431 | static int |
432 | l2tp_call_send_data_packet(l2tp_call *_this, bytebuffer *buffer) |
433 | { |
434 | int rval; |
435 | struct l2tp_header *hdr; |
436 | |
437 | bytebuffer_flip(buffer); |
438 | hdr = (struct l2tp_header *)bytebuffer_pointer(buffer); |
439 | memset(hdr, 0, sizeof(*hdr) - 4); /* Nr, NS are option */ |
440 | |
441 | hdr->t = 0; |
442 | hdr->ver = L2TP_HEADER_VERSION_RFC26610x02; |
443 | hdr->l = 1; |
444 | hdr->length = htons(bytebuffer_remaining(buffer))(__uint16_t)(__builtin_constant_p(bytebuffer_remaining(buffer )) ? (__uint16_t)(((__uint16_t)(bytebuffer_remaining(buffer)) & 0xffU) << 8 | ((__uint16_t)(bytebuffer_remaining (buffer)) & 0xff00U) >> 8) : __swap16md(bytebuffer_remaining (buffer))); |
445 | hdr->tunnel_id = htons(_this->ctrl->peer_tunnel_id)(__uint16_t)(__builtin_constant_p(_this->ctrl->peer_tunnel_id ) ? (__uint16_t)(((__uint16_t)(_this->ctrl->peer_tunnel_id ) & 0xffU) << 8 | ((__uint16_t)(_this->ctrl-> peer_tunnel_id) & 0xff00U) >> 8) : __swap16md(_this ->ctrl->peer_tunnel_id)); |
446 | hdr->session_id = htons(_this->peer_session_id)(__uint16_t)(__builtin_constant_p(_this->peer_session_id) ? (__uint16_t)(((__uint16_t)(_this->peer_session_id) & 0xffU ) << 8 | ((__uint16_t)(_this->peer_session_id) & 0xff00U) >> 8) : __swap16md(_this->peer_session_id) ); |
447 | if (_this->use_seq) { |
448 | hdr->s = 1; |
449 | hdr->ns = htons(_this->snd_nxt++)(__uint16_t)(__builtin_constant_p(_this->snd_nxt++) ? (__uint16_t )(((__uint16_t)(_this->snd_nxt++) & 0xffU) << 8 | ((__uint16_t)(_this->snd_nxt++) & 0xff00U) >> 8 ) : __swap16md(_this->snd_nxt++)); |
450 | hdr->nr = htons(_this->rcv_nxt)(__uint16_t)(__builtin_constant_p(_this->rcv_nxt) ? (__uint16_t )(((__uint16_t)(_this->rcv_nxt) & 0xffU) << 8 | ( (__uint16_t)(_this->rcv_nxt) & 0xff00U) >> 8) : __swap16md (_this->rcv_nxt)); |
451 | } |
452 | |
453 | if (L2TP_CTRL_CONF(_this->ctrl)((l2tpd_listener *)slist_get(&(_this->ctrl)->l2tpd-> listener, (_this->ctrl)->listener_index))->conf->data_out_pktdump != 0) { |
454 | l2tpd_log(_this->ctrl->l2tpd, LOG_DEBUG7, |
455 | "ctrl=%u call=%u L2TP Data output packet dump", |
456 | _this->ctrl->id, _this->id); |
457 | show_hd(debug_get_debugfp(), bytebuffer_pointer(buffer), |
458 | bytebuffer_remaining(buffer)); |
459 | } |
460 | if ((rval = l2tp_ctrl_send(_this->ctrl, bytebuffer_pointer(buffer), |
461 | bytebuffer_remaining(buffer))) < 0) { |
462 | L2TP_CALL_DBG((_this, LOG_DEBUG, "sendto() failed: %m")); |
463 | } |
464 | |
465 | return (rval == bytebuffer_remaining(buffer))? 0 : 1; |
466 | } |
467 | |
468 | /* |
469 | * receive ICCN |
470 | * @return return 0 if the ICCN is acceptable. |
471 | * other value means fail to receive, and |
472 | * CDN was sent and status was updated. |
473 | */ |
474 | static int |
475 | l2tp_call_recv_ICCN(l2tp_call *_this, u_char *pkt, int pktlen, |
476 | dialin_proxy_info *dpi) |
477 | { |
478 | int avpsz, tx_conn_speed; |
479 | uint32_t framing_type = 0; |
480 | struct l2tp_avp *avp; |
481 | char buf[L2TP_AVP_MAXSIZ1024], emes[256]; |
482 | |
483 | tx_conn_speed = 0; |
484 | avp = (struct l2tp_avp *)buf; |
485 | while (pktlen >= 6 && (avpsz = avp_enum(avp, pkt, pktlen, 1)) > 0) { |
486 | pkt += avpsz; |
487 | pktlen -= avpsz; |
488 | if (avp->vendor_id != 0) { |
489 | L2TP_CALL_DBG((_this, LOG_DEBUG, |
490 | "Received a Vendor-specific AVP vendor-id=%d " |
491 | "type=%d", avp->vendor_id, avp->attr_type)); |
492 | continue; |
493 | } |
494 | if (avp->is_hidden != 0) { |
495 | l2tp_call_log(_this, LOG_WARNING4, |
496 | "Received AVP (%s/%d) is hidden. But we don't " |
497 | "share secret.", |
498 | avp_attr_type_string(avp->attr_type), |
499 | avp->attr_type); |
500 | if (avp->is_mandatory != 0) { |
501 | l2tp_call_disconnect(_this, |
502 | L2TP_CDN_RCODE_ERROR_CODE2, |
503 | L2TP_ECODE_UNKNOWN_MANDATORY_AVP8, NULL((void*)0), |
504 | NULL((void*)0), 0); |
505 | return 1; |
506 | } |
507 | continue; |
508 | } |
509 | switch (avp->attr_type) { |
510 | case L2TP_AVP_TYPE_MESSAGE_TYPE0: |
511 | AVP_SIZE_CHECK(avp, ==, 8)do { if (!((avp)->length == (8))) { snprintf(emes, sizeof( emes), "invalid packet size %s %d" "==" "%d)", avp_attr_type_string ((avp)->attr_type), (avp)->length, (8)); goto size_check_failed ; } } while ( 0); |
512 | continue; |
513 | case L2TP_AVP_TYPE_RX_CONNECT_SPEED38: |
514 | /* |
515 | * As RFC 2661 this AVP is not mandatory. But `xl2tpd' |
516 | * sends this as a mandatory AVP. Handle this to |
517 | * ignore the xl2tpd' bug. |
518 | */ |
519 | AVP_SIZE_CHECK(avp, ==, 10)do { if (!((avp)->length == (10))) { snprintf(emes, sizeof (emes), "invalid packet size %s %d" "==" "%d)", avp_attr_type_string ((avp)->attr_type), (avp)->length, (10)); goto size_check_failed ; } } while ( 0); |
520 | continue; |
521 | case L2TP_AVP_TYPE_TX_CONNECT_SPEED24: |
522 | AVP_SIZE_CHECK(avp, ==, 10)do { if (!((avp)->length == (10))) { snprintf(emes, sizeof (emes), "invalid packet size %s %d" "==" "%d)", avp_attr_type_string ((avp)->attr_type), (avp)->length, (10)); goto size_check_failed ; } } while ( 0); |
523 | tx_conn_speed = avp_get_val32(avp); |
524 | continue; |
525 | case L2TP_AVP_TYPE_FRAMING_TYPE19: |
526 | AVP_SIZE_CHECK(avp, ==, 10)do { if (!((avp)->length == (10))) { snprintf(emes, sizeof (emes), "invalid packet size %s %d" "==" "%d)", avp_attr_type_string ((avp)->attr_type), (avp)->length, (10)); goto size_check_failed ; } } while ( 0); |
527 | framing_type = avp_get_val32(avp); |
528 | continue; |
529 | case L2TP_AVP_TYPE_SEQUENCING_REQUIRED39: |
530 | _this->seq_required = 1; |
531 | _this->use_seq = 1; |
532 | continue; |
533 | /* |
534 | * AVP's for Proxy-LCP and Proxy-Authen |
535 | */ |
536 | case L2TP_AVP_TYPE_LAST_SENT_LCP_CONFREQ27: |
537 | AVP_MAXLEN_CHECK(avp, sizeof(dpi->last_sent_lcp.data))do { if ((avp)->length > (sizeof(dpi->last_sent_lcp. data)) + 6) { snprintf(emes, sizeof(emes), "Attribute value is too long %s %d > %d" , avp_attr_type_string((avp)->attr_type), (avp)->length - 6, (int)(sizeof(dpi->last_sent_lcp.data))); goto size_check_failed ; } } while ( 0); |
538 | memcpy(dpi->last_sent_lcp.data, avp->attr_value, |
539 | avp_attr_length(avp)((avp)->length - 6)); |
540 | dpi->last_sent_lcp.ldata = avp_attr_length(avp)((avp)->length - 6); |
541 | break; |
542 | case L2TP_AVP_TYPE_LAST_RECV_LCP_CONFREQ28: |
543 | AVP_MAXLEN_CHECK(avp, sizeof(dpi->last_recv_lcp.data))do { if ((avp)->length > (sizeof(dpi->last_recv_lcp. data)) + 6) { snprintf(emes, sizeof(emes), "Attribute value is too long %s %d > %d" , avp_attr_type_string((avp)->attr_type), (avp)->length - 6, (int)(sizeof(dpi->last_recv_lcp.data))); goto size_check_failed ; } } while ( 0); |
544 | memcpy(dpi->last_recv_lcp.data, avp->attr_value, |
545 | avp_attr_length(avp)((avp)->length - 6)); |
546 | dpi->last_recv_lcp.ldata = avp_attr_length(avp)((avp)->length - 6); |
547 | break; |
548 | case L2TP_AVP_TYPE_PROXY_AUTHEN_CHALLENGE31: |
549 | AVP_MAXLEN_CHECK(avp, sizeof(dpi->auth_chall))do { if ((avp)->length > (sizeof(dpi->auth_chall)) + 6) { snprintf(emes, sizeof(emes), "Attribute value is too long %s %d > %d" , avp_attr_type_string((avp)->attr_type), (avp)->length - 6, (int)(sizeof(dpi->auth_chall))); goto size_check_failed ; } } while ( 0); |
550 | memcpy(dpi->auth_chall, avp->attr_value, |
551 | avp_attr_length(avp)((avp)->length - 6)); |
552 | dpi->lauth_chall = avp_attr_length(avp)((avp)->length - 6); |
553 | break; |
554 | case L2TP_AVP_TYPE_PROXY_AUTHEN_ID32: |
555 | AVP_SIZE_CHECK(avp, ==, 8)do { if (!((avp)->length == (8))) { snprintf(emes, sizeof( emes), "invalid packet size %s %d" "==" "%d)", avp_attr_type_string ((avp)->attr_type), (avp)->length, (8)); goto size_check_failed ; } } while ( 0); |
556 | dpi->auth_id = avp_get_val16(avp); |
557 | break; |
558 | case L2TP_AVP_TYPE_PROXY_AUTHEN_NAME30: |
559 | AVP_MAXLEN_CHECK(avp, sizeof(dpi->username) - 1)do { if ((avp)->length > (sizeof(dpi->username) - 1) + 6) { snprintf(emes, sizeof(emes), "Attribute value is too long %s %d > %d" , avp_attr_type_string((avp)->attr_type), (avp)->length - 6, (int)(sizeof(dpi->username) - 1)); goto size_check_failed ; } } while ( 0); |
560 | memcpy(dpi->username, avp->attr_value, |
561 | avp_attr_length(avp)((avp)->length - 6)); |
562 | break; |
563 | case L2TP_AVP_TYPE_PROXY_AUTHEN_RESPONSE33: |
564 | AVP_MAXLEN_CHECK(avp, sizeof(dpi->auth_resp))do { if ((avp)->length > (sizeof(dpi->auth_resp)) + 6 ) { snprintf(emes, sizeof(emes), "Attribute value is too long %s %d > %d" , avp_attr_type_string((avp)->attr_type), (avp)->length - 6, (int)(sizeof(dpi->auth_resp))); goto size_check_failed ; } } while ( 0); |
565 | memcpy(dpi->auth_resp, avp->attr_value, |
566 | avp_attr_length(avp)((avp)->length - 6)); |
567 | dpi->lauth_resp = avp_attr_length(avp)((avp)->length - 6); |
568 | break; |
569 | case L2TP_AVP_TYPE_PROXY_AUTHEN_TYPE29: |
570 | AVP_SIZE_CHECK(avp, ==, 8)do { if (!((avp)->length == (8))) { snprintf(emes, sizeof( emes), "invalid packet size %s %d" "==" "%d)", avp_attr_type_string ((avp)->attr_type), (avp)->length, (8)); goto size_check_failed ; } } while ( 0); |
571 | switch (avp_get_val16(avp)) { |
572 | default: |
573 | l2tp_call_log(_this, LOG_WARNING4, |
574 | "RecvICCN Unknown proxy-authen-type=%d", |
575 | avp_get_val16(avp)); |
576 | /* FALLTHROUGH */ |
577 | case L2TP_AUTH_TYPE_NO_AUTH4: |
578 | dpi->auth_type = 0; |
579 | break; |
580 | case L2TP_AUTH_TYPE_PPP_CHAP2: |
581 | dpi->auth_type = PPP_AUTH_CHAP_MD50x05; |
582 | break; |
583 | case L2TP_AUTH_TYPE_PPP_PAP3: |
584 | dpi->auth_type = PPP_AUTH_PAP0xc023; |
585 | break; |
586 | case L2TP_AUTH_TYPE_MS_CHAP_V15: |
587 | dpi->auth_type = PPP_AUTH_CHAP_MS0x80; |
588 | break; |
589 | } |
590 | break; |
591 | default: |
592 | if (avp->is_mandatory != 0) { |
593 | l2tp_call_log(_this, LOG_WARNING4, |
594 | "AVP (%s/%d) is not supported, but it's " |
595 | "mandatory", |
596 | avp_attr_type_string(avp->attr_type), |
597 | avp->attr_type); |
598 | l2tp_call_disconnect(_this, |
599 | L2TP_CDN_RCODE_ERROR_CODE2, |
600 | L2TP_ECODE_UNKNOWN_MANDATORY_AVP8, NULL((void*)0), |
601 | NULL((void*)0), 0); |
602 | return 1; |
603 | #ifdef L2TP_CALL_DEBUG |
604 | } else { |
605 | L2TP_CALL_DBG((_this, LOG_DEBUG, |
606 | "AVP (%s/%d) is not handled", |
607 | avp_attr_type_string(avp->attr_type), |
608 | avp->attr_type)); |
609 | #endif |
610 | } |
611 | } |
612 | } |
613 | l2tp_call_log(_this, LOG_INFO6, "RecvICCN " |
614 | "session_id=%u calling_number=%s tx_conn_speed=%u framing=%s", |
615 | _this->peer_session_id, _this->calling_number, tx_conn_speed, |
616 | ((framing_type & L2TP_FRAMING_CAP_FLAGS_ASYNC0x00000002) != 0)? "async" : |
617 | ((framing_type & L2TP_FRAMING_CAP_FLAGS_SYNC0x00000001) != 0)? "sync" : |
618 | "unknown"); |
619 | |
620 | return 0; |
621 | size_check_failed: |
622 | l2tp_call_log(_this, LOG_ERR3, "Received bad ICCN: %s", emes); |
623 | l2tp_call_disconnect(_this, L2TP_CDN_RCODE_ERROR_CODE2, |
624 | L2TP_ECODE_WRONG_LENGTH2, NULL((void*)0), NULL((void*)0), 0); |
625 | return 1; |
626 | } |
627 | |
628 | /* receive CDN */ |
629 | static int |
630 | l2tp_recv_CDN(l2tp_call *_this, u_char *pkt, int pktlen) |
631 | { |
632 | int result, error, avpsz, len, sessid; |
633 | struct l2tp_avp *avp; |
634 | char buf[L2TP_AVP_MAXSIZ1024], emes[256], pmes[256]; |
635 | |
636 | /* initialize */ |
637 | result = 0; |
638 | error = 0; |
639 | sessid = 0; |
640 | strlcpy(pmes, "(none)", sizeof(pmes)); |
641 | |
642 | avp = (struct l2tp_avp *)buf; |
643 | while (pktlen >= 6 && (avpsz = avp_enum(avp, pkt, pktlen, 1)) > 0) { |
644 | pkt += avpsz; |
645 | pktlen -= avpsz; |
646 | if (avp->vendor_id != 0) { |
647 | L2TP_CALL_DBG((_this, LOG_DEBUG, |
648 | "Received a Vendor-specific AVP vendor-id=%d " |
649 | "type=%d", avp->vendor_id, avp->attr_type)); |
650 | continue; |
651 | } |
652 | if (avp->is_hidden != 0) { |
653 | l2tp_call_log(_this, LOG_WARNING4, |
654 | "Received AVP (%s/%d) is hidden. But we don't " |
655 | "share secret.", |
656 | avp_attr_type_string(avp->attr_type), |
657 | avp->attr_type); |
658 | if (avp->is_mandatory != 0) { |
659 | l2tp_call_disconnect(_this, |
660 | L2TP_CDN_RCODE_ERROR_CODE2, |
661 | L2TP_ECODE_UNKNOWN_MANDATORY_AVP8, NULL((void*)0), |
662 | NULL((void*)0), 0); |
663 | return 1; |
664 | } |
665 | continue; |
666 | } |
667 | switch (avp->attr_type) { |
668 | case L2TP_AVP_TYPE_MESSAGE_TYPE0: |
669 | AVP_SIZE_CHECK(avp, ==, 8)do { if (!((avp)->length == (8))) { snprintf(emes, sizeof( emes), "invalid packet size %s %d" "==" "%d)", avp_attr_type_string ((avp)->attr_type), (avp)->length, (8)); goto size_check_failed ; } } while ( 0); |
670 | continue; |
671 | case L2TP_AVP_TYPE_RESULT_CODE1: |
672 | AVP_SIZE_CHECK(avp, >=, 8)do { if (!((avp)->length >= (8))) { snprintf(emes, sizeof (emes), "invalid packet size %s %d" ">=" "%d)", avp_attr_type_string ((avp)->attr_type), (avp)->length, (8)); goto size_check_failed ; } } while ( 0); |
673 | result = avp->attr_value[0] << 8 | avp->attr_value[1]; |
674 | if (avp->length >= 10) { |
675 | error = avp->attr_value[2] << 8 | |
676 | avp->attr_value[3]; |
677 | len = avp->length - 12; |
678 | if (len > 0) { |
679 | len = MINIMUM(len, sizeof(pmes) - 1)(((len) < (sizeof(pmes) - 1)) ? (len) : (sizeof(pmes) - 1) ); |
680 | memcpy(pmes, &avp->attr_value[4], len); |
681 | pmes[len] = '\0'; |
682 | } |
683 | } |
684 | continue; |
685 | case L2TP_AVP_TYPE_ASSIGNED_SESSION_ID14: |
686 | AVP_SIZE_CHECK(avp, >=, 8)do { if (!((avp)->length >= (8))) { snprintf(emes, sizeof (emes), "invalid packet size %s %d" ">=" "%d)", avp_attr_type_string ((avp)->attr_type), (avp)->length, (8)); goto size_check_failed ; } } while ( 0); |
687 | sessid = avp_get_val16(avp); |
Value stored to 'sessid' is never read | |
688 | continue; |
689 | default: |
690 | if (avp->is_mandatory) { |
691 | l2tp_call_log(_this, LOG_WARNING4, |
692 | "AVP (%s/%d) is not supported, but it's " |
693 | "mandatory", |
694 | avp_attr_type_string(avp->attr_type), |
695 | avp->attr_type); |
696 | if (avp->is_mandatory != 0) { |
697 | l2tp_call_disconnect(_this, |
698 | L2TP_CDN_RCODE_ERROR_CODE2, |
699 | L2TP_ECODE_UNKNOWN_MANDATORY_AVP8, |
700 | NULL((void*)0), NULL((void*)0), 0); |
701 | return 1; |
702 | } |
703 | #ifdef L2TP_CALL_DEBUG |
704 | } else { |
705 | L2TP_CALL_DBG((_this, LOG_DEBUG, |
706 | "AVP (%s/%d) is not handled", |
707 | avp_attr_type_string(avp->attr_type), |
708 | avp->attr_type)); |
709 | #endif |
710 | } |
711 | } |
712 | } |
713 | if (error == 0) { |
714 | l2tp_call_log(_this, LOG_INFO6, |
715 | "RecvCDN result=%s/%d", l2tp_cdn_rcode_string(result), |
716 | result); |
717 | } else { |
718 | l2tp_call_log(_this, LOG_INFO6, |
719 | "RecvCDN result=%s/%d error=%s/%d message=%s", |
720 | l2tp_cdn_rcode_string(result), result, |
721 | l2tp_ecode_string(error), error, pmes); |
722 | } |
723 | |
724 | return 0; |
725 | |
726 | size_check_failed: |
727 | /* continue to process even if the CDN message was broken */ |
728 | l2tp_call_log(_this, LOG_ERR3, "Received bad CDN: %s", emes); |
729 | |
730 | return 0; |
731 | } |
732 | |
733 | /* send CDN */ |
734 | static int |
735 | l2tp_call_send_CDN(l2tp_call *_this, int result_code, int error_code, const |
736 | char *errmes, struct l2tp_avp *addavp[], int naddavp) |
737 | { |
738 | uint32_t val32; |
739 | int i, avplen, len; |
740 | struct l2tp_avp *avp; |
741 | char buf[L2TP_AVP_MAXSIZ1024]; |
742 | bytebuffer *bytebuf; |
743 | |
744 | L2TP_CALL_ASSERT(_this != NULL); |
745 | bytebuf = l2tp_ctrl_prepare_snd_buffer(_this->ctrl, 1); |
746 | if (bytebuf == NULL((void*)0)) { |
747 | l2tp_call_log(_this, LOG_ERR3, "sending CDN failed: no buffer"); |
748 | return 1; |
749 | } |
750 | avp = (struct l2tp_avp *)buf; |
751 | |
752 | /* Message Type = CDN */ |
753 | memset(avp, 0, sizeof(*avp)); |
754 | avp->is_mandatory = 1; |
755 | avp->attr_type = L2TP_AVP_TYPE_MESSAGE_TYPE0; |
756 | avp_set_val16(avp, L2TP_AVP_MESSAGE_TYPE_CDN14); |
757 | bytebuf_add_avp(bytebuf, avp, 2); |
758 | |
759 | /* Result Code */ |
760 | memset(avp, 0, sizeof(*avp)); |
761 | avp->is_mandatory = 1; |
762 | avp->attr_type = L2TP_AVP_TYPE_RESULT_CODE1; |
763 | #if 0 |
764 | /* |
765 | * Windows 2000 work around: |
766 | * Windows 2000 will return "2 - Length is wrong" in StopCCN, |
767 | * when it received "length = 8 and no error code AVP". |
768 | * Avoid the error, use AVP length = 10. |
769 | */ |
770 | if (error_code > 0) { |
771 | val32 = (result_code << 16) | (error_code & 0xffff); |
772 | avplen = 4; |
773 | avp_set_val32(avp, val32); |
774 | } else { |
775 | avplen = 2; |
776 | avp_set_val16(avp, result_code); |
777 | } |
778 | #else |
779 | val32 = (result_code << 16) | (error_code & 0xffff); |
780 | avplen = 4; |
781 | avp_set_val32(avp, val32); |
782 | #endif |
783 | |
784 | if (errmes != NULL((void*)0)) { |
785 | len = MINIMUM(strlen(errmes), L2TP_AVP_MAXSIZ - 128)(((strlen(errmes)) < (1024 - 128)) ? (strlen(errmes)) : (1024 - 128)); |
786 | memcpy(&avp->attr_value[avplen], errmes, len); |
787 | avplen += len; |
788 | } |
789 | bytebuf_add_avp(bytebuf, avp, avplen); |
790 | |
791 | /* Assigned Session Id */ |
792 | memset(avp, 0, sizeof(*avp)); |
793 | avp->is_mandatory = 1; |
794 | avp->attr_type = L2TP_AVP_TYPE_ASSIGNED_SESSION_ID14; |
795 | if (_this != NULL((void*)0) && _this->session_id != 0) |
796 | avp_set_val16(avp, _this->session_id); |
797 | else |
798 | avp_set_val16(avp, 0); |
799 | bytebuf_add_avp(bytebuf, avp, 2); |
800 | |
801 | for (i = 0; i < naddavp; i++) |
802 | bytebuf_add_avp(bytebuf, addavp[i], addavp[i]->length - 6); |
803 | |
804 | if (l2tp_ctrl_send_packet(_this->ctrl, _this->peer_session_id, |
805 | bytebuf) != 0) { |
806 | l2tp_call_log(_this, LOG_ERR3, "Error sending CDN: %m"); |
807 | return 1; |
808 | } |
809 | |
810 | if (error_code > 0) { |
811 | l2tp_call_log(_this, LOG_INFO6, |
812 | "SendCDN result=%s/%d error=%s/%d message=%s", |
813 | l2tp_cdn_rcode_string(result_code), result_code, |
814 | l2tp_ecode_string(error_code), error_code, |
815 | (errmes == NULL((void*)0))? "none" : errmes); |
816 | } else { |
817 | l2tp_call_log(_this, LOG_INFO6, "SendCDN result=%s/%d", |
818 | l2tp_cdn_rcode_string(result_code), result_code); |
819 | } |
820 | |
821 | return 0; |
822 | } |
823 | |
824 | /* send ZLB */ |
825 | static int |
826 | l2tp_call_send_ZLB(l2tp_call *_this) |
827 | { |
828 | bytebuffer *bytebuf; |
829 | |
830 | l2tp_call_log(_this, LOG_INFO6, "SendZLB"); |
831 | bytebuf = l2tp_ctrl_prepare_snd_buffer(_this->ctrl, 1); |
832 | if (bytebuf == NULL((void*)0)) { |
833 | l2tp_call_log(_this, LOG_ERR3, "sending ZLB failed: no buffer"); |
834 | return 1; |
835 | } |
836 | return l2tp_ctrl_send_packet(_this->ctrl, _this->peer_session_id, |
837 | bytebuf); |
838 | } |
839 | |
840 | /* |
841 | * misc |
842 | */ |
843 | /* logging with the label of the instance */ |
844 | static void |
845 | l2tp_call_log(l2tp_call *_this, int prio, const char *fmt, ...) |
846 | { |
847 | char logbuf[BUFSIZ1024]; |
848 | va_list ap; |
849 | |
850 | va_start(ap, fmt)__builtin_va_start(ap, fmt); |
851 | #ifdef L2TPD_MULTIPLE |
852 | snprintf(logbuf, sizeof(logbuf), "l2tpd id=%u ctrl=%u call=%u %s", |
853 | _this->ctrl->l2tpd->id, _this->ctrl->id, _this->id, fmt); |
854 | #else |
855 | snprintf(logbuf, sizeof(logbuf), "l2tpd ctrl=%u call=%u %s", |
856 | _this->ctrl->id, _this->id, fmt); |
857 | #endif |
858 | vlog_printf(prio, logbuf, ap); |
859 | va_end(ap)__builtin_va_end(ap); |
860 | } |
861 | |
862 | /* convert current status to strings */ |
863 | static inline const char * |
864 | l2tp_call_state_string(l2tp_call *_this) |
865 | { |
866 | switch (_this->state) { |
867 | case L2TP_CALL_STATE_IDLE0: return "idle"; |
868 | case L2TP_CALL_STATE_WAIT_CONN1: return "wait-conn"; |
869 | case L2TP_CALL_STATE_ESTABLISHED2: return "established"; |
870 | case L2TP_CALL_STATE_CLEANUP_WAIT3: return "cleanup-wait"; |
871 | } |
872 | return "unknown"; |
873 | } |
874 | |
875 | /* |
876 | * npppd physical layer |
877 | */ |
878 | |
879 | /* input packet to ppp */ |
880 | void |
881 | l2tp_call_ppp_input(l2tp_call *_this, u_char *pkt, int pktlen, int delayed) |
882 | { |
883 | int rval; |
884 | npppd_ppp *ppp; |
885 | |
886 | ppp = _this->ppp; |
887 | rval = ppp->recv_packet(ppp, pkt, pktlen, |
888 | delayed ? PPP_IO_FLAGS_DELAYED0x0002 : 0); |
889 | |
890 | if (_this->ppp == NULL((void*)0)) /* ppp is freed */ |
891 | return; |
892 | |
893 | if (rval != 0) |
894 | ppp->ierrors++; |
895 | else { |
896 | ppp->ipackets++; |
897 | ppp->ibytes += pktlen; |
898 | } |
899 | } |
900 | |
901 | /* called ppp output a packet */ |
902 | static int |
903 | l2tp_call_ppp_output(npppd_ppp *ppp, unsigned char *bytes, int nbytes, |
904 | int flags) |
905 | { |
906 | l2tp_call *_this; |
907 | bytebuffer *bytebuf; |
908 | |
909 | _this = ppp->phy_context; |
910 | |
911 | bytebuf = l2tp_ctrl_prepare_snd_buffer(_this->ctrl, _this->use_seq); |
912 | |
913 | if (bytebuf != NULL((void*)0)) { |
914 | bytebuffer_put(bytebuf, bytes, nbytes); |
915 | if (l2tp_call_send_data_packet(_this, bytebuf) != 0) |
916 | ppp->oerrors++; |
917 | else { |
918 | ppp->opackets++; |
919 | ppp->obytes += nbytes; |
920 | } |
921 | } else |
922 | ppp->oerrors++; |
923 | |
924 | return 0; |
925 | } |
926 | |
927 | /* it will be called when the connection was closed at ppp */ |
928 | static void |
929 | l2tp_call_closed_by_ppp(npppd_ppp *ppp) |
930 | { |
931 | l2tp_call *_this; |
932 | |
933 | L2TP_CALL_ASSERT(ppp != NULL); |
934 | L2TP_CALL_ASSERT(ppp->phy_context != NULL); |
935 | |
936 | _this = ppp->phy_context; |
937 | |
938 | /* do before l2tp_call_disconnect() */ |
939 | _this->ppp = NULL((void*)0); |
940 | |
941 | if (_this->state == L2TP_CALL_STATE_CLEANUP_WAIT3) { |
942 | /* no need to call l2tp_call_disconnect */ |
943 | } else if (ppp->disconnect_code == PPP_DISCON_NO_INFORMATION) { |
944 | l2tp_call_disconnect(_this, |
945 | L2TP_CDN_RCODE_ADMINISTRATIVE_REASON3, 0, NULL((void*)0), NULL((void*)0), 0); |
946 | } else { |
947 | /* |
948 | * RFC3145 L2TP Disconnect Cause Information |
949 | */ |
950 | struct l2tp_avp *avp[1]; |
951 | struct _ppp_cause { |
952 | struct l2tp_avp avp; |
953 | uint16_t code; |
954 | uint16_t proto; |
955 | uint8_t direction; |
956 | char message[128]; |
957 | } __attribute__((__packed__)) ppp_cause; |
958 | |
959 | ppp_cause.avp.is_mandatory = 0; |
960 | ppp_cause.avp.is_hidden = 0; |
961 | ppp_cause.avp.vendor_id = 0; /* ietf */ |
962 | ppp_cause.avp.attr_type = |
963 | L2TP_AVP_TYPE_PPP_DISCONNECT_CAUSE_CODE46; |
964 | ppp_cause.code = htons(ppp->disconnect_code)(__uint16_t)(__builtin_constant_p(ppp->disconnect_code) ? ( __uint16_t)(((__uint16_t)(ppp->disconnect_code) & 0xffU ) << 8 | ((__uint16_t)(ppp->disconnect_code) & 0xff00U ) >> 8) : __swap16md(ppp->disconnect_code)); |
965 | ppp_cause.proto = htons(ppp->disconnect_proto)(__uint16_t)(__builtin_constant_p(ppp->disconnect_proto) ? (__uint16_t)(((__uint16_t)(ppp->disconnect_proto) & 0xffU ) << 8 | ((__uint16_t)(ppp->disconnect_proto) & 0xff00U ) >> 8) : __swap16md(ppp->disconnect_proto)); |
966 | ppp_cause.direction = ppp->disconnect_direction; |
967 | ppp_cause.avp.length = offsetof(struct _ppp_cause, message[0])__builtin_offsetof(struct _ppp_cause, message[0]); |
968 | |
969 | if (ppp->disconnect_message != NULL((void*)0)) { |
970 | strlcpy(ppp_cause.message, ppp->disconnect_message, |
971 | sizeof(ppp_cause.message)); |
972 | ppp_cause.avp.length += strlen(ppp_cause.message); |
973 | } |
974 | avp[0] = &ppp_cause.avp; |
975 | l2tp_call_disconnect(_this, |
976 | L2TP_CDN_RCODE_ERROR_CODE2, L2TP_ECODE_GENERIC_ERROR6, |
977 | "Disconnected by local PPP", avp, 1); |
978 | } |
979 | l2tp_call_log(_this, LOG_NOTICE5, "logtype=PPPUnbind"); |
980 | } |
981 | |
982 | /* notify disconnection to ppp to terminate or free of ppp */ |
983 | static void |
984 | l2tp_call_notify_down(l2tp_call *_this) |
985 | { |
986 | if (_this->ppp != NULL((void*)0)) |
987 | ppp_phy_downed(_this->ppp); |
988 | } |
989 | |
990 | /* bind ppp */ |
991 | static int |
992 | l2tp_call_bind_ppp(l2tp_call *_this, dialin_proxy_info *dpi) |
993 | { |
994 | int code, errcode; |
995 | npppd_ppp *ppp; |
996 | |
997 | code = L2TP_CDN_RCODE_BUSY8; |
998 | errcode = 0; |
999 | ppp = NULL((void*)0); |
1000 | if ((ppp = ppp_create()) == NULL((void*)0)) |
1001 | goto fail; |
1002 | |
1003 | ASSERT(_this->ppp == NULL)((void)0);; |
1004 | |
1005 | if (_this->ppp != NULL((void*)0)) |
1006 | return -1; |
1007 | |
1008 | _this->ppp = ppp; |
1009 | |
1010 | ppp->tunnel_type = NPPPD_TUNNEL_L2TP1; |
1011 | ppp->tunnel_session_id = _this->session_id; |
1012 | ppp->phy_context = _this; |
1013 | ppp->send_packet = l2tp_call_ppp_output; |
1014 | ppp->phy_close = l2tp_call_closed_by_ppp; |
1015 | |
1016 | strlcpy(ppp->phy_label, L2TP_CTRL_LISTENER_TUN_NAME(_this->ctrl)((l2tpd_listener *)slist_get(&(_this->ctrl)->l2tpd-> listener, (_this->ctrl)->listener_index))->tun_name, |
1017 | sizeof(ppp->phy_label)); |
1018 | L2TP_CALL_ASSERT(sizeof(ppp->phy_info) >= _this->ctrl->peer.ss_len); |
1019 | memcpy(&ppp->phy_info, &_this->ctrl->peer, |
1020 | MINIMUM(sizeof(ppp->phy_info), _this->ctrl->peer.ss_len)(((sizeof(ppp->phy_info)) < (_this->ctrl->peer.ss_len )) ? (sizeof(ppp->phy_info)) : (_this->ctrl->peer.ss_len ))); |
1021 | strlcpy(ppp->calling_number, _this->calling_number, |
1022 | sizeof(ppp->calling_number)); |
1023 | if (ppp_init(npppd_get_npppd(), ppp) != 0) { |
1024 | l2tp_call_log(_this, LOG_ERR3, "failed binding ppp"); |
1025 | goto fail; |
1026 | } |
1027 | |
1028 | l2tp_call_log(_this, LOG_NOTICE5, "logtype=PPPBind ppp=%d", ppp->id); |
1029 | if (DIALIN_PROXY_IS_REQUESTED(dpi)(((dpi)->last_sent_lcp.ldata > 0)? 1 : 0)) { |
1030 | if (!L2TP_CTRL_CONF(_this->ctrl)((l2tpd_listener *)slist_get(&(_this->ctrl)->l2tpd-> listener, (_this->ctrl)->listener_index))->conf->accept_dialin) { |
1031 | l2tp_call_log(_this, LOG_ERR3, |
1032 | "'accept_dialin' is 'false' in the setting."); |
1033 | code = L2TP_CDN_RCODE_ERROR_CODE2; |
1034 | errcode = L2TP_ECODE_INVALID_MESSAGE3; |
1035 | goto fail; |
1036 | } |
1037 | |
1038 | if (ppp_dialin_proxy_prepare(ppp, dpi) != 0) { |
1039 | code = L2TP_CDN_RCODE_TEMP_NOT_AVALIABLE4; |
1040 | goto fail; |
1041 | } |
1042 | } |
1043 | ppp_start(ppp); |
1044 | |
1045 | return 0; |
1046 | fail: |
1047 | if (ppp != NULL((void*)0)) |
1048 | ppp_destroy(ppp); |
1049 | _this->ppp = NULL((void*)0); |
1050 | |
1051 | l2tp_call_disconnect(_this, code, errcode, NULL((void*)0), NULL((void*)0), 0); |
1052 | return 1; |
1053 | } |