Bug Summary

File:src/usr.sbin/npppd/npppd/../pptp/pptp_ctrl.c
Warning:line 1046, column 2
Value stored to 'reason' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name pptp_ctrl.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/npppd/npppd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/npppd/npppd/../common -I /usr/src/usr.sbin/npppd/npppd -I /usr/src/usr.sbin/npppd/npppd/../pptp -I /usr/src/usr.sbin/npppd/npppd/../l2tp -I /usr/src/usr.sbin/npppd/npppd/../pppoe -D USE_NPPPD_PPTP -D USE_NPPPD_L2TP -D USE_NPPPD_PPPOE -D __COPYRIGHT(x)= -D __RCSID(x)= -D NPPPD_MAX_IFACE=8 -D NPPPD_MAX_POOL=8 -D USE_NPPPD_MPPE -D USE_NPPPD_PIPEX -D USE_NPPPD_RADIUS -D USE_SA_COOKIE -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/npppd/npppd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/npppd/npppd/../pptp/pptp_ctrl.c
1/* $OpenBSD: pptp_ctrl.c,v 1.13 2021/03/29 03:54:40 yasuoka Exp $ */
2
3/*-
4 * Copyright (c) 2009 Internet Initiative Japan Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28/**@file
29 * PPTP(RFC 2637) control connection implementation.
30 * currently it only support PAC part
31 */
32/* $Id: pptp_ctrl.c,v 1.13 2021/03/29 03:54:40 yasuoka Exp $ */
33#include <sys/types.h>
34#include <sys/socket.h>
35#include <netinet/in.h>
36#include <stdio.h>
37#include <stdarg.h>
38#include <stdlib.h>
39#include <netdb.h>
40#include <unistd.h>
41#include <syslog.h>
42#include <time.h>
43#include <fcntl.h>
44#include <errno(*__errno()).h>
45#include <string.h>
46#include <event.h>
47
48#include "bytebuf.h"
49#include "debugutil.h"
50#include "hash.h"
51#include "slist.h"
52#include "time_utils.h"
53
54#include "version.h"
55
56#include "pptp.h"
57#include "pptp_local.h"
58#include "pptp_subr.h"
59
60#define MINIMUM(a, b)(((a) < (b)) ? (a) : (b)) (((a) < (b)) ? (a) : (b))
61#define MAXIMUM(a, b)(((a) > (b)) ? (a) : (b)) (((a) > (b)) ? (a) : (b))
62
63/* periods of pptp_ctrl_timeout */
64#define PPTP_CTRL_TIMEOUT_IVAL_SEC2 2
65
66#ifdef PPTP_CTRL_DEBUG
67#define PPTP_CTRL_ASSERT(x) ASSERT(x)((void)0);
68#define PPTP_CTRL_DBG(x) pptp_ctrl_log x
69#else
70#define PPTP_CTRL_ASSERT(x)
71#define PPTP_CTRL_DBG(x)
72#endif
73
74static unsigned pptp_ctrl_seqno = 0;
75
76static void pptp_ctrl_log (pptp_ctrl *, int, const char *, ...) __printflike(3,4)__attribute__((__format__ (__printf__, 3, 4)));
77static void pptp_ctrl_timeout (int, short, void *);
78static void pptp_ctrl_reset_timeout (pptp_ctrl *);
79static void pptp_ctrl_io_event (int, short, void *);
80static void pptp_ctrl_set_io_event (pptp_ctrl *);
81static int pptp_ctrl_output_flush (pptp_ctrl *);
82static void pptp_ctrl_SCCRx_string (struct pptp_scc *, u_char *, int);
83static int pptp_ctrl_recv_SCCRQ (pptp_ctrl *, u_char *, int);
84static int pptp_ctrl_recv_StopCCRP (pptp_ctrl *, u_char *, int);
85static int pptp_ctrl_send_StopCCRQ (pptp_ctrl *, int);
86static int pptp_ctrl_recv_StopCCRQ (pptp_ctrl *, u_char *, int);
87static int pptp_ctrl_send_StopCCRP (pptp_ctrl *, int, int);
88static int pptp_ctrl_send_SCCRP (pptp_ctrl *, int, int);
89static void pptp_ctrl_send_CDN (pptp_ctrl *, int, int, int, const char *);
90static void pptp_ctrl_process_echo_req (pptp_ctrl *, u_char *, int);
91static int pptp_ctrl_recv_echo_rep (pptp_ctrl *, u_char *, int);
92static void pptp_ctrl_send_echo_req (pptp_ctrl *);
93static int pptp_ctrl_input (pptp_ctrl *, u_char *, int);
94static int pptp_ctrl_call_input (pptp_ctrl *, int, u_char *, int);
95static const char *pptp_ctrl_state_string (int);
96static void pptp_ctrl_fini(pptp_ctrl *);
97
98/*
99 * pptp_ctrl instance operation functions
100 */
101pptp_ctrl *
102pptp_ctrl_create(void)
103{
104 pptp_ctrl *_this;
105
106 if ((_this = malloc(sizeof(pptp_ctrl))) == NULL((void *)0))
107 return NULL((void *)0);
108
109 return _this;
110}
111
112int
113pptp_ctrl_init(pptp_ctrl *_this)
114{
115 time_t curr_time;
116
117 PPTP_CTRL_ASSERT(_this != NULL);
118 curr_time = get_monosec()((time_t)(get_nanotime() / 1000000000LL));
119 memset(_this, 0, sizeof(pptp_ctrl));
120 _this->id = pptp_ctrl_seqno++;
121 _this->sock = -1;
122
123 if ((_this->recv_buf = bytebuffer_create(PPTP_BUFSIZ1024)) == NULL((void *)0)) {
124 pptp_ctrl_log(_this, LOG_ERR3, "bytebuffer_create() failed at "
125 "%s(): %m", __func__);
126 goto fail;
127 }
128 if ((_this->send_buf = bytebuffer_create(PPTP_BUFSIZ1024)) == NULL((void *)0)) {
129 pptp_ctrl_log(_this, LOG_ERR3, "bytebuffer_create() failed at "
130 "%s(): %m", __func__);
131 goto fail;
132 }
133 _this->last_rcv_ctrl = curr_time;
134 _this->last_snd_ctrl = curr_time;
135 _this->echo_seq = arc4random();
136 _this->echo_interval = PPTP_CTRL_DEFAULT_ECHO_INTERVAL60;
137 _this->echo_timeout = PPTP_CTRL_DEFAULT_ECHO_TIMEOUT60;
138 slist_init(&_this->call_list);
139 evtimer_set(&_this->ev_timer, pptp_ctrl_timeout, _this)event_set(&_this->ev_timer, -1, 0, pptp_ctrl_timeout, _this
)
;
140
141 return 0;
142fail:
143 return 1;
144}
145
146int
147pptp_ctrl_start(pptp_ctrl *_this)
148{
149 int ival;
150 char hbuf0[NI_MAXHOST256], sbuf0[NI_MAXSERV32];
151 char hbuf1[NI_MAXHOST256], sbuf1[NI_MAXSERV32];
152 struct sockaddr_storage sock;
153 socklen_t socklen;
154
155 PPTP_CTRL_ASSERT(_this != NULL);
156 PPTP_CTRL_ASSERT(_this->sock >= 0);
157
158 /* convert address to strings for logging */
159 strlcpy(hbuf0, "<unknown>", sizeof(hbuf0));
160 strlcpy(sbuf0, "<unknown>", sizeof(sbuf0));
161 strlcpy(hbuf1, "<unknown>", sizeof(hbuf1));
162 strlcpy(sbuf1, "<unknown>", sizeof(sbuf1));
163 if (getnameinfo((struct sockaddr *)&_this->peer, _this->peer.ss_len,
164 hbuf0, sizeof(hbuf0), sbuf0, sizeof(sbuf0),
165 NI_NUMERICHOST1 | NI_NUMERICSERV2) != 0) {
166 pptp_ctrl_log(_this, LOG_ERR3,
167 "getnameinfo() failed at %s(): %m", __func__);
168 }
169 socklen = sizeof(sock);
170 if (getsockname(_this->sock, (struct sockaddr *)&sock, &socklen) != 0) {
171 pptp_ctrl_log(_this, LOG_ERR3,
172 "getsockname() failed at %s(): %m", __func__);
173 goto fail;
174 }
175 if (getnameinfo((struct sockaddr *)&sock, sock.ss_len, hbuf1,
176 sizeof(hbuf1), sbuf1, sizeof(sbuf1),
177 NI_NUMERICHOST1 | NI_NUMERICSERV2) != 0) {
178 pptp_ctrl_log(_this, LOG_ERR3,
179 "getnameinfo() failed at %s(): %m", __func__);
180 }
181 pptp_ctrl_log(_this, LOG_INFO6, "Starting peer=%s:%s/tcp "
182 "sock=%s:%s/tcp", hbuf0, sbuf0, hbuf1, sbuf1);
183
184 if ((ival = fcntl(_this->sock, F_GETFL3)) < 0) {
185 pptp_ctrl_log(_this, LOG_ERR3,
186 "fcntl(F_GET_FL) failed at %s(): %m", __func__);
187 goto fail;
188 } else if (fcntl(_this->sock, F_SETFL4, ival | O_NONBLOCK0x0004) < 0) {
189 pptp_ctrl_log(_this, LOG_ERR3,
190 "fcntl(F_SET_FL) failed at %s(): %m", __func__);
191 goto fail;
192 }
193 pptp_ctrl_set_io_event(_this);
194 pptp_ctrl_reset_timeout(_this);
195
196 return 0;
197fail:
198 return 1;
199}
200
201/* Timer */
202static void
203pptp_ctrl_timeout(int fd, short event, void *ctx)
204{
205 int i;
206 pptp_call *call;
207 pptp_ctrl *_this;
208 time_t last, curr_time;
209
210 _this = ctx;
211 curr_time = get_monosec()((time_t)(get_nanotime() / 1000000000LL));
212
213 PPTP_CTRL_DBG((_this, DEBUG_LEVEL_3, "enter %s()", __func__));
214 /* clean up call */
215 i = 0;
216 while (i < slist_length(&_this->call_list)) {
217 call = slist_get(&_this->call_list, i);
218 if (call->state == PPTP_CALL_STATE_CLEANUP_WAIT3 &&
219 curr_time - call->last_io > PPTP_CALL_CLEANUP_WAIT_TIME3) {
220 pptp_call_stop(call);
221 pptp_call_destroy(call);
222 slist_remove(&_this->call_list, i);
223 } else
224 i++;
225 }
226
227 /* State machine: Timeout */
228 switch (_this->state) {
229 default:
230 case PPTP_CTRL_STATE_WAIT_CTRL_REPLY1:
231 case PPTP_CTRL_STATE_IDLE0:
232 if (curr_time - _this->last_rcv_ctrl > PPTPD_IDLE_TIMEOUT60) {
233 pptp_ctrl_log(_this, LOG_ERR3,
234 "Timeout in state %s",
235 pptp_ctrl_state_string(_this->state));
236 pptp_ctrl_fini(_this);
237 return;
238 }
239 break;
240 case PPTP_CTRL_STATE_ESTABLISHED2:
241 last = MAXIMUM(_this->last_rcv_ctrl, _this->last_snd_ctrl)(((_this->last_rcv_ctrl) > (_this->last_snd_ctrl)) ?
(_this->last_rcv_ctrl) : (_this->last_snd_ctrl))
;
242
243 if (curr_time - _this->last_rcv_ctrl
244 >= _this->echo_interval + _this->echo_timeout) {
245 pptp_ctrl_log(_this, LOG_INFO6,
246 "Timeout waiting for echo reply");
247 pptp_ctrl_fini(_this);
248 return;
249 }
250 if (curr_time - last >= _this->echo_interval) {
251 PPTP_CTRL_DBG((_this, LOG_DEBUG, "Echo"));
252 _this->echo_seq++;
253 pptp_ctrl_send_echo_req(_this);
254 }
255 break;
256 case PPTP_CTRL_STATE_WAIT_STOP_REPLY3:
257 if (curr_time - _this->last_snd_ctrl >
258 PPTP_CTRL_StopCCRP_WAIT_TIME3) {
259 pptp_ctrl_log(_this, LOG_WARNING4,
260 "Timeout waiting for StopCCRP");
261 pptp_ctrl_fini(_this);
262 return;
263 }
264 break;
265 case PPTP_CTRL_STATE_DISPOSING4:
266 pptp_ctrl_fini(_this);
267 return;
268 }
269 pptp_ctrl_reset_timeout(_this);
270}
271
272static void
273pptp_ctrl_reset_timeout(pptp_ctrl *_this)
274{
275 struct timeval tv;
276
277 switch (_this->state) {
278 case PPTP_CTRL_STATE_DISPOSING4:
279 /* call back immediately */
280 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
281 break;
282 default:
283 tv.tv_sec = PPTP_CTRL_TIMEOUT_IVAL_SEC2;
284 tv.tv_usec = 0;
285 break;
286 }
287 evtimer_add(&_this->ev_timer, &tv)event_add(&_this->ev_timer, &tv);
288}
289
290/**
291 * Terminate PPTP control connection
292 * @result The value for Stop-Control-Connection-Request(StopCCRQ) result.
293 This function will not sent StopCCRQ when the value == 0 and
294 the specification does not require to sent it.
295 * @see ::#PPTP_StopCCRQ_REASON_STOP_PROTOCOL
296 * @see ::#PPTP_StopCCRQ_REASON_STOP_LOCAL_SHUTDOWN
297 */
298void
299pptp_ctrl_stop(pptp_ctrl *_this, int result)
300{
301 int i;
302 pptp_call *call;
303
304 switch (_this->state) {
305 case PPTP_CTRL_STATE_WAIT_STOP_REPLY3:
306 /* waiting response. */
307 /* this state will timeout by pptp_ctrl_timeout */
308 break;
309 case PPTP_CTRL_STATE_ESTABLISHED2:
310 if (result != 0) {
311 for (i = 0; i < slist_length(&_this->call_list); i++) {
312 call = slist_get(&_this->call_list, i);
313 pptp_call_disconnect(call,
314 PPTP_CDN_RESULT_ADMIN_SHUTDOWN3, 0, NULL((void *)0));
315 }
316 pptp_ctrl_send_StopCCRQ(_this, result);
317 _this->state = PPTP_CTRL_STATE_WAIT_STOP_REPLY3;
318 break;
319 }
320 /* FALLTHROUGH */
321 default:
322 pptp_ctrl_fini(_this);
323 }
324 return;
325}
326
327
328/* finish PPTP control */
329static void
330pptp_ctrl_fini(pptp_ctrl *_this)
331{
332 pptp_call *call;
333
334 PPTP_CTRL_ASSERT(_this != NULL);
335
336 if (_this->sock >= 0) {
337 event_del(&_this->ev_sock);
338 close(_this->sock);
339 _this->sock = -1;
340 }
341 for (slist_itr_first(&_this->call_list);
342 slist_itr_has_next(&_this->call_list);) {
343 call = slist_itr_next(&_this->call_list);
344 pptp_call_stop(call);
345 pptp_call_destroy(call);
346 slist_itr_remove(&_this->call_list);
347 }
348
349 if (_this->on_io_event != 0) {
350 /*
351 * as the complete terminate process needs complicated
352 * exception handling, do partially at here.
353 * rest of part will be handled by timer-event-handler.
354 */
355 PPTP_CTRL_DBG((_this, LOG_DEBUG, "Disposing"));
356 _this->state = PPTP_CTRL_STATE_DISPOSING4;
357 pptp_ctrl_reset_timeout(_this);
358 return;
359 }
360
361 evtimer_del(&_this->ev_timer)event_del(&_this->ev_timer);
362 slist_fini(&_this->call_list);
363
364 pptp_ctrl_log (_this, LOG_NOTICE5, "logtype=Finished");
365
366 /* disable _this */
367 pptpd_ctrl_finished_notify(_this->pptpd, _this);
368}
369
370/* free PPTP control context */
371void
372pptp_ctrl_destroy(pptp_ctrl *_this)
373{
374 if (_this->send_buf != NULL((void *)0)) {
375 bytebuffer_destroy(_this->send_buf);
376 _this->send_buf = NULL((void *)0);
377 }
378 if (_this->recv_buf != NULL((void *)0)) {
379 bytebuffer_destroy(_this->recv_buf);
380 _this->recv_buf = NULL((void *)0);
381 }
382 free(_this);
383}
384
385/*
386 * network I/O
387 */
388/* I/O event dispather */
389static void
390pptp_ctrl_io_event(int fd, short evmask, void *ctx)
391{
392 int sz, lpkt, hdrlen;
393 u_char *pkt;
394 pptp_ctrl *_this;
395
396 _this = ctx;
397 PPTP_CTRL_ASSERT(_this != NULL);
398
399 _this->on_io_event = 1;
400 if ((evmask & EV_WRITE0x04) != 0) {
401 if (pptp_ctrl_output_flush(_this) != 0 ||
402 _this->state == PPTP_CTRL_STATE_DISPOSING4)
403 goto fail;
404 _this->send_ready = 1;
405 }
406 if ((evmask & EV_READ0x02) != 0) {
407 sz = read(_this->sock, bytebuffer_pointer(_this->recv_buf),
408 bytebuffer_remaining(_this->recv_buf));
409 if (sz <= 0) {
410 if (sz == 0 || errno(*__errno()) == ECONNRESET54) {
411 pptp_ctrl_log(_this, LOG_INFO6,
412 "Connection closed by foreign host");
413 pptp_ctrl_fini(_this);
414 goto fail;
415 } else if (errno(*__errno()) != EAGAIN35 && errno(*__errno()) != EINTR4) {
416 pptp_ctrl_log(_this, LOG_INFO6,
417 "read() failed at %s(): %m", __func__);
418 pptp_ctrl_fini(_this);
419 goto fail;
420 }
421 }
422 bytebuffer_put(_this->recv_buf, BYTEBUFFER_PUT_DIRECT, sz);
423 bytebuffer_flip(_this->recv_buf);
424
425 for (;;) {
426 pkt = bytebuffer_pointer(_this->recv_buf);
427 lpkt = bytebuffer_remaining(_this->recv_buf);
428 if (pkt == NULL((void *)0) ||
429 lpkt < sizeof(struct pptp_ctrl_header))
430 break; /* read again */
431
432 hdrlen = pkt[0] << 8 | pkt[1];
433 if (lpkt < hdrlen)
434 break; /* read again */
435
436 bytebuffer_get(_this->recv_buf, NULL((void *)0), hdrlen);
437 if (pptp_ctrl_input(_this, pkt, hdrlen) != 0 ||
438 _this->state == PPTP_CTRL_STATE_DISPOSING4) {
439 bytebuffer_compact(_this->recv_buf);
440 goto fail;
441 }
442 }
443 bytebuffer_compact(_this->recv_buf);
444 }
445 if (pptp_ctrl_output_flush(_this) != 0)
446 goto fail;
447 pptp_ctrl_set_io_event(_this);
448fail:
449 _this->on_io_event = 0;
450}
451
452
453/* set i/o event mask */
454static void
455pptp_ctrl_set_io_event(pptp_ctrl *_this)
456{
457 int evmask;
458
459 PPTP_CTRL_ASSERT(_this != NULL);
460 PPTP_CTRL_ASSERT(_this->sock >= 0);
461
462 evmask = 0;
463 if (bytebuffer_remaining(_this->recv_buf) > 128)
464 evmask |= EV_READ0x02;
465 if (_this->send_ready == 0)
466 evmask |= EV_WRITE0x04;
467
468 event_del(&_this->ev_sock);
469 if (evmask != 0) {
470 event_set(&_this->ev_sock, _this->sock, evmask,
471 pptp_ctrl_io_event, _this);
472 event_add(&_this->ev_sock, NULL((void *)0));
473 }
474}
475
476/**
477 * Output PPTP control packet
478 * @param pkt pointer to packet buffer.
479 * when it was appended by _this-.send_buf using bytebuffer,
480 * specify NULL.
481 * @param lpkt packet length
482 */
483void
484pptp_ctrl_output(pptp_ctrl *_this, u_char *pkt, int lpkt)
485{
486 PPTP_CTRL_ASSERT(_this != NULL);
487 PPTP_CTRL_ASSERT(lpkt > 0);
488
489 /* just put the packet into the buffer now. send it later */
490 bytebuffer_put(_this->send_buf, pkt, lpkt);
491
492 if (_this->on_io_event != 0) {
493 /*
494 * pptp_ctrl_output_flush() will be called by the end of
495 * the I/O event handler.
496 */
497 } else {
498 /*
499 * When this function is called by other than I/O event handler,
500 * we need to call pptp_ctrl_output_flush(). However if we do
501 * it here, then we need to consider the situation
502 * 'flush => write failure => finalize'. The situation requires
503 * the caller function to handle the exception and causes
504 * complication. So we call pptp_ctrl_output_flush() by the
505 * the next send ready event.
506 */
507 _this->send_ready = 0; /* clear 'send ready' */
508 pptp_ctrl_set_io_event(_this); /* wait 'send ready */
509 }
510
511 return;
512}
513
514/* Send Stop-Control-Connection-Request */
515
516/* flush output packet */
517static int
518pptp_ctrl_output_flush(pptp_ctrl *_this)
519{
520 int sz;
521 time_t curr_time;
522
523 curr_time = get_monosec()((time_t)(get_nanotime() / 1000000000LL));
524
525 if (bytebuffer_position(_this->send_buf) <= 0)
526 return 0; /* nothing to write */
527 if (_this->send_ready == 0) {
528 pptp_ctrl_set_io_event(_this);
529 return 0; /* not ready to write */
530 }
531
532 bytebuffer_flip(_this->send_buf);
533
534 if (PPTP_CTRL_CONF(_this)((pptpd_listener *)slist_get(&(_this)->pptpd->listener
, (_this)->listener_index))->conf
->ctrl_out_pktdump != 0) {
535 pptp_ctrl_log(_this, LOG_DEBUG7, "PPTP Control output packet");
536 show_hd(debug_get_debugfp(),
537 bytebuffer_pointer(_this->send_buf),
538 bytebuffer_remaining(_this->send_buf));
539 }
540 if ((sz = write(_this->sock, bytebuffer_pointer(_this->send_buf),
541 bytebuffer_remaining(_this->send_buf))) < 0) {
542 pptp_ctrl_log(_this, LOG_ERR3, "write to socket failed: %m");
543 pptp_ctrl_fini(_this);
544
545 return 1;
546 }
547 _this->last_snd_ctrl = curr_time;
548 bytebuffer_get(_this->send_buf, NULL((void *)0), sz);
549 bytebuffer_compact(_this->send_buf);
550 _this->send_ready = 0;
551
552 return 0;
553}
554
555/* convert Start-Control-Connection-{Request,Reply} packet to strings */
556static void
557pptp_ctrl_SCCRx_string(struct pptp_scc *scc, u_char *buf, int lbuf)
558{
559 char results[128];
560
561 if (scc->result_code != 0)
562 snprintf(results, sizeof(results), "result=%d error=%d ",
563 scc->result_code, scc->error_code);
564 else
565 results[0] = '\0';
566
567 snprintf(buf, lbuf,
568 "protocol_version=%d.%d %sframing=%s bearer=%s max_channels=%d "
569 "firmware_revision=%d(0x%04x) host_name=\"%.*s\" "
570 "vendor_string=\"%.*s\"",
571 scc->protocol_version >> 8, scc->protocol_version & 0xff, results,
572 pptp_framing_string(scc->framing_caps),
573 pptp_bearer_string(scc->bearer_caps), scc->max_channels,
574 scc->firmware_revision, scc->firmware_revision,
575 (u_int)sizeof(scc->host_name), scc->host_name,
576 (u_int)sizeof(scc->vendor_string), scc->vendor_string);
577}
578
579/* receive Start-Control-Connection-Request */
580static int
581pptp_ctrl_recv_SCCRQ(pptp_ctrl *_this, u_char *pkt, int lpkt)
582{
583 char logbuf[512];
584 struct pptp_scc *scc;
585
586 /* sanity check */
587 if (lpkt < sizeof(struct pptp_scc)) {
588 pptp_ctrl_log(_this, LOG_ERR3, "Received bad SCCRQ: packet too "
589 "short: %d < %d", lpkt, (int)sizeof(struct pptp_scc));
590 return 1;
591 }
592 scc = (struct pptp_scc *)pkt;
593
594 scc->protocol_version = ntohs(scc->protocol_version)(__uint16_t)(__builtin_constant_p(scc->protocol_version) ?
(__uint16_t)(((__uint16_t)(scc->protocol_version) & 0xffU
) << 8 | ((__uint16_t)(scc->protocol_version) & 0xff00U
) >> 8) : __swap16md(scc->protocol_version))
;
595 scc->framing_caps = htonl(scc->framing_caps)(__uint32_t)(__builtin_constant_p(scc->framing_caps) ? (__uint32_t
)(((__uint32_t)(scc->framing_caps) & 0xff) << 24
| ((__uint32_t)(scc->framing_caps) & 0xff00) <<
8 | ((__uint32_t)(scc->framing_caps) & 0xff0000) >>
8 | ((__uint32_t)(scc->framing_caps) & 0xff000000) >>
24) : __swap32md(scc->framing_caps))
;
596 scc->bearer_caps = htonl(scc->bearer_caps)(__uint32_t)(__builtin_constant_p(scc->bearer_caps) ? (__uint32_t
)(((__uint32_t)(scc->bearer_caps) & 0xff) << 24 |
((__uint32_t)(scc->bearer_caps) & 0xff00) << 8 |
((__uint32_t)(scc->bearer_caps) & 0xff0000) >> 8
| ((__uint32_t)(scc->bearer_caps) & 0xff000000) >>
24) : __swap32md(scc->bearer_caps))
;
597 scc->max_channels = htons(scc->max_channels)(__uint16_t)(__builtin_constant_p(scc->max_channels) ? (__uint16_t
)(((__uint16_t)(scc->max_channels) & 0xffU) << 8
| ((__uint16_t)(scc->max_channels) & 0xff00U) >>
8) : __swap16md(scc->max_channels))
;
598 scc->firmware_revision = htons(scc->firmware_revision)(__uint16_t)(__builtin_constant_p(scc->firmware_revision) ?
(__uint16_t)(((__uint16_t)(scc->firmware_revision) & 0xffU
) << 8 | ((__uint16_t)(scc->firmware_revision) &
0xff00U) >> 8) : __swap16md(scc->firmware_revision)
)
;
599
600 /* check protocol version */
601 if (scc->protocol_version != PPTP_RFC_2637_VERSION0x0100) {
602 pptp_ctrl_log(_this, LOG_ERR3, "Received bad SCCRQ: "
603 "unknown protocol version %d", scc->protocol_version);
604 return 1;
605 }
606
607 pptp_ctrl_SCCRx_string(scc, logbuf, sizeof(logbuf));
608 pptp_ctrl_log(_this, LOG_INFO6, "RecvSCCRQ %s", logbuf);
609
610 return 0;
611}
612
613/* Receive Stop-Control-Connection-Reply */
614static int
615pptp_ctrl_recv_StopCCRP(pptp_ctrl *_this, u_char *pkt, int lpkt)
616{
617 struct pptp_stop_ccrp *stop_ccrp;
618
619 if (lpkt < sizeof(struct pptp_stop_ccrp)) {
620 pptp_ctrl_log(_this, LOG_ERR3, "Received bad StopCCRP: packet "
621 "too short: %d < %d", lpkt,
622 (int)sizeof(struct pptp_stop_ccrp));
623 return 1;
624 }
625 stop_ccrp = (struct pptp_stop_ccrp *)pkt;
626
627 pptp_ctrl_log(_this, LOG_INFO6, "RecvStopCCRP reason=%s(%u)",
628 pptp_StopCCRP_result_string(stop_ccrp->result), stop_ccrp->result);
629
630 return 0;
631}
632
633static int
634pptp_ctrl_send_StopCCRQ(pptp_ctrl *_this, int reason)
635{
636 int lpkt;
637 struct pptp_stop_ccrq *stop_ccrq;
638
639 stop_ccrq = bytebuffer_pointer(_this->send_buf);
640 lpkt = bytebuffer_remaining(_this->send_buf);
641 if (lpkt < sizeof(struct pptp_stop_ccrq)) {
642 pptp_ctrl_log(_this, LOG_ERR3,
643 "SendCCRP failed: No buffer space available");
644 return -1;
645 }
646 memset(stop_ccrq, 0, sizeof(struct pptp_stop_ccrq));
647
648 pptp_init_header(&stop_ccrq->header, sizeof(struct pptp_stop_ccrq),
649 PPTP_CTRL_MES_CODE_StopCCRQ3);
650
651 stop_ccrq->reason = reason;
652
653 pptp_ctrl_log(_this, LOG_INFO6, "SendStopCCRQ reason=%s(%u)",
654 pptp_StopCCRQ_reason_string(stop_ccrq->reason), stop_ccrq->reason);
655
656 pptp_ctrl_output(_this, NULL((void *)0), sizeof(struct pptp_stop_ccrq));
657
658 return 0;
659}
660
661/* Receive Stop-Control-Connection-Request */
662static int
663pptp_ctrl_recv_StopCCRQ(pptp_ctrl *_this, u_char *pkt, int lpkt)
664{
665 struct pptp_stop_ccrq *stop_ccrq;
666
667 if (lpkt < sizeof(struct pptp_stop_ccrq)) {
668 pptp_ctrl_log(_this, LOG_ERR3, "Received bad StopCCRQ: packet "
669 "too short: %d < %d", lpkt,
670 (int)sizeof(struct pptp_stop_ccrq));
671 return 1;
672 }
673 stop_ccrq = (struct pptp_stop_ccrq *)pkt;
674
675 pptp_ctrl_log(_this, LOG_INFO6, "RecvStopCCRQ reason=%s(%u)",
676 pptp_StopCCRQ_reason_string(stop_ccrq->reason), stop_ccrq->reason);
677
678 return 0;
679}
680
681/* Send Stop-Control-Connection-Reply */
682static int
683pptp_ctrl_send_StopCCRP(pptp_ctrl *_this, int result, int error)
684{
685 int lpkt;
686 struct pptp_stop_ccrp *stop_ccrp;
687
688 stop_ccrp = bytebuffer_pointer(_this->send_buf);
689
690 lpkt = bytebuffer_remaining(_this->send_buf);
691 if (lpkt < sizeof(struct pptp_stop_ccrp)) {
692 pptp_ctrl_log(_this, LOG_ERR3,
693 "SendCCRQ failed: No buffer space available");
694 return -1;
695 }
696 memset(stop_ccrp, 0, sizeof(struct pptp_stop_ccrp));
697
698 pptp_init_header(&stop_ccrp->header, sizeof(struct pptp_stop_ccrp),
699 PPTP_CTRL_MES_CODE_StopCCRP4);
700
701 stop_ccrp->result = result;
702 stop_ccrp->error = error;
703
704 pptp_ctrl_log(_this, LOG_INFO6,
705 "SendStopCCRP result=%s(%u) error=%s(%u)",
706 pptp_StopCCRP_result_string(stop_ccrp->result), stop_ccrp->result,
707 pptp_general_error_string(stop_ccrp->error), stop_ccrp->error);
708
709 pptp_ctrl_output(_this, NULL((void *)0), sizeof(struct pptp_stop_ccrp));
710
711 return 0;
712}
713
714/* Send Start-Control-Connection-Reply */
715static int
716pptp_ctrl_send_SCCRP(pptp_ctrl *_this, int result, int error)
717{
718 int lpkt;
719 struct pptp_scc *scc;
720 char logbuf[512];
721 const char *val;
722
723 scc = bytebuffer_pointer(_this->send_buf);
724 lpkt = bytebuffer_remaining(_this->send_buf);
725 if (lpkt < sizeof(struct pptp_scc)) {
726 pptp_ctrl_log(_this, LOG_ERR3,
727 "SendSCCRP failed: No buffer space available");
728 return -1;
729 }
730 memset(scc, 0, sizeof(struct pptp_scc));
731
732 pptp_init_header(&scc->header, sizeof(struct pptp_scc),
733 PPTP_CTRL_MES_CODE_SCCRP2);
734
735 scc->protocol_version = PPTP_RFC_2637_VERSION0x0100;
736 scc->result_code = result;
737 scc->error_code = error;
738
739 /* XXX only support sync frames */
740 scc->framing_caps = PPTP_CTRL_FRAMING_SYNC2;
741 scc->bearer_caps = PPTP_CTRL_BEARER_DIGITAL2;
742
743 scc->max_channels = 4; /* XXX */
744 scc->firmware_revision = MAJOR_VERSION5 << 8 | MINOR_VERSION2;
745
746 /* this implementation only support these strings up to
747 * 63 character */
748 /* host name */
749
750 if ((val = PPTP_CTRL_CONF(_this)((pptpd_listener *)slist_get(&(_this)->pptpd->listener
, (_this)->listener_index))->conf
->hostname) == NULL((void *)0))
751 val = "";
752 strlcpy(scc->host_name, val, sizeof(scc->host_name));
753
754 /* vendor name */
755 if (PPTP_CTRL_CONF(_this)((pptpd_listener *)slist_get(&(_this)->pptpd->listener
, (_this)->listener_index))->conf
->vendor_name == NULL((void *)0))
756 val = PPTPD_DEFAULT_VENDOR_NAME"";
757 strlcpy(scc->vendor_string, val, sizeof(scc->vendor_string));
758
759 pptp_ctrl_SCCRx_string(scc, logbuf, sizeof(logbuf));
760 pptp_ctrl_log(_this, LOG_INFO6, "SendSCCRP %s", logbuf);
761
762 scc->protocol_version = htons(scc->protocol_version)(__uint16_t)(__builtin_constant_p(scc->protocol_version) ?
(__uint16_t)(((__uint16_t)(scc->protocol_version) & 0xffU
) << 8 | ((__uint16_t)(scc->protocol_version) & 0xff00U
) >> 8) : __swap16md(scc->protocol_version))
;
763 scc->framing_caps = htonl(scc->framing_caps)(__uint32_t)(__builtin_constant_p(scc->framing_caps) ? (__uint32_t
)(((__uint32_t)(scc->framing_caps) & 0xff) << 24
| ((__uint32_t)(scc->framing_caps) & 0xff00) <<
8 | ((__uint32_t)(scc->framing_caps) & 0xff0000) >>
8 | ((__uint32_t)(scc->framing_caps) & 0xff000000) >>
24) : __swap32md(scc->framing_caps))
;
764 scc->bearer_caps = htonl(scc->bearer_caps)(__uint32_t)(__builtin_constant_p(scc->bearer_caps) ? (__uint32_t
)(((__uint32_t)(scc->bearer_caps) & 0xff) << 24 |
((__uint32_t)(scc->bearer_caps) & 0xff00) << 8 |
((__uint32_t)(scc->bearer_caps) & 0xff0000) >> 8
| ((__uint32_t)(scc->bearer_caps) & 0xff000000) >>
24) : __swap32md(scc->bearer_caps))
;
765 scc->max_channels = htons(scc->max_channels)(__uint16_t)(__builtin_constant_p(scc->max_channels) ? (__uint16_t
)(((__uint16_t)(scc->max_channels) & 0xffU) << 8
| ((__uint16_t)(scc->max_channels) & 0xff00U) >>
8) : __swap16md(scc->max_channels))
;
766 scc->firmware_revision = htons(scc->firmware_revision)(__uint16_t)(__builtin_constant_p(scc->firmware_revision) ?
(__uint16_t)(((__uint16_t)(scc->firmware_revision) & 0xffU
) << 8 | ((__uint16_t)(scc->firmware_revision) &
0xff00U) >> 8) : __swap16md(scc->firmware_revision)
)
;
767
768 pptp_ctrl_output(_this, NULL((void *)0), sizeof(struct pptp_scc));
769
770 return 0;
771}
772
773/* receive ECHO and reply */
774static void
775pptp_ctrl_process_echo_req(pptp_ctrl *_this, u_char *pkt, int lpkt)
776{
777 struct pptp_echo_rq *echo_rq;
778 struct pptp_echo_rp *echo_rp;
779
780 if (lpkt < sizeof(struct pptp_echo_rq)) {
781 pptp_ctrl_log(_this, LOG_ERR3, "Received bad EchoReq: packet "
782 "too short: %d < %d", lpkt,
783 (int)sizeof(struct pptp_echo_rq));
784 return;
785 }
786 echo_rq = (struct pptp_echo_rq *)pkt;
787
788 PPTP_CTRL_DBG((_this, LOG_DEBUG, "RecvEchoReq"));
789
790 echo_rp = bytebuffer_pointer(_this->send_buf);
791 lpkt = bytebuffer_remaining(_this->send_buf);
792 if (echo_rp == NULL((void *)0) || lpkt < sizeof(struct pptp_echo_rp)) {
793 pptp_ctrl_log(_this, LOG_ERR3,
794 "Failed to send EchoReq: No buffer space available");
795 return;
796 }
797 memset(echo_rp, 0, sizeof(struct pptp_echo_rp));
798
799 pptp_init_header(&echo_rp->header, sizeof(struct pptp_echo_rp),
800 PPTP_CTRL_MES_CODE_ECHO_RP6);
801
802 echo_rp->identifier = echo_rq->identifier;
803 echo_rp->result_code = PPTP_ECHO_RP_RESULT_OK1;
804 echo_rp->error_code = PPTP_ERROR_NONE0;
805 echo_rp->reserved1 = htons(0)(__uint16_t)(__builtin_constant_p(0) ? (__uint16_t)(((__uint16_t
)(0) & 0xffU) << 8 | ((__uint16_t)(0) & 0xff00U
) >> 8) : __swap16md(0))
;
806
807 pptp_ctrl_output(_this, NULL((void *)0), sizeof(struct pptp_echo_rp));
808 PPTP_CTRL_DBG((_this, LOG_DEBUG, "SendEchoReply"));
809}
810
811/* receiver Echo-Reply */
812static int
813pptp_ctrl_recv_echo_rep(pptp_ctrl *_this, u_char *pkt, int lpkt)
814{
815 struct pptp_echo_rp *echo_rp;
816
817 if (lpkt < sizeof(struct pptp_echo_rp)) {
818 pptp_ctrl_log(_this, LOG_ERR3, "Received bad EchoReq: packet "
819 "too short: %d < %d", lpkt,
820 (int)sizeof(struct pptp_echo_rp));
821 return 1;
822 }
823 echo_rp = (struct pptp_echo_rp *)pkt;
824
825 if (echo_rp->result_code != PPTP_ECHO_RP_RESULT_OK1) {
826 pptp_ctrl_log(_this, LOG_ERR3, "Received negative EchoReply: %s",
827 pptp_general_error_string(echo_rp->error_code));
828 return 1;
829 }
830 if (_this->echo_seq != ntohl(echo_rp->identifier)(__uint32_t)(__builtin_constant_p(echo_rp->identifier) ? (
__uint32_t)(((__uint32_t)(echo_rp->identifier) & 0xff)
<< 24 | ((__uint32_t)(echo_rp->identifier) & 0xff00
) << 8 | ((__uint32_t)(echo_rp->identifier) & 0xff0000
) >> 8 | ((__uint32_t)(echo_rp->identifier) & 0xff000000
) >> 24) : __swap32md(echo_rp->identifier))
) {
831 pptp_ctrl_log(_this, LOG_ERR3, "Received bad EchoReply: "
832 "Identifier mismatch sent=%u recv=%u",
833 _this->echo_seq , ntohl(echo_rp->identifier)(__uint32_t)(__builtin_constant_p(echo_rp->identifier) ? (
__uint32_t)(((__uint32_t)(echo_rp->identifier) & 0xff)
<< 24 | ((__uint32_t)(echo_rp->identifier) & 0xff00
) << 8 | ((__uint32_t)(echo_rp->identifier) & 0xff0000
) >> 8 | ((__uint32_t)(echo_rp->identifier) & 0xff000000
) >> 24) : __swap32md(echo_rp->identifier))
);
834 return 1;
835 }
836 PPTP_CTRL_DBG((_this, LOG_DEBUG, "RecvEchoReply"));
837 return 0;
838}
839
840/* send Echo-Request */
841static void
842pptp_ctrl_send_echo_req(pptp_ctrl *_this)
843{
844 int lpkt;
845 struct pptp_echo_rq *echo_rq;
846
847 echo_rq = (struct pptp_echo_rq *)bytebuffer_pointer(_this->send_buf);
848 lpkt = bytebuffer_remaining(_this->send_buf);
849 if (echo_rq == NULL((void *)0) || lpkt < sizeof(struct pptp_echo_rq)) {
850 pptp_ctrl_log(_this, LOG_ERR3,
851 "SendEchoReq failed: No buffer space available");
852 return;
853 }
854 memset(echo_rq, 0, sizeof(struct pptp_echo_rq));
855
856 pptp_init_header(&echo_rq->header, sizeof(struct pptp_echo_rq),
857 PPTP_CTRL_MES_CODE_ECHO_RQ5);
858
859 echo_rq->identifier = htonl(_this->echo_seq)(__uint32_t)(__builtin_constant_p(_this->echo_seq) ? (__uint32_t
)(((__uint32_t)(_this->echo_seq) & 0xff) << 24 |
((__uint32_t)(_this->echo_seq) & 0xff00) << 8 |
((__uint32_t)(_this->echo_seq) & 0xff0000) >> 8
| ((__uint32_t)(_this->echo_seq) & 0xff000000) >>
24) : __swap32md(_this->echo_seq))
;
860
861 pptp_ctrl_output(_this, NULL((void *)0), sizeof(struct pptp_echo_rq));
862 PPTP_CTRL_DBG((_this, LOG_DEBUG, "SendEchoReq"));
863}
864
865/* send Call-Disconnect-Notify */
866static void
867pptp_ctrl_send_CDN(pptp_ctrl *_this, int result, int error, int cause,
868 const char *statistics)
869{
870 int lpkt;
871 struct pptp_cdn *cdn;
872
873 cdn = bytebuffer_pointer(_this->send_buf);
874 lpkt = bytebuffer_remaining(_this->send_buf);
875 if (lpkt < sizeof(struct pptp_cdn)) {
876 pptp_ctrl_log(_this, LOG_ERR3,
877 "SendCCR failed: No buffer space available");
878 return;
879 }
880 memset(cdn, 0, sizeof(struct pptp_cdn));
881
882 pptp_init_header(&cdn->header, sizeof(struct pptp_cdn),
883 PPTP_CTRL_MES_CODE_CDN13);
884
885 cdn->call_id = _this->id;
886 cdn->result_code = result;
887 cdn->error_code = error;
888 cdn->cause_code = cause;
889 if (statistics != NULL((void *)0))
890 strlcpy(cdn->statistics, statistics, sizeof(cdn->statistics));
891
892 cdn->call_id = htons(cdn->call_id)(__uint16_t)(__builtin_constant_p(cdn->call_id) ? (__uint16_t
)(((__uint16_t)(cdn->call_id) & 0xffU) << 8 | ((
__uint16_t)(cdn->call_id) & 0xff00U) >> 8) : __swap16md
(cdn->call_id))
;
893 cdn->cause_code = htons(cdn->cause_code)(__uint16_t)(__builtin_constant_p(cdn->cause_code) ? (__uint16_t
)(((__uint16_t)(cdn->cause_code) & 0xffU) << 8 |
((__uint16_t)(cdn->cause_code) & 0xff00U) >> 8)
: __swap16md(cdn->cause_code))
;
894
895 pptp_ctrl_output(_this, NULL((void *)0), sizeof(struct pptp_cdn));
896}
897
898/* receive Control-packet */
899static int
900pptp_ctrl_input(pptp_ctrl *_this, u_char *pkt, int lpkt)
901{
902 char errmes[256];
903 time_t curr_time;
904 struct pptp_ctrl_header *hdr;
905
906 PPTP_CTRL_ASSERT(lpkt >= sizeof(struct pptp_ctrl_header));
907
908 curr_time = get_monosec()((time_t)(get_nanotime() / 1000000000LL));
909 hdr = (struct pptp_ctrl_header *)pkt;
910
911 hdr->length = ntohs(hdr->length)(__uint16_t)(__builtin_constant_p(hdr->length) ? (__uint16_t
)(((__uint16_t)(hdr->length) & 0xffU) << 8 | ((__uint16_t
)(hdr->length) & 0xff00U) >> 8) : __swap16md(hdr
->length))
;
912 hdr->pptp_message_type = ntohs(hdr->pptp_message_type)(__uint16_t)(__builtin_constant_p(hdr->pptp_message_type) ?
(__uint16_t)(((__uint16_t)(hdr->pptp_message_type) & 0xffU
) << 8 | ((__uint16_t)(hdr->pptp_message_type) &
0xff00U) >> 8) : __swap16md(hdr->pptp_message_type)
)
;
913 hdr->magic_cookie = ntohl(hdr->magic_cookie)(__uint32_t)(__builtin_constant_p(hdr->magic_cookie) ? (__uint32_t
)(((__uint32_t)(hdr->magic_cookie) & 0xff) << 24
| ((__uint32_t)(hdr->magic_cookie) & 0xff00) <<
8 | ((__uint32_t)(hdr->magic_cookie) & 0xff0000) >>
8 | ((__uint32_t)(hdr->magic_cookie) & 0xff000000) >>
24) : __swap32md(hdr->magic_cookie))
;
914 hdr->control_message_type = ntohs(hdr->control_message_type)(__uint16_t)(__builtin_constant_p(hdr->control_message_type
) ? (__uint16_t)(((__uint16_t)(hdr->control_message_type) &
0xffU) << 8 | ((__uint16_t)(hdr->control_message_type
) & 0xff00U) >> 8) : __swap16md(hdr->control_message_type
))
;
915 hdr->reserved0 = ntohs(hdr->reserved0)(__uint16_t)(__builtin_constant_p(hdr->reserved0) ? (__uint16_t
)(((__uint16_t)(hdr->reserved0) & 0xffU) << 8 | (
(__uint16_t)(hdr->reserved0) & 0xff00U) >> 8) : __swap16md
(hdr->reserved0))
;
916
917 /* sanity check */
918 PPTP_CTRL_ASSERT(hdr->length <= lpkt);
919
920 _this->last_rcv_ctrl = curr_time;
921
922 if (PPTP_CTRL_CONF(_this)((pptpd_listener *)slist_get(&(_this)->pptpd->listener
, (_this)->listener_index))->conf
->ctrl_in_pktdump != 0) {
923 pptp_ctrl_log(_this, LOG_DEBUG7,
924 "PPTP Control input packet dump: mestype=%s(%d)",
925 pptp_ctrl_mes_type_string(hdr->control_message_type),
926 hdr->control_message_type);
927 show_hd(debug_get_debugfp(), pkt, lpkt);
928 }
929
930 /* inspect packet body */
931 /* message type */
932 if (hdr->pptp_message_type != PPTP_MES_TYPE_CTRL1) {
933 snprintf(errmes, sizeof(errmes), "unknown message type %d",
934 hdr->pptp_message_type);
935 goto bad_packet;
936 }
937 /* magic cookie */
938 if (hdr->magic_cookie != PPTP_MAGIC_COOKIE0x1a2b3c4d) {
939 snprintf(errmes, sizeof(errmes), "wrong magic %08x != %08x",
940 hdr->magic_cookie, PPTP_MAGIC_COOKIE0x1a2b3c4d);
941 goto bad_packet;
942 }
943
944 /* As there is possibility of state conflicts,
945 * ECHO Reply requiries special care.
946 */
947 switch (hdr->control_message_type) {
948 case PPTP_CTRL_MES_CODE_ECHO_RP6:
949 if (pptp_ctrl_recv_echo_rep(_this, pkt, lpkt) != 0) {
950 pptp_ctrl_fini(_this);
951 return 1;
952 }
953 return 0;
954 }
955
956 /*
957 * State machine
958 */
959 switch (_this->state) {
960 case PPTP_CTRL_STATE_IDLE0:
961 switch (hdr->control_message_type) {
962 case PPTP_CTRL_MES_CODE_SCCRQ1:
963 if (pptp_ctrl_recv_SCCRQ(_this, pkt, lpkt) != 0) {
964 return 0;
965 }
966 if (pptp_ctrl_send_SCCRP(_this,
967 PPTP_SCCRP_RESULT_SUCCESS1, PPTP_ERROR_NONE0) != 0) {
968 return 0;
969 }
970 _this->state = PPTP_CTRL_STATE_ESTABLISHED2;
971 return 0;
972 default:
973 break;
974 }
975 break;
976 case PPTP_CTRL_STATE_ESTABLISHED2:
977 switch (hdr->control_message_type) {
978 case PPTP_CTRL_MES_CODE_ECHO_RQ5:
979 pptp_ctrl_process_echo_req(_this, pkt, lpkt);
980 return 0;
981 /* dispatch to pptp_call_input() if it is call-related-packet */
982 case PPTP_CTRL_MES_CODE_SLI15:
983 case PPTP_CTRL_MES_CODE_ICRQ9:
984 case PPTP_CTRL_MES_CODE_ICRP10:
985 case PPTP_CTRL_MES_CODE_OCRQ7:
986 case PPTP_CTRL_MES_CODE_OCRP8:
987 case PPTP_CTRL_MES_CODE_ICCN11:
988 case PPTP_CTRL_MES_CODE_CDN13:
989 case PPTP_CTRL_MES_CODE_CCR12:
990 return pptp_ctrl_call_input(_this,
991 hdr->control_message_type, pkt, lpkt);
992 case PPTP_CTRL_MES_CODE_StopCCRQ3:
993 if (pptp_ctrl_recv_StopCCRQ(_this, pkt, lpkt) != 0) {
994 pptp_ctrl_stop(_this,
995 PPTP_StopCCRQ_REASON_STOP_PROTOCOL2);
996 return 0;
997 }
998 if (pptp_ctrl_send_StopCCRP(_this,
999 PPTP_StopCCRP_RESULT_OK1, PPTP_ERROR_NONE0)!= 0) {
1000 return 0;
1001 }
1002 pptp_ctrl_fini(_this);
1003 return 1;
1004 default:
1005 break;
1006 }
1007 case PPTP_CTRL_STATE_WAIT_STOP_REPLY3:
1008 switch (hdr->control_message_type) {
1009 case PPTP_CTRL_MES_CODE_StopCCRP4:
1010 pptp_ctrl_recv_StopCCRP(_this, pkt, lpkt);
1011 pptp_ctrl_fini(_this);
1012 return 1;
1013 }
1014 break;
1015 case PPTP_CTRL_STATE_WAIT_CTRL_REPLY1:
1016 /* XXX this implementation only support PAC mode */
1017 break;
1018 }
1019 pptp_ctrl_log(_this, LOG_WARNING4,
1020 "Unhandled control message type=%s(%d)",
1021 pptp_ctrl_mes_type_string(hdr->control_message_type),
1022 hdr->control_message_type);
1023 return 0;
1024
1025bad_packet:
1026 pptp_ctrl_log(_this, LOG_ERR3, "Received bad packet: %s", errmes);
1027 pptp_ctrl_stop(_this, PPTP_StopCCRQ_REASON_STOP_PROTOCOL2);
1028
1029 return 0;
1030}
1031
1032/* receiver PPTP Call related messages */
1033static int
1034pptp_ctrl_call_input(pptp_ctrl *_this, int mes_type, u_char *pkt, int lpkt)
1035{
1036 int i, call_id, lpkt0;
1037 pptp_call *call;
1038 const char *reason;
1039 u_char *pkt0;
1040
1041 pkt0 = pkt;
1042 lpkt0 = lpkt;
1043 call_id = -1;
1044 pkt += sizeof(struct pptp_ctrl_header);
1045 lpkt -= sizeof(struct pptp_ctrl_header);
1046 reason = "(no reason)";
Value stored to 'reason' is never read
1047
1048 /* sanity check */
1049 if (lpkt < 4) {
1050 reason = "received packet is too short";
1051 goto badpacket;
1052 }
1053 call = NULL((void *)0);
1054 call_id = ntohs(*(uint16_t *)pkt)(__uint16_t)(__builtin_constant_p(*(uint16_t *)pkt) ? (__uint16_t
)(((__uint16_t)(*(uint16_t *)pkt) & 0xffU) << 8 | (
(__uint16_t)(*(uint16_t *)pkt) & 0xff00U) >> 8) : __swap16md
(*(uint16_t *)pkt))
;
1055
1056 switch (mes_type) {
1057 case PPTP_CTRL_MES_CODE_SLI15: /* PNS <=> PAC */
1058 /* only SLI contains Call-ID of this peer */
1059 for (i = 0; i < slist_length(&_this->call_list); i++) {
1060 call = slist_get(&_this->call_list, i);
1061 if (call->id == call_id)
1062 break;
1063 call = NULL((void *)0);
1064 }
1065 if (call == NULL((void *)0)) {
1066 reason = "Call Id is not associated by this control";
1067 goto badpacket;
1068 }
1069 goto call_searched;
1070 case PPTP_CTRL_MES_CODE_ICRP10: /* PNS => PAC */
1071 /*
1072 * as this implementation never sent ICRQ, this case
1073 * should not happen.
1074 * But just to make sure, pptp_call.c can handle this
1075 * message.
1076 */
1077 /* FALLTHROUGH */
1078 case PPTP_CTRL_MES_CODE_OCRQ7: /* PNS => PAC */
1079 case PPTP_CTRL_MES_CODE_CCR12: /* PNS => PAC */
1080 /* liner-search will be enough */
1081 for (i = 0; i < slist_length(&_this->call_list); i++) {
1082 call = slist_get(&_this->call_list, i);
1083 if (call->peers_call_id == call_id)
1084 break;
1085 call = NULL((void *)0);
1086 }
1087 if (call == NULL((void *)0) && mes_type == PPTP_CTRL_MES_CODE_CCR12) {
1088 pptp_ctrl_send_CDN(_this, PPTP_CDN_RESULT_GENRIC_ERROR2,
1089 PPTP_ERROR_BAD_CALL4, 0, NULL((void *)0));
1090 goto call_searched;
1091 }
1092 if (mes_type == PPTP_CTRL_MES_CODE_OCRQ7) {
1093 /* make new call */
1094 if (call != NULL((void *)0)) {
1095 pptp_call_input(call, mes_type, pkt0, lpkt0);
1096 return 0;
1097 }
1098 if ((call = pptp_call_create()) == NULL((void *)0)) {
1099 pptp_ctrl_log(_this, LOG_ERR3,
1100 "pptp_call_create() failed: %m");
1101 goto fail;
1102 }
1103 if (pptp_call_init(call, _this) != 0) {
1104 pptp_ctrl_log(_this, LOG_ERR3,
1105 "pptp_call_init() failed: %m");
1106 pptp_call_destroy(call);
1107 goto fail;
1108 }
1109 slist_add(&_this->call_list, call);
1110 }
1111call_searched:
1112 if (call == NULL((void *)0)) {
1113 reason = "Call Id is not associated by this control";
1114 goto badpacket;
1115 }
1116 pptp_call_input(call, mes_type, pkt0, lpkt0);
1117 return 0;
1118 case PPTP_CTRL_MES_CODE_OCRP8: /* PAC => PNS */
1119 case PPTP_CTRL_MES_CODE_ICRQ9: /* PAC => PNS */
1120 case PPTP_CTRL_MES_CODE_ICCN11: /* PAC => PNS */
1121 case PPTP_CTRL_MES_CODE_CDN13: /* PAC => PNS */
1122 /* don't receive because above messages are only of PNS */
1123 default:
1124 break;
1125 }
1126 reason = "Message type is unexpected.";
1127 /* FALLTHROUGH */
1128badpacket:
1129 pptp_ctrl_log(_this, LOG_INFO6,
1130 "Received a bad %s(%d) call_id=%d: %s",
1131 pptp_ctrl_mes_type_string(mes_type), mes_type, call_id, reason);
1132 return 0;
1133fail:
1134 pptp_ctrl_stop(_this, PPTP_StopCCRQ_REASON_STOP_PROTOCOL2);
1135 return 0;
1136}
1137
1138
1139/*
1140 * utilities
1141 */
1142
1143/* logging with the label of the instance */
1144static void
1145pptp_ctrl_log(pptp_ctrl *_this, int prio, const char *fmt, ...)
1146{
1147 char logbuf[BUFSIZ1024];
1148 va_list ap;
1149
1150 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1151#ifdef PPTPD_MULTIPLE
1152 snprintf(logbuf, sizeof(logbuf), "pptpd id=%u ctrl=%u %s",
1153 _this->pptpd->id, _this->id, fmt);
1154#else
1155 snprintf(logbuf, sizeof(logbuf), "pptpd ctrl=%u %s", _this->id, fmt);
1156#endif
1157 vlog_printf(prio, logbuf, ap);
1158 va_end(ap)__builtin_va_end(ap);
1159}
1160
1161static const char *
1162pptp_ctrl_state_string(int state)
1163{
1164 switch (state) {
1165 case PPTP_CTRL_STATE_IDLE0:
1166 return "idle";
1167 case PPTP_CTRL_STATE_WAIT_CTRL_REPLY1:
1168 return "wait-ctrl-reply";
1169 case PPTP_CTRL_STATE_ESTABLISHED2:
1170 return "established";
1171 case PPTP_CTRL_STATE_WAIT_STOP_REPLY3:
1172 return "wait-stop-reply";
1173 }
1174 return "unknown";
1175}