1/*	$OpenBSD: l2tpd.c,v 1.22 2021/03/29 03:54:39 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 L2TP(Layer Two Tunneling Protocol "L2TP") / RFC2661 */
29/* $Id: l2tpd.c,v 1.22 2021/03/29 03:54:39 yasuoka Exp $ */
30#include <sys/types.h>
31#include <sys/socket.h>
32#include <sys/time.h>
33#include <netinet/in.h>
34#include <netinet/udp.h>
35#include <stdlib.h>
36#include <arpa/inet.h>
37#include <stdio.h>
38#include <unistd.h>
39#include <netdb.h>
40#include <syslog.h>
41#include <signal.h>
42#include <string.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <stdarg.h>
46#include <event.h>
47
48#ifdef USE_LIBSOCKUTIL
49#include <seil/sockfromto.h>
50#else
51#include "recvfromto.h"
52#endif
53
54#include "bytebuf.h"
55#include "hash.h"
56#include "slist.h"
57#include "debugutil.h"
58#include "l2tp.h"
59#include "l2tp_subr.h"
60#include "l2tp_local.h"
61#include "addr_range.h"
62#include "net_utils.h"
63
64#ifdef	L2TPD_DEBUG
65#define	L2TPD_ASSERT(x)	ASSERT(x)
66#define	L2TPD_DBG(x)	l2tpd_log x
67#else
68#define	L2TPD_ASSERT(x)
69#endif
70#define L2TPD_IPSEC_POLICY_IN	"in ipsec esp/transport//require"
71#define L2TPD_IPSEC_POLICY_OUT	"out ipsec esp/transport//require"
72
73static void             l2tpd_io_event (int, short, void *);
74static inline int       short_cmp (const void *, const void *);
75static inline uint32_t  short_hash (const void *, int);
76
77/* sequence # of l2tpd ID */
78static u_int l2tpd_id_seq = 0;
79
80/* L2TP daemon instance */
81
82/**
83 * initialize L2TP daemon instance
84 * <p>
85 * {@link _l2tpd#bind_sin} will return with .sin_family = AF_INET,
86 * .sin_port = 1701 and .sin_len = "appropriate value"
87 * </p>
88 */
89int
90l2tpd_init(l2tpd *_this)
91{
92	int i, off;
93	u_int id;
94
95	L2TPD_ASSERT(_this != NULL);
96	memset(_this, 0, sizeof(l2tpd));
97
98	slist_init(&_this->listener);
99	slist_init(&_this->free_session_id_list);
100
101	_this->id = l2tpd_id_seq++;
102
103	if ((_this->ctrl_map = hash_create(short_cmp, short_hash,
104	    L2TPD_TUNNEL_HASH_SIZ)) == NULL) {
105		log_printf(LOG_ERR, "hash_create() failed in %s(): %m",
106		    __func__);
107		return 1;
108	}
109
110	if (slist_add(&_this->free_session_id_list,
111	    (void *)L2TP_SESSION_ID_SHUFFLE_MARK) == NULL) {
112		l2tpd_log(_this, LOG_ERR, "slist_add() failed on %s(): %m",
113		    __func__);
114		return 1;
115	}
116	off = arc4random() & L2TP_SESSION_ID_MASK;
117	for (i = 0; i < L2TP_NCALL; i++) {
118		id = (i + off) & L2TP_SESSION_ID_MASK;
119		if (id == 0)
120			id = (off - 1) & L2TP_SESSION_ID_MASK;
121		if (slist_add(&_this->free_session_id_list,
122		    (void *)(uintptr_t)id) == NULL) {
123			l2tpd_log(_this, LOG_ERR,
124			    "slist_add() failed on %s(): %m", __func__);
125			return 1;
126		}
127	}
128	_this->purge_ipsec_sa = 1;
129	_this->state = L2TPD_STATE_INIT;
130
131	return 0;
132}
133
134/*
135 * Add a {@link :l2tpd_listener} to the {@link ::l2tpd L2TP daemon}
136 * @param	_this	{@link ::l2tpd L2TP daemon}
137 * @param	idx	index of the lisnter
138 * @param	tun_name	tunnel name (ex. "L2TP")
139 * @param	bindaddr	bind address
140 */
141int
142l2tpd_add_listener(l2tpd *_this, int idx, struct l2tp_conf *conf,
143    struct sockaddr *addr)
144{
145	l2tpd_listener *plistener, *plsnr;
146
147	plistener = NULL;
148	if (idx == 0 && slist_length(&_this->listener) > 0) {
149		slist_itr_first(&_this->listener);
150		while (slist_itr_has_next(&_this->listener)) {
151			slist_itr_next(&_this->listener);
152			plsnr = slist_itr_remove(&_this->listener);
153			L2TPD_ASSERT(plsnr != NULL);
154			L2TPD_ASSERT(plsnr->sock == -1);
155			free(plsnr);
156		}
157	}
158	L2TPD_ASSERT(slist_length(&_this->listener) == idx);
159	if (slist_length(&_this->listener) != idx) {
160		l2tpd_log(_this, LOG_ERR,
161		    "Invalid argument error on %s(): idx must be %d but %d",
162		    __func__, slist_length(&_this->listener), idx);
163		goto fail;
164	}
165	if ((plistener = calloc(1, sizeof(l2tpd_listener))) == NULL) {
166		l2tpd_log(_this, LOG_ERR, "calloc() failed in %s: %m",
167		    __func__);
168		goto fail;
169	}
170	L2TPD_ASSERT(sizeof(plistener->bind) >= addr->sa_len);
171	memcpy(&plistener->bind, addr, addr->sa_len);
172
173	if (plistener->bind.sin6.sin6_port == 0)
174		plistener->bind.sin6.sin6_port = htons(L2TPD_DEFAULT_UDP_PORT);
175
176	plistener->sock = -1;
177	plistener->self = _this;
178	plistener->index = idx;
179	plistener->conf = conf;
180	strlcpy(plistener->tun_name, conf->name, sizeof(plistener->tun_name));
181
182	if (slist_add(&_this->listener, plistener) == NULL) {
183		l2tpd_log(_this, LOG_ERR, "slist_add() failed in %s: %m",
184		    __func__);
185		goto fail;
186	}
187	return 0;
188fail:
189	free(plistener);
190	return 1;
191}
192
193/* finalize L2TP daemon instance */
194void
195l2tpd_uninit(l2tpd *_this)
196{
197	l2tpd_listener *plsnr;
198
199	L2TPD_ASSERT(_this != NULL);
200
201	slist_fini(&_this->free_session_id_list);
202	if (_this->ctrl_map != NULL) {
203		hash_free(_this->ctrl_map);
204		_this->ctrl_map = NULL;
205	}
206
207	slist_itr_first(&_this->listener);
208	while (slist_itr_has_next(&_this->listener)) {
209		plsnr = slist_itr_next(&_this->listener);
210		L2TPD_ASSERT(plsnr != NULL);
211		L2TPD_ASSERT(plsnr->sock == -1);
212		free(plsnr);
213	}
214	slist_fini(&_this->listener);
215
216	event_del(&_this->ev_timeout);	/* just in case */
217	_this->state = L2TPD_STATE_STOPPED;
218}
219
220/** assign the call to the l2tpd */
221int
222l2tpd_assign_call(l2tpd *_this, l2tp_call *call)
223{
224	int    shuffle_cnt;
225	u_int  session_id;
226
227	shuffle_cnt = 0;
228	do {
229		session_id = (uintptr_t)slist_remove_first(
230		    &_this->free_session_id_list);
231		if (session_id != L2TP_SESSION_ID_SHUFFLE_MARK)
232			break;
233		L2TPD_ASSERT(shuffle_cnt == 0);
234		if (shuffle_cnt++ > 0) {
235			l2tpd_log(_this, LOG_ERR,
236			    "unexpected error in %s(): free_session_id_list "
237			    "full", __func__);
238			slist_add(&_this->free_session_id_list,
239			    (void *)L2TP_SESSION_ID_SHUFFLE_MARK);
240			return 1;
241		}
242		slist_shuffle(&_this->free_session_id_list);
243		slist_add(&_this->free_session_id_list,
244		    (void *)L2TP_SESSION_ID_SHUFFLE_MARK);
245	} while (1);
246	call->id = session_id;
247
248	return 0;
249}
250
251/* this function will be called when the call is released */
252void
253l2tpd_release_call(l2tpd *_this, l2tp_call *call)
254{
255	slist_add(&_this->free_session_id_list, (void *)(uintptr_t)call->id);
256}
257
258/* start l2tpd listener */
259static int
260l2tpd_listener_start(l2tpd_listener *_this)
261{
262	l2tpd *_l2tpd;
263	int    af, lvl, opt, sock, ival;
264	char   hbuf[NI_MAXHOST + NI_MAXSERV + 16];
265
266	_l2tpd = _this->self;
267	sock = -1;
268	af = _this->bind.sin6.sin6_family;
269	lvl = (af == AF_INET)? IPPROTO_IP : IPPROTO_IPV6;
270
271	if (_this->tun_name[0] == '\0')
272		strlcpy(_this->tun_name, L2TPD_DEFAULT_LAYER2_LABEL,
273		    sizeof(_this->tun_name));
274	if ((sock = socket(_this->bind.sin6.sin6_family,
275	    SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP)) < 0) {
276		l2tpd_log(_l2tpd, LOG_ERR,
277		    "socket() failed in %s(): %m", __func__);
278		goto fail;
279	}
280#if defined(IP_STRICT_RCVIF) && defined(USE_STRICT_RCVIF)
281	ival = 1;
282	if (setsockopt(sock, IPPROTO_IP, IP_STRICT_RCVIF, &ival, sizeof(ival))
283	    != 0)
284		l2tpd_log(_l2tpd, LOG_WARNING,
285		    "%s(): setsockopt(IP_STRICT_RCVIF) failed: %m", __func__);
286#endif
287	ival = 1;
288	if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &ival, sizeof(ival))
289	    != 0) {
290		l2tpd_log(_l2tpd, LOG_ERR,
291		    "setsockopt(,,SO_REUSEPORT) failed in %s(): %m", __func__);
292		goto fail;
293	}
294	if (bind(sock, (struct sockaddr *)&_this->bind,
295	    _this->bind.sin6.sin6_len) != 0) {
296		l2tpd_log(_l2tpd, LOG_ERR, "Binding %s/udp: %m",
297		    addrport_tostring((struct sockaddr *)&_this->bind,
298		    _this->bind.sin6.sin6_len, hbuf, sizeof(hbuf)));
299		goto fail;
300	}
301#ifdef USE_LIBSOCKUTIL
302	if (setsockoptfromto(sock) != 0) {
303		l2tpd_log(_l2tpd, LOG_ERR,
304		    "setsockoptfromto() failed in %s(): %m", __func__);
305		goto fail;
306	}
307#else
308	opt = (af == AF_INET)? IP_RECVDSTADDR : IPV6_RECVPKTINFO;
309	ival = 1;
310	if (setsockopt(sock, lvl, opt, &ival, sizeof(ival)) != 0) {
311		l2tpd_log(_l2tpd, LOG_ERR,
312		    "setsockopt(,,IP{,V6}_RECVDSTADDR) failed in %s(): %m",
313		    __func__);
314		goto fail;
315	}
316#endif
317#ifdef USE_SA_COOKIE
318	if (af == AF_INET) {
319		ival = 1;
320		if (setsockopt(sock, IPPROTO_IP, IP_IPSECFLOWINFO, &ival,
321		    sizeof(ival)) != 0) {
322			l2tpd_log(_l2tpd, LOG_ERR,
323			    "setsockopt(,,IP_IPSECFLOWINFO) failed in %s(): %m",
324			    __func__);
325			goto fail;
326		}
327	}
328#endif
329#ifdef IP_PIPEX
330	opt = (af == AF_INET)? IP_PIPEX : IPV6_PIPEX;
331	ival = 1;
332	if (setsockopt(sock, lvl, opt, &ival, sizeof(ival)) != 0)
333		l2tpd_log(_l2tpd, LOG_WARNING,
334		    "%s(): setsockopt(IP{,V6}_PIPEX) failed: %m", __func__);
335#endif
336	if (_this->conf->require_ipsec) {
337#ifdef IP_IPSEC_POLICY
338		caddr_t  ipsec_policy_in, ipsec_policy_out;
339
340		opt = (af == AF_INET)? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY;
341		/*
342		 * Note: ipsec_set_policy() will assign the buffer for
343		 * yacc parser stack, however it never free.
344		 * it cause memory leak (-2000byte).
345		 */
346		if ((ipsec_policy_in = ipsec_set_policy(L2TPD_IPSEC_POLICY_IN,
347		    strlen(L2TPD_IPSEC_POLICY_IN))) == NULL) {
348			l2tpd_log(_l2tpd, LOG_ERR,
349			    "ipsec_set_policy(L2TPD_IPSEC_POLICY_IN) failed "
350			    "at %s(): %s: %m", __func__, ipsec_strerror());
351		} else if (setsockopt(sock, lvl, opt, ipsec_policy_in,
352		    ipsec_get_policylen(ipsec_policy_in)) < 0) {
353			l2tpd_log(_l2tpd, LOG_WARNING,
354			    "setsockopt(,,IP_IPSEC_POLICY(in)) failed "
355			    "in %s(): %m", __func__);
356		}
357		if ((ipsec_policy_out = ipsec_set_policy(L2TPD_IPSEC_POLICY_OUT,
358		    strlen(L2TPD_IPSEC_POLICY_OUT))) == NULL) {
359			l2tpd_log(_l2tpd, LOG_ERR,
360			    "ipsec_set_policy(L2TPD_IPSEC_POLICY_OUT) failed "
361			    "at %s(): %s: %m", __func__, ipsec_strerror());
362		}
363		if (ipsec_policy_out != NULL &&
364		    setsockopt(sock, lvl, opt, ipsec_policy_out,
365		    ipsec_get_policylen(ipsec_policy_out)) < 0) {
366			l2tpd_log(_l2tpd, LOG_WARNING,
367			    "setsockopt(,,IP_IPSEC_POLICY(out)) failed "
368			    "in %s(): %m", __func__);
369		}
370		free(ipsec_policy_in);
371		free(ipsec_policy_out);
372#elif defined(IP_ESP_TRANS_LEVEL)
373		opt = (af == AF_INET)
374		    ? IP_ESP_TRANS_LEVEL : IPV6_ESP_TRANS_LEVEL;
375		ival = IPSEC_LEVEL_REQUIRE;
376		if (setsockopt(sock, lvl, opt, &ival, sizeof(ival)) != 0) {
377			l2tpd_log(_l2tpd, LOG_WARNING,
378			    "setsockopt(,,IP{,V6}_ESP_TRANS_LEVEL(out)) failed "
379			    "in %s(): %m", __func__);
380		}
381#else
382#error IP_IPSEC_POLICY or IP_ESP_TRANS_LEVEL must be usable.
383#endif
384	}
385
386	_this->sock = sock;
387
388	event_set(&_this->ev_sock, _this->sock, EV_READ | EV_PERSIST,
389	    l2tpd_io_event, _this);
390	event_add(&_this->ev_sock, NULL);
391
392	l2tpd_log(_l2tpd, LOG_INFO, "Listening %s/udp (L2TP LNS) [%s]",
393	    addrport_tostring((struct sockaddr *)&_this->bind,
394	    _this->bind.sin6.sin6_len, hbuf, sizeof(hbuf)), _this->tun_name);
395
396	return 0;
397fail:
398	if (sock >= 0)
399		close(sock);
400
401	return 1;
402}
403
404/* start L2TP daemon */
405int
406l2tpd_start(l2tpd *_this)
407{
408	int rval;
409	l2tpd_listener *plsnr;
410
411	rval = 0;
412
413	L2TPD_ASSERT(_this->state == L2TPD_STATE_INIT);
414	if (_this->state != L2TPD_STATE_INIT) {
415		l2tpd_log(_this, LOG_ERR, "Failed to start l2tpd: illegal "
416		    "state.");
417		return -1;
418	}
419
420	slist_itr_first(&_this->listener);
421	while (slist_itr_has_next(&_this->listener)) {
422		plsnr = slist_itr_next(&_this->listener);
423		rval |= l2tpd_listener_start(plsnr);
424	}
425
426	if (rval == 0)
427		_this->state = L2TPD_STATE_RUNNING;
428
429	return rval;
430}
431
432/* stop l2tp lisnter */
433static void
434l2tpd_listener_stop(l2tpd_listener *_this)
435{
436	char hbuf[NI_MAXHOST + NI_MAXSERV + 16];
437
438	if (_this->sock >= 0) {
439		event_del(&_this->ev_sock);
440		close(_this->sock);
441		l2tpd_log(_this->self, LOG_INFO,
442		    "Shutdown %s/udp (L2TP LNS)",
443		    addrport_tostring((struct sockaddr *)&_this->bind,
444		    _this->bind.sin6.sin6_len, hbuf, sizeof(hbuf)));
445		_this->sock = -1;
446	}
447}
448
449/* stop immediattly without disconnect operation */
450void
451l2tpd_stop_immediatly(l2tpd *_this)
452{
453	l2tpd_listener *plsnr;
454
455	slist_itr_first(&_this->listener);
456	while (slist_itr_has_next(&_this->listener)) {
457		plsnr = slist_itr_next(&_this->listener);
458		l2tpd_listener_stop(plsnr);
459	}
460	event_del(&_this->ev_timeout);	/* XXX */
461	_this->state = L2TPD_STATE_STOPPED;
462}
463
464/*
465 * this function will be called when {@link ::_l2tp_ctrl control}
466 * is terminated.
467 */
468void
469l2tpd_ctrl_finished_notify(l2tpd *_this)
470{
471	if (_this->state != L2TPD_STATE_SHUTTING_DOWN)
472		return;
473
474	if (hash_first(_this->ctrl_map) != NULL)
475		return;
476
477	l2tpd_stop_immediatly(_this);
478}
479
480static void
481l2tpd_stop_timeout(int fd, short evtype, void *ctx)
482{
483	hash_link *hl;
484	l2tp_ctrl *ctrl;
485	l2tpd *_this;
486
487	_this = ctx;
488	l2tpd_log(_this, LOG_INFO, "Shutdown timeout");
489	for (hl = hash_first(_this->ctrl_map); hl != NULL;
490	    hl = hash_next(_this->ctrl_map)) {
491		ctrl = hl->item;
492		l2tp_ctrl_stop(ctrl, 0);
493	}
494	l2tpd_stop_immediatly(_this);
495}
496
497/* stop L2TP daemon */
498void
499l2tpd_stop(l2tpd *_this)
500{
501	int nctrls = 0;
502	hash_link *hl;
503	l2tp_ctrl *ctrl;
504
505	nctrls = 0;
506	event_del(&_this->ev_timeout);
507	if (l2tpd_is_stopped(_this))
508		return;
509	if (l2tpd_is_shutting_down(_this)) {
510		/* terminate immediately, when 2nd call */
511		l2tpd_stop_immediatly(_this);
512		return;
513	}
514	for (hl = hash_first(_this->ctrl_map); hl != NULL;
515	    hl = hash_next(_this->ctrl_map)) {
516		ctrl = hl->item;
517		l2tp_ctrl_stop(ctrl, L2TP_STOP_CCN_RCODE_SHUTTING_DOWN);
518		nctrls++;
519	}
520	_this->state = L2TPD_STATE_SHUTTING_DOWN;
521	if (nctrls > 0) {
522		struct timeval tv0;
523
524		tv0.tv_usec = 0;
525		tv0.tv_sec = L2TPD_SHUTDOWN_TIMEOUT;
526
527		evtimer_set(&_this->ev_timeout, l2tpd_stop_timeout, _this);
528		evtimer_add(&_this->ev_timeout, &tv0);
529
530		return;
531	}
532	l2tpd_stop_immediatly(_this);
533}
534
535/*
536 * Configuration
537 */
538int
539l2tpd_reload(l2tpd *_this, struct l2tp_confs *l2tp_conf)
540{
541	int			 i;
542	struct l2tp_conf	*conf;
543	l2tpd_listener		*listener;
544	struct l2tp_listen_addr	*addr;
545
546	if (slist_length(&_this->listener) > 0) {
547		/*
548		 * TODO: add / remove / restart listener.
549		 */
550		slist_itr_first(&_this->listener);
551		while (slist_itr_has_next(&_this->listener)) {
552			listener = slist_itr_next(&_this->listener);
553			TAILQ_FOREACH(conf, l2tp_conf, entry) {
554				if (strcmp(listener->tun_name,
555				    conf->name) == 0) {
556					listener->conf = conf;
557					break;
558				}
559			}
560		}
561
562		return 0;
563	}
564
565	i = 0;
566	TAILQ_FOREACH(conf, l2tp_conf, entry) {
567		TAILQ_FOREACH(addr, &conf->listen, entry)
568			l2tpd_add_listener(_this, i++, conf,
569			    (struct sockaddr *)&addr->addr);
570	}
571	if (l2tpd_start(_this) != 0)
572		return -1;
573
574	return 0;
575}
576
577/*
578 * I/O functions
579 */
580/* logging when deny an access */
581void
582l2tpd_log_access_deny(l2tpd *_this, const char *reason, struct sockaddr *peer)
583{
584	char buf[BUFSIZ];
585
586	l2tpd_log(_this, LOG_ALERT, "Received packet from %s/udp: "
587	    "%s", addrport_tostring(peer, peer->sa_len, buf, sizeof(buf)),
588	    reason);
589}
590
591/* I/O event handler */
592static void
593l2tpd_io_event(int fd, short evtype, void *ctx)
594{
595	int sz;
596	l2tpd *_l2tpd;
597	l2tpd_listener *_this;
598	socklen_t peerlen, socklen;
599	struct sockaddr_storage peer, sock;
600	u_char buf[8192];
601	void *nat_t;
602
603	_this = ctx;
604	_l2tpd = _this->self;
605	if ((evtype & EV_READ) != 0) {
606		peerlen = sizeof(peer);
607		socklen = sizeof(sock);
608		while (!l2tpd_is_stopped(_l2tpd)) {
609#if defined(USE_LIBSOCKUTIL) || defined(USE_SA_COOKIE)
610			int sa_cookie_len;
611			struct in_ipsec_sa_cookie sa_cookie;
612
613			sa_cookie_len = sizeof(sa_cookie);
614			if ((sz = recvfromto_nat_t(_this->sock, buf,
615			    sizeof(buf), 0,
616			    (struct sockaddr *)&peer, &peerlen,
617			    (struct sockaddr *)&sock, &socklen,
618			    &sa_cookie, &sa_cookie_len)) == -1) {
619#else
620			if ((sz = recvfromto(_this->sock, buf,
621			    sizeof(buf), 0,
622			    (struct sockaddr *)&peer, &peerlen,
623			    (struct sockaddr *)&sock, &socklen)) == -1) {
624#endif
625				if (errno == EAGAIN || errno == EINTR)
626					break;
627				l2tpd_log(_l2tpd, LOG_ERR,
628				    "recvfrom() failed in %s(): %m",
629				    __func__);
630				l2tpd_stop(_l2tpd);
631				return;
632			}
633			/* source address check (allows.in) */
634			switch (peer.ss_family) {
635			case AF_INET:
636#if defined(USE_LIBSOCKUTIL) || defined(USE_SA_COOKIE)
637				if (sa_cookie_len > 0)
638					nat_t = &sa_cookie;
639				else
640					nat_t = NULL;
641#else
642				nat_t = NULL;
643#endif
644				l2tp_ctrl_input(_l2tpd, _this->index,
645				    (struct sockaddr *)&peer,
646				    (struct sockaddr *)&sock, nat_t,
647				    buf, sz);
648				break;
649			case AF_INET6:
650				l2tp_ctrl_input(_l2tpd, _this->index,
651				    (struct sockaddr *)&peer,
652				    (struct sockaddr *)&sock, NULL,
653				    buf, sz);
654				break;
655			default:
656				l2tpd_log(_l2tpd, LOG_ERR,
657				    "received from unknown address family = %d",
658				    peer.ss_family);
659				break;
660			}
661		}
662	}
663}
664
665/*
666 * L2TP control
667 */
668l2tp_ctrl *
669l2tpd_get_ctrl(l2tpd *_this, unsigned tunid)
670{
671	hash_link *hl;
672
673	hl = hash_lookup(_this->ctrl_map, (void *)(uintptr_t)tunid);
674	if (hl == NULL)
675		return NULL;
676
677	return hl->item;
678}
679
680void
681l2tpd_add_ctrl(l2tpd *_this, l2tp_ctrl *ctrl)
682{
683	hash_insert(_this->ctrl_map, (void *)(uintptr_t)ctrl->tunnel_id, ctrl);
684}
685
686void
687l2tpd_remove_ctrl(l2tpd *_this, unsigned tunid)
688{
689	hash_delete(_this->ctrl_map, (void *)(uintptr_t)tunid, 0);
690}
691
692
693/*
694 * misc
695 */
696
697void
698l2tpd_log(l2tpd *_this, int prio, const char *fmt, ...)
699{
700	char logbuf[BUFSIZ];
701	va_list ap;
702
703	va_start(ap, fmt);
704#ifdef	L2TPD_MULTIPLE
705	snprintf(logbuf, sizeof(logbuf), "l2tpd id=%u %s", _this->id, fmt);
706#else
707	snprintf(logbuf, sizeof(logbuf), "l2tpd %s", fmt);
708#endif
709	vlog_printf(prio, logbuf, ap);
710	va_end(ap);
711}
712