1*0fbf3537Syasuoka /*- 2*0fbf3537Syasuoka * Copyright (c) 2009 Internet Initiative Japan Inc. 3*0fbf3537Syasuoka * All rights reserved. 4*0fbf3537Syasuoka * 5*0fbf3537Syasuoka * Redistribution and use in source and binary forms, with or without 6*0fbf3537Syasuoka * modification, are permitted provided that the following conditions 7*0fbf3537Syasuoka * are met: 8*0fbf3537Syasuoka * 1. Redistributions of source code must retain the above copyright 9*0fbf3537Syasuoka * notice, this list of conditions and the following disclaimer. 10*0fbf3537Syasuoka * 2. Redistributions in binary form must reproduce the above copyright 11*0fbf3537Syasuoka * notice, this list of conditions and the following disclaimer in the 12*0fbf3537Syasuoka * documentation and/or other materials provided with the distribution. 13*0fbf3537Syasuoka * 14*0fbf3537Syasuoka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*0fbf3537Syasuoka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*0fbf3537Syasuoka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*0fbf3537Syasuoka * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*0fbf3537Syasuoka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*0fbf3537Syasuoka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*0fbf3537Syasuoka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*0fbf3537Syasuoka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*0fbf3537Syasuoka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*0fbf3537Syasuoka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*0fbf3537Syasuoka * SUCH DAMAGE. 25*0fbf3537Syasuoka */ 26*0fbf3537Syasuoka /**@file 27*0fbf3537Syasuoka * PPTP(RFC 2637) ����ȥ�����³���μ�����PAC�Τߡ� 28*0fbf3537Syasuoka */ 29*0fbf3537Syasuoka /* $Id: pptp_ctrl.c,v 1.1 2010/01/11 04:20:57 yasuoka Exp $ */ 30*0fbf3537Syasuoka #include <sys/types.h> 31*0fbf3537Syasuoka #include <sys/param.h> 32*0fbf3537Syasuoka #include <sys/socket.h> 33*0fbf3537Syasuoka #include <netinet/in.h> 34*0fbf3537Syasuoka #include <stdio.h> 35*0fbf3537Syasuoka #include <stdarg.h> 36*0fbf3537Syasuoka #include <stdlib.h> 37*0fbf3537Syasuoka #include <netdb.h> 38*0fbf3537Syasuoka #include <unistd.h> 39*0fbf3537Syasuoka #include <syslog.h> 40*0fbf3537Syasuoka #include <time.h> 41*0fbf3537Syasuoka #include <fcntl.h> 42*0fbf3537Syasuoka #include <errno.h> 43*0fbf3537Syasuoka #include <string.h> 44*0fbf3537Syasuoka #include <event.h> 45*0fbf3537Syasuoka 46*0fbf3537Syasuoka #include "bytebuf.h" 47*0fbf3537Syasuoka #include "debugutil.h" 48*0fbf3537Syasuoka #include "hash.h" 49*0fbf3537Syasuoka #include "slist.h" 50*0fbf3537Syasuoka #include "time_utils.h" 51*0fbf3537Syasuoka 52*0fbf3537Syasuoka #include "version.h" 53*0fbf3537Syasuoka 54*0fbf3537Syasuoka #include "pptp.h" 55*0fbf3537Syasuoka #include "pptp_local.h" 56*0fbf3537Syasuoka #include "pptp_subr.h" 57*0fbf3537Syasuoka 58*0fbf3537Syasuoka /** 2 ����� pptp_ctrl_timeout */ 59*0fbf3537Syasuoka #define PPTP_CTRL_TIMEOUT_IVAL_SEC 2 60*0fbf3537Syasuoka 61*0fbf3537Syasuoka #ifdef PPTP_CTRL_DEBUG 62*0fbf3537Syasuoka #define PPTP_CTRL_ASSERT(x) ASSERT(x) 63*0fbf3537Syasuoka #define PPTP_CTRL_DBG(x) pptp_ctrl_log x 64*0fbf3537Syasuoka #else 65*0fbf3537Syasuoka #define PPTP_CTRL_ASSERT(x) 66*0fbf3537Syasuoka #define PPTP_CTRL_DBG(x) 67*0fbf3537Syasuoka #endif 68*0fbf3537Syasuoka 69*0fbf3537Syasuoka static unsigned pptp_ctrl_seqno = 0; 70*0fbf3537Syasuoka 71*0fbf3537Syasuoka static void pptp_ctrl_log (pptp_ctrl *, int, const char *, ...) __printflike(3,4); 72*0fbf3537Syasuoka static void pptp_ctrl_timeout (int, short, void *); 73*0fbf3537Syasuoka static void pptp_ctrl_reset_timeout (pptp_ctrl *); 74*0fbf3537Syasuoka static void pptp_ctrl_io_event (int, short, void *); 75*0fbf3537Syasuoka static void pptp_ctrl_set_io_event (pptp_ctrl *); 76*0fbf3537Syasuoka static int pptp_ctrl_output_flush (pptp_ctrl *); 77*0fbf3537Syasuoka static void pptp_ctrl_SCCRx_string (struct pptp_scc *, u_char *, int); 78*0fbf3537Syasuoka static int pptp_ctrl_recv_SCCRQ (pptp_ctrl *, u_char *, int); 79*0fbf3537Syasuoka static int pptp_ctrl_recv_StopCCRP (pptp_ctrl *, u_char *, int); 80*0fbf3537Syasuoka static int pptp_ctrl_send_StopCCRQ (pptp_ctrl *, int); 81*0fbf3537Syasuoka static int pptp_ctrl_recv_StopCCRQ (pptp_ctrl *, u_char *, int); 82*0fbf3537Syasuoka static int pptp_ctrl_send_StopCCRP (pptp_ctrl *, int, int); 83*0fbf3537Syasuoka static int pptp_ctrl_send_SCCRP (pptp_ctrl *, int, int); 84*0fbf3537Syasuoka static void pptp_ctrl_send_CDN (pptp_ctrl *, int, int, int, const char *); 85*0fbf3537Syasuoka static void pptp_ctrl_process_echo_req (pptp_ctrl *, u_char *, int); 86*0fbf3537Syasuoka static int pptp_ctrl_recv_echo_rep (pptp_ctrl *, u_char *, int); 87*0fbf3537Syasuoka static void pptp_ctrl_send_echo_req (pptp_ctrl *); 88*0fbf3537Syasuoka static int pptp_ctrl_input (pptp_ctrl *, u_char *, int); 89*0fbf3537Syasuoka static int pptp_ctrl_call_input (pptp_ctrl *, int, u_char *, int); 90*0fbf3537Syasuoka static const char *pptp_ctrl_state_string (int); 91*0fbf3537Syasuoka static void pptp_ctrl_fini(pptp_ctrl *); 92*0fbf3537Syasuoka 93*0fbf3537Syasuoka /************************************************************************ 94*0fbf3537Syasuoka * pptp_ctrl ��������� 95*0fbf3537Syasuoka ************************************************************************/ 96*0fbf3537Syasuoka pptp_ctrl * 97*0fbf3537Syasuoka pptp_ctrl_create(void) 98*0fbf3537Syasuoka { 99*0fbf3537Syasuoka pptp_ctrl *_this; 100*0fbf3537Syasuoka 101*0fbf3537Syasuoka if ((_this = malloc(sizeof(pptp_ctrl))) == NULL) 102*0fbf3537Syasuoka return NULL; 103*0fbf3537Syasuoka 104*0fbf3537Syasuoka return _this; 105*0fbf3537Syasuoka } 106*0fbf3537Syasuoka 107*0fbf3537Syasuoka int 108*0fbf3537Syasuoka pptp_ctrl_init(pptp_ctrl *_this) 109*0fbf3537Syasuoka { 110*0fbf3537Syasuoka time_t curr_time; 111*0fbf3537Syasuoka 112*0fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 113*0fbf3537Syasuoka curr_time = get_monosec(); 114*0fbf3537Syasuoka memset(_this, 0, sizeof(pptp_ctrl)); 115*0fbf3537Syasuoka _this->id = pptp_ctrl_seqno++; 116*0fbf3537Syasuoka _this->sock = -1; 117*0fbf3537Syasuoka 118*0fbf3537Syasuoka if ((_this->recv_buf = bytebuffer_create(PPTP_BUFSIZ)) == NULL) { 119*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "bytebuffer_create() failed at " 120*0fbf3537Syasuoka "%s(): %m", __func__); 121*0fbf3537Syasuoka goto reigai; 122*0fbf3537Syasuoka } 123*0fbf3537Syasuoka if ((_this->send_buf = bytebuffer_create(PPTP_BUFSIZ)) == NULL) { 124*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "bytebuffer_create() failed at " 125*0fbf3537Syasuoka "%s(): %m", __func__); 126*0fbf3537Syasuoka goto reigai; 127*0fbf3537Syasuoka } 128*0fbf3537Syasuoka _this->last_rcv_ctrl = curr_time; 129*0fbf3537Syasuoka _this->last_snd_ctrl = curr_time; 130*0fbf3537Syasuoka _this->echo_seq = (random() << 16 )| (random() & 0xffff); 131*0fbf3537Syasuoka _this->echo_interval = PPTP_CTRL_DEFAULT_ECHO_INTERVAL; 132*0fbf3537Syasuoka _this->echo_timeout = PPTP_CTRL_DEFAULT_ECHO_TIMEOUT; 133*0fbf3537Syasuoka slist_init(&_this->call_list); 134*0fbf3537Syasuoka evtimer_set(&_this->ev_timer, pptp_ctrl_timeout, _this); 135*0fbf3537Syasuoka 136*0fbf3537Syasuoka return 0; 137*0fbf3537Syasuoka reigai: 138*0fbf3537Syasuoka return 1; 139*0fbf3537Syasuoka } 140*0fbf3537Syasuoka 141*0fbf3537Syasuoka int 142*0fbf3537Syasuoka pptp_ctrl_start(pptp_ctrl *_this) 143*0fbf3537Syasuoka { 144*0fbf3537Syasuoka int ival; 145*0fbf3537Syasuoka char hbuf0[NI_MAXHOST], sbuf0[NI_MAXSERV]; 146*0fbf3537Syasuoka char hbuf1[NI_MAXHOST], sbuf1[NI_MAXSERV]; 147*0fbf3537Syasuoka struct sockaddr_storage sock; 148*0fbf3537Syasuoka socklen_t socklen; 149*0fbf3537Syasuoka 150*0fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 151*0fbf3537Syasuoka PPTP_CTRL_ASSERT(_this->sock >= 0); 152*0fbf3537Syasuoka 153*0fbf3537Syasuoka /* ���Ѥ˥��ɥ쥹=>ʸ�����Ѵ� */ 154*0fbf3537Syasuoka 155*0fbf3537Syasuoka strlcpy(hbuf0, "<unknown>", sizeof(hbuf0)); 156*0fbf3537Syasuoka strlcpy(sbuf0, "<unknown>", sizeof(sbuf0)); 157*0fbf3537Syasuoka strlcpy(hbuf1, "<unknown>", sizeof(hbuf1)); 158*0fbf3537Syasuoka strlcpy(sbuf1, "<unknown>", sizeof(sbuf1)); 159*0fbf3537Syasuoka if (getnameinfo((struct sockaddr *)&_this->peer, _this->peer.ss_len, 160*0fbf3537Syasuoka hbuf0, sizeof(hbuf0), sbuf0, sizeof(sbuf0), 161*0fbf3537Syasuoka NI_NUMERICHOST | NI_NUMERICSERV) != 0) { 162*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 163*0fbf3537Syasuoka "getnameinfo() failed at %s(): %m", __func__); 164*0fbf3537Syasuoka } 165*0fbf3537Syasuoka socklen = sizeof(sock); 166*0fbf3537Syasuoka if (getsockname(_this->sock, (struct sockaddr *)&sock, &socklen) != 0) { 167*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 168*0fbf3537Syasuoka "getsockname() failed at %s(): %m", __func__); 169*0fbf3537Syasuoka goto reigai; 170*0fbf3537Syasuoka } 171*0fbf3537Syasuoka if (getnameinfo((struct sockaddr *)&sock, sock.ss_len, hbuf1, 172*0fbf3537Syasuoka sizeof(hbuf1), sbuf1, sizeof(sbuf1), 173*0fbf3537Syasuoka NI_NUMERICHOST | NI_NUMERICSERV) != 0) { 174*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 175*0fbf3537Syasuoka "getnameinfo() failed at %s(): %m", __func__); 176*0fbf3537Syasuoka } 177*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "Starting peer=%s:%s/tcp " 178*0fbf3537Syasuoka "sock=%s:%s/tcp", hbuf0, sbuf0, hbuf1, sbuf1); 179*0fbf3537Syasuoka 180*0fbf3537Syasuoka if ((ival = fcntl(_this->sock, F_GETFL, 0)) < 0) { 181*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 182*0fbf3537Syasuoka "fcntl(F_GET_FL) failed at %s(): %m", __func__); 183*0fbf3537Syasuoka goto reigai; 184*0fbf3537Syasuoka } else if (fcntl(_this->sock, F_SETFL, ival | O_NONBLOCK) < 0) { 185*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 186*0fbf3537Syasuoka "fcntl(F_SET_FL) failed at %s(): %m", __func__); 187*0fbf3537Syasuoka goto reigai; 188*0fbf3537Syasuoka } 189*0fbf3537Syasuoka pptp_ctrl_set_io_event(_this); 190*0fbf3537Syasuoka pptp_ctrl_reset_timeout(_this); 191*0fbf3537Syasuoka 192*0fbf3537Syasuoka return 0; 193*0fbf3537Syasuoka reigai: 194*0fbf3537Syasuoka return 1; 195*0fbf3537Syasuoka } 196*0fbf3537Syasuoka 197*0fbf3537Syasuoka /** �����ޡ����� */ 198*0fbf3537Syasuoka static void 199*0fbf3537Syasuoka pptp_ctrl_timeout(int fd, short event, void *ctx) 200*0fbf3537Syasuoka { 201*0fbf3537Syasuoka int i; 202*0fbf3537Syasuoka pptp_call *call; 203*0fbf3537Syasuoka pptp_ctrl *_this; 204*0fbf3537Syasuoka time_t last, curr_time; 205*0fbf3537Syasuoka 206*0fbf3537Syasuoka _this = ctx; 207*0fbf3537Syasuoka curr_time = get_monosec(); 208*0fbf3537Syasuoka 209*0fbf3537Syasuoka PPTP_CTRL_DBG((_this, DEBUG_LEVEL_3, "enter %s()", __func__)); 210*0fbf3537Syasuoka /* call �Υ���å� */ 211*0fbf3537Syasuoka i = 0; 212*0fbf3537Syasuoka while (i < slist_length(&_this->call_list)) { 213*0fbf3537Syasuoka call = slist_get(&_this->call_list, i); 214*0fbf3537Syasuoka if (call->state == PPTP_CALL_STATE_CLEANUP_WAIT && 215*0fbf3537Syasuoka curr_time - call->last_io > PPTP_CALL_CLEANUP_WAIT_TIME) { 216*0fbf3537Syasuoka pptp_call_stop(call); 217*0fbf3537Syasuoka pptp_call_destroy(call); 218*0fbf3537Syasuoka slist_remove(&_this->call_list, i); 219*0fbf3537Syasuoka } else 220*0fbf3537Syasuoka i++; 221*0fbf3537Syasuoka } 222*0fbf3537Syasuoka 223*0fbf3537Syasuoka /* ���ơ��ȥޥ���Timeout���� */ 224*0fbf3537Syasuoka switch (_this->state) { 225*0fbf3537Syasuoka default: 226*0fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_CTRL_REPLY: 227*0fbf3537Syasuoka case PPTP_CTRL_STATE_IDLE: 228*0fbf3537Syasuoka if (curr_time - _this->last_rcv_ctrl > PPTPD_IDLE_TIMEOUT) { 229*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 230*0fbf3537Syasuoka "Timeout in state %s", 231*0fbf3537Syasuoka pptp_ctrl_state_string(_this->state)); 232*0fbf3537Syasuoka pptp_ctrl_fini(_this); 233*0fbf3537Syasuoka return; 234*0fbf3537Syasuoka } 235*0fbf3537Syasuoka break; 236*0fbf3537Syasuoka case PPTP_CTRL_STATE_ESTABLISHED: 237*0fbf3537Syasuoka last = MAX(_this->last_rcv_ctrl, _this->last_snd_ctrl); 238*0fbf3537Syasuoka 239*0fbf3537Syasuoka if (curr_time - _this->last_rcv_ctrl 240*0fbf3537Syasuoka >= _this->echo_interval + _this->echo_timeout) { 241*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 242*0fbf3537Syasuoka "Timeout waiting for echo reply"); 243*0fbf3537Syasuoka pptp_ctrl_fini(_this); 244*0fbf3537Syasuoka return; 245*0fbf3537Syasuoka } 246*0fbf3537Syasuoka if (curr_time - last >= _this->echo_interval) { 247*0fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "Echo")); 248*0fbf3537Syasuoka _this->echo_seq++; 249*0fbf3537Syasuoka pptp_ctrl_send_echo_req(_this); 250*0fbf3537Syasuoka } 251*0fbf3537Syasuoka break; 252*0fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_STOP_REPLY: 253*0fbf3537Syasuoka // �����դ� 254*0fbf3537Syasuoka if (curr_time - _this->last_snd_ctrl > 255*0fbf3537Syasuoka PPTP_CTRL_StopCCRP_WAIT_TIME) { 256*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_WARNING, 257*0fbf3537Syasuoka "Timeout waiting for StopCCRP"); 258*0fbf3537Syasuoka pptp_ctrl_fini(_this); 259*0fbf3537Syasuoka return; 260*0fbf3537Syasuoka } 261*0fbf3537Syasuoka break; 262*0fbf3537Syasuoka case PPTP_CTRL_STATE_DISPOSING: 263*0fbf3537Syasuoka pptp_ctrl_fini(_this); 264*0fbf3537Syasuoka return; 265*0fbf3537Syasuoka } 266*0fbf3537Syasuoka pptp_ctrl_reset_timeout(_this); 267*0fbf3537Syasuoka } 268*0fbf3537Syasuoka 269*0fbf3537Syasuoka static void 270*0fbf3537Syasuoka pptp_ctrl_reset_timeout(pptp_ctrl *_this) 271*0fbf3537Syasuoka { 272*0fbf3537Syasuoka struct timeval tv; 273*0fbf3537Syasuoka 274*0fbf3537Syasuoka switch (_this->state) { 275*0fbf3537Syasuoka case PPTP_CTRL_STATE_DISPOSING: 276*0fbf3537Syasuoka tv.tv_sec = 0; /* ������ call back */ 277*0fbf3537Syasuoka tv.tv_usec = 0; 278*0fbf3537Syasuoka break; 279*0fbf3537Syasuoka default: 280*0fbf3537Syasuoka tv.tv_sec = PPTP_CTRL_TIMEOUT_IVAL_SEC; 281*0fbf3537Syasuoka tv.tv_usec = 0; 282*0fbf3537Syasuoka break; 283*0fbf3537Syasuoka } 284*0fbf3537Syasuoka evtimer_add(&_this->ev_timer, &tv); 285*0fbf3537Syasuoka } 286*0fbf3537Syasuoka 287*0fbf3537Syasuoka /** 288*0fbf3537Syasuoka * PPTP����ȥ��륳�ͥ�������λ���ޤ��� 289*0fbf3537Syasuoka * @result Stop-Control-Connection-Request(StopCCRQ) �� result �˻��ꤹ�� 290*0fbf3537Syasuoka * �͡�0 ����ꤹ��ȡ�StopCCRQ �����������ˡ���λ���ޤ����ޤ��� 291*0fbf3537Syasuoka * �ץ�ȥ���塢StopCCRQ ����������ɬ�פ��ʤ������������ޤ��� 292*0fbf3537Syasuoka * @see ::#PPTP_StopCCRQ_REASON_STOP_PROTOCOL 293*0fbf3537Syasuoka * @see ::#PPTP_StopCCRQ_REASON_STOP_LOCAL_SHUTDOWN 294*0fbf3537Syasuoka */ 295*0fbf3537Syasuoka void 296*0fbf3537Syasuoka pptp_ctrl_stop(pptp_ctrl *_this, int result) 297*0fbf3537Syasuoka { 298*0fbf3537Syasuoka int i; 299*0fbf3537Syasuoka pptp_call *call; 300*0fbf3537Syasuoka 301*0fbf3537Syasuoka switch (_this->state) { 302*0fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_STOP_REPLY: 303*0fbf3537Syasuoka // �ֻ��Ԥ���pptp_ctrl_timeout �ǽ�������ޤ��� 304*0fbf3537Syasuoka break; 305*0fbf3537Syasuoka case PPTP_CTRL_STATE_ESTABLISHED: 306*0fbf3537Syasuoka if (result != 0) { 307*0fbf3537Syasuoka for (i = 0; i < slist_length(&_this->call_list); i++) { 308*0fbf3537Syasuoka call = slist_get(&_this->call_list, i); 309*0fbf3537Syasuoka pptp_call_disconnect(call, 310*0fbf3537Syasuoka PPTP_CDN_RESULT_ADMIN_SHUTDOWN, 0, NULL); 311*0fbf3537Syasuoka } 312*0fbf3537Syasuoka pptp_ctrl_send_StopCCRQ(_this, result); 313*0fbf3537Syasuoka _this->state = PPTP_CTRL_STATE_WAIT_STOP_REPLY; 314*0fbf3537Syasuoka break; 315*0fbf3537Syasuoka } 316*0fbf3537Syasuoka // FALL THROUGH 317*0fbf3537Syasuoka default: 318*0fbf3537Syasuoka pptp_ctrl_fini(_this); 319*0fbf3537Syasuoka } 320*0fbf3537Syasuoka return; 321*0fbf3537Syasuoka } 322*0fbf3537Syasuoka 323*0fbf3537Syasuoka 324*0fbf3537Syasuoka /** PPTP ����ȥ����λ�����ޤ���*/ 325*0fbf3537Syasuoka static void 326*0fbf3537Syasuoka pptp_ctrl_fini(pptp_ctrl *_this) 327*0fbf3537Syasuoka { 328*0fbf3537Syasuoka pptp_call *call; 329*0fbf3537Syasuoka 330*0fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 331*0fbf3537Syasuoka 332*0fbf3537Syasuoka if (_this->sock >= 0) { 333*0fbf3537Syasuoka event_del(&_this->ev_sock); 334*0fbf3537Syasuoka close(_this->sock); 335*0fbf3537Syasuoka _this->sock = -1; 336*0fbf3537Syasuoka } 337*0fbf3537Syasuoka for (slist_itr_first(&_this->call_list); 338*0fbf3537Syasuoka slist_itr_has_next(&_this->call_list);) { 339*0fbf3537Syasuoka call = slist_itr_next(&_this->call_list); 340*0fbf3537Syasuoka pptp_call_stop(call); 341*0fbf3537Syasuoka pptp_call_destroy(call); 342*0fbf3537Syasuoka slist_itr_remove(&_this->call_list); 343*0fbf3537Syasuoka } 344*0fbf3537Syasuoka 345*0fbf3537Syasuoka if (_this->on_io_event != 0) { 346*0fbf3537Syasuoka /* 347*0fbf3537Syasuoka * I/O ���٥�ȥϥ�ɥ���Ǥν�λ�������ϡ��Ǹ�ޤǹԤ��� 348*0fbf3537Syasuoka * �㳰������ʣ���ˤʤ�Τǡ�����ޤǤ����Ԥ魯��³���ϡ� 349*0fbf3537Syasuoka * �����ޥ��٥�ȥϥ�ɥ�ǹԤ��� 350*0fbf3537Syasuoka */ 351*0fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "Disposing")); 352*0fbf3537Syasuoka _this->state = PPTP_CTRL_STATE_DISPOSING; 353*0fbf3537Syasuoka pptp_ctrl_reset_timeout(_this); 354*0fbf3537Syasuoka return; 355*0fbf3537Syasuoka } 356*0fbf3537Syasuoka 357*0fbf3537Syasuoka evtimer_del(&_this->ev_timer); 358*0fbf3537Syasuoka slist_fini(&_this->call_list); 359*0fbf3537Syasuoka 360*0fbf3537Syasuoka pptp_ctrl_log (_this, LOG_NOTICE, "logtype=Finished"); 361*0fbf3537Syasuoka 362*0fbf3537Syasuoka /* ���θ� _this �ϻ��ѤǤ��ʤ� */ 363*0fbf3537Syasuoka pptpd_ctrl_finished_notify(_this->pptpd, _this); 364*0fbf3537Syasuoka } 365*0fbf3537Syasuoka 366*0fbf3537Syasuoka /* PPTP ����ȥ��륳��ƥ����Ȥ�������ޤ���*/ 367*0fbf3537Syasuoka void 368*0fbf3537Syasuoka pptp_ctrl_destroy(pptp_ctrl *_this) 369*0fbf3537Syasuoka { 370*0fbf3537Syasuoka if (_this->send_buf != NULL) { 371*0fbf3537Syasuoka bytebuffer_destroy(_this->send_buf); 372*0fbf3537Syasuoka _this->send_buf = NULL; 373*0fbf3537Syasuoka } 374*0fbf3537Syasuoka if (_this->recv_buf != NULL) { 375*0fbf3537Syasuoka bytebuffer_destroy(_this->recv_buf); 376*0fbf3537Syasuoka _this->recv_buf = NULL; 377*0fbf3537Syasuoka } 378*0fbf3537Syasuoka free(_this); 379*0fbf3537Syasuoka } 380*0fbf3537Syasuoka 381*0fbf3537Syasuoka /************************************************************************ 382*0fbf3537Syasuoka * �ͥåȥ�� I/O 383*0fbf3537Syasuoka ************************************************************************/ 384*0fbf3537Syasuoka /** I/O ���٥�ȥǥ����ѥå��� */ 385*0fbf3537Syasuoka static void 386*0fbf3537Syasuoka pptp_ctrl_io_event(int fd, short evmask, void *ctx) 387*0fbf3537Syasuoka { 388*0fbf3537Syasuoka int sz, lpkt, hdrlen; 389*0fbf3537Syasuoka u_char *pkt; 390*0fbf3537Syasuoka pptp_ctrl *_this; 391*0fbf3537Syasuoka 392*0fbf3537Syasuoka _this = ctx; 393*0fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 394*0fbf3537Syasuoka 395*0fbf3537Syasuoka _this->on_io_event = 1; 396*0fbf3537Syasuoka if ((evmask & EV_WRITE) != 0) { 397*0fbf3537Syasuoka if (pptp_ctrl_output_flush(_this) != 0 || 398*0fbf3537Syasuoka _this->state == PPTP_CTRL_STATE_DISPOSING) 399*0fbf3537Syasuoka goto reigai; 400*0fbf3537Syasuoka _this->send_ready = 1; 401*0fbf3537Syasuoka } 402*0fbf3537Syasuoka if ((evmask & EV_READ) != 0) { 403*0fbf3537Syasuoka sz = read(_this->sock, bytebuffer_pointer(_this->recv_buf), 404*0fbf3537Syasuoka bytebuffer_remaining(_this->recv_buf)); 405*0fbf3537Syasuoka if (sz <= 0) { 406*0fbf3537Syasuoka if (errno == ECONNRESET || sz == 0) { 407*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 408*0fbf3537Syasuoka "Connection closed by foreign host"); 409*0fbf3537Syasuoka pptp_ctrl_fini(_this); 410*0fbf3537Syasuoka goto reigai; 411*0fbf3537Syasuoka } else if (errno != EAGAIN && errno != EINTR) { 412*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 413*0fbf3537Syasuoka "read() failed at %s(): %m", __func__); 414*0fbf3537Syasuoka pptp_ctrl_fini(_this); 415*0fbf3537Syasuoka goto reigai; 416*0fbf3537Syasuoka } 417*0fbf3537Syasuoka } 418*0fbf3537Syasuoka bytebuffer_put(_this->recv_buf, BYTEBUFFER_PUT_DIRECT, sz); 419*0fbf3537Syasuoka bytebuffer_flip(_this->recv_buf); 420*0fbf3537Syasuoka 421*0fbf3537Syasuoka for (;;) { 422*0fbf3537Syasuoka pkt = bytebuffer_pointer(_this->recv_buf); 423*0fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->recv_buf); 424*0fbf3537Syasuoka if (pkt == NULL || 425*0fbf3537Syasuoka lpkt < sizeof(struct pptp_ctrl_header)) 426*0fbf3537Syasuoka break; /* read again */ 427*0fbf3537Syasuoka 428*0fbf3537Syasuoka hdrlen = pkt[0] << 8 | pkt[1]; 429*0fbf3537Syasuoka if (lpkt < hdrlen) 430*0fbf3537Syasuoka break; /* read again */ 431*0fbf3537Syasuoka 432*0fbf3537Syasuoka bytebuffer_get(_this->recv_buf, NULL, hdrlen); 433*0fbf3537Syasuoka if (pptp_ctrl_input(_this, pkt, hdrlen) != 0 || 434*0fbf3537Syasuoka _this->state == PPTP_CTRL_STATE_DISPOSING) { 435*0fbf3537Syasuoka bytebuffer_compact(_this->recv_buf); 436*0fbf3537Syasuoka goto reigai; 437*0fbf3537Syasuoka } 438*0fbf3537Syasuoka } 439*0fbf3537Syasuoka bytebuffer_compact(_this->recv_buf); 440*0fbf3537Syasuoka } 441*0fbf3537Syasuoka if (pptp_ctrl_output_flush(_this) != 0) 442*0fbf3537Syasuoka goto reigai; 443*0fbf3537Syasuoka pptp_ctrl_set_io_event(_this); 444*0fbf3537Syasuoka reigai: 445*0fbf3537Syasuoka _this->on_io_event = 0; 446*0fbf3537Syasuoka } 447*0fbf3537Syasuoka 448*0fbf3537Syasuoka 449*0fbf3537Syasuoka /** ���٥�ȥޥ��������ꤹ�� */ 450*0fbf3537Syasuoka static void 451*0fbf3537Syasuoka pptp_ctrl_set_io_event(pptp_ctrl *_this) 452*0fbf3537Syasuoka { 453*0fbf3537Syasuoka int evmask; 454*0fbf3537Syasuoka 455*0fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 456*0fbf3537Syasuoka PPTP_CTRL_ASSERT(_this->sock >= 0); 457*0fbf3537Syasuoka 458*0fbf3537Syasuoka evmask = 0; 459*0fbf3537Syasuoka if (bytebuffer_remaining(_this->recv_buf) > 128) 460*0fbf3537Syasuoka evmask |= EV_READ; 461*0fbf3537Syasuoka if (_this->send_ready == 0) 462*0fbf3537Syasuoka evmask |= EV_WRITE; 463*0fbf3537Syasuoka 464*0fbf3537Syasuoka event_del(&_this->ev_sock); 465*0fbf3537Syasuoka if (evmask != 0) { 466*0fbf3537Syasuoka event_set(&_this->ev_sock, _this->sock, evmask, 467*0fbf3537Syasuoka pptp_ctrl_io_event, _this); 468*0fbf3537Syasuoka event_add(&_this->ev_sock, NULL); 469*0fbf3537Syasuoka } 470*0fbf3537Syasuoka } 471*0fbf3537Syasuoka 472*0fbf3537Syasuoka /** 473*0fbf3537Syasuoka * PPTP����ȥ���ѥ��åȤ���Ϥ��ޤ��� 474*0fbf3537Syasuoka * @param pkt �ѥ��åȤ��ΰ�ؤΥݥ��� 475*0fbf3537Syasuoka * bytebuffer ��Ȥäơ�_this->send_buf ���ɵ����Ƥ�����ˤϡ� 476*0fbf3537Syasuoka * NULL ����ꤷ�ޤ��� 477*0fbf3537Syasuoka * @param lpkt �ѥ��åȤ�Ĺ���� 478*0fbf3537Syasuoka */ 479*0fbf3537Syasuoka void 480*0fbf3537Syasuoka pptp_ctrl_output(pptp_ctrl *_this, u_char *pkt, int lpkt) 481*0fbf3537Syasuoka { 482*0fbf3537Syasuoka PPTP_CTRL_ASSERT(_this != NULL); 483*0fbf3537Syasuoka PPTP_CTRL_ASSERT(lpkt > 0); 484*0fbf3537Syasuoka 485*0fbf3537Syasuoka bytebuffer_put(_this->send_buf, pkt, lpkt); 486*0fbf3537Syasuoka /* �ºݤˤϽΤϸ� */ 487*0fbf3537Syasuoka 488*0fbf3537Syasuoka if (_this->on_io_event != 0) { 489*0fbf3537Syasuoka /* pptp_ctrl_io_event �� pptp_ctrl_output_flush ��ƤӽФ� */ 490*0fbf3537Syasuoka } else { 491*0fbf3537Syasuoka /* 492*0fbf3537Syasuoka * I/O ���٥�ȥϥ�ɥ餫��θƽФ��ǤϤʤ����ϡ� 493*0fbf3537Syasuoka * pptp_ctrl_output_flush() ��ƤӽФ�ɬ�פ����뤬 flush => 494*0fbf3537Syasuoka * write ���� => finalize �Ȥʤ�ȡ����δؿ��ƤӽФ�¦���㳰 495*0fbf3537Syasuoka * ������������ѻ��ˤʤ�Τǡ�write ready ���٥�Ȥ�ȯ�Ԥ� 496*0fbf3537Syasuoka * �Ƥ��äơ������� flush�� 497*0fbf3537Syasuoka */ 498*0fbf3537Syasuoka _this->send_ready = 0; 499*0fbf3537Syasuoka pptp_ctrl_set_io_event(_this); 500*0fbf3537Syasuoka } 501*0fbf3537Syasuoka 502*0fbf3537Syasuoka return; 503*0fbf3537Syasuoka } 504*0fbf3537Syasuoka 505*0fbf3537Syasuoka /** Stop-Control-Connection-Request ������ */ 506*0fbf3537Syasuoka 507*0fbf3537Syasuoka /** �ºݤ˥ѥ��å����� */ 508*0fbf3537Syasuoka static int 509*0fbf3537Syasuoka pptp_ctrl_output_flush(pptp_ctrl *_this) 510*0fbf3537Syasuoka { 511*0fbf3537Syasuoka int sz; 512*0fbf3537Syasuoka time_t curr_time; 513*0fbf3537Syasuoka 514*0fbf3537Syasuoka curr_time = get_monosec(); 515*0fbf3537Syasuoka 516*0fbf3537Syasuoka if (bytebuffer_position(_this->send_buf) <= 0) 517*0fbf3537Syasuoka return 0; // nothing to write 518*0fbf3537Syasuoka if (_this->send_ready == 0) { 519*0fbf3537Syasuoka pptp_ctrl_set_io_event(_this); 520*0fbf3537Syasuoka return 0; // not ready to write 521*0fbf3537Syasuoka } 522*0fbf3537Syasuoka 523*0fbf3537Syasuoka bytebuffer_flip(_this->send_buf); 524*0fbf3537Syasuoka 525*0fbf3537Syasuoka if (_this->pptpd->ctrl_out_pktdump != 0) { 526*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_DEBUG, "PPTP Control output packet"); 527*0fbf3537Syasuoka show_hd(debug_get_debugfp(), 528*0fbf3537Syasuoka bytebuffer_pointer(_this->send_buf), 529*0fbf3537Syasuoka bytebuffer_remaining(_this->send_buf)); 530*0fbf3537Syasuoka } 531*0fbf3537Syasuoka if ((sz = write(_this->sock, bytebuffer_pointer(_this->send_buf), 532*0fbf3537Syasuoka bytebuffer_remaining(_this->send_buf))) < 0) { 533*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "write to socket failed: %m"); 534*0fbf3537Syasuoka pptp_ctrl_fini(_this); 535*0fbf3537Syasuoka 536*0fbf3537Syasuoka return 1; 537*0fbf3537Syasuoka } 538*0fbf3537Syasuoka _this->last_snd_ctrl = curr_time; 539*0fbf3537Syasuoka bytebuffer_get(_this->send_buf, NULL, sz); 540*0fbf3537Syasuoka bytebuffer_compact(_this->send_buf); 541*0fbf3537Syasuoka _this->send_ready = 0; 542*0fbf3537Syasuoka 543*0fbf3537Syasuoka return 0; 544*0fbf3537Syasuoka } 545*0fbf3537Syasuoka 546*0fbf3537Syasuoka /** Start-Control-Connection-Request��-Reply �ѥ��åȤ�ʸ�����ɽ������ */ 547*0fbf3537Syasuoka static void 548*0fbf3537Syasuoka pptp_ctrl_SCCRx_string(struct pptp_scc *scc, u_char *buf, int lbuf) 549*0fbf3537Syasuoka { 550*0fbf3537Syasuoka char buf1[128], buf2[128], buf3[128]; 551*0fbf3537Syasuoka 552*0fbf3537Syasuoka // 64�Х��ȥ��ꥮ��ޤ����äƤ����礬����Τ� 553*0fbf3537Syasuoka strlcpy(buf1, scc->host_name, sizeof(buf1)); 554*0fbf3537Syasuoka strlcpy(buf2, scc->vendor_string, sizeof(buf2)); 555*0fbf3537Syasuoka 556*0fbf3537Syasuoka if (scc->result_code != 0) 557*0fbf3537Syasuoka snprintf(buf3, sizeof(buf3), "result=%d error=%d ", 558*0fbf3537Syasuoka scc->result_code, scc->error_code); 559*0fbf3537Syasuoka else 560*0fbf3537Syasuoka buf3[0] = '\0'; 561*0fbf3537Syasuoka 562*0fbf3537Syasuoka snprintf(buf, lbuf, 563*0fbf3537Syasuoka "protocol_version=%d.%d %sframing=%s bearer=%s max_channels=%d " 564*0fbf3537Syasuoka "firmware_revision=%d(0x%04x) host_name=\"%s\" " 565*0fbf3537Syasuoka "vendor_string=\"%s\"", 566*0fbf3537Syasuoka scc->protocol_version >> 8, scc->protocol_version & 0xff, buf3, 567*0fbf3537Syasuoka pptp_framing_string(scc->framing_caps), 568*0fbf3537Syasuoka pptp_bearer_string(scc->bearer_caps), scc->max_channels, 569*0fbf3537Syasuoka scc->firmware_revision, scc->firmware_revision, buf1, buf2); 570*0fbf3537Syasuoka } 571*0fbf3537Syasuoka 572*0fbf3537Syasuoka /** Start-Control-Connection-Request ����� */ 573*0fbf3537Syasuoka static int 574*0fbf3537Syasuoka pptp_ctrl_recv_SCCRQ(pptp_ctrl *_this, u_char *pkt, int lpkt) 575*0fbf3537Syasuoka { 576*0fbf3537Syasuoka char logbuf[512]; 577*0fbf3537Syasuoka struct pptp_scc *scc; 578*0fbf3537Syasuoka 579*0fbf3537Syasuoka // ���������� 580*0fbf3537Syasuoka if (lpkt < sizeof(struct pptp_scc)) { 581*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad SCCRQ: packet too " 582*0fbf3537Syasuoka "short: %d < %d", lpkt, (int)sizeof(struct pptp_scc)); 583*0fbf3537Syasuoka return 1; 584*0fbf3537Syasuoka } 585*0fbf3537Syasuoka scc = (struct pptp_scc *)pkt; 586*0fbf3537Syasuoka 587*0fbf3537Syasuoka // �Х��ȥ������� 588*0fbf3537Syasuoka scc->protocol_version = ntohs(scc->protocol_version); 589*0fbf3537Syasuoka scc->framing_caps = htonl(scc->framing_caps); 590*0fbf3537Syasuoka scc->bearer_caps = htonl(scc->bearer_caps); 591*0fbf3537Syasuoka scc->max_channels = htons(scc->max_channels); 592*0fbf3537Syasuoka scc->firmware_revision = htons(scc->firmware_revision); 593*0fbf3537Syasuoka 594*0fbf3537Syasuoka // �ץ�ȥ���С������ 595*0fbf3537Syasuoka if (scc->protocol_version != PPTP_RFC_2637_VERSION) { 596*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad SCCRQ: " 597*0fbf3537Syasuoka "unknown protocol version %d", scc->protocol_version); 598*0fbf3537Syasuoka return 1; 599*0fbf3537Syasuoka } 600*0fbf3537Syasuoka 601*0fbf3537Syasuoka pptp_ctrl_SCCRx_string(scc, logbuf, sizeof(logbuf)); 602*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "RecvSCCRQ %s", logbuf); 603*0fbf3537Syasuoka 604*0fbf3537Syasuoka return 0; 605*0fbf3537Syasuoka } 606*0fbf3537Syasuoka 607*0fbf3537Syasuoka /** Stop-Control-Connection-Reply �μ��� */ 608*0fbf3537Syasuoka static int 609*0fbf3537Syasuoka pptp_ctrl_recv_StopCCRP(pptp_ctrl *_this, u_char *pkt, int lpkt) 610*0fbf3537Syasuoka { 611*0fbf3537Syasuoka struct pptp_stop_ccrp *stop_ccrp; 612*0fbf3537Syasuoka 613*0fbf3537Syasuoka if (lpkt < sizeof(struct pptp_stop_ccrp)) { 614*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad StopCCRP: packet " 615*0fbf3537Syasuoka "too short: %d < %d", lpkt, 616*0fbf3537Syasuoka (int)sizeof(struct pptp_stop_ccrp)); 617*0fbf3537Syasuoka return 1; 618*0fbf3537Syasuoka } 619*0fbf3537Syasuoka stop_ccrp = (struct pptp_stop_ccrp *)pkt; 620*0fbf3537Syasuoka 621*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "RecvStopCCRP reason=%s(%u)", 622*0fbf3537Syasuoka pptp_StopCCRP_result_string(stop_ccrp->result), stop_ccrp->result); 623*0fbf3537Syasuoka 624*0fbf3537Syasuoka return 0; 625*0fbf3537Syasuoka } 626*0fbf3537Syasuoka 627*0fbf3537Syasuoka static int 628*0fbf3537Syasuoka pptp_ctrl_send_StopCCRQ(pptp_ctrl *_this, int reason) 629*0fbf3537Syasuoka { 630*0fbf3537Syasuoka int lpkt; 631*0fbf3537Syasuoka struct pptp_stop_ccrq *stop_ccrq; 632*0fbf3537Syasuoka 633*0fbf3537Syasuoka stop_ccrq = bytebuffer_pointer(_this->send_buf); 634*0fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 635*0fbf3537Syasuoka if (lpkt < sizeof(struct pptp_stop_ccrq)) { 636*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 637*0fbf3537Syasuoka "SendCCRP failed: No buffer space available"); 638*0fbf3537Syasuoka return -1; 639*0fbf3537Syasuoka } 640*0fbf3537Syasuoka memset(stop_ccrq, 0, sizeof(struct pptp_stop_ccrq)); 641*0fbf3537Syasuoka 642*0fbf3537Syasuoka pptp_init_header(&stop_ccrq->header, sizeof(struct pptp_stop_ccrq), 643*0fbf3537Syasuoka PPTP_CTRL_MES_CODE_StopCCRQ); 644*0fbf3537Syasuoka 645*0fbf3537Syasuoka stop_ccrq->reason = reason; 646*0fbf3537Syasuoka 647*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "SendStopCCRQ reason=%s(%u)", 648*0fbf3537Syasuoka pptp_StopCCRQ_reason_string(stop_ccrq->reason), stop_ccrq->reason); 649*0fbf3537Syasuoka 650*0fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_stop_ccrq)); 651*0fbf3537Syasuoka 652*0fbf3537Syasuoka return 0; 653*0fbf3537Syasuoka } 654*0fbf3537Syasuoka 655*0fbf3537Syasuoka /** Stop-Control-Connection-Request ����� */ 656*0fbf3537Syasuoka static int 657*0fbf3537Syasuoka pptp_ctrl_recv_StopCCRQ(pptp_ctrl *_this, u_char *pkt, int lpkt) 658*0fbf3537Syasuoka { 659*0fbf3537Syasuoka struct pptp_stop_ccrq *stop_ccrq; 660*0fbf3537Syasuoka 661*0fbf3537Syasuoka if (lpkt < sizeof(struct pptp_stop_ccrq)) { 662*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad StopCCRQ: packet " 663*0fbf3537Syasuoka "too short: %d < %d", lpkt, 664*0fbf3537Syasuoka (int)sizeof(struct pptp_stop_ccrq)); 665*0fbf3537Syasuoka return 1; 666*0fbf3537Syasuoka } 667*0fbf3537Syasuoka stop_ccrq = (struct pptp_stop_ccrq *)pkt; 668*0fbf3537Syasuoka 669*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "RecvStopCCRQ reason=%s(%u)", 670*0fbf3537Syasuoka pptp_StopCCRQ_reason_string(stop_ccrq->reason), stop_ccrq->reason); 671*0fbf3537Syasuoka 672*0fbf3537Syasuoka return 0; 673*0fbf3537Syasuoka } 674*0fbf3537Syasuoka 675*0fbf3537Syasuoka 676*0fbf3537Syasuoka 677*0fbf3537Syasuoka /** Stop-Control-Connection-Reply ������ */ 678*0fbf3537Syasuoka static int 679*0fbf3537Syasuoka pptp_ctrl_send_StopCCRP(pptp_ctrl *_this, int result, int error) 680*0fbf3537Syasuoka { 681*0fbf3537Syasuoka int lpkt; 682*0fbf3537Syasuoka struct pptp_stop_ccrp *stop_ccrp; 683*0fbf3537Syasuoka 684*0fbf3537Syasuoka stop_ccrp = bytebuffer_pointer(_this->send_buf); 685*0fbf3537Syasuoka 686*0fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 687*0fbf3537Syasuoka if (lpkt < sizeof(struct pptp_stop_ccrp)) { 688*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 689*0fbf3537Syasuoka "SendCCRQ failed: No buffer space available"); 690*0fbf3537Syasuoka return -1; 691*0fbf3537Syasuoka } 692*0fbf3537Syasuoka memset(stop_ccrp, 0, sizeof(struct pptp_stop_ccrp)); 693*0fbf3537Syasuoka 694*0fbf3537Syasuoka pptp_init_header(&stop_ccrp->header, sizeof(struct pptp_stop_ccrp), 695*0fbf3537Syasuoka PPTP_CTRL_MES_CODE_StopCCRP); 696*0fbf3537Syasuoka 697*0fbf3537Syasuoka stop_ccrp->result = result; 698*0fbf3537Syasuoka stop_ccrp->error = error; 699*0fbf3537Syasuoka 700*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 701*0fbf3537Syasuoka "SendStopCCRP result=%s(%u) error=%s(%u)", 702*0fbf3537Syasuoka pptp_StopCCRP_result_string(stop_ccrp->result), stop_ccrp->result, 703*0fbf3537Syasuoka pptp_general_error_string(stop_ccrp->error), stop_ccrp->error); 704*0fbf3537Syasuoka 705*0fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_stop_ccrp)); 706*0fbf3537Syasuoka 707*0fbf3537Syasuoka return 0; 708*0fbf3537Syasuoka } 709*0fbf3537Syasuoka 710*0fbf3537Syasuoka /** Start-Control-Connection-Reply ������ */ 711*0fbf3537Syasuoka static int 712*0fbf3537Syasuoka pptp_ctrl_send_SCCRP(pptp_ctrl *_this, int result, int error) 713*0fbf3537Syasuoka { 714*0fbf3537Syasuoka int lpkt; 715*0fbf3537Syasuoka struct pptp_scc *scc; 716*0fbf3537Syasuoka char logbuf[512]; 717*0fbf3537Syasuoka const char *val; 718*0fbf3537Syasuoka 719*0fbf3537Syasuoka scc = bytebuffer_pointer(_this->send_buf); 720*0fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 721*0fbf3537Syasuoka if (lpkt < sizeof(struct pptp_scc)) { 722*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 723*0fbf3537Syasuoka "SendSCCRP failed: No buffer space available"); 724*0fbf3537Syasuoka return -1; 725*0fbf3537Syasuoka } 726*0fbf3537Syasuoka memset(scc, 0, sizeof(struct pptp_scc)); 727*0fbf3537Syasuoka 728*0fbf3537Syasuoka pptp_init_header(&scc->header, sizeof(struct pptp_scc), 729*0fbf3537Syasuoka PPTP_CTRL_MES_CODE_SCCRP); 730*0fbf3537Syasuoka 731*0fbf3537Syasuoka scc->protocol_version = PPTP_RFC_2637_VERSION; 732*0fbf3537Syasuoka scc->result_code = result; 733*0fbf3537Syasuoka scc->error_code = error; 734*0fbf3537Syasuoka // Ʊ���ե졼�ष�����ݡ��Ȥ����� 735*0fbf3537Syasuoka //scc->framing_caps = PPTP_CTRL_FRAMING_ASYNC; 736*0fbf3537Syasuoka scc->framing_caps = PPTP_CTRL_FRAMING_SYNC; 737*0fbf3537Syasuoka scc->bearer_caps = PPTP_CTRL_BEARER_DIGITAL; 738*0fbf3537Syasuoka 739*0fbf3537Syasuoka scc->max_channels = 4; // XX ����? 740*0fbf3537Syasuoka scc->firmware_revision = MAJOR_VERSION << 8 | MINOR_VERSION; 741*0fbf3537Syasuoka 742*0fbf3537Syasuoka // 63ʸ�����ڤ�Ƥⵤ�ˤ��ʤ� 743*0fbf3537Syasuoka 744*0fbf3537Syasuoka // �ۥ���̾ 745*0fbf3537Syasuoka if ((val = pptp_ctrl_config_str(_this, "pptp.host_name")) == NULL) 746*0fbf3537Syasuoka val = ""; 747*0fbf3537Syasuoka strlcpy(scc->host_name, val, sizeof(scc->host_name)); 748*0fbf3537Syasuoka 749*0fbf3537Syasuoka // �٥��̾ 750*0fbf3537Syasuoka if ((val = pptp_ctrl_config_str(_this, "pptp.vendor_name")) == NULL) 751*0fbf3537Syasuoka val = PPTPD_DEFAULT_VENDOR_NAME; 752*0fbf3537Syasuoka 753*0fbf3537Syasuoka strlcpy(scc->vendor_string, val, sizeof(scc->vendor_string)); 754*0fbf3537Syasuoka 755*0fbf3537Syasuoka pptp_ctrl_SCCRx_string(scc, logbuf, sizeof(logbuf)); 756*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, "SendSCCRP %s", logbuf); 757*0fbf3537Syasuoka 758*0fbf3537Syasuoka scc->protocol_version = htons(scc->protocol_version); 759*0fbf3537Syasuoka scc->framing_caps = htonl(scc->framing_caps); 760*0fbf3537Syasuoka scc->bearer_caps = htonl(scc->bearer_caps); 761*0fbf3537Syasuoka scc->max_channels = htons(scc->max_channels); 762*0fbf3537Syasuoka scc->firmware_revision = htons(scc->firmware_revision); 763*0fbf3537Syasuoka 764*0fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_scc)); 765*0fbf3537Syasuoka 766*0fbf3537Syasuoka return 0; 767*0fbf3537Syasuoka } 768*0fbf3537Syasuoka 769*0fbf3537Syasuoka /** ECHO �μ��� => �ֿ� */ 770*0fbf3537Syasuoka static void 771*0fbf3537Syasuoka pptp_ctrl_process_echo_req(pptp_ctrl *_this, u_char *pkt, int lpkt) 772*0fbf3537Syasuoka { 773*0fbf3537Syasuoka struct pptp_echo_rq *echo_rq; 774*0fbf3537Syasuoka struct pptp_echo_rp *echo_rp; 775*0fbf3537Syasuoka 776*0fbf3537Syasuoka if (lpkt < sizeof(struct pptp_echo_rq)) { 777*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad EchoReq: packet " 778*0fbf3537Syasuoka "too short: %d < %d", lpkt, 779*0fbf3537Syasuoka (int)sizeof(struct pptp_echo_rq)); 780*0fbf3537Syasuoka return; 781*0fbf3537Syasuoka } 782*0fbf3537Syasuoka echo_rq = (struct pptp_echo_rq *)pkt; 783*0fbf3537Syasuoka 784*0fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "RecvEchoReq")); 785*0fbf3537Syasuoka 786*0fbf3537Syasuoka echo_rp = bytebuffer_pointer(_this->send_buf); 787*0fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 788*0fbf3537Syasuoka if (echo_rp == NULL || lpkt < sizeof(struct pptp_echo_rp)) { 789*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 790*0fbf3537Syasuoka "Failed to send EchoReq: No buffer space available"); 791*0fbf3537Syasuoka return; 792*0fbf3537Syasuoka } 793*0fbf3537Syasuoka memset(echo_rp, 0, sizeof(struct pptp_echo_rp)); 794*0fbf3537Syasuoka 795*0fbf3537Syasuoka pptp_init_header(&echo_rp->header, sizeof(struct pptp_echo_rp), 796*0fbf3537Syasuoka PPTP_CTRL_MES_CODE_ECHO_RP); 797*0fbf3537Syasuoka 798*0fbf3537Syasuoka echo_rp->identifier = echo_rq->identifier; 799*0fbf3537Syasuoka echo_rp->result_code = PPTP_ECHO_RP_RESULT_OK; 800*0fbf3537Syasuoka echo_rp->error_code = PPTP_ERROR_NONE; 801*0fbf3537Syasuoka echo_rp->reserved1 = htons(0); 802*0fbf3537Syasuoka 803*0fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_echo_rp)); 804*0fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "SendEchoReply")); 805*0fbf3537Syasuoka } 806*0fbf3537Syasuoka 807*0fbf3537Syasuoka /** Echo-Reply �μ��� */ 808*0fbf3537Syasuoka static int 809*0fbf3537Syasuoka pptp_ctrl_recv_echo_rep(pptp_ctrl *_this, u_char *pkt, int lpkt) 810*0fbf3537Syasuoka { 811*0fbf3537Syasuoka struct pptp_echo_rp *echo_rp; 812*0fbf3537Syasuoka 813*0fbf3537Syasuoka if (lpkt < sizeof(struct pptp_echo_rp)) { 814*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad EchoReq: packet " 815*0fbf3537Syasuoka "too short: %d < %d", lpkt, 816*0fbf3537Syasuoka (int)sizeof(struct pptp_echo_rp)); 817*0fbf3537Syasuoka return 1; 818*0fbf3537Syasuoka } 819*0fbf3537Syasuoka echo_rp = (struct pptp_echo_rp *)pkt; 820*0fbf3537Syasuoka 821*0fbf3537Syasuoka if (echo_rp->result_code != PPTP_ECHO_RP_RESULT_OK) { 822*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received negative EchoReply: %s", 823*0fbf3537Syasuoka pptp_general_error_string(echo_rp->error_code)); 824*0fbf3537Syasuoka return 1; 825*0fbf3537Syasuoka } 826*0fbf3537Syasuoka if (_this->echo_seq != ntohl(echo_rp->identifier)) { 827*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad EchoReply: " 828*0fbf3537Syasuoka "Identifier mismatch sent=%u recv=%u", 829*0fbf3537Syasuoka _this->echo_seq , ntohl(echo_rp->identifier)); 830*0fbf3537Syasuoka return 1; 831*0fbf3537Syasuoka } 832*0fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "RecvEchoReply")); 833*0fbf3537Syasuoka return 0; 834*0fbf3537Syasuoka } 835*0fbf3537Syasuoka 836*0fbf3537Syasuoka /** Echo-Request ������ */ 837*0fbf3537Syasuoka static void 838*0fbf3537Syasuoka pptp_ctrl_send_echo_req(pptp_ctrl *_this) 839*0fbf3537Syasuoka { 840*0fbf3537Syasuoka int lpkt; 841*0fbf3537Syasuoka struct pptp_echo_rq *echo_rq; 842*0fbf3537Syasuoka 843*0fbf3537Syasuoka echo_rq = (struct pptp_echo_rq *)bytebuffer_pointer(_this->send_buf); 844*0fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 845*0fbf3537Syasuoka if (echo_rq == NULL || lpkt < sizeof(struct pptp_echo_rq)) { 846*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 847*0fbf3537Syasuoka "SendEchoReq failed: No buffer space available"); 848*0fbf3537Syasuoka return; 849*0fbf3537Syasuoka } 850*0fbf3537Syasuoka memset(echo_rq, 0, sizeof(struct pptp_echo_rq)); 851*0fbf3537Syasuoka 852*0fbf3537Syasuoka pptp_init_header(&echo_rq->header, sizeof(struct pptp_echo_rq), 853*0fbf3537Syasuoka PPTP_CTRL_MES_CODE_ECHO_RQ); 854*0fbf3537Syasuoka 855*0fbf3537Syasuoka echo_rq->identifier = htonl(_this->echo_seq); 856*0fbf3537Syasuoka 857*0fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_echo_rq)); 858*0fbf3537Syasuoka PPTP_CTRL_DBG((_this, LOG_DEBUG, "SendEchoReq")); 859*0fbf3537Syasuoka } 860*0fbf3537Syasuoka 861*0fbf3537Syasuoka /* Call-Disconnect-Notify ������ */ 862*0fbf3537Syasuoka static void 863*0fbf3537Syasuoka pptp_ctrl_send_CDN(pptp_ctrl *_this, int result, int error, int cause, 864*0fbf3537Syasuoka const char *statistics) 865*0fbf3537Syasuoka { 866*0fbf3537Syasuoka int lpkt; 867*0fbf3537Syasuoka struct pptp_cdn *cdn; 868*0fbf3537Syasuoka 869*0fbf3537Syasuoka cdn = bytebuffer_pointer(_this->send_buf); 870*0fbf3537Syasuoka lpkt = bytebuffer_remaining(_this->send_buf); 871*0fbf3537Syasuoka if (lpkt < sizeof(struct pptp_cdn)) { 872*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 873*0fbf3537Syasuoka "SendCCR failed: No buffer space available"); 874*0fbf3537Syasuoka return; 875*0fbf3537Syasuoka } 876*0fbf3537Syasuoka memset(cdn, 0, sizeof(struct pptp_cdn)); 877*0fbf3537Syasuoka 878*0fbf3537Syasuoka pptp_init_header(&cdn->header, sizeof(struct pptp_cdn), 879*0fbf3537Syasuoka PPTP_CTRL_MES_CODE_CDN); 880*0fbf3537Syasuoka 881*0fbf3537Syasuoka cdn->call_id = _this->id; 882*0fbf3537Syasuoka cdn->result_code = result; 883*0fbf3537Syasuoka cdn->error_code = error; 884*0fbf3537Syasuoka cdn->cause_code = cause; 885*0fbf3537Syasuoka if (statistics != NULL) 886*0fbf3537Syasuoka strlcpy(cdn->statistics, statistics, sizeof(cdn->statistics)); 887*0fbf3537Syasuoka 888*0fbf3537Syasuoka cdn->call_id = htons(cdn->call_id); 889*0fbf3537Syasuoka cdn->cause_code = htons(cdn->cause_code); 890*0fbf3537Syasuoka 891*0fbf3537Syasuoka pptp_ctrl_output(_this, NULL, sizeof(struct pptp_cdn)); 892*0fbf3537Syasuoka } 893*0fbf3537Syasuoka 894*0fbf3537Syasuoka /** ����ȥ���ѥ��åȼ��� */ 895*0fbf3537Syasuoka static int 896*0fbf3537Syasuoka pptp_ctrl_input(pptp_ctrl *_this, u_char *pkt, int lpkt) 897*0fbf3537Syasuoka { 898*0fbf3537Syasuoka char errmes[256]; 899*0fbf3537Syasuoka time_t curr_time; 900*0fbf3537Syasuoka struct pptp_ctrl_header *hdr; 901*0fbf3537Syasuoka 902*0fbf3537Syasuoka PPTP_CTRL_ASSERT(lpkt >= sizeof(struct pptp_ctrl_header)); 903*0fbf3537Syasuoka 904*0fbf3537Syasuoka curr_time = get_monosec(); 905*0fbf3537Syasuoka hdr = (struct pptp_ctrl_header *)pkt; 906*0fbf3537Syasuoka 907*0fbf3537Syasuoka // �Х��ȥ������� 908*0fbf3537Syasuoka hdr->length = ntohs(hdr->length); 909*0fbf3537Syasuoka hdr->pptp_message_type = ntohs(hdr->pptp_message_type); 910*0fbf3537Syasuoka hdr->magic_cookie = ntohl(hdr->magic_cookie); 911*0fbf3537Syasuoka hdr->control_message_type = ntohs(hdr->control_message_type); 912*0fbf3537Syasuoka hdr->reserved0 = ntohs(hdr->reserved0); 913*0fbf3537Syasuoka 914*0fbf3537Syasuoka // Ĺ������ 915*0fbf3537Syasuoka PPTP_CTRL_ASSERT(hdr->length <= lpkt); 916*0fbf3537Syasuoka 917*0fbf3537Syasuoka _this->last_rcv_ctrl = curr_time; 918*0fbf3537Syasuoka 919*0fbf3537Syasuoka if (_this->pptpd->ctrl_in_pktdump != 0) { 920*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_DEBUG, 921*0fbf3537Syasuoka "PPTP Control input packet dump: mestype=%s(%d)", 922*0fbf3537Syasuoka pptp_ctrl_mes_type_string(hdr->control_message_type), 923*0fbf3537Syasuoka hdr->control_message_type); 924*0fbf3537Syasuoka show_hd(debug_get_debugfp(), pkt, lpkt); 925*0fbf3537Syasuoka } 926*0fbf3537Syasuoka 927*0fbf3537Syasuoka /* �ѥ��åȸ��� */ 928*0fbf3537Syasuoka // ��å����������� 929*0fbf3537Syasuoka if (hdr->pptp_message_type != PPTP_MES_TYPE_CTRL) { 930*0fbf3537Syasuoka snprintf(errmes, sizeof(errmes), "unknown message type %d", 931*0fbf3537Syasuoka hdr->pptp_message_type); 932*0fbf3537Syasuoka goto bad_packet; 933*0fbf3537Syasuoka } 934*0fbf3537Syasuoka // �ޥ��å����å��� 935*0fbf3537Syasuoka if (hdr->magic_cookie != PPTP_MAGIC_COOKIE) { 936*0fbf3537Syasuoka snprintf(errmes, sizeof(errmes), "wrong magic %08x != %08x", 937*0fbf3537Syasuoka hdr->magic_cookie, PPTP_MAGIC_COOKIE); 938*0fbf3537Syasuoka goto bad_packet; 939*0fbf3537Syasuoka } 940*0fbf3537Syasuoka 941*0fbf3537Syasuoka // ECHO Reply ���̽��������ơ��Ȥ���������ǽ��������Τǡ�*/ 942*0fbf3537Syasuoka switch (hdr->control_message_type) { 943*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ECHO_RP: 944*0fbf3537Syasuoka if (pptp_ctrl_recv_echo_rep(_this, pkt, lpkt) != 0) { 945*0fbf3537Syasuoka pptp_ctrl_fini(_this); 946*0fbf3537Syasuoka return 1; 947*0fbf3537Syasuoka } 948*0fbf3537Syasuoka return 0; 949*0fbf3537Syasuoka } 950*0fbf3537Syasuoka /* 951*0fbf3537Syasuoka * ���ơ��ȥޥ��� 952*0fbf3537Syasuoka * - ����˽���������ä��顢return ���롣 953*0fbf3537Syasuoka */ 954*0fbf3537Syasuoka switch (_this->state) { 955*0fbf3537Syasuoka case PPTP_CTRL_STATE_IDLE: 956*0fbf3537Syasuoka switch (hdr->control_message_type) { 957*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_SCCRQ: 958*0fbf3537Syasuoka if (pptp_ctrl_recv_SCCRQ(_this, pkt, lpkt) != 0) { 959*0fbf3537Syasuoka return 0; 960*0fbf3537Syasuoka } 961*0fbf3537Syasuoka if (pptp_ctrl_send_SCCRP(_this, 962*0fbf3537Syasuoka PPTP_SCCRP_RESULT_SUCCESS, PPTP_ERROR_NONE) != 0) { 963*0fbf3537Syasuoka return 0; 964*0fbf3537Syasuoka } 965*0fbf3537Syasuoka _this->state = PPTP_CTRL_STATE_ESTABLISHED; 966*0fbf3537Syasuoka return 0; 967*0fbf3537Syasuoka default: 968*0fbf3537Syasuoka break; 969*0fbf3537Syasuoka } 970*0fbf3537Syasuoka break; 971*0fbf3537Syasuoka case PPTP_CTRL_STATE_ESTABLISHED: 972*0fbf3537Syasuoka switch (hdr->control_message_type) { 973*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ECHO_RQ: 974*0fbf3537Syasuoka pptp_ctrl_process_echo_req(_this, pkt, lpkt); 975*0fbf3537Syasuoka return 0; 976*0fbf3537Syasuoka //�������Ϣ�ѥ��åȤϡ�pptp_call_input �˥ǥ����ѥå� 977*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_SLI: 978*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICRQ: 979*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICRP: 980*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_OCRQ: 981*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_OCRP: 982*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICCN: 983*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_CDN: 984*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_CCR: 985*0fbf3537Syasuoka return pptp_ctrl_call_input(_this, 986*0fbf3537Syasuoka hdr->control_message_type, pkt, lpkt); 987*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_StopCCRQ: 988*0fbf3537Syasuoka if (pptp_ctrl_recv_StopCCRQ(_this, pkt, lpkt) != 0) { 989*0fbf3537Syasuoka pptp_ctrl_stop(_this, 990*0fbf3537Syasuoka PPTP_StopCCRQ_REASON_STOP_PROTOCOL); 991*0fbf3537Syasuoka return 0; 992*0fbf3537Syasuoka } 993*0fbf3537Syasuoka if (pptp_ctrl_send_StopCCRP(_this, 994*0fbf3537Syasuoka PPTP_StopCCRP_RESULT_OK, PPTP_ERROR_NONE)!= 0) { 995*0fbf3537Syasuoka return 0; 996*0fbf3537Syasuoka } 997*0fbf3537Syasuoka pptp_ctrl_fini(_this); 998*0fbf3537Syasuoka return 1; 999*0fbf3537Syasuoka default: 1000*0fbf3537Syasuoka break; 1001*0fbf3537Syasuoka } 1002*0fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_STOP_REPLY: 1003*0fbf3537Syasuoka switch (hdr->control_message_type) { 1004*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_StopCCRP: 1005*0fbf3537Syasuoka pptp_ctrl_recv_StopCCRP(_this, pkt, lpkt); 1006*0fbf3537Syasuoka pptp_ctrl_fini(_this); 1007*0fbf3537Syasuoka return 1; 1008*0fbf3537Syasuoka } 1009*0fbf3537Syasuoka break; 1010*0fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_CTRL_REPLY: 1011*0fbf3537Syasuoka // PAC �μ��������ʤΤ� 1012*0fbf3537Syasuoka break; 1013*0fbf3537Syasuoka } 1014*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_WARNING, 1015*0fbf3537Syasuoka "Unhandled control message type=%s(%d)", 1016*0fbf3537Syasuoka pptp_ctrl_mes_type_string(hdr->control_message_type), 1017*0fbf3537Syasuoka hdr->control_message_type); 1018*0fbf3537Syasuoka return 0; 1019*0fbf3537Syasuoka 1020*0fbf3537Syasuoka bad_packet: 1021*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, "Received bad packet: %s", errmes); 1022*0fbf3537Syasuoka pptp_ctrl_stop(_this, PPTP_StopCCRQ_REASON_STOP_PROTOCOL); 1023*0fbf3537Syasuoka 1024*0fbf3537Syasuoka return 0; 1025*0fbf3537Syasuoka } 1026*0fbf3537Syasuoka 1027*0fbf3537Syasuoka /** PPTP Call ��Ϣ�Υ�å���������� */ 1028*0fbf3537Syasuoka static int 1029*0fbf3537Syasuoka pptp_ctrl_call_input(pptp_ctrl *_this, int mes_type, u_char *pkt, int lpkt) 1030*0fbf3537Syasuoka { 1031*0fbf3537Syasuoka int i, call_id, lpkt0; 1032*0fbf3537Syasuoka pptp_call *call; 1033*0fbf3537Syasuoka const char *reason; 1034*0fbf3537Syasuoka u_char *pkt0; 1035*0fbf3537Syasuoka 1036*0fbf3537Syasuoka pkt0 = pkt; 1037*0fbf3537Syasuoka lpkt0 = lpkt; 1038*0fbf3537Syasuoka call_id = -1; 1039*0fbf3537Syasuoka pkt += sizeof(struct pptp_ctrl_header); 1040*0fbf3537Syasuoka lpkt -= sizeof(struct pptp_ctrl_header); 1041*0fbf3537Syasuoka reason = "(no reason)"; 1042*0fbf3537Syasuoka 1043*0fbf3537Syasuoka // callId 1044*0fbf3537Syasuoka if (lpkt < 4) { 1045*0fbf3537Syasuoka reason = "received packet is too short"; 1046*0fbf3537Syasuoka goto badpacket; 1047*0fbf3537Syasuoka } 1048*0fbf3537Syasuoka call = NULL; 1049*0fbf3537Syasuoka call_id = ntohs(*(uint16_t *)pkt); 1050*0fbf3537Syasuoka 1051*0fbf3537Syasuoka switch (mes_type) { 1052*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_SLI: /* PNS <=> PAC */ 1053*0fbf3537Syasuoka /* SLI �����ϡ�������� Call-ID �����äƤ��� */ 1054*0fbf3537Syasuoka for (i = 0; i < slist_length(&_this->call_list); i++) { 1055*0fbf3537Syasuoka call = slist_get(&_this->call_list, i); 1056*0fbf3537Syasuoka if (call->id == call_id) 1057*0fbf3537Syasuoka break; 1058*0fbf3537Syasuoka call = NULL; 1059*0fbf3537Syasuoka } 1060*0fbf3537Syasuoka if (call == NULL) { 1061*0fbf3537Syasuoka reason = "Call Id is not associated by this control"; 1062*0fbf3537Syasuoka goto badpacket; 1063*0fbf3537Syasuoka } 1064*0fbf3537Syasuoka goto call_searched; 1065*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICRP: /* PNS => PAC */ 1066*0fbf3537Syasuoka /* 1067*0fbf3537Syasuoka * ICRQ ���ꤲ�ʤ��ΤǤ��Υ�å������ϼ������ʤ������������� 1068*0fbf3537Syasuoka * pptp_call.c ¦�ǽ��������� 1069*0fbf3537Syasuoka */ 1070*0fbf3537Syasuoka // FALL THROUGH 1071*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_OCRQ: /* PNS => PAC */ 1072*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_CCR: /* PNS => PAC */ 1073*0fbf3537Syasuoka // ��˥��������Ǥ褤�� 1074*0fbf3537Syasuoka for (i = 0; i < slist_length(&_this->call_list); i++) { 1075*0fbf3537Syasuoka call = slist_get(&_this->call_list, i); 1076*0fbf3537Syasuoka if (call->peers_call_id == call_id) 1077*0fbf3537Syasuoka break; 1078*0fbf3537Syasuoka call = NULL; 1079*0fbf3537Syasuoka } 1080*0fbf3537Syasuoka if (call == NULL && mes_type == PPTP_CTRL_MES_CODE_CCR) { 1081*0fbf3537Syasuoka pptp_ctrl_send_CDN(_this, PPTP_CDN_RESULT_GENRIC_ERROR, 1082*0fbf3537Syasuoka PPTP_ERROR_BAD_CALL, 0, NULL); 1083*0fbf3537Syasuoka goto call_searched; 1084*0fbf3537Syasuoka } 1085*0fbf3537Syasuoka if (mes_type == PPTP_CTRL_MES_CODE_OCRQ) { 1086*0fbf3537Syasuoka // ������ Call ����� 1087*0fbf3537Syasuoka if (call != NULL) { 1088*0fbf3537Syasuoka pptp_call_input(call, mes_type, pkt0, lpkt0); 1089*0fbf3537Syasuoka return 0; 1090*0fbf3537Syasuoka } 1091*0fbf3537Syasuoka if ((call = pptp_call_create()) == NULL) { 1092*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 1093*0fbf3537Syasuoka "pptp_call_create() failed: %m"); 1094*0fbf3537Syasuoka goto reigai; 1095*0fbf3537Syasuoka } 1096*0fbf3537Syasuoka if (pptp_call_init(call, _this) != 0) { 1097*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_ERR, 1098*0fbf3537Syasuoka "pptp_call_init() failed: %m"); 1099*0fbf3537Syasuoka pptp_call_destroy(call); 1100*0fbf3537Syasuoka goto reigai; 1101*0fbf3537Syasuoka } 1102*0fbf3537Syasuoka slist_add(&_this->call_list, call); 1103*0fbf3537Syasuoka } 1104*0fbf3537Syasuoka call_searched: 1105*0fbf3537Syasuoka if (call == NULL) { 1106*0fbf3537Syasuoka reason = "Call Id is not associated by this control"; 1107*0fbf3537Syasuoka goto badpacket; 1108*0fbf3537Syasuoka } 1109*0fbf3537Syasuoka pptp_call_input(call, mes_type, pkt0, lpkt0); 1110*0fbf3537Syasuoka return 0; 1111*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_OCRP: /* PAC => PNS */ 1112*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICRQ: /* PAC => PNS */ 1113*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_ICCN: /* PAC => PNS */ 1114*0fbf3537Syasuoka case PPTP_CTRL_MES_CODE_CDN: /* PAC => PNS */ 1115*0fbf3537Syasuoka /* �ʾ� PNS �ѤʤΤǡ��������ʤ� */ 1116*0fbf3537Syasuoka default: 1117*0fbf3537Syasuoka break; 1118*0fbf3537Syasuoka } 1119*0fbf3537Syasuoka reason = "Message type is unexpected."; 1120*0fbf3537Syasuoka // FALL THROUGH 1121*0fbf3537Syasuoka badpacket: 1122*0fbf3537Syasuoka pptp_ctrl_log(_this, LOG_INFO, 1123*0fbf3537Syasuoka "Received a bad %s(%d) call_id=%d: %s", 1124*0fbf3537Syasuoka pptp_ctrl_mes_type_string(mes_type), mes_type, call_id, reason); 1125*0fbf3537Syasuoka return 0; 1126*0fbf3537Syasuoka reigai: 1127*0fbf3537Syasuoka pptp_ctrl_stop(_this, PPTP_StopCCRQ_REASON_STOP_PROTOCOL); 1128*0fbf3537Syasuoka return 0; 1129*0fbf3537Syasuoka } 1130*0fbf3537Syasuoka 1131*0fbf3537Syasuoka 1132*0fbf3537Syasuoka /************************************************************************ 1133*0fbf3537Syasuoka * ��¿�ʴؿ� 1134*0fbf3537Syasuoka ************************************************************************/ 1135*0fbf3537Syasuoka 1136*0fbf3537Syasuoka /** ���Υ����˴�Ť�����٥뤫��Ϥޤ����Ͽ���ޤ��� */ 1137*0fbf3537Syasuoka static void 1138*0fbf3537Syasuoka pptp_ctrl_log(pptp_ctrl *_this, int prio, const char *fmt, ...) 1139*0fbf3537Syasuoka { 1140*0fbf3537Syasuoka char logbuf[BUFSIZ]; 1141*0fbf3537Syasuoka va_list ap; 1142*0fbf3537Syasuoka 1143*0fbf3537Syasuoka va_start(ap, fmt); 1144*0fbf3537Syasuoka #ifdef PPTPD_MULITPLE 1145*0fbf3537Syasuoka snprintf(logbuf, sizeof(logbuf), "pptpd id=%u ctrl=%u %s", 1146*0fbf3537Syasuoka _this->pptpd->id, _this->id, fmt); 1147*0fbf3537Syasuoka #else 1148*0fbf3537Syasuoka snprintf(logbuf, sizeof(logbuf), "pptpd ctrl=%u %s", _this->id, fmt); 1149*0fbf3537Syasuoka #endif 1150*0fbf3537Syasuoka vlog_printf(prio, logbuf, ap); 1151*0fbf3537Syasuoka va_end(ap); 1152*0fbf3537Syasuoka } 1153*0fbf3537Syasuoka 1154*0fbf3537Syasuoka static const char * 1155*0fbf3537Syasuoka pptp_ctrl_state_string(int state) 1156*0fbf3537Syasuoka { 1157*0fbf3537Syasuoka switch (state) { 1158*0fbf3537Syasuoka case PPTP_CTRL_STATE_IDLE: 1159*0fbf3537Syasuoka return "idle"; 1160*0fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_CTRL_REPLY: 1161*0fbf3537Syasuoka return "wait-ctrl-reply"; 1162*0fbf3537Syasuoka case PPTP_CTRL_STATE_ESTABLISHED: 1163*0fbf3537Syasuoka return "established"; 1164*0fbf3537Syasuoka case PPTP_CTRL_STATE_WAIT_STOP_REPLY: 1165*0fbf3537Syasuoka return "wait-stop-reply"; 1166*0fbf3537Syasuoka } 1167*0fbf3537Syasuoka return "unknown"; 1168*0fbf3537Syasuoka } 1169