1*c8939cf4Skrw /* $OpenBSD: pptp_ctrl.c,v 1.11 2016/04/16 18:32:29 krw Exp $ */ 2e109dc18Syasuoka 30fbf3537Syasuoka /*- 40fbf3537Syasuoka * Copyright (c) 2009 Internet Initiative Japan Inc. 50fbf3537Syasuoka * All rights reserved. 60fbf3537Syasuoka * 70fbf3537Syasuoka * Redistribution and use in source and binary forms, with or without 80fbf3537Syasuoka * modification, are permitted provided that the following conditions 90fbf3537Syasuoka * are met: 100fbf3537Syasuoka * 1. Redistributions of source code must retain the above copyright 110fbf3537Syasuoka * notice, this list of conditions and the following disclaimer. 120fbf3537Syasuoka * 2. Redistributions in binary form must reproduce the above copyright 130fbf3537Syasuoka * notice, this list of conditions and the following disclaimer in the 140fbf3537Syasuoka * documentation and/or other materials provided with the distribution. 150fbf3537Syasuoka * 160fbf3537Syasuoka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 170fbf3537Syasuoka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 180fbf3537Syasuoka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 190fbf3537Syasuoka * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 200fbf3537Syasuoka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 210fbf3537Syasuoka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 220fbf3537Syasuoka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 230fbf3537Syasuoka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 240fbf3537Syasuoka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 250fbf3537Syasuoka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 260fbf3537Syasuoka * SUCH DAMAGE. 270fbf3537Syasuoka */ 280fbf3537Syasuoka /**@file 29f0a4e295Syasuoka * PPTP(RFC 2637) control connection implementation. 30f0a4e295Syasuoka * currently it only support PAC part 310fbf3537Syasuoka */ 32*c8939cf4Skrw /* $Id: pptp_ctrl.c,v 1.11 2016/04/16 18:32:29 krw Exp $ */ 330fbf3537Syasuoka #include <sys/types.h> 340fbf3537Syasuoka #include <sys/socket.h> 350fbf3537Syasuoka #include <netinet/in.h> 360fbf3537Syasuoka #include <stdio.h> 370fbf3537Syasuoka #include <stdarg.h> 380fbf3537Syasuoka #include <stdlib.h> 390fbf3537Syasuoka #include <netdb.h> 400fbf3537Syasuoka #include <unistd.h> 410fbf3537Syasuoka #include <syslog.h> 420fbf3537Syasuoka #include <time.h> 430fbf3537Syasuoka #include <fcntl.h> 440fbf3537Syasuoka #include <errno.h> 450fbf3537Syasuoka #include <string.h> 460fbf3537Syasuoka #include <event.h> 470fbf3537Syasuoka 480fbf3537Syasuoka #include "bytebuf.h" 490fbf3537Syasuoka #include "debugutil.h" 500fbf3537Syasuoka #include "hash.h" 510fbf3537Syasuoka #include "slist.h" 520fbf3537Syasuoka #include "time_utils.h" 530fbf3537Syasuoka 540fbf3537Syasuoka #include "version.h" 550fbf3537Syasuoka 560fbf3537Syasuoka #include "pptp.h" 570fbf3537Syasuoka #include "pptp_local.h" 580fbf3537Syasuoka #include "pptp_subr.h" 590fbf3537Syasuoka 60dbad4650Sderaadt #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) 61dbad4650Sderaadt #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) 62dbad4650Sderaadt 63f0a4e295Syasuoka /* periods of pptp_ctrl_timeout */ 640fbf3537Syasuoka #define PPTP_CTRL_TIMEOUT_IVAL_SEC 2 650fbf3537Syasuoka 660fbf3537Syasuoka #ifdef PPTP_CTRL_DEBUG 670fbf3537Syasuoka #define PPTP_CTRL_ASSERT(x) ASSERT(x) 680fbf3537Syasuoka #define PPTP_CTRL_DBG(x) pptp_ctrl_log x 690fbf3537Syasuoka #else 700fbf3537Syasuoka #define PPTP_CTRL_ASSERT(x) 710fbf3537Syasuoka #define PPTP_CTRL_DBG(x) 720fbf3537Syasuoka #endif 730fbf3537Syasuoka 740fbf3537Syasuoka static unsigned pptp_ctrl_seqno = 0; 750fbf3537Syasuoka 760fbf3537Syasuoka static void pptp_ctrl_log (pptp_ctrl *, int, const char *, ...) __printflike(3,4); 770fbf3537Syasuoka static void pptp_ctrl_timeout (int, short, void *); 780fbf3537Syasuoka static void pptp_ctrl_reset_timeout (pptp_ctrl *); 790fbf3537Syasuoka static void pptp_ctrl_io_event (int, short, void *); 800fbf3537Syasuoka static void pptp_ctrl_set_io_event (pptp_ctrl *); 810fbf3537Syasuoka static int pptp_ctrl_output_flush (pptp_ctrl *); 820fbf3537Syasuoka static void pptp_ctrl_SCCRx_string (struct pptp_scc *, u_char *, int); 830fbf3537Syasuoka static int pptp_ctrl_recv_SCCRQ (pptp_ctrl *, u_char *, int); 840fbf3537Syasuoka static int pptp_ctrl_recv_StopCCRP (pptp_ctrl *, u_char *, int); 850fbf3537Syasuoka static int pptp_ctrl_send_StopCCRQ (pptp_ctrl *, int); 860fbf3537Syasuoka static int pptp_ctrl_recv_StopCCRQ (pptp_ctrl *, u_char *, int); 870fbf3537Syasuoka static int pptp_ctrl_send_StopCCRP (pptp_ctrl *, int, int); 880fbf3537Syasuoka static int pptp_ctrl_send_SCCRP (pptp_ctrl *, int, int); 890fbf3537Syasuoka static void pptp_ctrl_send_CDN (pptp_ctrl *, int, int, int, const char *); 900fbf3537Syasuoka static void pptp_ctrl_process_echo_req (pptp_ctrl *, u_char *, int); 910fbf3537Syasuoka static int pptp_ctrl_recv_echo_rep (pptp_ctrl *, u_char *, int); 920fbf3537Syasuoka static void pptp_ctrl_send_echo_req (pptp_ctrl *); 930fbf3537Syasuoka static int pptp_ctrl_input (pptp_ctrl *, u_char *, int); 940fbf3537Syasuoka static int pptp_ctrl_call_input (pptp_ctrl *, int, u_char *, int); 950fbf3537Syasuoka static const char *pptp_ctrl_state_string (int); 960fbf3537Syasuoka static void pptp_ctrl_fini(pptp_ctrl *); 970fbf3537Syasuoka 98f0a4e295Syasuoka /* 99f0a4e295Syasuoka * pptp_ctrl instance operation functions 100f0a4e295Syasuoka */ 1010fbf3537Syasuoka pptp_ctrl * 1020fbf3537Syasuoka pptp_ctrl_create(void) 1030fbf3537Syasuoka { 1040fbf3537Syasuoka pptp_ctrl *_this; 1050fbf3537Syasuoka 1060fbf3537Syasuoka if ((_this = malloc(sizeof(pptp_ctrl))) == NULL) 1070fbf3537Syasuoka return NULL; 1080fbf3537Syasuoka 1090fbf3537Syasuoka return _this; 1100fbf3537Syasuoka } 1110fbf3537Syasuoka 1120fbf3537Syasuoka int 1130fbf3537Syasuoka pptp_ctrl_init(pptp_ctrl *_this) 1140fbf3537Syasuoka { 1150fbf3537Syasuoka time_t curr_time; 1160fbf3537Syasuoka 1170fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 1180fbf3537Syasuoka curr_time = get_monosec(); 1190fbf3537Syasuoka memset(_this, 0, sizeof(pptp_ctrl)); 1200fbf3537Syasuoka _this->id = pptp_ctrl_seqno++; 1210fbf3537Syasuoka _this->sock = -1; 1220fbf3537Syasuoka 1230fbf3537Syasuoka if ((_this->recv_buf = bytebuffer_create(PPTP_BUFSIZ)) == NULL) { 1240fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "bytebuffer_create() failed at " 1250fbf3537Syasuoka "%s(): %m", __func__); 126f0a4e295Syasuoka goto fail; 1270fbf3537Syasuoka } 1280fbf3537Syasuoka if ((_this->send_buf = bytebuffer_create(PPTP_BUFSIZ)) == NULL) { 1290fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "bytebuffer_create() failed at " 1300fbf3537Syasuoka "%s(): %m", __func__); 131f0a4e295Syasuoka goto fail; 1320fbf3537Syasuoka } 1330fbf3537Syasuoka _this->last_rcv_ctrl = curr_time; 1340fbf3537Syasuoka _this->last_snd_ctrl = curr_time; 135c2307f15Syasuoka _this->echo_seq = arc4random(); 1360fbf3537Syasuoka _this->echo_interval = PPTP_CTRL_DEFAULT_ECHO_INTERVAL; 1370fbf3537Syasuoka _this->echo_timeout = PPTP_CTRL_DEFAULT_ECHO_TIMEOUT; 1380fbf3537Syasuoka slist_init(&_this->call_list); 1390fbf3537Syasuoka evtimer_set(&_this->ev_timer, pptp_ctrl_timeout, _this); 1400fbf3537Syasuoka 1410fbf3537Syasuoka return 0; 142f0a4e295Syasuoka fail: 1430fbf3537Syasuoka return 1; 1440fbf3537Syasuoka } 1450fbf3537Syasuoka 1460fbf3537Syasuoka int 1470fbf3537Syasuoka pptp_ctrl_start(pptp_ctrl *_this) 1480fbf3537Syasuoka { 1490fbf3537Syasuoka int ival; 1500fbf3537Syasuoka char hbuf0[NI_MAXHOST], sbuf0[NI_MAXSERV]; 1510fbf3537Syasuoka char hbuf1[NI_MAXHOST], sbuf1[NI_MAXSERV]; 1520fbf3537Syasuoka struct sockaddr_storage sock; 1530fbf3537Syasuoka socklen_t socklen; 1540fbf3537Syasuoka 1550fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 1560fbf3537Syasuoka PPTP_CTRL_ASSERT(_this->sock >= 0); 1570fbf3537Syasuoka 158f0a4e295Syasuoka /* convert address to strings for logging */ 1590fbf3537Syasuoka strlcpy(hbuf0, "<unknown>", sizeof(hbuf0)); 1600fbf3537Syasuoka strlcpy(sbuf0, "<unknown>", sizeof(sbuf0)); 1610fbf3537Syasuoka strlcpy(hbuf1, "<unknown>", sizeof(hbuf1)); 1620fbf3537Syasuoka strlcpy(sbuf1, "<unknown>", sizeof(sbuf1)); 1630fbf3537Syasuoka if (getnameinfo((struct sockaddr *)&_this->peer, _this->peer.ss_len, 1640fbf3537Syasuoka hbuf0, sizeof(hbuf0), sbuf0, sizeof(sbuf0), 1650fbf3537Syasuoka NI_NUMERICHOST | NI_NUMERICSERV) != 0) { 1660fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 1670fbf3537Syasuoka "getnameinfo() failed at %s(): %m", __func__); 1680fbf3537Syasuoka } 1690fbf3537Syasuoka socklen = sizeof(sock); 1700fbf3537Syasuoka if (getsockname(_this->sock, (struct sockaddr *)&sock, &socklen) != 0) { 1710fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 1720fbf3537Syasuoka "getsockname() failed at %s(): %m", __func__); 173f0a4e295Syasuoka goto fail; 1740fbf3537Syasuoka } 1750fbf3537Syasuoka if (getnameinfo((struct sockaddr *)&sock, sock.ss_len, hbuf1, 1760fbf3537Syasuoka sizeof(hbuf1), sbuf1, sizeof(sbuf1), 1770fbf3537Syasuoka NI_NUMERICHOST | NI_NUMERICSERV) != 0) { 1780fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 1790fbf3537Syasuoka "getnameinfo() failed at %s(): %m", __func__); 1800fbf3537Syasuoka } 1810fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "Starting peer=%s:%s/tcp " 1820fbf3537Syasuoka "sock=%s:%s/tcp", hbuf0, sbuf0, hbuf1, sbuf1); 1830fbf3537Syasuoka 184*c8939cf4Skrw if ((ival = fcntl(_this->sock, F_GETFL)) < 0) { 1850fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 1860fbf3537Syasuoka "fcntl(F_GET_FL) failed at %s(): %m", __func__); 187f0a4e295Syasuoka goto fail; 1880fbf3537Syasuoka } else if (fcntl(_this->sock, F_SETFL, ival | O_NONBLOCK) < 0) { 1890fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 1900fbf3537Syasuoka "fcntl(F_SET_FL) failed at %s(): %m", __func__); 191f0a4e295Syasuoka goto fail; 1920fbf3537Syasuoka } 1930fbf3537Syasuoka pptp_ctrl_set_io_event(_this); 1940fbf3537Syasuoka pptp_ctrl_reset_timeout(_this); 1950fbf3537Syasuoka 1960fbf3537Syasuoka return 0; 197f0a4e295Syasuoka fail: 1980fbf3537Syasuoka return 1; 1990fbf3537Syasuoka } 2000fbf3537Syasuoka 201f0a4e295Syasuoka /* Timer */ 2020fbf3537Syasuoka static void 2030fbf3537Syasuoka pptp_ctrl_timeout(int fd, short event, void *ctx) 2040fbf3537Syasuoka { 2050fbf3537Syasuoka int i; 2060fbf3537Syasuoka pptp_call *call; 2070fbf3537Syasuoka pptp_ctrl *_this; 2080fbf3537Syasuoka time_t last, curr_time; 2090fbf3537Syasuoka 2100fbf3537Syasuoka _this = ctx; 2110fbf3537Syasuoka curr_time = get_monosec(); 2120fbf3537Syasuoka 2130fbf3537Syasuoka PPTP_CTRL_DBG((_this, DEBUG_LEVEL_3, "enter %s()", __func__)); 214f0a4e295Syasuoka /* clean up call */ 2150fbf3537Syasuoka i = 0; 2160fbf3537Syasuoka while (i < slist_length(&_this->call_list)) { 2170fbf3537Syasuoka call = slist_get(&_this->call_list, i); 2180fbf3537Syasuoka if (call->state == PPTP_CALL_STATE_CLEANUP_WAIT && 2190fbf3537Syasuoka curr_time - call->last_io > PPTP_CALL_CLEANUP_WAIT_TIME) { 2200fbf3537Syasuoka pptp_call_stop(call); 2210fbf3537Syasuoka pptp_call_destroy(call); 2220fbf3537Syasuoka slist_remove(&_this->call_list, i); 2230fbf3537Syasuoka } else 2240fbf3537Syasuoka i++; 2250fbf3537Syasuoka } 2260fbf3537Syasuoka 227f0a4e295Syasuoka /* State machine: Timeout */ 2280fbf3537Syasuoka switch (_this->state) { 2290fbf3537Syasuoka default: 2300fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_CTRL_REPLY: 2310fbf3537Syasuoka case PPTP_CTRL_STATE_IDLE: 2320fbf3537Syasuoka if (curr_time - _this->last_rcv_ctrl > PPTPD_IDLE_TIMEOUT) { 2330fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 2340fbf3537Syasuoka "Timeout in state %s", 2350fbf3537Syasuoka pptp_ctrl_state_string(_this->state)); 2360fbf3537Syasuoka pptp_ctrl_fini(_this); 2370fbf3537Syasuoka return; 2380fbf3537Syasuoka } 2390fbf3537Syasuoka break; 2400fbf3537Syasuoka case PPTP_CTRL_STATE_ESTABLISHED: 241dbad4650Sderaadt last = MAXIMUM(_this->last_rcv_ctrl, _this->last_snd_ctrl); 2420fbf3537Syasuoka 2430fbf3537Syasuoka if (curr_time - _this->last_rcv_ctrl 2440fbf3537Syasuoka >= _this->echo_interval + _this->echo_timeout) { 2450fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 2460fbf3537Syasuoka "Timeout waiting for echo reply"); 2470fbf3537Syasuoka pptp_ctrl_fini(_this); 2480fbf3537Syasuoka return; 2490fbf3537Syasuoka } 2500fbf3537Syasuoka if (curr_time - last >= _this->echo_interval) { 2510fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "Echo")); 2520fbf3537Syasuoka _this->echo_seq++; 2530fbf3537Syasuoka pptp_ctrl_send_echo_req(_this); 2540fbf3537Syasuoka } 2550fbf3537Syasuoka break; 2560fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_STOP_REPLY: 2570fbf3537Syasuoka if (curr_time - _this->last_snd_ctrl > 2580fbf3537Syasuoka PPTP_CTRL_StopCCRP_WAIT_TIME) { 2590fbf3537Syasuoka pptp_ctrl_log(_this, LOG_WARNING, 2600fbf3537Syasuoka "Timeout waiting for StopCCRP"); 2610fbf3537Syasuoka pptp_ctrl_fini(_this); 2620fbf3537Syasuoka return; 2630fbf3537Syasuoka } 2640fbf3537Syasuoka break; 2650fbf3537Syasuoka case PPTP_CTRL_STATE_DISPOSING: 2660fbf3537Syasuoka pptp_ctrl_fini(_this); 2670fbf3537Syasuoka return; 2680fbf3537Syasuoka } 2690fbf3537Syasuoka pptp_ctrl_reset_timeout(_this); 2700fbf3537Syasuoka } 2710fbf3537Syasuoka 2720fbf3537Syasuoka static void 2730fbf3537Syasuoka pptp_ctrl_reset_timeout(pptp_ctrl *_this) 2740fbf3537Syasuoka { 2750fbf3537Syasuoka struct timeval tv; 2760fbf3537Syasuoka 2770fbf3537Syasuoka switch (_this->state) { 2780fbf3537Syasuoka case PPTP_CTRL_STATE_DISPOSING: 279adafb749Sokan /* call back immediately */ 280adafb749Sokan timerclear(&tv); 2810fbf3537Syasuoka break; 2820fbf3537Syasuoka default: 2830fbf3537Syasuoka tv.tv_sec = PPTP_CTRL_TIMEOUT_IVAL_SEC; 2840fbf3537Syasuoka tv.tv_usec = 0; 2850fbf3537Syasuoka break; 2860fbf3537Syasuoka } 2870fbf3537Syasuoka evtimer_add(&_this->ev_timer, &tv); 2880fbf3537Syasuoka } 2890fbf3537Syasuoka 2900fbf3537Syasuoka /** 291f0a4e295Syasuoka * Terminate PPTP control connection 292f0a4e295Syasuoka * @result The value for Stop-Control-Connection-Request(StopCCRQ) result. 293f0a4e295Syasuoka This function will not sent StopCCRQ when the value == 0 and 294f0a4e295Syasuoka the specification does not require to sent it. 2950fbf3537Syasuoka * @see ::#PPTP_StopCCRQ_REASON_STOP_PROTOCOL 2960fbf3537Syasuoka * @see ::#PPTP_StopCCRQ_REASON_STOP_LOCAL_SHUTDOWN 2970fbf3537Syasuoka */ 2980fbf3537Syasuoka void 2990fbf3537Syasuoka pptp_ctrl_stop(pptp_ctrl *_this, int result) 3000fbf3537Syasuoka { 3010fbf3537Syasuoka int i; 3020fbf3537Syasuoka pptp_call *call; 3030fbf3537Syasuoka 3040fbf3537Syasuoka switch (_this->state) { 3050fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_STOP_REPLY: 306f0a4e295Syasuoka /* waiting responce. */ 307f0a4e295Syasuoka /* this state will timeout by pptp_ctrl_timeout */ 3080fbf3537Syasuoka break; 3090fbf3537Syasuoka case PPTP_CTRL_STATE_ESTABLISHED: 3100fbf3537Syasuoka if (result != 0) { 3110fbf3537Syasuoka for (i = 0; i < slist_length(&_this->call_list); i++) { 3120fbf3537Syasuoka call = slist_get(&_this->call_list, i); 3130fbf3537Syasuoka pptp_call_disconnect(call, 3140fbf3537Syasuoka PPTP_CDN_RESULT_ADMIN_SHUTDOWN, 0, NULL); 3150fbf3537Syasuoka } 3160fbf3537Syasuoka pptp_ctrl_send_StopCCRQ(_this, result); 3170fbf3537Syasuoka _this->state = PPTP_CTRL_STATE_WAIT_STOP_REPLY; 3180fbf3537Syasuoka break; 3190fbf3537Syasuoka } 320f0a4e295Syasuoka /* FALLTHROUGH */ 3210fbf3537Syasuoka default: 3220fbf3537Syasuoka pptp_ctrl_fini(_this); 3230fbf3537Syasuoka } 3240fbf3537Syasuoka return; 3250fbf3537Syasuoka } 3260fbf3537Syasuoka 3270fbf3537Syasuoka 328f0a4e295Syasuoka /* finish PPTP control */ 3290fbf3537Syasuoka static void 3300fbf3537Syasuoka pptp_ctrl_fini(pptp_ctrl *_this) 3310fbf3537Syasuoka { 3320fbf3537Syasuoka pptp_call *call; 3330fbf3537Syasuoka 3340fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 3350fbf3537Syasuoka 3360fbf3537Syasuoka if (_this->sock >= 0) { 3370fbf3537Syasuoka event_del(&_this->ev_sock); 3380fbf3537Syasuoka close(_this->sock); 3390fbf3537Syasuoka _this->sock = -1; 3400fbf3537Syasuoka } 3410fbf3537Syasuoka for (slist_itr_first(&_this->call_list); 3420fbf3537Syasuoka slist_itr_has_next(&_this->call_list);) { 3430fbf3537Syasuoka call = slist_itr_next(&_this->call_list); 3440fbf3537Syasuoka pptp_call_stop(call); 3450fbf3537Syasuoka pptp_call_destroy(call); 3460fbf3537Syasuoka slist_itr_remove(&_this->call_list); 3470fbf3537Syasuoka } 3480fbf3537Syasuoka 3490fbf3537Syasuoka if (_this->on_io_event != 0) { 3500fbf3537Syasuoka /* 351f0a4e295Syasuoka * as the complete terminate process needs complicated 352f0a4e295Syasuoka * exception handling, do partially at here. 353f0a4e295Syasuoka * rest of part will be handled by timer-event-handler. 3540fbf3537Syasuoka */ 3550fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "Disposing")); 3560fbf3537Syasuoka _this->state = PPTP_CTRL_STATE_DISPOSING; 3570fbf3537Syasuoka pptp_ctrl_reset_timeout(_this); 3580fbf3537Syasuoka return; 3590fbf3537Syasuoka } 3600fbf3537Syasuoka 3610fbf3537Syasuoka evtimer_del(&_this->ev_timer); 3620fbf3537Syasuoka slist_fini(&_this->call_list); 3630fbf3537Syasuoka 3640fbf3537Syasuoka pptp_ctrl_log (_this, LOG_NOTICE, "logtype=Finished"); 3650fbf3537Syasuoka 366f0a4e295Syasuoka /* disable _this */ 3670fbf3537Syasuoka pptpd_ctrl_finished_notify(_this->pptpd, _this); 3680fbf3537Syasuoka } 3690fbf3537Syasuoka 370f0a4e295Syasuoka /* free PPTP control context */ 3710fbf3537Syasuoka void 3720fbf3537Syasuoka pptp_ctrl_destroy(pptp_ctrl *_this) 3730fbf3537Syasuoka { 3740fbf3537Syasuoka if (_this->send_buf != NULL) { 3750fbf3537Syasuoka bytebuffer_destroy(_this->send_buf); 3760fbf3537Syasuoka _this->send_buf = NULL; 3770fbf3537Syasuoka } 3780fbf3537Syasuoka if (_this->recv_buf != NULL) { 3790fbf3537Syasuoka bytebuffer_destroy(_this->recv_buf); 3800fbf3537Syasuoka _this->recv_buf = NULL; 3810fbf3537Syasuoka } 3820fbf3537Syasuoka free(_this); 3830fbf3537Syasuoka } 3840fbf3537Syasuoka 385f0a4e295Syasuoka /* 386f0a4e295Syasuoka * network I/O 387f0a4e295Syasuoka */ 388f0a4e295Syasuoka /* I/O event dispather */ 3890fbf3537Syasuoka static void 3900fbf3537Syasuoka pptp_ctrl_io_event(int fd, short evmask, void *ctx) 3910fbf3537Syasuoka { 3920fbf3537Syasuoka int sz, lpkt, hdrlen; 3930fbf3537Syasuoka u_char *pkt; 3940fbf3537Syasuoka pptp_ctrl *_this; 3950fbf3537Syasuoka 3960fbf3537Syasuoka _this = ctx; 3970fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 3980fbf3537Syasuoka 3990fbf3537Syasuoka _this->on_io_event = 1; 4000fbf3537Syasuoka if ((evmask & EV_WRITE) != 0) { 4010fbf3537Syasuoka if (pptp_ctrl_output_flush(_this) != 0 || 4020fbf3537Syasuoka _this->state == PPTP_CTRL_STATE_DISPOSING) 403f0a4e295Syasuoka goto fail; 4040fbf3537Syasuoka _this->send_ready = 1; 4050fbf3537Syasuoka } 4060fbf3537Syasuoka if ((evmask & EV_READ) != 0) { 4070fbf3537Syasuoka sz = read(_this->sock, bytebuffer_pointer(_this->recv_buf), 4080fbf3537Syasuoka bytebuffer_remaining(_this->recv_buf)); 4090fbf3537Syasuoka if (sz <= 0) { 4109a200ddfSyasuoka if (sz == 0 || errno == ECONNRESET) { 4110fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 4120fbf3537Syasuoka "Connection closed by foreign host"); 4130fbf3537Syasuoka pptp_ctrl_fini(_this); 414f0a4e295Syasuoka goto fail; 4150fbf3537Syasuoka } else if (errno != EAGAIN && errno != EINTR) { 4160fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 4170fbf3537Syasuoka "read() failed at %s(): %m", __func__); 4180fbf3537Syasuoka pptp_ctrl_fini(_this); 419f0a4e295Syasuoka goto fail; 4200fbf3537Syasuoka } 4210fbf3537Syasuoka } 4220fbf3537Syasuoka bytebuffer_put(_this->recv_buf, BYTEBUFFER_PUT_DIRECT, sz); 4230fbf3537Syasuoka bytebuffer_flip(_this->recv_buf); 4240fbf3537Syasuoka 4250fbf3537Syasuoka for (;;) { 4260fbf3537Syasuoka pkt = bytebuffer_pointer(_this->recv_buf); 4270fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->recv_buf); 4280fbf3537Syasuoka if (pkt == NULL || 4290fbf3537Syasuoka lpkt < sizeof(struct pptp_ctrl_header)) 4300fbf3537Syasuoka break; /* read again */ 4310fbf3537Syasuoka 4320fbf3537Syasuoka hdrlen = pkt[0] << 8 | pkt[1]; 4330fbf3537Syasuoka if (lpkt < hdrlen) 4340fbf3537Syasuoka break; /* read again */ 4350fbf3537Syasuoka 4360fbf3537Syasuoka bytebuffer_get(_this->recv_buf, NULL, hdrlen); 4370fbf3537Syasuoka if (pptp_ctrl_input(_this, pkt, hdrlen) != 0 || 4380fbf3537Syasuoka _this->state == PPTP_CTRL_STATE_DISPOSING) { 4390fbf3537Syasuoka bytebuffer_compact(_this->recv_buf); 440f0a4e295Syasuoka goto fail; 4410fbf3537Syasuoka } 4420fbf3537Syasuoka } 4430fbf3537Syasuoka bytebuffer_compact(_this->recv_buf); 4440fbf3537Syasuoka } 4450fbf3537Syasuoka if (pptp_ctrl_output_flush(_this) != 0) 446f0a4e295Syasuoka goto fail; 4470fbf3537Syasuoka pptp_ctrl_set_io_event(_this); 448f0a4e295Syasuoka fail: 4490fbf3537Syasuoka _this->on_io_event = 0; 4500fbf3537Syasuoka } 4510fbf3537Syasuoka 4520fbf3537Syasuoka 453f0a4e295Syasuoka /* set i/o event mask */ 4540fbf3537Syasuoka static void 4550fbf3537Syasuoka pptp_ctrl_set_io_event(pptp_ctrl *_this) 4560fbf3537Syasuoka { 4570fbf3537Syasuoka int evmask; 4580fbf3537Syasuoka 4590fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 4600fbf3537Syasuoka PPTP_CTRL_ASSERT(_this->sock >= 0); 4610fbf3537Syasuoka 4620fbf3537Syasuoka evmask = 0; 4630fbf3537Syasuoka if (bytebuffer_remaining(_this->recv_buf) > 128) 4640fbf3537Syasuoka evmask |= EV_READ; 4650fbf3537Syasuoka if (_this->send_ready == 0) 4660fbf3537Syasuoka evmask |= EV_WRITE; 4670fbf3537Syasuoka 4680fbf3537Syasuoka event_del(&_this->ev_sock); 4690fbf3537Syasuoka if (evmask != 0) { 4700fbf3537Syasuoka event_set(&_this->ev_sock, _this->sock, evmask, 4710fbf3537Syasuoka pptp_ctrl_io_event, _this); 4720fbf3537Syasuoka event_add(&_this->ev_sock, NULL); 4730fbf3537Syasuoka } 4740fbf3537Syasuoka } 4750fbf3537Syasuoka 4760fbf3537Syasuoka /** 477f0a4e295Syasuoka * Output PPTP control packet 478f0a4e295Syasuoka * @param pkt pointer to packet buffer. 479f0a4e295Syasuoka * when it was appended by _this-.send_buf using bytebuffer, 480f0a4e295Syasuoka * specify NULL. 481f0a4e295Syasuoka * @param lpkt packet length 4820fbf3537Syasuoka */ 4830fbf3537Syasuoka void 4840fbf3537Syasuoka pptp_ctrl_output(pptp_ctrl *_this, u_char *pkt, int lpkt) 4850fbf3537Syasuoka { 4860fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 4870fbf3537Syasuoka PPTP_CTRL_ASSERT(lpkt > 0); 4880fbf3537Syasuoka 489f0a4e295Syasuoka /* just put the packet into the buffer now. send it later */ 4900fbf3537Syasuoka bytebuffer_put(_this->send_buf, pkt, lpkt); 4910fbf3537Syasuoka 4920fbf3537Syasuoka if (_this->on_io_event != 0) { 493f0a4e295Syasuoka /* 494f0a4e295Syasuoka * pptp_ctrl_output_flush() will be called by the end of 495f0a4e295Syasuoka * the I/O event handler. 496f0a4e295Syasuoka */ 4970fbf3537Syasuoka } else { 4980fbf3537Syasuoka /* 499f0a4e295Syasuoka * When this function is called by other than I/O event handler, 500f0a4e295Syasuoka * we need to call pptp_ctrl_output_flush(). However if we do 501f0a4e295Syasuoka * it here, then we need to consider the situation 502f0a4e295Syasuoka * 'flush => write failure => finalize'. The situation requires 503f0a4e295Syasuoka * the caller function to handle the exception and causes 504f0a4e295Syasuoka * complication. So we call pptp_ctrl_output_flush() by the 505f0a4e295Syasuoka * the next send ready event. 5060fbf3537Syasuoka */ 507f0a4e295Syasuoka _this->send_ready = 0; /* clear 'send ready' */ 508f0a4e295Syasuoka pptp_ctrl_set_io_event(_this); /* wait 'send ready */ 5090fbf3537Syasuoka } 5100fbf3537Syasuoka 5110fbf3537Syasuoka return; 5120fbf3537Syasuoka } 5130fbf3537Syasuoka 514f0a4e295Syasuoka /* Send Stop-Control-Connection-Request */ 5150fbf3537Syasuoka 516f0a4e295Syasuoka /* flush output packet */ 5170fbf3537Syasuoka static int 5180fbf3537Syasuoka pptp_ctrl_output_flush(pptp_ctrl *_this) 5190fbf3537Syasuoka { 5200fbf3537Syasuoka int sz; 5210fbf3537Syasuoka time_t curr_time; 5220fbf3537Syasuoka 5230fbf3537Syasuoka curr_time = get_monosec(); 5240fbf3537Syasuoka 5250fbf3537Syasuoka if (bytebuffer_position(_this->send_buf) <= 0) 526f0a4e295Syasuoka return 0; /* nothing to write */ 5270fbf3537Syasuoka if (_this->send_ready == 0) { 5280fbf3537Syasuoka pptp_ctrl_set_io_event(_this); 529f0a4e295Syasuoka return 0; /* not ready to write */ 5300fbf3537Syasuoka } 5310fbf3537Syasuoka 5320fbf3537Syasuoka bytebuffer_flip(_this->send_buf); 5330fbf3537Syasuoka 534821f7c56Syasuoka if (PPTP_CTRL_CONF(_this)->ctrl_out_pktdump != 0) { 5350fbf3537Syasuoka pptp_ctrl_log(_this, LOG_DEBUG, "PPTP Control output packet"); 5360fbf3537Syasuoka show_hd(debug_get_debugfp(), 5370fbf3537Syasuoka bytebuffer_pointer(_this->send_buf), 5380fbf3537Syasuoka bytebuffer_remaining(_this->send_buf)); 5390fbf3537Syasuoka } 5400fbf3537Syasuoka if ((sz = write(_this->sock, bytebuffer_pointer(_this->send_buf), 5410fbf3537Syasuoka bytebuffer_remaining(_this->send_buf))) < 0) { 5420fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "write to socket failed: %m"); 5430fbf3537Syasuoka pptp_ctrl_fini(_this); 5440fbf3537Syasuoka 5450fbf3537Syasuoka return 1; 5460fbf3537Syasuoka } 5470fbf3537Syasuoka _this->last_snd_ctrl = curr_time; 5480fbf3537Syasuoka bytebuffer_get(_this->send_buf, NULL, sz); 5490fbf3537Syasuoka bytebuffer_compact(_this->send_buf); 5500fbf3537Syasuoka _this->send_ready = 0; 5510fbf3537Syasuoka 5520fbf3537Syasuoka return 0; 5530fbf3537Syasuoka } 5540fbf3537Syasuoka 555f0a4e295Syasuoka /* convert Start-Control-Connection-{Request,Reply} packet to strings */ 5560fbf3537Syasuoka static void 5570fbf3537Syasuoka pptp_ctrl_SCCRx_string(struct pptp_scc *scc, u_char *buf, int lbuf) 5580fbf3537Syasuoka { 5590fbf3537Syasuoka char buf1[128], buf2[128], buf3[128]; 5600fbf3537Syasuoka 561f0a4e295Syasuoka /* sanity check */ 5620fbf3537Syasuoka strlcpy(buf1, scc->host_name, sizeof(buf1)); 5630fbf3537Syasuoka strlcpy(buf2, scc->vendor_string, sizeof(buf2)); 5640fbf3537Syasuoka 5650fbf3537Syasuoka if (scc->result_code != 0) 5660fbf3537Syasuoka snprintf(buf3, sizeof(buf3), "result=%d error=%d ", 5670fbf3537Syasuoka scc->result_code, scc->error_code); 5680fbf3537Syasuoka else 5690fbf3537Syasuoka buf3[0] = '\0'; 5700fbf3537Syasuoka 5710fbf3537Syasuoka snprintf(buf, lbuf, 5720fbf3537Syasuoka "protocol_version=%d.%d %sframing=%s bearer=%s max_channels=%d " 5730fbf3537Syasuoka "firmware_revision=%d(0x%04x) host_name=\"%s\" " 5740fbf3537Syasuoka "vendor_string=\"%s\"", 5750fbf3537Syasuoka scc->protocol_version >> 8, scc->protocol_version & 0xff, buf3, 5760fbf3537Syasuoka pptp_framing_string(scc->framing_caps), 5770fbf3537Syasuoka pptp_bearer_string(scc->bearer_caps), scc->max_channels, 5780fbf3537Syasuoka scc->firmware_revision, scc->firmware_revision, buf1, buf2); 5790fbf3537Syasuoka } 5800fbf3537Syasuoka 581f0a4e295Syasuoka /* receive Start-Control-Connection-Request */ 5820fbf3537Syasuoka static int 5830fbf3537Syasuoka pptp_ctrl_recv_SCCRQ(pptp_ctrl *_this, u_char *pkt, int lpkt) 5840fbf3537Syasuoka { 5850fbf3537Syasuoka char logbuf[512]; 5860fbf3537Syasuoka struct pptp_scc *scc; 5870fbf3537Syasuoka 588f0a4e295Syasuoka /* sanity check */ 5890fbf3537Syasuoka if (lpkt < sizeof(struct pptp_scc)) { 5900fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad SCCRQ: packet too " 5910fbf3537Syasuoka "short: %d < %d", lpkt, (int)sizeof(struct pptp_scc)); 5920fbf3537Syasuoka return 1; 5930fbf3537Syasuoka } 5940fbf3537Syasuoka scc = (struct pptp_scc *)pkt; 5950fbf3537Syasuoka 5960fbf3537Syasuoka scc->protocol_version = ntohs(scc->protocol_version); 5970fbf3537Syasuoka scc->framing_caps = htonl(scc->framing_caps); 5980fbf3537Syasuoka scc->bearer_caps = htonl(scc->bearer_caps); 5990fbf3537Syasuoka scc->max_channels = htons(scc->max_channels); 6000fbf3537Syasuoka scc->firmware_revision = htons(scc->firmware_revision); 6010fbf3537Syasuoka 602f0a4e295Syasuoka /* check protocol version */ 6030fbf3537Syasuoka if (scc->protocol_version != PPTP_RFC_2637_VERSION) { 6040fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad SCCRQ: " 6050fbf3537Syasuoka "unknown protocol version %d", scc->protocol_version); 6060fbf3537Syasuoka return 1; 6070fbf3537Syasuoka } 6080fbf3537Syasuoka 6090fbf3537Syasuoka pptp_ctrl_SCCRx_string(scc, logbuf, sizeof(logbuf)); 6100fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "RecvSCCRQ %s", logbuf); 6110fbf3537Syasuoka 6120fbf3537Syasuoka return 0; 6130fbf3537Syasuoka } 6140fbf3537Syasuoka 615f0a4e295Syasuoka /* Receive Stop-Control-Connection-Reply */ 6160fbf3537Syasuoka static int 6170fbf3537Syasuoka pptp_ctrl_recv_StopCCRP(pptp_ctrl *_this, u_char *pkt, int lpkt) 6180fbf3537Syasuoka { 6190fbf3537Syasuoka struct pptp_stop_ccrp *stop_ccrp; 6200fbf3537Syasuoka 6210fbf3537Syasuoka if (lpkt < sizeof(struct pptp_stop_ccrp)) { 6220fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad StopCCRP: packet " 6230fbf3537Syasuoka "too short: %d < %d", lpkt, 6240fbf3537Syasuoka (int)sizeof(struct pptp_stop_ccrp)); 6250fbf3537Syasuoka return 1; 6260fbf3537Syasuoka } 6270fbf3537Syasuoka stop_ccrp = (struct pptp_stop_ccrp *)pkt; 6280fbf3537Syasuoka 6290fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "RecvStopCCRP reason=%s(%u)", 6300fbf3537Syasuoka pptp_StopCCRP_result_string(stop_ccrp->result), stop_ccrp->result); 6310fbf3537Syasuoka 6320fbf3537Syasuoka return 0; 6330fbf3537Syasuoka } 6340fbf3537Syasuoka 6350fbf3537Syasuoka static int 6360fbf3537Syasuoka pptp_ctrl_send_StopCCRQ(pptp_ctrl *_this, int reason) 6370fbf3537Syasuoka { 6380fbf3537Syasuoka int lpkt; 6390fbf3537Syasuoka struct pptp_stop_ccrq *stop_ccrq; 6400fbf3537Syasuoka 6410fbf3537Syasuoka stop_ccrq = bytebuffer_pointer(_this->send_buf); 6420fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 6430fbf3537Syasuoka if (lpkt < sizeof(struct pptp_stop_ccrq)) { 6440fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 6450fbf3537Syasuoka "SendCCRP failed: No buffer space available"); 6460fbf3537Syasuoka return -1; 6470fbf3537Syasuoka } 6480fbf3537Syasuoka memset(stop_ccrq, 0, sizeof(struct pptp_stop_ccrq)); 6490fbf3537Syasuoka 6500fbf3537Syasuoka pptp_init_header(&stop_ccrq->header, sizeof(struct pptp_stop_ccrq), 6510fbf3537Syasuoka PPTP_CTRL_MES_CODE_StopCCRQ); 6520fbf3537Syasuoka 6530fbf3537Syasuoka stop_ccrq->reason = reason; 6540fbf3537Syasuoka 6550fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "SendStopCCRQ reason=%s(%u)", 6560fbf3537Syasuoka pptp_StopCCRQ_reason_string(stop_ccrq->reason), stop_ccrq->reason); 6570fbf3537Syasuoka 6580fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_stop_ccrq)); 6590fbf3537Syasuoka 6600fbf3537Syasuoka return 0; 6610fbf3537Syasuoka } 6620fbf3537Syasuoka 663f0a4e295Syasuoka /* Receive Stop-Control-Connection-Request */ 6640fbf3537Syasuoka static int 6650fbf3537Syasuoka pptp_ctrl_recv_StopCCRQ(pptp_ctrl *_this, u_char *pkt, int lpkt) 6660fbf3537Syasuoka { 6670fbf3537Syasuoka struct pptp_stop_ccrq *stop_ccrq; 6680fbf3537Syasuoka 6690fbf3537Syasuoka if (lpkt < sizeof(struct pptp_stop_ccrq)) { 6700fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad StopCCRQ: packet " 6710fbf3537Syasuoka "too short: %d < %d", lpkt, 6720fbf3537Syasuoka (int)sizeof(struct pptp_stop_ccrq)); 6730fbf3537Syasuoka return 1; 6740fbf3537Syasuoka } 6750fbf3537Syasuoka stop_ccrq = (struct pptp_stop_ccrq *)pkt; 6760fbf3537Syasuoka 6770fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "RecvStopCCRQ reason=%s(%u)", 6780fbf3537Syasuoka pptp_StopCCRQ_reason_string(stop_ccrq->reason), stop_ccrq->reason); 6790fbf3537Syasuoka 6800fbf3537Syasuoka return 0; 6810fbf3537Syasuoka } 6820fbf3537Syasuoka 683f0a4e295Syasuoka /* Send Stop-Control-Connection-Reply */ 6840fbf3537Syasuoka static int 6850fbf3537Syasuoka pptp_ctrl_send_StopCCRP(pptp_ctrl *_this, int result, int error) 6860fbf3537Syasuoka { 6870fbf3537Syasuoka int lpkt; 6880fbf3537Syasuoka struct pptp_stop_ccrp *stop_ccrp; 6890fbf3537Syasuoka 6900fbf3537Syasuoka stop_ccrp = bytebuffer_pointer(_this->send_buf); 6910fbf3537Syasuoka 6920fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 6930fbf3537Syasuoka if (lpkt < sizeof(struct pptp_stop_ccrp)) { 6940fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 6950fbf3537Syasuoka "SendCCRQ failed: No buffer space available"); 6960fbf3537Syasuoka return -1; 6970fbf3537Syasuoka } 6980fbf3537Syasuoka memset(stop_ccrp, 0, sizeof(struct pptp_stop_ccrp)); 6990fbf3537Syasuoka 7000fbf3537Syasuoka pptp_init_header(&stop_ccrp->header, sizeof(struct pptp_stop_ccrp), 7010fbf3537Syasuoka PPTP_CTRL_MES_CODE_StopCCRP); 7020fbf3537Syasuoka 7030fbf3537Syasuoka stop_ccrp->result = result; 7040fbf3537Syasuoka stop_ccrp->error = error; 7050fbf3537Syasuoka 7060fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 7070fbf3537Syasuoka "SendStopCCRP result=%s(%u) error=%s(%u)", 7080fbf3537Syasuoka pptp_StopCCRP_result_string(stop_ccrp->result), stop_ccrp->result, 7090fbf3537Syasuoka pptp_general_error_string(stop_ccrp->error), stop_ccrp->error); 7100fbf3537Syasuoka 7110fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_stop_ccrp)); 7120fbf3537Syasuoka 7130fbf3537Syasuoka return 0; 7140fbf3537Syasuoka } 7150fbf3537Syasuoka 716f0a4e295Syasuoka /* Send Start-Control-Connection-Reply */ 7170fbf3537Syasuoka static int 7180fbf3537Syasuoka pptp_ctrl_send_SCCRP(pptp_ctrl *_this, int result, int error) 7190fbf3537Syasuoka { 7200fbf3537Syasuoka int lpkt; 7210fbf3537Syasuoka struct pptp_scc *scc; 7220fbf3537Syasuoka char logbuf[512]; 7230fbf3537Syasuoka const char *val; 7240fbf3537Syasuoka 7250fbf3537Syasuoka scc = bytebuffer_pointer(_this->send_buf); 7260fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 7270fbf3537Syasuoka if (lpkt < sizeof(struct pptp_scc)) { 7280fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 7290fbf3537Syasuoka "SendSCCRP failed: No buffer space available"); 7300fbf3537Syasuoka return -1; 7310fbf3537Syasuoka } 7320fbf3537Syasuoka memset(scc, 0, sizeof(struct pptp_scc)); 7330fbf3537Syasuoka 7340fbf3537Syasuoka pptp_init_header(&scc->header, sizeof(struct pptp_scc), 7350fbf3537Syasuoka PPTP_CTRL_MES_CODE_SCCRP); 7360fbf3537Syasuoka 7370fbf3537Syasuoka scc->protocol_version = PPTP_RFC_2637_VERSION; 7380fbf3537Syasuoka scc->result_code = result; 7390fbf3537Syasuoka scc->error_code = error; 740f0a4e295Syasuoka 741f0a4e295Syasuoka /* XXX only support sync frames */ 7420fbf3537Syasuoka scc->framing_caps = PPTP_CTRL_FRAMING_SYNC; 7430fbf3537Syasuoka scc->bearer_caps = PPTP_CTRL_BEARER_DIGITAL; 7440fbf3537Syasuoka 745f0a4e295Syasuoka scc->max_channels = 4; /* XXX */ 7460fbf3537Syasuoka scc->firmware_revision = MAJOR_VERSION << 8 | MINOR_VERSION; 7470fbf3537Syasuoka 748f0a4e295Syasuoka /* this implementation only support these strings up to 749f0a4e295Syasuoka * 63 character */ 750f0a4e295Syasuoka /* host name */ 751821f7c56Syasuoka 752e402d49cSyasuoka if ((val = PPTP_CTRL_CONF(_this)->hostname) == NULL) 7530fbf3537Syasuoka val = ""; 7540fbf3537Syasuoka strlcpy(scc->host_name, val, sizeof(scc->host_name)); 7550fbf3537Syasuoka 756f0a4e295Syasuoka /* vender name */ 757821f7c56Syasuoka if (PPTP_CTRL_CONF(_this)->vendor_name == NULL) 7580fbf3537Syasuoka val = PPTPD_DEFAULT_VENDOR_NAME; 7590fbf3537Syasuoka strlcpy(scc->vendor_string, val, sizeof(scc->vendor_string)); 7600fbf3537Syasuoka 7610fbf3537Syasuoka pptp_ctrl_SCCRx_string(scc, logbuf, sizeof(logbuf)); 7620fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "SendSCCRP %s", logbuf); 7630fbf3537Syasuoka 7640fbf3537Syasuoka scc->protocol_version = htons(scc->protocol_version); 7650fbf3537Syasuoka scc->framing_caps = htonl(scc->framing_caps); 7660fbf3537Syasuoka scc->bearer_caps = htonl(scc->bearer_caps); 7670fbf3537Syasuoka scc->max_channels = htons(scc->max_channels); 7680fbf3537Syasuoka scc->firmware_revision = htons(scc->firmware_revision); 7690fbf3537Syasuoka 7700fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_scc)); 7710fbf3537Syasuoka 7720fbf3537Syasuoka return 0; 7730fbf3537Syasuoka } 7740fbf3537Syasuoka 775f0a4e295Syasuoka /* receive ECHO and reply */ 7760fbf3537Syasuoka static void 7770fbf3537Syasuoka pptp_ctrl_process_echo_req(pptp_ctrl *_this, u_char *pkt, int lpkt) 7780fbf3537Syasuoka { 7790fbf3537Syasuoka struct pptp_echo_rq *echo_rq; 7800fbf3537Syasuoka struct pptp_echo_rp *echo_rp; 7810fbf3537Syasuoka 7820fbf3537Syasuoka if (lpkt < sizeof(struct pptp_echo_rq)) { 7830fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad EchoReq: packet " 7840fbf3537Syasuoka "too short: %d < %d", lpkt, 7850fbf3537Syasuoka (int)sizeof(struct pptp_echo_rq)); 7860fbf3537Syasuoka return; 7870fbf3537Syasuoka } 7880fbf3537Syasuoka echo_rq = (struct pptp_echo_rq *)pkt; 7890fbf3537Syasuoka 7900fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "RecvEchoReq")); 7910fbf3537Syasuoka 7920fbf3537Syasuoka echo_rp = bytebuffer_pointer(_this->send_buf); 7930fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 7940fbf3537Syasuoka if (echo_rp == NULL || lpkt < sizeof(struct pptp_echo_rp)) { 7950fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 7960fbf3537Syasuoka "Failed to send EchoReq: No buffer space available"); 7970fbf3537Syasuoka return; 7980fbf3537Syasuoka } 7990fbf3537Syasuoka memset(echo_rp, 0, sizeof(struct pptp_echo_rp)); 8000fbf3537Syasuoka 8010fbf3537Syasuoka pptp_init_header(&echo_rp->header, sizeof(struct pptp_echo_rp), 8020fbf3537Syasuoka PPTP_CTRL_MES_CODE_ECHO_RP); 8030fbf3537Syasuoka 8040fbf3537Syasuoka echo_rp->identifier = echo_rq->identifier; 8050fbf3537Syasuoka echo_rp->result_code = PPTP_ECHO_RP_RESULT_OK; 8060fbf3537Syasuoka echo_rp->error_code = PPTP_ERROR_NONE; 8070fbf3537Syasuoka echo_rp->reserved1 = htons(0); 8080fbf3537Syasuoka 8090fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_echo_rp)); 8100fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "SendEchoReply")); 8110fbf3537Syasuoka } 8120fbf3537Syasuoka 813f0a4e295Syasuoka /* receiver Echo-Reply */ 8140fbf3537Syasuoka static int 8150fbf3537Syasuoka pptp_ctrl_recv_echo_rep(pptp_ctrl *_this, u_char *pkt, int lpkt) 8160fbf3537Syasuoka { 8170fbf3537Syasuoka struct pptp_echo_rp *echo_rp; 8180fbf3537Syasuoka 8190fbf3537Syasuoka if (lpkt < sizeof(struct pptp_echo_rp)) { 8200fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad EchoReq: packet " 8210fbf3537Syasuoka "too short: %d < %d", lpkt, 8220fbf3537Syasuoka (int)sizeof(struct pptp_echo_rp)); 8230fbf3537Syasuoka return 1; 8240fbf3537Syasuoka } 8250fbf3537Syasuoka echo_rp = (struct pptp_echo_rp *)pkt; 8260fbf3537Syasuoka 8270fbf3537Syasuoka if (echo_rp->result_code != PPTP_ECHO_RP_RESULT_OK) { 8280fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received negative EchoReply: %s", 8290fbf3537Syasuoka pptp_general_error_string(echo_rp->error_code)); 8300fbf3537Syasuoka return 1; 8310fbf3537Syasuoka } 8320fbf3537Syasuoka if (_this->echo_seq != ntohl(echo_rp->identifier)) { 8330fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad EchoReply: " 8340fbf3537Syasuoka "Identifier mismatch sent=%u recv=%u", 8350fbf3537Syasuoka _this->echo_seq , ntohl(echo_rp->identifier)); 8360fbf3537Syasuoka return 1; 8370fbf3537Syasuoka } 8380fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "RecvEchoReply")); 8390fbf3537Syasuoka return 0; 8400fbf3537Syasuoka } 8410fbf3537Syasuoka 842f0a4e295Syasuoka /* send Echo-Request */ 8430fbf3537Syasuoka static void 8440fbf3537Syasuoka pptp_ctrl_send_echo_req(pptp_ctrl *_this) 8450fbf3537Syasuoka { 8460fbf3537Syasuoka int lpkt; 8470fbf3537Syasuoka struct pptp_echo_rq *echo_rq; 8480fbf3537Syasuoka 8490fbf3537Syasuoka echo_rq = (struct pptp_echo_rq *)bytebuffer_pointer(_this->send_buf); 8500fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 8510fbf3537Syasuoka if (echo_rq == NULL || lpkt < sizeof(struct pptp_echo_rq)) { 8520fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 8530fbf3537Syasuoka "SendEchoReq failed: No buffer space available"); 8540fbf3537Syasuoka return; 8550fbf3537Syasuoka } 8560fbf3537Syasuoka memset(echo_rq, 0, sizeof(struct pptp_echo_rq)); 8570fbf3537Syasuoka 8580fbf3537Syasuoka pptp_init_header(&echo_rq->header, sizeof(struct pptp_echo_rq), 8590fbf3537Syasuoka PPTP_CTRL_MES_CODE_ECHO_RQ); 8600fbf3537Syasuoka 8610fbf3537Syasuoka echo_rq->identifier = htonl(_this->echo_seq); 8620fbf3537Syasuoka 8630fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_echo_rq)); 8640fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "SendEchoReq")); 8650fbf3537Syasuoka } 8660fbf3537Syasuoka 867f0a4e295Syasuoka /* send Call-Disconnect-Notify */ 8680fbf3537Syasuoka static void 8690fbf3537Syasuoka pptp_ctrl_send_CDN(pptp_ctrl *_this, int result, int error, int cause, 8700fbf3537Syasuoka const char *statistics) 8710fbf3537Syasuoka { 8720fbf3537Syasuoka int lpkt; 8730fbf3537Syasuoka struct pptp_cdn *cdn; 8740fbf3537Syasuoka 8750fbf3537Syasuoka cdn = bytebuffer_pointer(_this->send_buf); 8760fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 8770fbf3537Syasuoka if (lpkt < sizeof(struct pptp_cdn)) { 8780fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 8790fbf3537Syasuoka "SendCCR failed: No buffer space available"); 8800fbf3537Syasuoka return; 8810fbf3537Syasuoka } 8820fbf3537Syasuoka memset(cdn, 0, sizeof(struct pptp_cdn)); 8830fbf3537Syasuoka 8840fbf3537Syasuoka pptp_init_header(&cdn->header, sizeof(struct pptp_cdn), 8850fbf3537Syasuoka PPTP_CTRL_MES_CODE_CDN); 8860fbf3537Syasuoka 8870fbf3537Syasuoka cdn->call_id = _this->id; 8880fbf3537Syasuoka cdn->result_code = result; 8890fbf3537Syasuoka cdn->error_code = error; 8900fbf3537Syasuoka cdn->cause_code = cause; 8910fbf3537Syasuoka if (statistics != NULL) 8920fbf3537Syasuoka strlcpy(cdn->statistics, statistics, sizeof(cdn->statistics)); 8930fbf3537Syasuoka 8940fbf3537Syasuoka cdn->call_id = htons(cdn->call_id); 8950fbf3537Syasuoka cdn->cause_code = htons(cdn->cause_code); 8960fbf3537Syasuoka 8970fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_cdn)); 8980fbf3537Syasuoka } 8990fbf3537Syasuoka 900f0a4e295Syasuoka /* receive Control-packet */ 9010fbf3537Syasuoka static int 9020fbf3537Syasuoka pptp_ctrl_input(pptp_ctrl *_this, u_char *pkt, int lpkt) 9030fbf3537Syasuoka { 9040fbf3537Syasuoka char errmes[256]; 9050fbf3537Syasuoka time_t curr_time; 9060fbf3537Syasuoka struct pptp_ctrl_header *hdr; 9070fbf3537Syasuoka 9080fbf3537Syasuoka PPTP_CTRL_ASSERT(lpkt >= sizeof(struct pptp_ctrl_header)); 9090fbf3537Syasuoka 9100fbf3537Syasuoka curr_time = get_monosec(); 9110fbf3537Syasuoka hdr = (struct pptp_ctrl_header *)pkt; 9120fbf3537Syasuoka 9130fbf3537Syasuoka hdr->length = ntohs(hdr->length); 9140fbf3537Syasuoka hdr->pptp_message_type = ntohs(hdr->pptp_message_type); 9150fbf3537Syasuoka hdr->magic_cookie = ntohl(hdr->magic_cookie); 9160fbf3537Syasuoka hdr->control_message_type = ntohs(hdr->control_message_type); 9170fbf3537Syasuoka hdr->reserved0 = ntohs(hdr->reserved0); 9180fbf3537Syasuoka 919f0a4e295Syasuoka /* sanity check */ 9200fbf3537Syasuoka PPTP_CTRL_ASSERT(hdr->length <= lpkt); 9210fbf3537Syasuoka 9220fbf3537Syasuoka _this->last_rcv_ctrl = curr_time; 9230fbf3537Syasuoka 924821f7c56Syasuoka if (PPTP_CTRL_CONF(_this)->ctrl_in_pktdump != 0) { 9250fbf3537Syasuoka pptp_ctrl_log(_this, LOG_DEBUG, 9260fbf3537Syasuoka "PPTP Control input packet dump: mestype=%s(%d)", 9270fbf3537Syasuoka pptp_ctrl_mes_type_string(hdr->control_message_type), 9280fbf3537Syasuoka hdr->control_message_type); 9290fbf3537Syasuoka show_hd(debug_get_debugfp(), pkt, lpkt); 9300fbf3537Syasuoka } 9310fbf3537Syasuoka 932f0a4e295Syasuoka /* inspect packet body */ 933f0a4e295Syasuoka /* message type */ 9340fbf3537Syasuoka if (hdr->pptp_message_type != PPTP_MES_TYPE_CTRL) { 9350fbf3537Syasuoka snprintf(errmes, sizeof(errmes), "unknown message type %d", 9360fbf3537Syasuoka hdr->pptp_message_type); 9370fbf3537Syasuoka goto bad_packet; 9380fbf3537Syasuoka } 939f0a4e295Syasuoka /* magic cookie */ 9400fbf3537Syasuoka if (hdr->magic_cookie != PPTP_MAGIC_COOKIE) { 9410fbf3537Syasuoka snprintf(errmes, sizeof(errmes), "wrong magic %08x != %08x", 9420fbf3537Syasuoka hdr->magic_cookie, PPTP_MAGIC_COOKIE); 9430fbf3537Syasuoka goto bad_packet; 9440fbf3537Syasuoka } 9450fbf3537Syasuoka 946f0a4e295Syasuoka /* As there is possibility of state conflicts, 947f0a4e295Syasuoka * ECHO Reply requiries special care. 948f0a4e295Syasuoka */ 9490fbf3537Syasuoka switch (hdr->control_message_type) { 9500fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ECHO_RP: 9510fbf3537Syasuoka if (pptp_ctrl_recv_echo_rep(_this, pkt, lpkt) != 0) { 9520fbf3537Syasuoka pptp_ctrl_fini(_this); 9530fbf3537Syasuoka return 1; 9540fbf3537Syasuoka } 9550fbf3537Syasuoka return 0; 9560fbf3537Syasuoka } 957f0a4e295Syasuoka 9580fbf3537Syasuoka /* 959f0a4e295Syasuoka * State machine 9600fbf3537Syasuoka */ 9610fbf3537Syasuoka switch (_this->state) { 9620fbf3537Syasuoka case PPTP_CTRL_STATE_IDLE: 9630fbf3537Syasuoka switch (hdr->control_message_type) { 9640fbf3537Syasuoka case PPTP_CTRL_MES_CODE_SCCRQ: 9650fbf3537Syasuoka if (pptp_ctrl_recv_SCCRQ(_this, pkt, lpkt) != 0) { 9660fbf3537Syasuoka return 0; 9670fbf3537Syasuoka } 9680fbf3537Syasuoka if (pptp_ctrl_send_SCCRP(_this, 9690fbf3537Syasuoka PPTP_SCCRP_RESULT_SUCCESS, PPTP_ERROR_NONE) != 0) { 9700fbf3537Syasuoka return 0; 9710fbf3537Syasuoka } 9720fbf3537Syasuoka _this->state = PPTP_CTRL_STATE_ESTABLISHED; 9730fbf3537Syasuoka return 0; 9740fbf3537Syasuoka default: 9750fbf3537Syasuoka break; 9760fbf3537Syasuoka } 9770fbf3537Syasuoka break; 9780fbf3537Syasuoka case PPTP_CTRL_STATE_ESTABLISHED: 9790fbf3537Syasuoka switch (hdr->control_message_type) { 9800fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ECHO_RQ: 9810fbf3537Syasuoka pptp_ctrl_process_echo_req(_this, pkt, lpkt); 9820fbf3537Syasuoka return 0; 983f0a4e295Syasuoka /* dispatch to pptp_call_input() if it is call-related-packet */ 9840fbf3537Syasuoka case PPTP_CTRL_MES_CODE_SLI: 9850fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICRQ: 9860fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICRP: 9870fbf3537Syasuoka case PPTP_CTRL_MES_CODE_OCRQ: 9880fbf3537Syasuoka case PPTP_CTRL_MES_CODE_OCRP: 9890fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICCN: 9900fbf3537Syasuoka case PPTP_CTRL_MES_CODE_CDN: 9910fbf3537Syasuoka case PPTP_CTRL_MES_CODE_CCR: 9920fbf3537Syasuoka return pptp_ctrl_call_input(_this, 9930fbf3537Syasuoka hdr->control_message_type, pkt, lpkt); 9940fbf3537Syasuoka case PPTP_CTRL_MES_CODE_StopCCRQ: 9950fbf3537Syasuoka if (pptp_ctrl_recv_StopCCRQ(_this, pkt, lpkt) != 0) { 9960fbf3537Syasuoka pptp_ctrl_stop(_this, 9970fbf3537Syasuoka PPTP_StopCCRQ_REASON_STOP_PROTOCOL); 9980fbf3537Syasuoka return 0; 9990fbf3537Syasuoka } 10000fbf3537Syasuoka if (pptp_ctrl_send_StopCCRP(_this, 10010fbf3537Syasuoka PPTP_StopCCRP_RESULT_OK, PPTP_ERROR_NONE)!= 0) { 10020fbf3537Syasuoka return 0; 10030fbf3537Syasuoka } 10040fbf3537Syasuoka pptp_ctrl_fini(_this); 10050fbf3537Syasuoka return 1; 10060fbf3537Syasuoka default: 10070fbf3537Syasuoka break; 10080fbf3537Syasuoka } 10090fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_STOP_REPLY: 10100fbf3537Syasuoka switch (hdr->control_message_type) { 10110fbf3537Syasuoka case PPTP_CTRL_MES_CODE_StopCCRP: 10120fbf3537Syasuoka pptp_ctrl_recv_StopCCRP(_this, pkt, lpkt); 10130fbf3537Syasuoka pptp_ctrl_fini(_this); 10140fbf3537Syasuoka return 1; 10150fbf3537Syasuoka } 10160fbf3537Syasuoka break; 10170fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_CTRL_REPLY: 1018f0a4e295Syasuoka /* XXX this implementation only support PAC mode */ 10190fbf3537Syasuoka break; 10200fbf3537Syasuoka } 10210fbf3537Syasuoka pptp_ctrl_log(_this, LOG_WARNING, 10220fbf3537Syasuoka "Unhandled control message type=%s(%d)", 10230fbf3537Syasuoka pptp_ctrl_mes_type_string(hdr->control_message_type), 10240fbf3537Syasuoka hdr->control_message_type); 10250fbf3537Syasuoka return 0; 10260fbf3537Syasuoka 10270fbf3537Syasuoka bad_packet: 10280fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad packet: %s", errmes); 10290fbf3537Syasuoka pptp_ctrl_stop(_this, PPTP_StopCCRQ_REASON_STOP_PROTOCOL); 10300fbf3537Syasuoka 10310fbf3537Syasuoka return 0; 10320fbf3537Syasuoka } 10330fbf3537Syasuoka 1034f0a4e295Syasuoka /* receiver PPTP Call related messages */ 10350fbf3537Syasuoka static int 10360fbf3537Syasuoka pptp_ctrl_call_input(pptp_ctrl *_this, int mes_type, u_char *pkt, int lpkt) 10370fbf3537Syasuoka { 10380fbf3537Syasuoka int i, call_id, lpkt0; 10390fbf3537Syasuoka pptp_call *call; 10400fbf3537Syasuoka const char *reason; 10410fbf3537Syasuoka u_char *pkt0; 10420fbf3537Syasuoka 10430fbf3537Syasuoka pkt0 = pkt; 10440fbf3537Syasuoka lpkt0 = lpkt; 10450fbf3537Syasuoka call_id = -1; 10460fbf3537Syasuoka pkt += sizeof(struct pptp_ctrl_header); 10470fbf3537Syasuoka lpkt -= sizeof(struct pptp_ctrl_header); 10480fbf3537Syasuoka reason = "(no reason)"; 10490fbf3537Syasuoka 1050f0a4e295Syasuoka /* sanity check */ 10510fbf3537Syasuoka if (lpkt < 4) { 10520fbf3537Syasuoka reason = "received packet is too short"; 10530fbf3537Syasuoka goto badpacket; 10540fbf3537Syasuoka } 10550fbf3537Syasuoka call = NULL; 10560fbf3537Syasuoka call_id = ntohs(*(uint16_t *)pkt); 10570fbf3537Syasuoka 10580fbf3537Syasuoka switch (mes_type) { 10590fbf3537Syasuoka case PPTP_CTRL_MES_CODE_SLI: /* PNS <=> PAC */ 1060f0a4e295Syasuoka /* only SLI contains Call-ID of this peer */ 10610fbf3537Syasuoka for (i = 0; i < slist_length(&_this->call_list); i++) { 10620fbf3537Syasuoka call = slist_get(&_this->call_list, i); 10630fbf3537Syasuoka if (call->id == call_id) 10640fbf3537Syasuoka break; 10650fbf3537Syasuoka call = NULL; 10660fbf3537Syasuoka } 10670fbf3537Syasuoka if (call == NULL) { 10680fbf3537Syasuoka reason = "Call Id is not associated by this control"; 10690fbf3537Syasuoka goto badpacket; 10700fbf3537Syasuoka } 10710fbf3537Syasuoka goto call_searched; 10720fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICRP: /* PNS => PAC */ 10730fbf3537Syasuoka /* 1074f0a4e295Syasuoka * as this implementation never sent ICRQ, this case 1075f0a4e295Syasuoka * should not happen. 1076f0a4e295Syasuoka * But just to make sure, pptp_call.c can handle this 1077f0a4e295Syasuoka * message. 10780fbf3537Syasuoka */ 1079f0a4e295Syasuoka /* FALLTHROUGH */ 10800fbf3537Syasuoka case PPTP_CTRL_MES_CODE_OCRQ: /* PNS => PAC */ 10810fbf3537Syasuoka case PPTP_CTRL_MES_CODE_CCR: /* PNS => PAC */ 1082f0a4e295Syasuoka /* liner-search will be enough */ 10830fbf3537Syasuoka for (i = 0; i < slist_length(&_this->call_list); i++) { 10840fbf3537Syasuoka call = slist_get(&_this->call_list, i); 10850fbf3537Syasuoka if (call->peers_call_id == call_id) 10860fbf3537Syasuoka break; 10870fbf3537Syasuoka call = NULL; 10880fbf3537Syasuoka } 10890fbf3537Syasuoka if (call == NULL && mes_type == PPTP_CTRL_MES_CODE_CCR) { 10900fbf3537Syasuoka pptp_ctrl_send_CDN(_this, PPTP_CDN_RESULT_GENRIC_ERROR, 10910fbf3537Syasuoka PPTP_ERROR_BAD_CALL, 0, NULL); 10920fbf3537Syasuoka goto call_searched; 10930fbf3537Syasuoka } 10940fbf3537Syasuoka if (mes_type == PPTP_CTRL_MES_CODE_OCRQ) { 1095f0a4e295Syasuoka /* make new call */ 10960fbf3537Syasuoka if (call != NULL) { 10970fbf3537Syasuoka pptp_call_input(call, mes_type, pkt0, lpkt0); 10980fbf3537Syasuoka return 0; 10990fbf3537Syasuoka } 11000fbf3537Syasuoka if ((call = pptp_call_create()) == NULL) { 11010fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 11020fbf3537Syasuoka "pptp_call_create() failed: %m"); 1103f0a4e295Syasuoka goto fail; 11040fbf3537Syasuoka } 11050fbf3537Syasuoka if (pptp_call_init(call, _this) != 0) { 11060fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 11070fbf3537Syasuoka "pptp_call_init() failed: %m"); 11080fbf3537Syasuoka pptp_call_destroy(call); 1109f0a4e295Syasuoka goto fail; 11100fbf3537Syasuoka } 11110fbf3537Syasuoka slist_add(&_this->call_list, call); 11120fbf3537Syasuoka } 11130fbf3537Syasuoka call_searched: 11140fbf3537Syasuoka if (call == NULL) { 11150fbf3537Syasuoka reason = "Call Id is not associated by this control"; 11160fbf3537Syasuoka goto badpacket; 11170fbf3537Syasuoka } 11180fbf3537Syasuoka pptp_call_input(call, mes_type, pkt0, lpkt0); 11190fbf3537Syasuoka return 0; 11200fbf3537Syasuoka case PPTP_CTRL_MES_CODE_OCRP: /* PAC => PNS */ 11210fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICRQ: /* PAC => PNS */ 11220fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICCN: /* PAC => PNS */ 11230fbf3537Syasuoka case PPTP_CTRL_MES_CODE_CDN: /* PAC => PNS */ 1124f0a4e295Syasuoka /* don't receive because above messages are only of PNS */ 11250fbf3537Syasuoka default: 11260fbf3537Syasuoka break; 11270fbf3537Syasuoka } 11280fbf3537Syasuoka reason = "Message type is unexpected."; 1129f0a4e295Syasuoka /* FALLTHROUGH */ 11300fbf3537Syasuoka badpacket: 11310fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 11320fbf3537Syasuoka "Received a bad %s(%d) call_id=%d: %s", 11330fbf3537Syasuoka pptp_ctrl_mes_type_string(mes_type), mes_type, call_id, reason); 11340fbf3537Syasuoka return 0; 1135f0a4e295Syasuoka fail: 11360fbf3537Syasuoka pptp_ctrl_stop(_this, PPTP_StopCCRQ_REASON_STOP_PROTOCOL); 11370fbf3537Syasuoka return 0; 11380fbf3537Syasuoka } 11390fbf3537Syasuoka 11400fbf3537Syasuoka 1141f0a4e295Syasuoka /* 1142f0a4e295Syasuoka * utilities 1143f0a4e295Syasuoka */ 11440fbf3537Syasuoka 1145f0a4e295Syasuoka /* logging with the label of the instance */ 11460fbf3537Syasuoka static void 11470fbf3537Syasuoka pptp_ctrl_log(pptp_ctrl *_this, int prio, const char *fmt, ...) 11480fbf3537Syasuoka { 11490fbf3537Syasuoka char logbuf[BUFSIZ]; 11500fbf3537Syasuoka va_list ap; 11510fbf3537Syasuoka 11520fbf3537Syasuoka va_start(ap, fmt); 11537a7bab9dSyasuoka #ifdef PPTPD_MULTIPLE 11540fbf3537Syasuoka snprintf(logbuf, sizeof(logbuf), "pptpd id=%u ctrl=%u %s", 11550fbf3537Syasuoka _this->pptpd->id, _this->id, fmt); 11560fbf3537Syasuoka #else 11570fbf3537Syasuoka snprintf(logbuf, sizeof(logbuf), "pptpd ctrl=%u %s", _this->id, fmt); 11580fbf3537Syasuoka #endif 11590fbf3537Syasuoka vlog_printf(prio, logbuf, ap); 11600fbf3537Syasuoka va_end(ap); 11610fbf3537Syasuoka } 11620fbf3537Syasuoka 11630fbf3537Syasuoka static const char * 11640fbf3537Syasuoka pptp_ctrl_state_string(int state) 11650fbf3537Syasuoka { 11660fbf3537Syasuoka switch (state) { 11670fbf3537Syasuoka case PPTP_CTRL_STATE_IDLE: 11680fbf3537Syasuoka return "idle"; 11690fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_CTRL_REPLY: 11700fbf3537Syasuoka return "wait-ctrl-reply"; 11710fbf3537Syasuoka case PPTP_CTRL_STATE_ESTABLISHED: 11720fbf3537Syasuoka return "established"; 11730fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_STOP_REPLY: 11740fbf3537Syasuoka return "wait-stop-reply"; 11750fbf3537Syasuoka } 11760fbf3537Syasuoka return "unknown"; 11770fbf3537Syasuoka } 1178