xref: /openbsd/usr.sbin/npppd/pptp/pptp_ctrl.c (revision 0fbf3537)
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