GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/npppd/npppd/../pptp/pptpd.c Lines: 0 382 0.0 %
Date: 2017-11-07 Branches: 0 198 0.0 %

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