xref: /openbsd/usr.sbin/npppd/pptp/pptpd.c (revision 3a50f0a9)
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