1*7a7bab9dSyasuoka /* $OpenBSD: pptp_ctrl.c,v 1.5 2012/05/08 13:15:12 yasuoka 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*7a7bab9dSyasuoka /* $Id: pptp_ctrl.c,v 1.5 2012/05/08 13:15:12 yasuoka Exp $ */ 330fbf3537Syasuoka #include <sys/types.h> 340fbf3537Syasuoka #include <sys/param.h> 350fbf3537Syasuoka #include <sys/socket.h> 360fbf3537Syasuoka #include <netinet/in.h> 370fbf3537Syasuoka #include <stdio.h> 380fbf3537Syasuoka #include <stdarg.h> 390fbf3537Syasuoka #include <stdlib.h> 400fbf3537Syasuoka #include <netdb.h> 410fbf3537Syasuoka #include <unistd.h> 420fbf3537Syasuoka #include <syslog.h> 430fbf3537Syasuoka #include <time.h> 440fbf3537Syasuoka #include <fcntl.h> 450fbf3537Syasuoka #include <errno.h> 460fbf3537Syasuoka #include <string.h> 470fbf3537Syasuoka #include <event.h> 480fbf3537Syasuoka 490fbf3537Syasuoka #include "bytebuf.h" 500fbf3537Syasuoka #include "debugutil.h" 510fbf3537Syasuoka #include "hash.h" 520fbf3537Syasuoka #include "slist.h" 530fbf3537Syasuoka #include "time_utils.h" 540fbf3537Syasuoka 550fbf3537Syasuoka #include "version.h" 560fbf3537Syasuoka 570fbf3537Syasuoka #include "pptp.h" 580fbf3537Syasuoka #include "pptp_local.h" 590fbf3537Syasuoka #include "pptp_subr.h" 600fbf3537Syasuoka 61f0a4e295Syasuoka /* periods of pptp_ctrl_timeout */ 620fbf3537Syasuoka #define PPTP_CTRL_TIMEOUT_IVAL_SEC 2 630fbf3537Syasuoka 640fbf3537Syasuoka #ifdef PPTP_CTRL_DEBUG 650fbf3537Syasuoka #define PPTP_CTRL_ASSERT(x) ASSERT(x) 660fbf3537Syasuoka #define PPTP_CTRL_DBG(x) pptp_ctrl_log x 670fbf3537Syasuoka #else 680fbf3537Syasuoka #define PPTP_CTRL_ASSERT(x) 690fbf3537Syasuoka #define PPTP_CTRL_DBG(x) 700fbf3537Syasuoka #endif 710fbf3537Syasuoka 720fbf3537Syasuoka static unsigned pptp_ctrl_seqno = 0; 730fbf3537Syasuoka 740fbf3537Syasuoka static void pptp_ctrl_log (pptp_ctrl *, int, const char *, ...) __printflike(3,4); 750fbf3537Syasuoka static void pptp_ctrl_timeout (int, short, void *); 760fbf3537Syasuoka static void pptp_ctrl_reset_timeout (pptp_ctrl *); 770fbf3537Syasuoka static void pptp_ctrl_io_event (int, short, void *); 780fbf3537Syasuoka static void pptp_ctrl_set_io_event (pptp_ctrl *); 790fbf3537Syasuoka static int pptp_ctrl_output_flush (pptp_ctrl *); 800fbf3537Syasuoka static void pptp_ctrl_SCCRx_string (struct pptp_scc *, u_char *, int); 810fbf3537Syasuoka static int pptp_ctrl_recv_SCCRQ (pptp_ctrl *, u_char *, int); 820fbf3537Syasuoka static int pptp_ctrl_recv_StopCCRP (pptp_ctrl *, u_char *, int); 830fbf3537Syasuoka static int pptp_ctrl_send_StopCCRQ (pptp_ctrl *, int); 840fbf3537Syasuoka static int pptp_ctrl_recv_StopCCRQ (pptp_ctrl *, u_char *, int); 850fbf3537Syasuoka static int pptp_ctrl_send_StopCCRP (pptp_ctrl *, int, int); 860fbf3537Syasuoka static int pptp_ctrl_send_SCCRP (pptp_ctrl *, int, int); 870fbf3537Syasuoka static void pptp_ctrl_send_CDN (pptp_ctrl *, int, int, int, const char *); 880fbf3537Syasuoka static void pptp_ctrl_process_echo_req (pptp_ctrl *, u_char *, int); 890fbf3537Syasuoka static int pptp_ctrl_recv_echo_rep (pptp_ctrl *, u_char *, int); 900fbf3537Syasuoka static void pptp_ctrl_send_echo_req (pptp_ctrl *); 910fbf3537Syasuoka static int pptp_ctrl_input (pptp_ctrl *, u_char *, int); 920fbf3537Syasuoka static int pptp_ctrl_call_input (pptp_ctrl *, int, u_char *, int); 930fbf3537Syasuoka static const char *pptp_ctrl_state_string (int); 940fbf3537Syasuoka static void pptp_ctrl_fini(pptp_ctrl *); 950fbf3537Syasuoka 96f0a4e295Syasuoka /* 97f0a4e295Syasuoka * pptp_ctrl instance operation functions 98f0a4e295Syasuoka */ 990fbf3537Syasuoka pptp_ctrl * 1000fbf3537Syasuoka pptp_ctrl_create(void) 1010fbf3537Syasuoka { 1020fbf3537Syasuoka pptp_ctrl *_this; 1030fbf3537Syasuoka 1040fbf3537Syasuoka if ((_this = malloc(sizeof(pptp_ctrl))) == NULL) 1050fbf3537Syasuoka return NULL; 1060fbf3537Syasuoka 1070fbf3537Syasuoka return _this; 1080fbf3537Syasuoka } 1090fbf3537Syasuoka 1100fbf3537Syasuoka int 1110fbf3537Syasuoka pptp_ctrl_init(pptp_ctrl *_this) 1120fbf3537Syasuoka { 1130fbf3537Syasuoka time_t curr_time; 1140fbf3537Syasuoka 1150fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 1160fbf3537Syasuoka curr_time = get_monosec(); 1170fbf3537Syasuoka memset(_this, 0, sizeof(pptp_ctrl)); 1180fbf3537Syasuoka _this->id = pptp_ctrl_seqno++; 1190fbf3537Syasuoka _this->sock = -1; 1200fbf3537Syasuoka 1210fbf3537Syasuoka if ((_this->recv_buf = bytebuffer_create(PPTP_BUFSIZ)) == NULL) { 1220fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "bytebuffer_create() failed at " 1230fbf3537Syasuoka "%s(): %m", __func__); 124f0a4e295Syasuoka goto fail; 1250fbf3537Syasuoka } 1260fbf3537Syasuoka if ((_this->send_buf = bytebuffer_create(PPTP_BUFSIZ)) == NULL) { 1270fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "bytebuffer_create() failed at " 1280fbf3537Syasuoka "%s(): %m", __func__); 129f0a4e295Syasuoka goto fail; 1300fbf3537Syasuoka } 1310fbf3537Syasuoka _this->last_rcv_ctrl = curr_time; 1320fbf3537Syasuoka _this->last_snd_ctrl = curr_time; 1330fbf3537Syasuoka _this->echo_seq = (random() << 16 )| (random() & 0xffff); 1340fbf3537Syasuoka _this->echo_interval = PPTP_CTRL_DEFAULT_ECHO_INTERVAL; 1350fbf3537Syasuoka _this->echo_timeout = PPTP_CTRL_DEFAULT_ECHO_TIMEOUT; 1360fbf3537Syasuoka slist_init(&_this->call_list); 1370fbf3537Syasuoka evtimer_set(&_this->ev_timer, pptp_ctrl_timeout, _this); 1380fbf3537Syasuoka 1390fbf3537Syasuoka return 0; 140f0a4e295Syasuoka fail: 1410fbf3537Syasuoka return 1; 1420fbf3537Syasuoka } 1430fbf3537Syasuoka 1440fbf3537Syasuoka int 1450fbf3537Syasuoka pptp_ctrl_start(pptp_ctrl *_this) 1460fbf3537Syasuoka { 1470fbf3537Syasuoka int ival; 1480fbf3537Syasuoka char hbuf0[NI_MAXHOST], sbuf0[NI_MAXSERV]; 1490fbf3537Syasuoka char hbuf1[NI_MAXHOST], sbuf1[NI_MAXSERV]; 1500fbf3537Syasuoka struct sockaddr_storage sock; 1510fbf3537Syasuoka socklen_t socklen; 1520fbf3537Syasuoka 1530fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 1540fbf3537Syasuoka PPTP_CTRL_ASSERT(_this->sock >= 0); 1550fbf3537Syasuoka 156f0a4e295Syasuoka /* convert address to strings for logging */ 1570fbf3537Syasuoka strlcpy(hbuf0, "<unknown>", sizeof(hbuf0)); 1580fbf3537Syasuoka strlcpy(sbuf0, "<unknown>", sizeof(sbuf0)); 1590fbf3537Syasuoka strlcpy(hbuf1, "<unknown>", sizeof(hbuf1)); 1600fbf3537Syasuoka strlcpy(sbuf1, "<unknown>", sizeof(sbuf1)); 1610fbf3537Syasuoka if (getnameinfo((struct sockaddr *)&_this->peer, _this->peer.ss_len, 1620fbf3537Syasuoka hbuf0, sizeof(hbuf0), sbuf0, sizeof(sbuf0), 1630fbf3537Syasuoka NI_NUMERICHOST | NI_NUMERICSERV) != 0) { 1640fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 1650fbf3537Syasuoka "getnameinfo() failed at %s(): %m", __func__); 1660fbf3537Syasuoka } 1670fbf3537Syasuoka socklen = sizeof(sock); 1680fbf3537Syasuoka if (getsockname(_this->sock, (struct sockaddr *)&sock, &socklen) != 0) { 1690fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 1700fbf3537Syasuoka "getsockname() failed at %s(): %m", __func__); 171f0a4e295Syasuoka goto fail; 1720fbf3537Syasuoka } 1730fbf3537Syasuoka if (getnameinfo((struct sockaddr *)&sock, sock.ss_len, hbuf1, 1740fbf3537Syasuoka sizeof(hbuf1), sbuf1, sizeof(sbuf1), 1750fbf3537Syasuoka NI_NUMERICHOST | NI_NUMERICSERV) != 0) { 1760fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 1770fbf3537Syasuoka "getnameinfo() failed at %s(): %m", __func__); 1780fbf3537Syasuoka } 1790fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "Starting peer=%s:%s/tcp " 1800fbf3537Syasuoka "sock=%s:%s/tcp", hbuf0, sbuf0, hbuf1, sbuf1); 1810fbf3537Syasuoka 1820fbf3537Syasuoka if ((ival = fcntl(_this->sock, F_GETFL, 0)) < 0) { 1830fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 1840fbf3537Syasuoka "fcntl(F_GET_FL) failed at %s(): %m", __func__); 185f0a4e295Syasuoka goto fail; 1860fbf3537Syasuoka } else if (fcntl(_this->sock, F_SETFL, ival | O_NONBLOCK) < 0) { 1870fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 1880fbf3537Syasuoka "fcntl(F_SET_FL) failed at %s(): %m", __func__); 189f0a4e295Syasuoka goto fail; 1900fbf3537Syasuoka } 1910fbf3537Syasuoka pptp_ctrl_set_io_event(_this); 1920fbf3537Syasuoka pptp_ctrl_reset_timeout(_this); 1930fbf3537Syasuoka 1940fbf3537Syasuoka return 0; 195f0a4e295Syasuoka fail: 1960fbf3537Syasuoka return 1; 1970fbf3537Syasuoka } 1980fbf3537Syasuoka 199f0a4e295Syasuoka /* Timer */ 2000fbf3537Syasuoka static void 2010fbf3537Syasuoka pptp_ctrl_timeout(int fd, short event, void *ctx) 2020fbf3537Syasuoka { 2030fbf3537Syasuoka int i; 2040fbf3537Syasuoka pptp_call *call; 2050fbf3537Syasuoka pptp_ctrl *_this; 2060fbf3537Syasuoka time_t last, curr_time; 2070fbf3537Syasuoka 2080fbf3537Syasuoka _this = ctx; 2090fbf3537Syasuoka curr_time = get_monosec(); 2100fbf3537Syasuoka 2110fbf3537Syasuoka PPTP_CTRL_DBG((_this, DEBUG_LEVEL_3, "enter %s()", __func__)); 212f0a4e295Syasuoka /* clean up call */ 2130fbf3537Syasuoka i = 0; 2140fbf3537Syasuoka while (i < slist_length(&_this->call_list)) { 2150fbf3537Syasuoka call = slist_get(&_this->call_list, i); 2160fbf3537Syasuoka if (call->state == PPTP_CALL_STATE_CLEANUP_WAIT && 2170fbf3537Syasuoka curr_time - call->last_io > PPTP_CALL_CLEANUP_WAIT_TIME) { 2180fbf3537Syasuoka pptp_call_stop(call); 2190fbf3537Syasuoka pptp_call_destroy(call); 2200fbf3537Syasuoka slist_remove(&_this->call_list, i); 2210fbf3537Syasuoka } else 2220fbf3537Syasuoka i++; 2230fbf3537Syasuoka } 2240fbf3537Syasuoka 225f0a4e295Syasuoka /* State machine: Timeout */ 2260fbf3537Syasuoka switch (_this->state) { 2270fbf3537Syasuoka default: 2280fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_CTRL_REPLY: 2290fbf3537Syasuoka case PPTP_CTRL_STATE_IDLE: 2300fbf3537Syasuoka if (curr_time - _this->last_rcv_ctrl > PPTPD_IDLE_TIMEOUT) { 2310fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 2320fbf3537Syasuoka "Timeout in state %s", 2330fbf3537Syasuoka pptp_ctrl_state_string(_this->state)); 2340fbf3537Syasuoka pptp_ctrl_fini(_this); 2350fbf3537Syasuoka return; 2360fbf3537Syasuoka } 2370fbf3537Syasuoka break; 2380fbf3537Syasuoka case PPTP_CTRL_STATE_ESTABLISHED: 2390fbf3537Syasuoka last = MAX(_this->last_rcv_ctrl, _this->last_snd_ctrl); 2400fbf3537Syasuoka 2410fbf3537Syasuoka if (curr_time - _this->last_rcv_ctrl 2420fbf3537Syasuoka >= _this->echo_interval + _this->echo_timeout) { 2430fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 2440fbf3537Syasuoka "Timeout waiting for echo reply"); 2450fbf3537Syasuoka pptp_ctrl_fini(_this); 2460fbf3537Syasuoka return; 2470fbf3537Syasuoka } 2480fbf3537Syasuoka if (curr_time - last >= _this->echo_interval) { 2490fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "Echo")); 2500fbf3537Syasuoka _this->echo_seq++; 2510fbf3537Syasuoka pptp_ctrl_send_echo_req(_this); 2520fbf3537Syasuoka } 2530fbf3537Syasuoka break; 2540fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_STOP_REPLY: 2550fbf3537Syasuoka if (curr_time - _this->last_snd_ctrl > 2560fbf3537Syasuoka PPTP_CTRL_StopCCRP_WAIT_TIME) { 2570fbf3537Syasuoka pptp_ctrl_log(_this, LOG_WARNING, 2580fbf3537Syasuoka "Timeout waiting for StopCCRP"); 2590fbf3537Syasuoka pptp_ctrl_fini(_this); 2600fbf3537Syasuoka return; 2610fbf3537Syasuoka } 2620fbf3537Syasuoka break; 2630fbf3537Syasuoka case PPTP_CTRL_STATE_DISPOSING: 2640fbf3537Syasuoka pptp_ctrl_fini(_this); 2650fbf3537Syasuoka return; 2660fbf3537Syasuoka } 2670fbf3537Syasuoka pptp_ctrl_reset_timeout(_this); 2680fbf3537Syasuoka } 2690fbf3537Syasuoka 2700fbf3537Syasuoka static void 2710fbf3537Syasuoka pptp_ctrl_reset_timeout(pptp_ctrl *_this) 2720fbf3537Syasuoka { 2730fbf3537Syasuoka struct timeval tv; 2740fbf3537Syasuoka 2750fbf3537Syasuoka switch (_this->state) { 2760fbf3537Syasuoka case PPTP_CTRL_STATE_DISPOSING: 277adafb749Sokan /* call back immediately */ 278adafb749Sokan timerclear(&tv); 2790fbf3537Syasuoka break; 2800fbf3537Syasuoka default: 2810fbf3537Syasuoka tv.tv_sec = PPTP_CTRL_TIMEOUT_IVAL_SEC; 2820fbf3537Syasuoka tv.tv_usec = 0; 2830fbf3537Syasuoka break; 2840fbf3537Syasuoka } 2850fbf3537Syasuoka evtimer_add(&_this->ev_timer, &tv); 2860fbf3537Syasuoka } 2870fbf3537Syasuoka 2880fbf3537Syasuoka /** 289f0a4e295Syasuoka * Terminate PPTP control connection 290f0a4e295Syasuoka * @result The value for Stop-Control-Connection-Request(StopCCRQ) result. 291f0a4e295Syasuoka This function will not sent StopCCRQ when the value == 0 and 292f0a4e295Syasuoka the specification does not require to sent it. 2930fbf3537Syasuoka * @see ::#PPTP_StopCCRQ_REASON_STOP_PROTOCOL 2940fbf3537Syasuoka * @see ::#PPTP_StopCCRQ_REASON_STOP_LOCAL_SHUTDOWN 2950fbf3537Syasuoka */ 2960fbf3537Syasuoka void 2970fbf3537Syasuoka pptp_ctrl_stop(pptp_ctrl *_this, int result) 2980fbf3537Syasuoka { 2990fbf3537Syasuoka int i; 3000fbf3537Syasuoka pptp_call *call; 3010fbf3537Syasuoka 3020fbf3537Syasuoka switch (_this->state) { 3030fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_STOP_REPLY: 304f0a4e295Syasuoka /* waiting responce. */ 305f0a4e295Syasuoka /* this state will timeout by pptp_ctrl_timeout */ 3060fbf3537Syasuoka break; 3070fbf3537Syasuoka case PPTP_CTRL_STATE_ESTABLISHED: 3080fbf3537Syasuoka if (result != 0) { 3090fbf3537Syasuoka for (i = 0; i < slist_length(&_this->call_list); i++) { 3100fbf3537Syasuoka call = slist_get(&_this->call_list, i); 3110fbf3537Syasuoka pptp_call_disconnect(call, 3120fbf3537Syasuoka PPTP_CDN_RESULT_ADMIN_SHUTDOWN, 0, NULL); 3130fbf3537Syasuoka } 3140fbf3537Syasuoka pptp_ctrl_send_StopCCRQ(_this, result); 3150fbf3537Syasuoka _this->state = PPTP_CTRL_STATE_WAIT_STOP_REPLY; 3160fbf3537Syasuoka break; 3170fbf3537Syasuoka } 318f0a4e295Syasuoka /* FALLTHROUGH */ 3190fbf3537Syasuoka default: 3200fbf3537Syasuoka pptp_ctrl_fini(_this); 3210fbf3537Syasuoka } 3220fbf3537Syasuoka return; 3230fbf3537Syasuoka } 3240fbf3537Syasuoka 3250fbf3537Syasuoka 326f0a4e295Syasuoka /* finish PPTP control */ 3270fbf3537Syasuoka static void 3280fbf3537Syasuoka pptp_ctrl_fini(pptp_ctrl *_this) 3290fbf3537Syasuoka { 3300fbf3537Syasuoka pptp_call *call; 3310fbf3537Syasuoka 3320fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 3330fbf3537Syasuoka 3340fbf3537Syasuoka if (_this->sock >= 0) { 3350fbf3537Syasuoka event_del(&_this->ev_sock); 3360fbf3537Syasuoka close(_this->sock); 3370fbf3537Syasuoka _this->sock = -1; 3380fbf3537Syasuoka } 3390fbf3537Syasuoka for (slist_itr_first(&_this->call_list); 3400fbf3537Syasuoka slist_itr_has_next(&_this->call_list);) { 3410fbf3537Syasuoka call = slist_itr_next(&_this->call_list); 3420fbf3537Syasuoka pptp_call_stop(call); 3430fbf3537Syasuoka pptp_call_destroy(call); 3440fbf3537Syasuoka slist_itr_remove(&_this->call_list); 3450fbf3537Syasuoka } 3460fbf3537Syasuoka 3470fbf3537Syasuoka if (_this->on_io_event != 0) { 3480fbf3537Syasuoka /* 349f0a4e295Syasuoka * as the complete terminate process needs complicated 350f0a4e295Syasuoka * exception handling, do partially at here. 351f0a4e295Syasuoka * rest of part will be handled by timer-event-handler. 3520fbf3537Syasuoka */ 3530fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "Disposing")); 3540fbf3537Syasuoka _this->state = PPTP_CTRL_STATE_DISPOSING; 3550fbf3537Syasuoka pptp_ctrl_reset_timeout(_this); 3560fbf3537Syasuoka return; 3570fbf3537Syasuoka } 3580fbf3537Syasuoka 3590fbf3537Syasuoka evtimer_del(&_this->ev_timer); 3600fbf3537Syasuoka slist_fini(&_this->call_list); 3610fbf3537Syasuoka 3620fbf3537Syasuoka pptp_ctrl_log (_this, LOG_NOTICE, "logtype=Finished"); 3630fbf3537Syasuoka 364f0a4e295Syasuoka /* disable _this */ 3650fbf3537Syasuoka pptpd_ctrl_finished_notify(_this->pptpd, _this); 3660fbf3537Syasuoka } 3670fbf3537Syasuoka 368f0a4e295Syasuoka /* free PPTP control context */ 3690fbf3537Syasuoka void 3700fbf3537Syasuoka pptp_ctrl_destroy(pptp_ctrl *_this) 3710fbf3537Syasuoka { 3720fbf3537Syasuoka if (_this->send_buf != NULL) { 3730fbf3537Syasuoka bytebuffer_destroy(_this->send_buf); 3740fbf3537Syasuoka _this->send_buf = NULL; 3750fbf3537Syasuoka } 3760fbf3537Syasuoka if (_this->recv_buf != NULL) { 3770fbf3537Syasuoka bytebuffer_destroy(_this->recv_buf); 3780fbf3537Syasuoka _this->recv_buf = NULL; 3790fbf3537Syasuoka } 3800fbf3537Syasuoka free(_this); 3810fbf3537Syasuoka } 3820fbf3537Syasuoka 383f0a4e295Syasuoka /* 384f0a4e295Syasuoka * network I/O 385f0a4e295Syasuoka */ 386f0a4e295Syasuoka /* I/O event dispather */ 3870fbf3537Syasuoka static void 3880fbf3537Syasuoka pptp_ctrl_io_event(int fd, short evmask, void *ctx) 3890fbf3537Syasuoka { 3900fbf3537Syasuoka int sz, lpkt, hdrlen; 3910fbf3537Syasuoka u_char *pkt; 3920fbf3537Syasuoka pptp_ctrl *_this; 3930fbf3537Syasuoka 3940fbf3537Syasuoka _this = ctx; 3950fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 3960fbf3537Syasuoka 3970fbf3537Syasuoka _this->on_io_event = 1; 3980fbf3537Syasuoka if ((evmask & EV_WRITE) != 0) { 3990fbf3537Syasuoka if (pptp_ctrl_output_flush(_this) != 0 || 4000fbf3537Syasuoka _this->state == PPTP_CTRL_STATE_DISPOSING) 401f0a4e295Syasuoka goto fail; 4020fbf3537Syasuoka _this->send_ready = 1; 4030fbf3537Syasuoka } 4040fbf3537Syasuoka if ((evmask & EV_READ) != 0) { 4050fbf3537Syasuoka sz = read(_this->sock, bytebuffer_pointer(_this->recv_buf), 4060fbf3537Syasuoka bytebuffer_remaining(_this->recv_buf)); 4070fbf3537Syasuoka if (sz <= 0) { 4080fbf3537Syasuoka if (errno == ECONNRESET || sz == 0) { 4090fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 4100fbf3537Syasuoka "Connection closed by foreign host"); 4110fbf3537Syasuoka pptp_ctrl_fini(_this); 412f0a4e295Syasuoka goto fail; 4130fbf3537Syasuoka } else if (errno != EAGAIN && errno != EINTR) { 4140fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 4150fbf3537Syasuoka "read() failed at %s(): %m", __func__); 4160fbf3537Syasuoka pptp_ctrl_fini(_this); 417f0a4e295Syasuoka goto fail; 4180fbf3537Syasuoka } 4190fbf3537Syasuoka } 4200fbf3537Syasuoka bytebuffer_put(_this->recv_buf, BYTEBUFFER_PUT_DIRECT, sz); 4210fbf3537Syasuoka bytebuffer_flip(_this->recv_buf); 4220fbf3537Syasuoka 4230fbf3537Syasuoka for (;;) { 4240fbf3537Syasuoka pkt = bytebuffer_pointer(_this->recv_buf); 4250fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->recv_buf); 4260fbf3537Syasuoka if (pkt == NULL || 4270fbf3537Syasuoka lpkt < sizeof(struct pptp_ctrl_header)) 4280fbf3537Syasuoka break; /* read again */ 4290fbf3537Syasuoka 4300fbf3537Syasuoka hdrlen = pkt[0] << 8 | pkt[1]; 4310fbf3537Syasuoka if (lpkt < hdrlen) 4320fbf3537Syasuoka break; /* read again */ 4330fbf3537Syasuoka 4340fbf3537Syasuoka bytebuffer_get(_this->recv_buf, NULL, hdrlen); 4350fbf3537Syasuoka if (pptp_ctrl_input(_this, pkt, hdrlen) != 0 || 4360fbf3537Syasuoka _this->state == PPTP_CTRL_STATE_DISPOSING) { 4370fbf3537Syasuoka bytebuffer_compact(_this->recv_buf); 438f0a4e295Syasuoka goto fail; 4390fbf3537Syasuoka } 4400fbf3537Syasuoka } 4410fbf3537Syasuoka bytebuffer_compact(_this->recv_buf); 4420fbf3537Syasuoka } 4430fbf3537Syasuoka if (pptp_ctrl_output_flush(_this) != 0) 444f0a4e295Syasuoka goto fail; 4450fbf3537Syasuoka pptp_ctrl_set_io_event(_this); 446f0a4e295Syasuoka fail: 4470fbf3537Syasuoka _this->on_io_event = 0; 4480fbf3537Syasuoka } 4490fbf3537Syasuoka 4500fbf3537Syasuoka 451f0a4e295Syasuoka /* set i/o event mask */ 4520fbf3537Syasuoka static void 4530fbf3537Syasuoka pptp_ctrl_set_io_event(pptp_ctrl *_this) 4540fbf3537Syasuoka { 4550fbf3537Syasuoka int evmask; 4560fbf3537Syasuoka 4570fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 4580fbf3537Syasuoka PPTP_CTRL_ASSERT(_this->sock >= 0); 4590fbf3537Syasuoka 4600fbf3537Syasuoka evmask = 0; 4610fbf3537Syasuoka if (bytebuffer_remaining(_this->recv_buf) > 128) 4620fbf3537Syasuoka evmask |= EV_READ; 4630fbf3537Syasuoka if (_this->send_ready == 0) 4640fbf3537Syasuoka evmask |= EV_WRITE; 4650fbf3537Syasuoka 4660fbf3537Syasuoka event_del(&_this->ev_sock); 4670fbf3537Syasuoka if (evmask != 0) { 4680fbf3537Syasuoka event_set(&_this->ev_sock, _this->sock, evmask, 4690fbf3537Syasuoka pptp_ctrl_io_event, _this); 4700fbf3537Syasuoka event_add(&_this->ev_sock, NULL); 4710fbf3537Syasuoka } 4720fbf3537Syasuoka } 4730fbf3537Syasuoka 4740fbf3537Syasuoka /** 475f0a4e295Syasuoka * Output PPTP control packet 476f0a4e295Syasuoka * @param pkt pointer to packet buffer. 477f0a4e295Syasuoka * when it was appended by _this-.send_buf using bytebuffer, 478f0a4e295Syasuoka * specify NULL. 479f0a4e295Syasuoka * @param lpkt packet length 4800fbf3537Syasuoka */ 4810fbf3537Syasuoka void 4820fbf3537Syasuoka pptp_ctrl_output(pptp_ctrl *_this, u_char *pkt, int lpkt) 4830fbf3537Syasuoka { 4840fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 4850fbf3537Syasuoka PPTP_CTRL_ASSERT(lpkt > 0); 4860fbf3537Syasuoka 487f0a4e295Syasuoka /* just put the packet into the buffer now. send it later */ 4880fbf3537Syasuoka bytebuffer_put(_this->send_buf, pkt, lpkt); 4890fbf3537Syasuoka 4900fbf3537Syasuoka if (_this->on_io_event != 0) { 491f0a4e295Syasuoka /* 492f0a4e295Syasuoka * pptp_ctrl_output_flush() will be called by the end of 493f0a4e295Syasuoka * the I/O event handler. 494f0a4e295Syasuoka */ 4950fbf3537Syasuoka } else { 4960fbf3537Syasuoka /* 497f0a4e295Syasuoka * When this function is called by other than I/O event handler, 498f0a4e295Syasuoka * we need to call pptp_ctrl_output_flush(). However if we do 499f0a4e295Syasuoka * it here, then we need to consider the situation 500f0a4e295Syasuoka * 'flush => write failure => finalize'. The situation requires 501f0a4e295Syasuoka * the caller function to handle the exception and causes 502f0a4e295Syasuoka * complication. So we call pptp_ctrl_output_flush() by the 503f0a4e295Syasuoka * the next send ready event. 5040fbf3537Syasuoka */ 505f0a4e295Syasuoka _this->send_ready = 0; /* clear 'send ready' */ 506f0a4e295Syasuoka pptp_ctrl_set_io_event(_this); /* wait 'send ready */ 5070fbf3537Syasuoka } 5080fbf3537Syasuoka 5090fbf3537Syasuoka return; 5100fbf3537Syasuoka } 5110fbf3537Syasuoka 512f0a4e295Syasuoka /* Send Stop-Control-Connection-Request */ 5130fbf3537Syasuoka 514f0a4e295Syasuoka /* flush output packet */ 5150fbf3537Syasuoka static int 5160fbf3537Syasuoka pptp_ctrl_output_flush(pptp_ctrl *_this) 5170fbf3537Syasuoka { 5180fbf3537Syasuoka int sz; 5190fbf3537Syasuoka time_t curr_time; 5200fbf3537Syasuoka 5210fbf3537Syasuoka curr_time = get_monosec(); 5220fbf3537Syasuoka 5230fbf3537Syasuoka if (bytebuffer_position(_this->send_buf) <= 0) 524f0a4e295Syasuoka return 0; /* nothing to write */ 5250fbf3537Syasuoka if (_this->send_ready == 0) { 5260fbf3537Syasuoka pptp_ctrl_set_io_event(_this); 527f0a4e295Syasuoka return 0; /* not ready to write */ 5280fbf3537Syasuoka } 5290fbf3537Syasuoka 5300fbf3537Syasuoka bytebuffer_flip(_this->send_buf); 5310fbf3537Syasuoka 5320fbf3537Syasuoka if (_this->pptpd->ctrl_out_pktdump != 0) { 5330fbf3537Syasuoka pptp_ctrl_log(_this, LOG_DEBUG, "PPTP Control output packet"); 5340fbf3537Syasuoka show_hd(debug_get_debugfp(), 5350fbf3537Syasuoka bytebuffer_pointer(_this->send_buf), 5360fbf3537Syasuoka bytebuffer_remaining(_this->send_buf)); 5370fbf3537Syasuoka } 5380fbf3537Syasuoka if ((sz = write(_this->sock, bytebuffer_pointer(_this->send_buf), 5390fbf3537Syasuoka bytebuffer_remaining(_this->send_buf))) < 0) { 5400fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "write to socket failed: %m"); 5410fbf3537Syasuoka pptp_ctrl_fini(_this); 5420fbf3537Syasuoka 5430fbf3537Syasuoka return 1; 5440fbf3537Syasuoka } 5450fbf3537Syasuoka _this->last_snd_ctrl = curr_time; 5460fbf3537Syasuoka bytebuffer_get(_this->send_buf, NULL, sz); 5470fbf3537Syasuoka bytebuffer_compact(_this->send_buf); 5480fbf3537Syasuoka _this->send_ready = 0; 5490fbf3537Syasuoka 5500fbf3537Syasuoka return 0; 5510fbf3537Syasuoka } 5520fbf3537Syasuoka 553f0a4e295Syasuoka /* convert Start-Control-Connection-{Request,Reply} packet to strings */ 5540fbf3537Syasuoka static void 5550fbf3537Syasuoka pptp_ctrl_SCCRx_string(struct pptp_scc *scc, u_char *buf, int lbuf) 5560fbf3537Syasuoka { 5570fbf3537Syasuoka char buf1[128], buf2[128], buf3[128]; 5580fbf3537Syasuoka 559f0a4e295Syasuoka /* sanity check */ 5600fbf3537Syasuoka strlcpy(buf1, scc->host_name, sizeof(buf1)); 5610fbf3537Syasuoka strlcpy(buf2, scc->vendor_string, sizeof(buf2)); 5620fbf3537Syasuoka 5630fbf3537Syasuoka if (scc->result_code != 0) 5640fbf3537Syasuoka snprintf(buf3, sizeof(buf3), "result=%d error=%d ", 5650fbf3537Syasuoka scc->result_code, scc->error_code); 5660fbf3537Syasuoka else 5670fbf3537Syasuoka buf3[0] = '\0'; 5680fbf3537Syasuoka 5690fbf3537Syasuoka snprintf(buf, lbuf, 5700fbf3537Syasuoka "protocol_version=%d.%d %sframing=%s bearer=%s max_channels=%d " 5710fbf3537Syasuoka "firmware_revision=%d(0x%04x) host_name=\"%s\" " 5720fbf3537Syasuoka "vendor_string=\"%s\"", 5730fbf3537Syasuoka scc->protocol_version >> 8, scc->protocol_version & 0xff, buf3, 5740fbf3537Syasuoka pptp_framing_string(scc->framing_caps), 5750fbf3537Syasuoka pptp_bearer_string(scc->bearer_caps), scc->max_channels, 5760fbf3537Syasuoka scc->firmware_revision, scc->firmware_revision, buf1, buf2); 5770fbf3537Syasuoka } 5780fbf3537Syasuoka 579f0a4e295Syasuoka /* receive Start-Control-Connection-Request */ 5800fbf3537Syasuoka static int 5810fbf3537Syasuoka pptp_ctrl_recv_SCCRQ(pptp_ctrl *_this, u_char *pkt, int lpkt) 5820fbf3537Syasuoka { 5830fbf3537Syasuoka char logbuf[512]; 5840fbf3537Syasuoka struct pptp_scc *scc; 5850fbf3537Syasuoka 586f0a4e295Syasuoka /* sanity check */ 5870fbf3537Syasuoka if (lpkt < sizeof(struct pptp_scc)) { 5880fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad SCCRQ: packet too " 5890fbf3537Syasuoka "short: %d < %d", lpkt, (int)sizeof(struct pptp_scc)); 5900fbf3537Syasuoka return 1; 5910fbf3537Syasuoka } 5920fbf3537Syasuoka scc = (struct pptp_scc *)pkt; 5930fbf3537Syasuoka 5940fbf3537Syasuoka scc->protocol_version = ntohs(scc->protocol_version); 5950fbf3537Syasuoka scc->framing_caps = htonl(scc->framing_caps); 5960fbf3537Syasuoka scc->bearer_caps = htonl(scc->bearer_caps); 5970fbf3537Syasuoka scc->max_channels = htons(scc->max_channels); 5980fbf3537Syasuoka scc->firmware_revision = htons(scc->firmware_revision); 5990fbf3537Syasuoka 600f0a4e295Syasuoka /* check protocol version */ 6010fbf3537Syasuoka if (scc->protocol_version != PPTP_RFC_2637_VERSION) { 6020fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad SCCRQ: " 6030fbf3537Syasuoka "unknown protocol version %d", scc->protocol_version); 6040fbf3537Syasuoka return 1; 6050fbf3537Syasuoka } 6060fbf3537Syasuoka 6070fbf3537Syasuoka pptp_ctrl_SCCRx_string(scc, logbuf, sizeof(logbuf)); 6080fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "RecvSCCRQ %s", logbuf); 6090fbf3537Syasuoka 6100fbf3537Syasuoka return 0; 6110fbf3537Syasuoka } 6120fbf3537Syasuoka 613f0a4e295Syasuoka /* Receive Stop-Control-Connection-Reply */ 6140fbf3537Syasuoka static int 6150fbf3537Syasuoka pptp_ctrl_recv_StopCCRP(pptp_ctrl *_this, u_char *pkt, int lpkt) 6160fbf3537Syasuoka { 6170fbf3537Syasuoka struct pptp_stop_ccrp *stop_ccrp; 6180fbf3537Syasuoka 6190fbf3537Syasuoka if (lpkt < sizeof(struct pptp_stop_ccrp)) { 6200fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad StopCCRP: packet " 6210fbf3537Syasuoka "too short: %d < %d", lpkt, 6220fbf3537Syasuoka (int)sizeof(struct pptp_stop_ccrp)); 6230fbf3537Syasuoka return 1; 6240fbf3537Syasuoka } 6250fbf3537Syasuoka stop_ccrp = (struct pptp_stop_ccrp *)pkt; 6260fbf3537Syasuoka 6270fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "RecvStopCCRP reason=%s(%u)", 6280fbf3537Syasuoka pptp_StopCCRP_result_string(stop_ccrp->result), stop_ccrp->result); 6290fbf3537Syasuoka 6300fbf3537Syasuoka return 0; 6310fbf3537Syasuoka } 6320fbf3537Syasuoka 6330fbf3537Syasuoka static int 6340fbf3537Syasuoka pptp_ctrl_send_StopCCRQ(pptp_ctrl *_this, int reason) 6350fbf3537Syasuoka { 6360fbf3537Syasuoka int lpkt; 6370fbf3537Syasuoka struct pptp_stop_ccrq *stop_ccrq; 6380fbf3537Syasuoka 6390fbf3537Syasuoka stop_ccrq = bytebuffer_pointer(_this->send_buf); 6400fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 6410fbf3537Syasuoka if (lpkt < sizeof(struct pptp_stop_ccrq)) { 6420fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 6430fbf3537Syasuoka "SendCCRP failed: No buffer space available"); 6440fbf3537Syasuoka return -1; 6450fbf3537Syasuoka } 6460fbf3537Syasuoka memset(stop_ccrq, 0, sizeof(struct pptp_stop_ccrq)); 6470fbf3537Syasuoka 6480fbf3537Syasuoka pptp_init_header(&stop_ccrq->header, sizeof(struct pptp_stop_ccrq), 6490fbf3537Syasuoka PPTP_CTRL_MES_CODE_StopCCRQ); 6500fbf3537Syasuoka 6510fbf3537Syasuoka stop_ccrq->reason = reason; 6520fbf3537Syasuoka 6530fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "SendStopCCRQ reason=%s(%u)", 6540fbf3537Syasuoka pptp_StopCCRQ_reason_string(stop_ccrq->reason), stop_ccrq->reason); 6550fbf3537Syasuoka 6560fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_stop_ccrq)); 6570fbf3537Syasuoka 6580fbf3537Syasuoka return 0; 6590fbf3537Syasuoka } 6600fbf3537Syasuoka 661f0a4e295Syasuoka /* Receive Stop-Control-Connection-Request */ 6620fbf3537Syasuoka static int 6630fbf3537Syasuoka pptp_ctrl_recv_StopCCRQ(pptp_ctrl *_this, u_char *pkt, int lpkt) 6640fbf3537Syasuoka { 6650fbf3537Syasuoka struct pptp_stop_ccrq *stop_ccrq; 6660fbf3537Syasuoka 6670fbf3537Syasuoka if (lpkt < sizeof(struct pptp_stop_ccrq)) { 6680fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad StopCCRQ: packet " 6690fbf3537Syasuoka "too short: %d < %d", lpkt, 6700fbf3537Syasuoka (int)sizeof(struct pptp_stop_ccrq)); 6710fbf3537Syasuoka return 1; 6720fbf3537Syasuoka } 6730fbf3537Syasuoka stop_ccrq = (struct pptp_stop_ccrq *)pkt; 6740fbf3537Syasuoka 6750fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "RecvStopCCRQ reason=%s(%u)", 6760fbf3537Syasuoka pptp_StopCCRQ_reason_string(stop_ccrq->reason), stop_ccrq->reason); 6770fbf3537Syasuoka 6780fbf3537Syasuoka return 0; 6790fbf3537Syasuoka } 6800fbf3537Syasuoka 681f0a4e295Syasuoka /* Send Stop-Control-Connection-Reply */ 6820fbf3537Syasuoka static int 6830fbf3537Syasuoka pptp_ctrl_send_StopCCRP(pptp_ctrl *_this, int result, int error) 6840fbf3537Syasuoka { 6850fbf3537Syasuoka int lpkt; 6860fbf3537Syasuoka struct pptp_stop_ccrp *stop_ccrp; 6870fbf3537Syasuoka 6880fbf3537Syasuoka stop_ccrp = bytebuffer_pointer(_this->send_buf); 6890fbf3537Syasuoka 6900fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 6910fbf3537Syasuoka if (lpkt < sizeof(struct pptp_stop_ccrp)) { 6920fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 6930fbf3537Syasuoka "SendCCRQ failed: No buffer space available"); 6940fbf3537Syasuoka return -1; 6950fbf3537Syasuoka } 6960fbf3537Syasuoka memset(stop_ccrp, 0, sizeof(struct pptp_stop_ccrp)); 6970fbf3537Syasuoka 6980fbf3537Syasuoka pptp_init_header(&stop_ccrp->header, sizeof(struct pptp_stop_ccrp), 6990fbf3537Syasuoka PPTP_CTRL_MES_CODE_StopCCRP); 7000fbf3537Syasuoka 7010fbf3537Syasuoka stop_ccrp->result = result; 7020fbf3537Syasuoka stop_ccrp->error = error; 7030fbf3537Syasuoka 7040fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 7050fbf3537Syasuoka "SendStopCCRP result=%s(%u) error=%s(%u)", 7060fbf3537Syasuoka pptp_StopCCRP_result_string(stop_ccrp->result), stop_ccrp->result, 7070fbf3537Syasuoka pptp_general_error_string(stop_ccrp->error), stop_ccrp->error); 7080fbf3537Syasuoka 7090fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_stop_ccrp)); 7100fbf3537Syasuoka 7110fbf3537Syasuoka return 0; 7120fbf3537Syasuoka } 7130fbf3537Syasuoka 714f0a4e295Syasuoka /* Send Start-Control-Connection-Reply */ 7150fbf3537Syasuoka static int 7160fbf3537Syasuoka pptp_ctrl_send_SCCRP(pptp_ctrl *_this, int result, int error) 7170fbf3537Syasuoka { 7180fbf3537Syasuoka int lpkt; 7190fbf3537Syasuoka struct pptp_scc *scc; 7200fbf3537Syasuoka char logbuf[512]; 7210fbf3537Syasuoka const char *val; 7220fbf3537Syasuoka 7230fbf3537Syasuoka scc = bytebuffer_pointer(_this->send_buf); 7240fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 7250fbf3537Syasuoka if (lpkt < sizeof(struct pptp_scc)) { 7260fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 7270fbf3537Syasuoka "SendSCCRP failed: No buffer space available"); 7280fbf3537Syasuoka return -1; 7290fbf3537Syasuoka } 7300fbf3537Syasuoka memset(scc, 0, sizeof(struct pptp_scc)); 7310fbf3537Syasuoka 7320fbf3537Syasuoka pptp_init_header(&scc->header, sizeof(struct pptp_scc), 7330fbf3537Syasuoka PPTP_CTRL_MES_CODE_SCCRP); 7340fbf3537Syasuoka 7350fbf3537Syasuoka scc->protocol_version = PPTP_RFC_2637_VERSION; 7360fbf3537Syasuoka scc->result_code = result; 7370fbf3537Syasuoka scc->error_code = error; 738f0a4e295Syasuoka 739f0a4e295Syasuoka /* XXX only support sync frames */ 7400fbf3537Syasuoka scc->framing_caps = PPTP_CTRL_FRAMING_SYNC; 7410fbf3537Syasuoka scc->bearer_caps = PPTP_CTRL_BEARER_DIGITAL; 7420fbf3537Syasuoka 743f0a4e295Syasuoka scc->max_channels = 4; /* XXX */ 7440fbf3537Syasuoka scc->firmware_revision = MAJOR_VERSION << 8 | MINOR_VERSION; 7450fbf3537Syasuoka 746f0a4e295Syasuoka /* this implementation only support these strings up to 747f0a4e295Syasuoka * 63 character */ 748f0a4e295Syasuoka /* host name */ 7490fbf3537Syasuoka if ((val = pptp_ctrl_config_str(_this, "pptp.host_name")) == NULL) 7500fbf3537Syasuoka val = ""; 7510fbf3537Syasuoka strlcpy(scc->host_name, val, sizeof(scc->host_name)); 7520fbf3537Syasuoka 753f0a4e295Syasuoka /* vender name */ 7540fbf3537Syasuoka if ((val = pptp_ctrl_config_str(_this, "pptp.vendor_name")) == NULL) 7550fbf3537Syasuoka val = PPTPD_DEFAULT_VENDOR_NAME; 7560fbf3537Syasuoka 7570fbf3537Syasuoka strlcpy(scc->vendor_string, val, sizeof(scc->vendor_string)); 7580fbf3537Syasuoka 7590fbf3537Syasuoka pptp_ctrl_SCCRx_string(scc, logbuf, sizeof(logbuf)); 7600fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "SendSCCRP %s", logbuf); 7610fbf3537Syasuoka 7620fbf3537Syasuoka scc->protocol_version = htons(scc->protocol_version); 7630fbf3537Syasuoka scc->framing_caps = htonl(scc->framing_caps); 7640fbf3537Syasuoka scc->bearer_caps = htonl(scc->bearer_caps); 7650fbf3537Syasuoka scc->max_channels = htons(scc->max_channels); 7660fbf3537Syasuoka scc->firmware_revision = htons(scc->firmware_revision); 7670fbf3537Syasuoka 7680fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_scc)); 7690fbf3537Syasuoka 7700fbf3537Syasuoka return 0; 7710fbf3537Syasuoka } 7720fbf3537Syasuoka 773f0a4e295Syasuoka /* receive ECHO and reply */ 7740fbf3537Syasuoka static void 7750fbf3537Syasuoka pptp_ctrl_process_echo_req(pptp_ctrl *_this, u_char *pkt, int lpkt) 7760fbf3537Syasuoka { 7770fbf3537Syasuoka struct pptp_echo_rq *echo_rq; 7780fbf3537Syasuoka struct pptp_echo_rp *echo_rp; 7790fbf3537Syasuoka 7800fbf3537Syasuoka if (lpkt < sizeof(struct pptp_echo_rq)) { 7810fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad EchoReq: packet " 7820fbf3537Syasuoka "too short: %d < %d", lpkt, 7830fbf3537Syasuoka (int)sizeof(struct pptp_echo_rq)); 7840fbf3537Syasuoka return; 7850fbf3537Syasuoka } 7860fbf3537Syasuoka echo_rq = (struct pptp_echo_rq *)pkt; 7870fbf3537Syasuoka 7880fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "RecvEchoReq")); 7890fbf3537Syasuoka 7900fbf3537Syasuoka echo_rp = bytebuffer_pointer(_this->send_buf); 7910fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 7920fbf3537Syasuoka if (echo_rp == NULL || lpkt < sizeof(struct pptp_echo_rp)) { 7930fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 7940fbf3537Syasuoka "Failed to send EchoReq: No buffer space available"); 7950fbf3537Syasuoka return; 7960fbf3537Syasuoka } 7970fbf3537Syasuoka memset(echo_rp, 0, sizeof(struct pptp_echo_rp)); 7980fbf3537Syasuoka 7990fbf3537Syasuoka pptp_init_header(&echo_rp->header, sizeof(struct pptp_echo_rp), 8000fbf3537Syasuoka PPTP_CTRL_MES_CODE_ECHO_RP); 8010fbf3537Syasuoka 8020fbf3537Syasuoka echo_rp->identifier = echo_rq->identifier; 8030fbf3537Syasuoka echo_rp->result_code = PPTP_ECHO_RP_RESULT_OK; 8040fbf3537Syasuoka echo_rp->error_code = PPTP_ERROR_NONE; 8050fbf3537Syasuoka echo_rp->reserved1 = htons(0); 8060fbf3537Syasuoka 8070fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_echo_rp)); 8080fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "SendEchoReply")); 8090fbf3537Syasuoka } 8100fbf3537Syasuoka 811f0a4e295Syasuoka /* receiver Echo-Reply */ 8120fbf3537Syasuoka static int 8130fbf3537Syasuoka pptp_ctrl_recv_echo_rep(pptp_ctrl *_this, u_char *pkt, int lpkt) 8140fbf3537Syasuoka { 8150fbf3537Syasuoka struct pptp_echo_rp *echo_rp; 8160fbf3537Syasuoka 8170fbf3537Syasuoka if (lpkt < sizeof(struct pptp_echo_rp)) { 8180fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad EchoReq: packet " 8190fbf3537Syasuoka "too short: %d < %d", lpkt, 8200fbf3537Syasuoka (int)sizeof(struct pptp_echo_rp)); 8210fbf3537Syasuoka return 1; 8220fbf3537Syasuoka } 8230fbf3537Syasuoka echo_rp = (struct pptp_echo_rp *)pkt; 8240fbf3537Syasuoka 8250fbf3537Syasuoka if (echo_rp->result_code != PPTP_ECHO_RP_RESULT_OK) { 8260fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received negative EchoReply: %s", 8270fbf3537Syasuoka pptp_general_error_string(echo_rp->error_code)); 8280fbf3537Syasuoka return 1; 8290fbf3537Syasuoka } 8300fbf3537Syasuoka if (_this->echo_seq != ntohl(echo_rp->identifier)) { 8310fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad EchoReply: " 8320fbf3537Syasuoka "Identifier mismatch sent=%u recv=%u", 8330fbf3537Syasuoka _this->echo_seq , ntohl(echo_rp->identifier)); 8340fbf3537Syasuoka return 1; 8350fbf3537Syasuoka } 8360fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "RecvEchoReply")); 8370fbf3537Syasuoka return 0; 8380fbf3537Syasuoka } 8390fbf3537Syasuoka 840f0a4e295Syasuoka /* send Echo-Request */ 8410fbf3537Syasuoka static void 8420fbf3537Syasuoka pptp_ctrl_send_echo_req(pptp_ctrl *_this) 8430fbf3537Syasuoka { 8440fbf3537Syasuoka int lpkt; 8450fbf3537Syasuoka struct pptp_echo_rq *echo_rq; 8460fbf3537Syasuoka 8470fbf3537Syasuoka echo_rq = (struct pptp_echo_rq *)bytebuffer_pointer(_this->send_buf); 8480fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 8490fbf3537Syasuoka if (echo_rq == NULL || lpkt < sizeof(struct pptp_echo_rq)) { 8500fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 8510fbf3537Syasuoka "SendEchoReq failed: No buffer space available"); 8520fbf3537Syasuoka return; 8530fbf3537Syasuoka } 8540fbf3537Syasuoka memset(echo_rq, 0, sizeof(struct pptp_echo_rq)); 8550fbf3537Syasuoka 8560fbf3537Syasuoka pptp_init_header(&echo_rq->header, sizeof(struct pptp_echo_rq), 8570fbf3537Syasuoka PPTP_CTRL_MES_CODE_ECHO_RQ); 8580fbf3537Syasuoka 8590fbf3537Syasuoka echo_rq->identifier = htonl(_this->echo_seq); 8600fbf3537Syasuoka 8610fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_echo_rq)); 8620fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "SendEchoReq")); 8630fbf3537Syasuoka } 8640fbf3537Syasuoka 865f0a4e295Syasuoka /* send Call-Disconnect-Notify */ 8660fbf3537Syasuoka static void 8670fbf3537Syasuoka pptp_ctrl_send_CDN(pptp_ctrl *_this, int result, int error, int cause, 8680fbf3537Syasuoka const char *statistics) 8690fbf3537Syasuoka { 8700fbf3537Syasuoka int lpkt; 8710fbf3537Syasuoka struct pptp_cdn *cdn; 8720fbf3537Syasuoka 8730fbf3537Syasuoka cdn = bytebuffer_pointer(_this->send_buf); 8740fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 8750fbf3537Syasuoka if (lpkt < sizeof(struct pptp_cdn)) { 8760fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 8770fbf3537Syasuoka "SendCCR failed: No buffer space available"); 8780fbf3537Syasuoka return; 8790fbf3537Syasuoka } 8800fbf3537Syasuoka memset(cdn, 0, sizeof(struct pptp_cdn)); 8810fbf3537Syasuoka 8820fbf3537Syasuoka pptp_init_header(&cdn->header, sizeof(struct pptp_cdn), 8830fbf3537Syasuoka PPTP_CTRL_MES_CODE_CDN); 8840fbf3537Syasuoka 8850fbf3537Syasuoka cdn->call_id = _this->id; 8860fbf3537Syasuoka cdn->result_code = result; 8870fbf3537Syasuoka cdn->error_code = error; 8880fbf3537Syasuoka cdn->cause_code = cause; 8890fbf3537Syasuoka if (statistics != NULL) 8900fbf3537Syasuoka strlcpy(cdn->statistics, statistics, sizeof(cdn->statistics)); 8910fbf3537Syasuoka 8920fbf3537Syasuoka cdn->call_id = htons(cdn->call_id); 8930fbf3537Syasuoka cdn->cause_code = htons(cdn->cause_code); 8940fbf3537Syasuoka 8950fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_cdn)); 8960fbf3537Syasuoka } 8970fbf3537Syasuoka 898f0a4e295Syasuoka /* receive Control-packet */ 8990fbf3537Syasuoka static int 9000fbf3537Syasuoka pptp_ctrl_input(pptp_ctrl *_this, u_char *pkt, int lpkt) 9010fbf3537Syasuoka { 9020fbf3537Syasuoka char errmes[256]; 9030fbf3537Syasuoka time_t curr_time; 9040fbf3537Syasuoka struct pptp_ctrl_header *hdr; 9050fbf3537Syasuoka 9060fbf3537Syasuoka PPTP_CTRL_ASSERT(lpkt >= sizeof(struct pptp_ctrl_header)); 9070fbf3537Syasuoka 9080fbf3537Syasuoka curr_time = get_monosec(); 9090fbf3537Syasuoka hdr = (struct pptp_ctrl_header *)pkt; 9100fbf3537Syasuoka 9110fbf3537Syasuoka hdr->length = ntohs(hdr->length); 9120fbf3537Syasuoka hdr->pptp_message_type = ntohs(hdr->pptp_message_type); 9130fbf3537Syasuoka hdr->magic_cookie = ntohl(hdr->magic_cookie); 9140fbf3537Syasuoka hdr->control_message_type = ntohs(hdr->control_message_type); 9150fbf3537Syasuoka hdr->reserved0 = ntohs(hdr->reserved0); 9160fbf3537Syasuoka 917f0a4e295Syasuoka /* sanity check */ 9180fbf3537Syasuoka PPTP_CTRL_ASSERT(hdr->length <= lpkt); 9190fbf3537Syasuoka 9200fbf3537Syasuoka _this->last_rcv_ctrl = curr_time; 9210fbf3537Syasuoka 9220fbf3537Syasuoka if (_this->pptpd->ctrl_in_pktdump != 0) { 9230fbf3537Syasuoka pptp_ctrl_log(_this, LOG_DEBUG, 9240fbf3537Syasuoka "PPTP Control input packet dump: mestype=%s(%d)", 9250fbf3537Syasuoka pptp_ctrl_mes_type_string(hdr->control_message_type), 9260fbf3537Syasuoka hdr->control_message_type); 9270fbf3537Syasuoka show_hd(debug_get_debugfp(), pkt, lpkt); 9280fbf3537Syasuoka } 9290fbf3537Syasuoka 930f0a4e295Syasuoka /* inspect packet body */ 931f0a4e295Syasuoka /* message type */ 9320fbf3537Syasuoka if (hdr->pptp_message_type != PPTP_MES_TYPE_CTRL) { 9330fbf3537Syasuoka snprintf(errmes, sizeof(errmes), "unknown message type %d", 9340fbf3537Syasuoka hdr->pptp_message_type); 9350fbf3537Syasuoka goto bad_packet; 9360fbf3537Syasuoka } 937f0a4e295Syasuoka /* magic cookie */ 9380fbf3537Syasuoka if (hdr->magic_cookie != PPTP_MAGIC_COOKIE) { 9390fbf3537Syasuoka snprintf(errmes, sizeof(errmes), "wrong magic %08x != %08x", 9400fbf3537Syasuoka hdr->magic_cookie, PPTP_MAGIC_COOKIE); 9410fbf3537Syasuoka goto bad_packet; 9420fbf3537Syasuoka } 9430fbf3537Syasuoka 944f0a4e295Syasuoka /* As there is possibility of state conflicts, 945f0a4e295Syasuoka * ECHO Reply requiries special care. 946f0a4e295Syasuoka */ 9470fbf3537Syasuoka switch (hdr->control_message_type) { 9480fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ECHO_RP: 9490fbf3537Syasuoka if (pptp_ctrl_recv_echo_rep(_this, pkt, lpkt) != 0) { 9500fbf3537Syasuoka pptp_ctrl_fini(_this); 9510fbf3537Syasuoka return 1; 9520fbf3537Syasuoka } 9530fbf3537Syasuoka return 0; 9540fbf3537Syasuoka } 955f0a4e295Syasuoka 9560fbf3537Syasuoka /* 957f0a4e295Syasuoka * State machine 9580fbf3537Syasuoka */ 9590fbf3537Syasuoka switch (_this->state) { 9600fbf3537Syasuoka case PPTP_CTRL_STATE_IDLE: 9610fbf3537Syasuoka switch (hdr->control_message_type) { 9620fbf3537Syasuoka case PPTP_CTRL_MES_CODE_SCCRQ: 9630fbf3537Syasuoka if (pptp_ctrl_recv_SCCRQ(_this, pkt, lpkt) != 0) { 9640fbf3537Syasuoka return 0; 9650fbf3537Syasuoka } 9660fbf3537Syasuoka if (pptp_ctrl_send_SCCRP(_this, 9670fbf3537Syasuoka PPTP_SCCRP_RESULT_SUCCESS, PPTP_ERROR_NONE) != 0) { 9680fbf3537Syasuoka return 0; 9690fbf3537Syasuoka } 9700fbf3537Syasuoka _this->state = PPTP_CTRL_STATE_ESTABLISHED; 9710fbf3537Syasuoka return 0; 9720fbf3537Syasuoka default: 9730fbf3537Syasuoka break; 9740fbf3537Syasuoka } 9750fbf3537Syasuoka break; 9760fbf3537Syasuoka case PPTP_CTRL_STATE_ESTABLISHED: 9770fbf3537Syasuoka switch (hdr->control_message_type) { 9780fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ECHO_RQ: 9790fbf3537Syasuoka pptp_ctrl_process_echo_req(_this, pkt, lpkt); 9800fbf3537Syasuoka return 0; 981f0a4e295Syasuoka /* dispatch to pptp_call_input() if it is call-related-packet */ 9820fbf3537Syasuoka case PPTP_CTRL_MES_CODE_SLI: 9830fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICRQ: 9840fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICRP: 9850fbf3537Syasuoka case PPTP_CTRL_MES_CODE_OCRQ: 9860fbf3537Syasuoka case PPTP_CTRL_MES_CODE_OCRP: 9870fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICCN: 9880fbf3537Syasuoka case PPTP_CTRL_MES_CODE_CDN: 9890fbf3537Syasuoka case PPTP_CTRL_MES_CODE_CCR: 9900fbf3537Syasuoka return pptp_ctrl_call_input(_this, 9910fbf3537Syasuoka hdr->control_message_type, pkt, lpkt); 9920fbf3537Syasuoka case PPTP_CTRL_MES_CODE_StopCCRQ: 9930fbf3537Syasuoka if (pptp_ctrl_recv_StopCCRQ(_this, pkt, lpkt) != 0) { 9940fbf3537Syasuoka pptp_ctrl_stop(_this, 9950fbf3537Syasuoka PPTP_StopCCRQ_REASON_STOP_PROTOCOL); 9960fbf3537Syasuoka return 0; 9970fbf3537Syasuoka } 9980fbf3537Syasuoka if (pptp_ctrl_send_StopCCRP(_this, 9990fbf3537Syasuoka PPTP_StopCCRP_RESULT_OK, PPTP_ERROR_NONE)!= 0) { 10000fbf3537Syasuoka return 0; 10010fbf3537Syasuoka } 10020fbf3537Syasuoka pptp_ctrl_fini(_this); 10030fbf3537Syasuoka return 1; 10040fbf3537Syasuoka default: 10050fbf3537Syasuoka break; 10060fbf3537Syasuoka } 10070fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_STOP_REPLY: 10080fbf3537Syasuoka switch (hdr->control_message_type) { 10090fbf3537Syasuoka case PPTP_CTRL_MES_CODE_StopCCRP: 10100fbf3537Syasuoka pptp_ctrl_recv_StopCCRP(_this, pkt, lpkt); 10110fbf3537Syasuoka pptp_ctrl_fini(_this); 10120fbf3537Syasuoka return 1; 10130fbf3537Syasuoka } 10140fbf3537Syasuoka break; 10150fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_CTRL_REPLY: 1016f0a4e295Syasuoka /* XXX this implementation only support PAC mode */ 10170fbf3537Syasuoka break; 10180fbf3537Syasuoka } 10190fbf3537Syasuoka pptp_ctrl_log(_this, LOG_WARNING, 10200fbf3537Syasuoka "Unhandled control message type=%s(%d)", 10210fbf3537Syasuoka pptp_ctrl_mes_type_string(hdr->control_message_type), 10220fbf3537Syasuoka hdr->control_message_type); 10230fbf3537Syasuoka return 0; 10240fbf3537Syasuoka 10250fbf3537Syasuoka bad_packet: 10260fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad packet: %s", errmes); 10270fbf3537Syasuoka pptp_ctrl_stop(_this, PPTP_StopCCRQ_REASON_STOP_PROTOCOL); 10280fbf3537Syasuoka 10290fbf3537Syasuoka return 0; 10300fbf3537Syasuoka } 10310fbf3537Syasuoka 1032f0a4e295Syasuoka /* receiver PPTP Call related messages */ 10330fbf3537Syasuoka static int 10340fbf3537Syasuoka pptp_ctrl_call_input(pptp_ctrl *_this, int mes_type, u_char *pkt, int lpkt) 10350fbf3537Syasuoka { 10360fbf3537Syasuoka int i, call_id, lpkt0; 10370fbf3537Syasuoka pptp_call *call; 10380fbf3537Syasuoka const char *reason; 10390fbf3537Syasuoka u_char *pkt0; 10400fbf3537Syasuoka 10410fbf3537Syasuoka pkt0 = pkt; 10420fbf3537Syasuoka lpkt0 = lpkt; 10430fbf3537Syasuoka call_id = -1; 10440fbf3537Syasuoka pkt += sizeof(struct pptp_ctrl_header); 10450fbf3537Syasuoka lpkt -= sizeof(struct pptp_ctrl_header); 10460fbf3537Syasuoka reason = "(no reason)"; 10470fbf3537Syasuoka 1048f0a4e295Syasuoka /* sanity check */ 10490fbf3537Syasuoka if (lpkt < 4) { 10500fbf3537Syasuoka reason = "received packet is too short"; 10510fbf3537Syasuoka goto badpacket; 10520fbf3537Syasuoka } 10530fbf3537Syasuoka call = NULL; 10540fbf3537Syasuoka call_id = ntohs(*(uint16_t *)pkt); 10550fbf3537Syasuoka 10560fbf3537Syasuoka switch (mes_type) { 10570fbf3537Syasuoka case PPTP_CTRL_MES_CODE_SLI: /* PNS <=> PAC */ 1058f0a4e295Syasuoka /* only SLI contains Call-ID of this peer */ 10590fbf3537Syasuoka for (i = 0; i < slist_length(&_this->call_list); i++) { 10600fbf3537Syasuoka call = slist_get(&_this->call_list, i); 10610fbf3537Syasuoka if (call->id == call_id) 10620fbf3537Syasuoka break; 10630fbf3537Syasuoka call = NULL; 10640fbf3537Syasuoka } 10650fbf3537Syasuoka if (call == NULL) { 10660fbf3537Syasuoka reason = "Call Id is not associated by this control"; 10670fbf3537Syasuoka goto badpacket; 10680fbf3537Syasuoka } 10690fbf3537Syasuoka goto call_searched; 10700fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICRP: /* PNS => PAC */ 10710fbf3537Syasuoka /* 1072f0a4e295Syasuoka * as this implementation never sent ICRQ, this case 1073f0a4e295Syasuoka * should not happen. 1074f0a4e295Syasuoka * But just to make sure, pptp_call.c can handle this 1075f0a4e295Syasuoka * message. 10760fbf3537Syasuoka */ 1077f0a4e295Syasuoka /* FALLTHROUGH */ 10780fbf3537Syasuoka case PPTP_CTRL_MES_CODE_OCRQ: /* PNS => PAC */ 10790fbf3537Syasuoka case PPTP_CTRL_MES_CODE_CCR: /* PNS => PAC */ 1080f0a4e295Syasuoka /* liner-search will be enough */ 10810fbf3537Syasuoka for (i = 0; i < slist_length(&_this->call_list); i++) { 10820fbf3537Syasuoka call = slist_get(&_this->call_list, i); 10830fbf3537Syasuoka if (call->peers_call_id == call_id) 10840fbf3537Syasuoka break; 10850fbf3537Syasuoka call = NULL; 10860fbf3537Syasuoka } 10870fbf3537Syasuoka if (call == NULL && mes_type == PPTP_CTRL_MES_CODE_CCR) { 10880fbf3537Syasuoka pptp_ctrl_send_CDN(_this, PPTP_CDN_RESULT_GENRIC_ERROR, 10890fbf3537Syasuoka PPTP_ERROR_BAD_CALL, 0, NULL); 10900fbf3537Syasuoka goto call_searched; 10910fbf3537Syasuoka } 10920fbf3537Syasuoka if (mes_type == PPTP_CTRL_MES_CODE_OCRQ) { 1093f0a4e295Syasuoka /* make new call */ 10940fbf3537Syasuoka if (call != NULL) { 10950fbf3537Syasuoka pptp_call_input(call, mes_type, pkt0, lpkt0); 10960fbf3537Syasuoka return 0; 10970fbf3537Syasuoka } 10980fbf3537Syasuoka if ((call = pptp_call_create()) == NULL) { 10990fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 11000fbf3537Syasuoka "pptp_call_create() failed: %m"); 1101f0a4e295Syasuoka goto fail; 11020fbf3537Syasuoka } 11030fbf3537Syasuoka if (pptp_call_init(call, _this) != 0) { 11040fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 11050fbf3537Syasuoka "pptp_call_init() failed: %m"); 11060fbf3537Syasuoka pptp_call_destroy(call); 1107f0a4e295Syasuoka goto fail; 11080fbf3537Syasuoka } 11090fbf3537Syasuoka slist_add(&_this->call_list, call); 11100fbf3537Syasuoka } 11110fbf3537Syasuoka call_searched: 11120fbf3537Syasuoka if (call == NULL) { 11130fbf3537Syasuoka reason = "Call Id is not associated by this control"; 11140fbf3537Syasuoka goto badpacket; 11150fbf3537Syasuoka } 11160fbf3537Syasuoka pptp_call_input(call, mes_type, pkt0, lpkt0); 11170fbf3537Syasuoka return 0; 11180fbf3537Syasuoka case PPTP_CTRL_MES_CODE_OCRP: /* PAC => PNS */ 11190fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICRQ: /* PAC => PNS */ 11200fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICCN: /* PAC => PNS */ 11210fbf3537Syasuoka case PPTP_CTRL_MES_CODE_CDN: /* PAC => PNS */ 1122f0a4e295Syasuoka /* don't receive because above messages are only of PNS */ 11230fbf3537Syasuoka default: 11240fbf3537Syasuoka break; 11250fbf3537Syasuoka } 11260fbf3537Syasuoka reason = "Message type is unexpected."; 1127f0a4e295Syasuoka /* FALLTHROUGH */ 11280fbf3537Syasuoka badpacket: 11290fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 11300fbf3537Syasuoka "Received a bad %s(%d) call_id=%d: %s", 11310fbf3537Syasuoka pptp_ctrl_mes_type_string(mes_type), mes_type, call_id, reason); 11320fbf3537Syasuoka return 0; 1133f0a4e295Syasuoka fail: 11340fbf3537Syasuoka pptp_ctrl_stop(_this, PPTP_StopCCRQ_REASON_STOP_PROTOCOL); 11350fbf3537Syasuoka return 0; 11360fbf3537Syasuoka } 11370fbf3537Syasuoka 11380fbf3537Syasuoka 1139f0a4e295Syasuoka /* 1140f0a4e295Syasuoka * utilities 1141f0a4e295Syasuoka */ 11420fbf3537Syasuoka 1143f0a4e295Syasuoka /* logging with the label of the instance */ 11440fbf3537Syasuoka static void 11450fbf3537Syasuoka pptp_ctrl_log(pptp_ctrl *_this, int prio, const char *fmt, ...) 11460fbf3537Syasuoka { 11470fbf3537Syasuoka char logbuf[BUFSIZ]; 11480fbf3537Syasuoka va_list ap; 11490fbf3537Syasuoka 11500fbf3537Syasuoka va_start(ap, fmt); 1151*7a7bab9dSyasuoka #ifdef PPTPD_MULTIPLE 11520fbf3537Syasuoka snprintf(logbuf, sizeof(logbuf), "pptpd id=%u ctrl=%u %s", 11530fbf3537Syasuoka _this->pptpd->id, _this->id, fmt); 11540fbf3537Syasuoka #else 11550fbf3537Syasuoka snprintf(logbuf, sizeof(logbuf), "pptpd ctrl=%u %s", _this->id, fmt); 11560fbf3537Syasuoka #endif 11570fbf3537Syasuoka vlog_printf(prio, logbuf, ap); 11580fbf3537Syasuoka va_end(ap); 11590fbf3537Syasuoka } 11600fbf3537Syasuoka 11610fbf3537Syasuoka static const char * 11620fbf3537Syasuoka pptp_ctrl_state_string(int state) 11630fbf3537Syasuoka { 11640fbf3537Syasuoka switch (state) { 11650fbf3537Syasuoka case PPTP_CTRL_STATE_IDLE: 11660fbf3537Syasuoka return "idle"; 11670fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_CTRL_REPLY: 11680fbf3537Syasuoka return "wait-ctrl-reply"; 11690fbf3537Syasuoka case PPTP_CTRL_STATE_ESTABLISHED: 11700fbf3537Syasuoka return "established"; 11710fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_STOP_REPLY: 11720fbf3537Syasuoka return "wait-stop-reply"; 11730fbf3537Syasuoka } 11740fbf3537Syasuoka return "unknown"; 11750fbf3537Syasuoka } 1176