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