1 /* $OpenBSD: pptpd.c,v 1.34 2022/12/28 21:30:17 jmc 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 /* $Id: pptpd.c,v 1.34 2022/12/28 21:30:17 jmc Exp $ */
29
30 /**@file
31 * This file provides a implementation of PPTP daemon. Currently it
32 * provides functions for PAC (PPTP Access Concentrator) only.
33 * $Id: pptpd.c,v 1.34 2022/12/28 21:30:17 jmc Exp $
34 */
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/sysctl.h>
38 #include <net/if.h>
39 #include <netinet/in.h>
40 #include <netinet/ip.h>
41 #include <netinet/ip_gre.h>
42 #include <arpa/inet.h>
43 #include <netdb.h>
44 #include <stdio.h>
45 #include <stdarg.h>
46 #include <signal.h>
47 #include <syslog.h>
48 #include <fcntl.h>
49 #include <unistd.h>
50 #include <stdlib.h>
51 #include <errno.h>
52 #include <string.h>
53 #include <event.h>
54
55 #ifdef USE_LIBSOCKUTIL
56 #include <seil/sockfromto.h>
57 #endif
58
59 #include "net_utils.h"
60 #include "bytebuf.h"
61 #include "debugutil.h"
62 #include "hash.h"
63 #include "slist.h"
64 #include "addr_range.h"
65
66 #include "pptp.h"
67 #include "pptp_local.h"
68 #include "privsep.h"
69 #include "accept.h"
70
71 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
72
73 static int pptpd_seqno = 0;
74
75 #ifdef PPTPD_DEBUG
76 #define PPTPD_ASSERT(x) ASSERT(x)
77 #define PPTPD_DBG(x) pptpd_log x
78 #else
79 #define PPTPD_ASSERT(x)
80 #define PPTPD_DBG(x)
81 #endif
82
83 static void pptpd_log (pptpd *, int, const char *, ...) __printflike(3,4);
84 static void pptpd_close_gre (pptpd *);
85 static void pptpd_close_1723 (pptpd *);
86 static void pptpd_io_event (int, short, void *);
87 static void pptpd_gre_io_event (int, short, void *);
88 static void pptpd_gre_input (pptpd_listener *, struct sockaddr *, u_char *, int);
89 static void pptp_ctrl_start_by_pptpd (pptpd *, int, int, struct sockaddr *);
90 static int pptp_call_cmp (const void *, const void *);
91 static uint32_t pptp_call_hash (const void *, int);
92 static void pptp_gre_header_string (struct pptp_gre_header *, char *, int);
93
94 #define PPTPD_SHUFFLE_MARK -1
95
96 /* initialize pptp daemon */
97 int
pptpd_init(pptpd * _this)98 pptpd_init(pptpd *_this)
99 {
100 int i, m;
101 uint16_t call0, call[UINT16_MAX - 1];
102
103 int mib[] = { CTL_NET, PF_INET, IPPROTO_GRE, GRECTL_ALLOW };
104 int value;
105 size_t size;
106 size = sizeof(value);
107
108 if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0) == 0) {
109 if(value == 0) {
110 pptpd_log(_this, LOG_WARNING, "GRE protocol not allowed");
111 }
112 }
113
114 memset(_this, 0, sizeof(pptpd));
115 _this->id = pptpd_seqno++;
116
117 slist_init(&_this->ctrl_list);
118 slist_init(&_this->call_free_list);
119
120 /* randomize call id */
121 for (i = 0; i < countof(call) ; i++)
122 call[i] = i + 1;
123 for (i = countof(call); i > 1; i--) {
124 m = arc4random_uniform(i);
125 call0 = call[m];
126 call[m] = call[i - 1];
127 call[i - 1] = call0;
128 }
129
130 for (i = 0; i < MINIMUM(PPTP_MAX_CALL, countof(call)); i++)
131 slist_add(&_this->call_free_list, (void *)(uintptr_t)call[i]);
132 slist_add(&_this->call_free_list, (void *)PPTPD_SHUFFLE_MARK);
133
134 if (_this->call_id_map == NULL)
135 _this->call_id_map = hash_create(pptp_call_cmp, pptp_call_hash,
136 0);
137
138 return 0;
139 }
140
141 /* add a listener to pptpd daemon context */
142 int
pptpd_add_listener(pptpd * _this,int idx,struct pptp_conf * conf,struct sockaddr * addr)143 pptpd_add_listener(pptpd *_this, int idx, struct pptp_conf *conf,
144 struct sockaddr *addr)
145 {
146 int inaddr_any;
147 pptpd_listener *plistener, *plstn;
148
149 plistener = NULL;
150 if (idx == 0 && slist_length(&_this->listener) > 0) {
151 slist_itr_first(&_this->listener);
152 while (slist_itr_has_next(&_this->listener)) {
153 slist_itr_next(&_this->listener);
154 plstn = slist_itr_remove(&_this->listener);
155 PPTPD_ASSERT(plstn != NULL);
156 PPTPD_ASSERT(plstn->sock == -1);
157 PPTPD_ASSERT(plstn->sock_gre == -1);
158 free(plstn);
159 }
160 }
161 PPTPD_ASSERT(slist_length(&_this->listener) == idx);
162 if (slist_length(&_this->listener) != idx) {
163 pptpd_log(_this, LOG_ERR,
164 "Invalid argument error on %s(): idx must be %d but %d",
165 __func__, slist_length(&_this->listener), idx);
166 goto fail;
167 }
168 if ((plistener = calloc(1, sizeof(pptpd_listener))) == NULL) {
169 pptpd_log(_this, LOG_ERR, "calloc() failed in %s: %m",
170 __func__);
171 goto fail;
172 }
173
174 PPTPD_ASSERT(sizeof(plistener->bind_sin) >= addr->sa_len);
175 memcpy(&plistener->bind_sin, addr, addr->sa_len);
176 memcpy(&plistener->bind_sin_gre, addr, addr->sa_len);
177
178 if (plistener->bind_sin.sin_port == 0)
179 plistener->bind_sin.sin_port = htons(PPTPD_DEFAULT_TCP_PORT);
180
181 /* When a raw socket binds both of an INADDR_ANY and specific IP
182 * address sockets, packets will be received by those sockets
183 * simultaneously. To avoid this duplicate receives, not
184 * permit such kind of configuration */
185 inaddr_any = 0;
186 slist_itr_first(&_this->listener);
187 while (slist_itr_has_next(&_this->listener)) {
188 plstn = slist_itr_next(&_this->listener);
189 if (plstn->bind_sin_gre.sin_addr.s_addr == INADDR_ANY)
190 inaddr_any++;
191 }
192 if (plistener->bind_sin_gre.sin_addr.s_addr == INADDR_ANY)
193 inaddr_any++;
194 if (inaddr_any > 0 && idx > 0) {
195 log_printf(LOG_ERR, "configuration error at pptpd.listener_in: "
196 "combination 0.0.0.0 and other address is not allowed.");
197 goto fail;
198 }
199
200 plistener->bind_sin_gre.sin_port = 0;
201 plistener->sock = -1;
202 plistener->sock_gre = -1;
203 plistener->self = _this;
204 plistener->index = idx;
205 plistener->conf = conf;
206 strlcpy(plistener->tun_name, conf->name, sizeof(plistener->tun_name));
207
208 if (slist_add(&_this->listener, plistener) == NULL) {
209 pptpd_log(_this, LOG_ERR, "slist_add() failed in %s: %m",
210 __func__);
211 goto fail;
212 }
213 return 0;
214 fail:
215 free(plistener);
216 return 1;
217 }
218
219 void
pptpd_uninit(pptpd * _this)220 pptpd_uninit(pptpd *_this)
221 {
222 pptpd_listener *plstn;
223
224 slist_fini(&_this->ctrl_list);
225 slist_fini(&_this->call_free_list);
226
227 slist_itr_first(&_this->listener);
228 while (slist_itr_has_next(&_this->listener)) {
229 plstn = slist_itr_next(&_this->listener);
230 PPTPD_ASSERT(plstn != NULL);
231 PPTPD_ASSERT(plstn->sock == -1);
232 PPTPD_ASSERT(plstn->sock_gre == -1);
233 free(plstn);
234 }
235 slist_fini(&_this->listener);
236 if (_this->call_id_map != NULL)
237 hash_free(_this->call_id_map);
238 _this->call_id_map = NULL;
239 }
240
241 #define CALL_ID_KEY(call_id, listener_idx) \
242 ((void *)((uintptr_t)(call_id) | (listener_idx) << 16))
243 #define CALL_KEY(call) \
244 CALL_ID_KEY((call)->id, (call)->ctrl->listener_index)
245 int
pptpd_assign_call(pptpd * _this,pptp_call * call)246 pptpd_assign_call(pptpd *_this, pptp_call *call)
247 {
248 int shuffle_cnt = 0;
249 u_int call_id;
250
251 shuffle_cnt = 0;
252 slist_itr_first(&_this->call_free_list);
253 while (slist_length(&_this->call_free_list) > 1 &&
254 slist_itr_has_next(&_this->call_free_list)) {
255 call_id = (uintptr_t)slist_itr_next(&_this->call_free_list);
256 if (call_id == 0)
257 break;
258 slist_itr_remove(&_this->call_free_list);
259 if (call_id == PPTPD_SHUFFLE_MARK) {
260 if (shuffle_cnt++ > 0)
261 break;
262 slist_shuffle(&_this->call_free_list);
263 slist_add(&_this->call_free_list,
264 (void *)PPTPD_SHUFFLE_MARK);
265 slist_itr_first(&_this->call_free_list);
266 continue;
267 }
268 call->id = call_id;
269 hash_insert(_this->call_id_map, CALL_KEY(call), call);
270
271 return 0;
272 }
273 errno = EBUSY;
274 pptpd_log(_this, LOG_ERR, "call request reached limit=%d",
275 PPTP_MAX_CALL);
276 return -1;
277 }
278
279 void
pptpd_release_call(pptpd * _this,pptp_call * call)280 pptpd_release_call(pptpd *_this, pptp_call *call)
281 {
282 if (call->id != 0)
283 slist_add(&_this->call_free_list, (void *)(uintptr_t)call->id);
284 hash_delete(_this->call_id_map, CALL_KEY(call), 0);
285 call->id = 0;
286 }
287
288 static int
pptpd_listener_start(pptpd_listener * _this)289 pptpd_listener_start(pptpd_listener *_this)
290 {
291 int sock, ival, sock_gre;
292 struct sockaddr_in bind_sin, bind_sin_gre;
293 int wildcardbinding;
294
295 wildcardbinding =
296 (_this->bind_sin.sin_addr.s_addr == INADDR_ANY)? 1 : 0;
297 sock = -1;
298 sock_gre = -1;
299 memcpy(&bind_sin, &_this->bind_sin, sizeof(bind_sin));
300 memcpy(&bind_sin_gre, &_this->bind_sin_gre, sizeof(bind_sin_gre));
301
302 if ((sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP))
303 < 0) {
304 pptpd_log(_this->self, LOG_ERR, "socket() failed at %s(): %m",
305 __func__);
306 goto fail;
307 }
308 ival = 1;
309 if(setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &ival, sizeof(ival)) < 0){
310 pptpd_log(_this->self, LOG_WARNING,
311 "setsockopt(SO_REUSEPORT) failed at %s(): %m", __func__);
312 }
313 #if defined(IP_STRICT_RCVIF) && defined(USE_STRICT_RCVIF)
314 ival = 1;
315 if (setsockopt(sock, IPPROTO_IP, IP_STRICT_RCVIF, &ival, sizeof(ival))
316 != 0)
317 pptpd_log(_this->self, LOG_WARNING,
318 "%s(): setsockopt(IP_STRICT_RCVIF) failed: %m", __func__);
319 #endif
320 if (bind(sock, (struct sockaddr *)&_this->bind_sin,
321 _this->bind_sin.sin_len) != 0) {
322 pptpd_log(_this->self, LOG_ERR,
323 "bind(%s:%u) failed at %s(): %m",
324 inet_ntoa(_this->bind_sin.sin_addr),
325 ntohs(_this->bind_sin.sin_port), __func__);
326 goto fail;
327 }
328 if (listen(sock, PPTP_BACKLOG) != 0) {
329 pptpd_log(_this->self, LOG_ERR,
330 "listen(%s:%u) failed at %s(): %m",
331 inet_ntoa(_this->bind_sin.sin_addr),
332 ntohs(_this->bind_sin.sin_port), __func__);
333 goto fail;
334 }
335 pptpd_log(_this->self, LOG_INFO, "Listening %s:%u/tcp (PPTP PAC) [%s]",
336 inet_ntoa(_this->bind_sin.sin_addr),
337 ntohs(_this->bind_sin.sin_port), _this->tun_name);
338
339 /* GRE */
340 bind_sin_gre.sin_port = 0;
341 if ((sock_gre = priv_socket(AF_INET, SOCK_RAW, IPPROTO_GRE)) < 0) {
342 pptpd_log(_this->self, LOG_ERR, "socket() failed at %s(): %m",
343 __func__);
344 goto fail;
345 }
346 #if defined(IP_STRICT_RCVIF) && defined(USE_STRICT_RCVIF)
347 ival = 1;
348 if (setsockopt(sock_gre, IPPROTO_IP, IP_STRICT_RCVIF, &ival,
349 sizeof(ival)) != 0)
350 pptpd_log(_this->self, LOG_WARNING,
351 "%s(): setsockopt(IP_STRICT_RCVIF) failed: %m", __func__);
352 #endif
353 #ifdef IP_PIPEX
354 ival = 1;
355 if (setsockopt(sock_gre, IPPROTO_IP, IP_PIPEX, &ival, sizeof(ival))
356 != 0)
357 pptpd_log(_this->self, LOG_WARNING,
358 "%s(): setsockopt(IP_PIPEX) failed: %m", __func__);
359 #endif
360 if ((ival = fcntl(sock_gre, F_GETFL)) < 0) {
361 pptpd_log(_this->self, LOG_ERR,
362 "fcntl(F_GET_FL) failed at %s(): %m", __func__);
363 goto fail;
364 } else if (fcntl(sock_gre, F_SETFL, ival | O_NONBLOCK) < 0) {
365 pptpd_log(_this->self, LOG_ERR,
366 "fcntl(F_SET_FL) failed at %s(): %m", __func__);
367 goto fail;
368 }
369 if (bind(sock_gre, (struct sockaddr *)&bind_sin_gre,
370 bind_sin_gre.sin_len) != 0) {
371 pptpd_log(_this->self, LOG_ERR,
372 "bind(%s:%u) failed at %s(): %m",
373 inet_ntoa(bind_sin_gre.sin_addr),
374 ntohs(bind_sin_gre.sin_port), __func__);
375 goto fail;
376 }
377 if (wildcardbinding) {
378 #ifdef USE_LIBSOCKUTIL
379 if (setsockoptfromto(sock) != 0) {
380 pptpd_log(_this->self, LOG_ERR,
381 "setsockoptfromto() failed in %s(): %m", __func__);
382 goto fail;
383 }
384 #else
385 /* nothing to do */
386 #endif
387 }
388 pptpd_log(_this->self, LOG_INFO, "Listening %s:gre (PPTP PAC)",
389 inet_ntoa(bind_sin_gre.sin_addr));
390
391 _this->sock = sock;
392 _this->sock_gre = sock_gre;
393
394 if (accept_add(_this->sock, pptpd_io_event, _this) != 0) {
395 pptpd_log(_this->self, LOG_ERR,
396 "accept_add() failed in %s(): %m", __func__);
397 goto fail;
398 }
399
400 event_set(&_this->ev_sock_gre, _this->sock_gre, EV_READ | EV_PERSIST,
401 pptpd_gre_io_event, _this);
402 event_add(&_this->ev_sock_gre, NULL);
403
404 return 0;
405 fail:
406 if (sock >= 0)
407 close(sock);
408 if (sock_gre >= 0)
409 close(sock_gre);
410
411 _this->sock = -1;
412 _this->sock_gre = -1;
413
414 return 1;
415 }
416
417 int
pptpd_start(pptpd * _this)418 pptpd_start(pptpd *_this)
419 {
420 int rval = 0;
421 pptpd_listener *plistener;
422
423 slist_itr_first(&_this->listener);
424 while (slist_itr_has_next(&_this->listener)) {
425 plistener = slist_itr_next(&_this->listener);
426 PPTPD_ASSERT(plistener != NULL);
427 rval |= pptpd_listener_start(plistener);
428 }
429 if (rval == 0)
430 _this->state = PPTPD_STATE_RUNNING;
431
432 return rval;
433 }
434
435 static void
pptpd_listener_close_gre(pptpd_listener * _this)436 pptpd_listener_close_gre(pptpd_listener *_this)
437 {
438 if (_this->sock_gre >= 0) {
439 event_del(&_this->ev_sock_gre);
440 close(_this->sock_gre);
441 pptpd_log(_this->self, LOG_INFO, "Shutdown %s/gre",
442 inet_ntoa(_this->bind_sin_gre.sin_addr));
443 }
444 _this->sock_gre = -1;
445 }
446
447 static void
pptpd_close_gre(pptpd * _this)448 pptpd_close_gre(pptpd *_this)
449 {
450 pptpd_listener *plistener;
451
452 slist_itr_first(&_this->listener);
453 while (slist_itr_has_next(&_this->listener)) {
454 plistener = slist_itr_next(&_this->listener);
455 pptpd_listener_close_gre(plistener);
456 }
457 }
458
459 static void
pptpd_listener_close_1723(pptpd_listener * _this)460 pptpd_listener_close_1723(pptpd_listener *_this)
461 {
462 if (_this->sock >= 0) {
463 accept_del(_this->sock);
464 close(_this->sock);
465 pptpd_log(_this->self, LOG_INFO, "Shutdown %s:%u/tcp",
466 inet_ntoa(_this->bind_sin.sin_addr),
467 ntohs(_this->bind_sin.sin_port));
468 }
469 _this->sock = -1;
470 }
471
472 static void
pptpd_close_1723(pptpd * _this)473 pptpd_close_1723(pptpd *_this)
474 {
475 pptpd_listener *plistener;
476
477 slist_itr_first(&_this->listener);
478 while (slist_itr_has_next(&_this->listener)) {
479 plistener = slist_itr_next(&_this->listener);
480 pptpd_listener_close_1723(plistener);
481 }
482 }
483
484 void
pptpd_stop_immediatly(pptpd * _this)485 pptpd_stop_immediatly(pptpd *_this)
486 {
487 pptp_ctrl *ctrl;
488
489 if (event_initialized(&_this->ev_timer))
490 evtimer_del(&_this->ev_timer);
491 if (_this->state != PPTPD_STATE_STOPPED) {
492 /* lock, to avoid multiple call from pptp_ctrl_stop() */
493 _this->state = PPTPD_STATE_STOPPED;
494
495 pptpd_close_1723(_this);
496 for (slist_itr_first(&_this->ctrl_list);
497 (ctrl = slist_itr_next(&_this->ctrl_list)) != NULL;) {
498 pptp_ctrl_stop(ctrl, 0);
499 }
500 pptpd_close_gre(_this);
501 slist_fini(&_this->ctrl_list);
502 slist_fini(&_this->call_free_list);
503 PPTPD_DBG((_this, LOG_DEBUG, "Stopped"));
504 } else {
505 PPTPD_DBG((_this, LOG_DEBUG, "(Already) Stopped"));
506 }
507 }
508
509 static void
pptpd_stop_timeout(int fd,short event,void * ctx)510 pptpd_stop_timeout(int fd, short event, void *ctx)
511 {
512 pptpd *_this;
513
514 _this = ctx;
515 pptpd_stop_immediatly(_this);
516 }
517
518 void
pptpd_stop(pptpd * _this)519 pptpd_stop(pptpd *_this)
520 {
521 int nctrl;
522 pptp_ctrl *ctrl;
523 struct timeval tv;
524
525 if (event_initialized(&_this->ev_timer))
526 evtimer_del(&_this->ev_timer);
527 pptpd_close_1723(_this);
528
529 /* XXX: use common procedure with l2tpd_stop */
530
531 if (pptpd_is_stopped(_this))
532 return;
533 if (pptpd_is_shutting_down(_this)) {
534 pptpd_stop_immediatly(_this);
535 return;
536 }
537 _this->state = PPTPD_STATE_SHUTTING_DOWN;
538 nctrl = 0;
539 for (slist_itr_first(&_this->ctrl_list);
540 (ctrl = slist_itr_next(&_this->ctrl_list)) != NULL;) {
541 pptp_ctrl_stop(ctrl, PPTP_CDN_RESULT_ADMIN_SHUTDOWN);
542 nctrl++;
543 }
544 if (nctrl > 0) {
545 tv.tv_sec = PPTPD_SHUTDOWN_TIMEOUT;
546 tv.tv_usec = 0;
547
548 evtimer_set(&_this->ev_timer, pptpd_stop_timeout, _this);
549 evtimer_add(&_this->ev_timer, &tv);
550
551 return;
552 }
553 pptpd_stop_immediatly(_this);
554 }
555
556 /*
557 * PPTP Configuration
558 */
559 int
pptpd_reload(pptpd * _this,struct pptp_confs * pptp_conf)560 pptpd_reload(pptpd *_this, struct pptp_confs *pptp_conf)
561 {
562 int i;
563 struct pptp_conf *conf;
564 pptpd_listener *listener;
565 struct pptp_listen_addr *addr;
566
567 if (slist_length(&_this->listener) > 0) {
568 /*
569 * TODO: add / remove / restart listener.
570 */
571 slist_itr_first(&_this->listener);
572 while (slist_itr_has_next(&_this->listener)) {
573 listener = slist_itr_next(&_this->listener);
574 TAILQ_FOREACH(conf, pptp_conf, entry) {
575 if (strcmp(listener->tun_name,
576 conf->name) == 0) {
577 listener->conf = conf;
578 break;
579 }
580 }
581 }
582
583 return 0;
584 }
585
586 i = 0;
587 TAILQ_FOREACH(conf, pptp_conf, entry) {
588 TAILQ_FOREACH(addr, &conf->listen, entry)
589 pptpd_add_listener(_this, i++, conf,
590 (struct sockaddr *)&addr->addr);
591 }
592 if (pptpd_start(_this) != 0)
593 return -1;
594
595 return 0;
596 }
597
598 /*
599 * I/O functions
600 */
601 /* I/O event handler of 1723/tcp */
602 static void
pptpd_io_event(int fd,short evmask,void * ctx)603 pptpd_io_event(int fd, short evmask, void *ctx)
604 {
605 int newsock;
606 const char *reason;
607 socklen_t peerlen;
608 struct sockaddr_storage peer;
609 pptpd *_this;
610 pptpd_listener *listener;
611
612 listener = ctx;
613 PPTPD_ASSERT(listener != NULL);
614 _this = listener->self;
615 PPTPD_ASSERT(_this != NULL);
616
617 if ((evmask & EV_READ) != 0) {
618 for (;;) { /* accept till EAGAIN occurred */
619 peerlen = sizeof(peer);
620 if ((newsock = accept(listener->sock,
621 (struct sockaddr *)&peer, &peerlen)) < 0) {
622 if (errno != EAGAIN && errno == EINTR &&
623 errno != ECONNABORTED) {
624 if (errno == EMFILE || errno == ENFILE)
625 accept_pause();
626 pptpd_log(_this, LOG_ERR,
627 "accept() failed at %s(): %m",
628 __func__);
629 }
630 break;
631 }
632 /* check peer */
633 switch (peer.ss_family) {
634 case AF_INET:
635 pptp_ctrl_start_by_pptpd(_this, newsock,
636 listener->index, (struct sockaddr *)&peer);
637 break;
638 default:
639 reason = "address family is not supported.";
640 break;
641 }
642 }
643 }
644 }
645
646 /* I/O event handler of GRE */
647 static void
pptpd_gre_io_event(int fd,short evmask,void * ctx)648 pptpd_gre_io_event(int fd, short evmask, void *ctx)
649 {
650 int sz;
651 u_char pkt[65535];
652 socklen_t peerlen;
653 struct sockaddr_storage peer;
654 pptpd *_this;
655 pptpd_listener *listener;
656
657 listener = ctx;
658 PPTPD_ASSERT(listener != NULL);
659 _this = listener->self;
660 PPTPD_ASSERT(_this != NULL);
661
662 if (evmask & EV_READ) {
663 for (;;) {
664 /* read till blocked */
665 peerlen = sizeof(peer);
666 if ((sz = recvfrom(listener->sock_gre, pkt, sizeof(pkt),
667 0, (struct sockaddr *)&peer, &peerlen)) == -1) {
668 if (errno == EAGAIN || errno == EINTR)
669 break;
670 pptpd_log(_this, LOG_INFO,
671 "read(GRE) failed: %m");
672 pptpd_stop(_this);
673 return;
674 }
675 pptpd_gre_input(listener, (struct sockaddr *)&peer, pkt,
676 sz);
677 }
678 }
679 }
680
681 /* receive GRE then route to pptp_call */
682 static void
pptpd_gre_input(pptpd_listener * listener,struct sockaddr * peer,u_char * pkt,int lpkt)683 pptpd_gre_input(pptpd_listener *listener, struct sockaddr *peer, u_char *pkt,
684 int lpkt)
685 {
686 int hlen, input_flags;
687 uint32_t seq, ack, call_id;
688 struct ip *iphdr;
689 struct pptp_gre_header *grehdr;
690 char hbuf0[NI_MAXHOST], logbuf[512];
691 const char *reason;
692 pptp_call *call;
693 hash_link *hl;
694 pptpd *_this;
695
696 seq = 0;
697 ack = 0;
698 input_flags = 0;
699 reason = "No error";
700 _this = listener->self;
701
702 PPTPD_ASSERT(peer->sa_family == AF_INET);
703
704 strlcpy(hbuf0, "<unknown>", sizeof(hbuf0));
705 if (getnameinfo(peer, peer->sa_len, hbuf0, sizeof(hbuf0), NULL, 0,
706 NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
707 pptpd_log(_this, LOG_ERR,
708 "getnameinfo() failed at %s(): %m", __func__);
709 goto fail;
710 }
711 if (listener->conf->data_in_pktdump != 0) {
712 pptpd_log(_this, LOG_DEBUG, "PPTP Data input packet dump");
713 show_hd(debug_get_debugfp(), pkt, lpkt);
714 }
715 if (peer->sa_family != AF_INET) {
716 pptpd_log(_this, LOG_ERR,
717 "Received malformed GRE packet: address family is not "
718 "supported: peer=%s af=%d", hbuf0, peer->sa_family);
719 goto fail;
720 }
721
722 if (lpkt < sizeof(struct ip)) {
723 pptpd_log(_this, LOG_ERR,
724 "Received a short length packet length=%d, from %s", lpkt,
725 hbuf0);
726 goto fail;
727 }
728 iphdr = (struct ip *)pkt;
729
730 iphdr->ip_len = ntohs(iphdr->ip_len);
731 hlen = iphdr->ip_hl * 4;
732
733 if (iphdr->ip_len > lpkt ||
734 iphdr->ip_len < hlen + sizeof(struct pptp_gre_header)) {
735 pptpd_log(_this, LOG_ERR,
736 "Received a broken packet: ip_hl=%d iplen=%d lpkt=%d", hlen,
737 iphdr->ip_len, lpkt);
738 show_hd(debug_get_debugfp(), pkt, lpkt);
739 goto fail;
740 }
741 pkt += hlen;
742 lpkt -= hlen;
743 grehdr = (struct pptp_gre_header *)pkt;
744 pkt += sizeof(struct pptp_gre_header);
745 lpkt -= sizeof(struct pptp_gre_header);
746
747 grehdr->protocol_type = htons(grehdr->protocol_type);
748 grehdr->payload_length = htons(grehdr->payload_length);
749 grehdr->call_id = htons(grehdr->call_id);
750
751 if (!(grehdr->protocol_type == PPTP_GRE_PROTOCOL_TYPE &&
752 grehdr->C == 0 && grehdr->R == 0 && grehdr->K != 0 &&
753 grehdr->recur == 0 && grehdr->s == 0 && grehdr->flags == 0 &&
754 grehdr->ver == PPTP_GRE_VERSION)) {
755 reason = "GRE header is broken";
756 goto bad_gre;
757 }
758 if (grehdr->S != 0) {
759 if (lpkt < 2) {
760 reason = "No enough space for seq number";
761 goto bad_gre;
762 }
763 input_flags |= PPTP_GRE_PKT_SEQ_PRESENT;
764 seq = ntohl(*(uint32_t *)pkt);
765 pkt += 4;
766 lpkt -= 4;
767 }
768
769 if (grehdr->A != 0) {
770 if (lpkt < 2) {
771 reason = "No enough space for ack number";
772 goto bad_gre;
773 }
774 input_flags |= PPTP_GRE_PKT_ACK_PRESENT;
775 ack = ntohl(*(uint32_t *)pkt);
776 pkt += 4;
777 lpkt -= 4;
778 }
779
780 if (grehdr->payload_length > lpkt) {
781 reason = "'Payload Length' is mismatch from actual length";
782 goto bad_gre;
783 }
784
785
786 /* route to pptp_call */
787 call_id = grehdr->call_id;
788
789 hl = hash_lookup(_this->call_id_map, CALL_ID_KEY(call_id, listener->index));
790 if (hl == NULL) {
791 reason = "Received GRE packet has unknown call_id";
792 goto bad_gre;
793 }
794 call = hl->item;
795 pptp_call_gre_input(call, seq, ack, input_flags, pkt, lpkt);
796
797 return;
798 bad_gre:
799 pptp_gre_header_string(grehdr, logbuf, sizeof(logbuf));
800 pptpd_log(_this, LOG_INFO,
801 "Received malformed GRE packet: %s: peer=%s sock=%s %s seq=%u: "
802 "ack=%u ifidx=%d", reason, hbuf0, inet_ntoa(iphdr->ip_dst), logbuf,
803 seq, ack, listener->index);
804 fail:
805 return;
806 }
807
808 /* start PPTP control, when new connection is established */
809 static void
pptp_ctrl_start_by_pptpd(pptpd * _this,int sock,int listener_index,struct sockaddr * peer)810 pptp_ctrl_start_by_pptpd(pptpd *_this, int sock, int listener_index,
811 struct sockaddr *peer)
812 {
813 pptp_ctrl *ctrl;
814 socklen_t sslen;
815
816 ctrl = NULL;
817 if ((ctrl = pptp_ctrl_create()) == NULL)
818 goto fail;
819 if (pptp_ctrl_init(ctrl) != 0)
820 goto fail;
821
822 memset(&ctrl->peer, 0, sizeof(ctrl->peer));
823 memcpy(&ctrl->peer, peer, peer->sa_len);
824 ctrl->pptpd = _this;
825 ctrl->sock = sock;
826 ctrl->listener_index = listener_index;
827
828 sslen = sizeof(ctrl->our);
829 if (getsockname(ctrl->sock, (struct sockaddr *)&ctrl->our,
830 &sslen) != 0) {
831 pptpd_log(_this, LOG_WARNING,
832 "getsockname() failed at %s(): %m", __func__);
833 goto fail;
834 }
835
836 if (PPTP_CTRL_CONF(ctrl)->echo_interval != 0)
837 ctrl->echo_interval = PPTP_CTRL_CONF(ctrl)->echo_interval;
838 if (PPTP_CTRL_CONF(ctrl)->echo_timeout != 0)
839 ctrl->echo_timeout = PPTP_CTRL_CONF(ctrl)->echo_timeout;
840
841 if (pptp_ctrl_start(ctrl) != 0)
842 goto fail;
843
844 slist_add(&_this->ctrl_list, ctrl);
845
846 return;
847 fail:
848 close(sock);
849 pptp_ctrl_destroy(ctrl);
850 return;
851 }
852
853 void
pptpd_ctrl_finished_notify(pptpd * _this,pptp_ctrl * ctrl)854 pptpd_ctrl_finished_notify(pptpd *_this, pptp_ctrl *ctrl)
855 {
856 pptp_ctrl *ctrl1;
857 int i, nctrl;
858
859 PPTPD_ASSERT(_this != NULL);
860 PPTPD_ASSERT(ctrl != NULL);
861
862 accept_unpause();
863
864 nctrl = 0;
865 for (i = 0; i < slist_length(&_this->ctrl_list); i++) {
866 ctrl1 = slist_get(&_this->ctrl_list, i);
867 if (ctrl1 == ctrl) {
868 slist_remove(&_this->ctrl_list, i);
869 break;
870 }
871 }
872 pptp_ctrl_destroy(ctrl);
873
874 PPTPD_DBG((_this, LOG_DEBUG, "Remains %d ctrls", nctrl));
875 if (pptpd_is_shutting_down(_this) && nctrl == 0)
876 pptpd_stop_immediatly(_this);
877 }
878
879 /*
880 * utility functions
881 */
882
883 /* logging with the this PPTP instance */
884 static void
pptpd_log(pptpd * _this,int prio,const char * fmt,...)885 pptpd_log(pptpd *_this, int prio, const char *fmt, ...)
886 {
887 char logbuf[BUFSIZ];
888 va_list ap;
889
890 PPTPD_ASSERT(_this != NULL);
891 va_start(ap, fmt);
892 #ifdef PPTPD_MULTIPLE
893 snprintf(logbuf, sizeof(logbuf), "pptpd id=%u %s", _this->id, fmt);
894 #else
895 snprintf(logbuf, sizeof(logbuf), "pptpd %s", fmt);
896 #endif
897 vlog_printf(prio, logbuf, ap);
898 va_end(ap);
899 }
900
901 static int
pptp_call_cmp(const void * a0,const void * b0)902 pptp_call_cmp(const void *a0, const void *b0)
903 {
904 return ((intptr_t)a0 - (intptr_t)b0);
905 }
906
907 static uint32_t
pptp_call_hash(const void * ctx,int size)908 pptp_call_hash(const void *ctx, int size)
909 {
910 return (uintptr_t)ctx % size;
911 }
912
913 /* convert GRE packet header to strings */
914 static void
pptp_gre_header_string(struct pptp_gre_header * grehdr,char * buf,int lbuf)915 pptp_gre_header_string(struct pptp_gre_header *grehdr, char *buf, int lbuf)
916 {
917 snprintf(buf, lbuf,
918 "[%s%s%s%s%s%s] ver=%d "
919 "protocol_type=%04x payload_length=%d call_id=%d",
920 (grehdr->C != 0)? "C" : "", (grehdr->R != 0)? "R" : "",
921 (grehdr->K != 0)? "K" : "", (grehdr->S != 0)? "S" : "",
922 (grehdr->s != 0)? "s" : "", (grehdr->A != 0)? "A" : "", grehdr->ver,
923 grehdr->protocol_type, grehdr->payload_length, grehdr->call_id);
924 }
925