1/***********************************************************************
2*
3* peer.c
4*
5* Manage lists of peers for L2TP
6*
7* Copyright (C) 2002 by Roaring Penguin Software Inc.
8*
9* This software may be distributed under the terms of the GNU General
10* Public License, Version 2, or (at your option) any later version.
11*
12* LIC: GPL
13*
14***********************************************************************/
15
16static char const RCSID[] =
17"$Id: peer.c 3323 2011-09-21 18:45:48Z lly.dev $";
18
19#include "l2tp.h"
20#include <stddef.h>
21#include <string.h>
22
23static hash_table all_peers;
24static int peer_process_option(EventSelector *es,
25			       char const *name,
26			       char const *value);
27
28static l2tp_peer prototype;
29
30static option_handler peer_option_handler = {
31    NULL, "peer", peer_process_option
32};
33
34static int port;
35
36static int handle_secret_option(EventSelector *es, l2tp_opt_descriptor *desc, char const *value);
37static int handle_hostname_option(EventSelector *es, l2tp_opt_descriptor *desc, char const *value);
38static int handle_peername_option(EventSelector *es, l2tp_opt_descriptor *desc, char const *value);
39static int set_lac_handler(EventSelector *es, l2tp_opt_descriptor *desc, char const *value);
40static int handle_lac_option(EventSelector *es, l2tp_opt_descriptor *desc, char const *value);
41static int set_lns_handler(EventSelector *es, l2tp_opt_descriptor *desc, char const *value);
42static int handle_lns_option(EventSelector *es, l2tp_opt_descriptor *desc, char const *value);
43
44/* Peer options */
45static l2tp_opt_descriptor peer_opts[] = {
46    /*  name               type                 addr */
47    { "peer",              OPT_TYPE_IPADDR,   &prototype.addr.sin_addr.s_addr},
48    { "mask",              OPT_TYPE_INT,      &prototype.mask_bits},
49    { "secret",            OPT_TYPE_CALLFUNC, (void *) handle_secret_option},
50    { "hostname",          OPT_TYPE_CALLFUNC, (void *) handle_hostname_option},
51    { "peername",          OPT_TYPE_CALLFUNC, (void *) handle_peername_option},
52    { "port",              OPT_TYPE_PORT,     &port },
53    { "lac-handler",       OPT_TYPE_CALLFUNC, (void *) set_lac_handler},
54    { "lac-opts",          OPT_TYPE_CALLFUNC, (void *) handle_lac_option},
55    { "lns-handler",       OPT_TYPE_CALLFUNC, (void *) set_lns_handler},
56    { "lns-opts",          OPT_TYPE_CALLFUNC, (void *) handle_lns_option},
57    { "hide-avps",         OPT_TYPE_BOOL,     &prototype.hide_avps},
58    { "retain-tunnel",     OPT_TYPE_BOOL,     &prototype.retain_tunnel},
59    { "persist",           OPT_TYPE_BOOL,     &prototype.persist},
60    { "holdoff",           OPT_TYPE_INT,      &prototype.holdoff},
61    { "maxfail",           OPT_TYPE_INT,      &prototype.maxfail},
62    { "strict-ip-check",   OPT_TYPE_BOOL,     &prototype.validate_peer_ip},
63#ifdef RTCONFIG_VPNC
64    { "vpnc",              OPT_TYPE_BOOL,     &vpnc},
65#endif
66    { NULL,                OPT_TYPE_BOOL,     NULL }
67};
68
69static int
70set_lac_handler(EventSelector *es,
71		l2tp_opt_descriptor *desc,
72		char const *value)
73{
74    l2tp_lac_handler *handler = l2tp_session_find_lac_handler(value);
75    if (!handler) {
76	l2tp_set_errmsg("No LAC handler named '%s'", value);
77	return -1;
78    }
79    prototype.lac_ops = handler->call_ops;
80    return 0;
81}
82
83static int
84set_lns_handler(EventSelector *es,
85		l2tp_opt_descriptor *desc,
86		char const *value)
87{
88    l2tp_lns_handler *handler = l2tp_session_find_lns_handler(value);
89    if (!handler) {
90	l2tp_set_errmsg("No LNS handler named '%s'", value);
91	return -1;
92    }
93    prototype.lns_ops = handler->call_ops;
94    return 0;
95}
96
97/**********************************************************************
98* %FUNCTION: handle_secret_option
99* %ARGUMENTS:
100*  es -- event selector
101*  desc -- descriptor
102*  value -- the secret
103* %RETURNS:
104*  0
105* %DESCRIPTION:
106*  Copies secret to prototype
107***********************************************************************/
108static int
109handle_secret_option(EventSelector *es,
110		     l2tp_opt_descriptor *desc,
111		     char const *value)
112{
113    strncpy(prototype.secret, value, MAX_SECRET_LEN);
114    prototype.secret[MAX_SECRET_LEN-1] = 0;
115    prototype.secret_len = strlen(prototype.secret);
116    return 0;
117}
118
119/**********************************************************************
120* %FUNCTION: handle_hostname_option
121* %ARGUMENTS:
122*  es -- event selector
123*  desc -- descriptor
124*  value -- the hostname
125* %RETURNS:
126*  0
127* %DESCRIPTION:
128*  Copies hostname to prototype
129***********************************************************************/
130static int
131handle_hostname_option(EventSelector *es,
132		     l2tp_opt_descriptor *desc,
133		     char const *value)
134{
135    strncpy(prototype.hostname, value, MAX_HOSTNAME);
136    prototype.hostname[MAX_HOSTNAME-1] = 0;
137    prototype.hostname_len = strlen(prototype.hostname);
138    return 0;
139}
140
141/**********************************************************************
142* %FUNCTION: handle_peername_option
143* %ARGUMENTS:
144*  es -- event selector
145*  desc -- descriptor
146*  value -- the hostname
147* %RETURNS:
148*  0
149* %DESCRIPTION:
150*  Copies peername to prototype
151***********************************************************************/
152static int
153handle_peername_option(EventSelector *es,
154		     l2tp_opt_descriptor *desc,
155		     char const *value)
156{
157    strncpy(prototype.peername, value, MAX_HOSTNAME);
158    prototype.peername[MAX_HOSTNAME-1] = 0;
159    prototype.peername_len = strlen(prototype.peername);
160    return 0;
161}
162
163/**********************************************************************
164* %FUNCTION: handle_lac_option
165* %ARGUMENTS:
166*  es -- event selector
167*  desc -- descriptor
168*  value -- the hostname
169* %RETURNS:
170*  0
171* %DESCRIPTION:
172*  Copies LAC options to prototype
173***********************************************************************/
174static int
175handle_lac_option(EventSelector *es,
176		     l2tp_opt_descriptor *desc,
177		     char const *value)
178{
179    char word[512];
180    while (value && *value) {
181        value = l2tp_chomp_word(value, word);
182        if (!word[0]) break;
183        if (prototype.num_lac_options < MAX_OPTS) {
184            char *x = strdup(word);
185            if (x) prototype.lac_options[prototype.num_lac_options++] = x;
186            prototype.lac_options[prototype.num_lac_options] = NULL;
187        } else {
188            break;
189        }
190    }
191    return 0;
192}
193
194/**********************************************************************
195* %FUNCTION: handle_lns_option
196* %ARGUMENTS:
197*  es -- event selector
198*  desc -- descriptor
199*  value -- the hostname
200* %RETURNS:
201*  0
202* %DESCRIPTION:
203*  Copies LNS options to prototype
204***********************************************************************/
205static int
206handle_lns_option(EventSelector *es,
207		     l2tp_opt_descriptor *desc,
208		     char const *value)
209{
210    char word[512];
211    while (value && *value) {
212        value = l2tp_chomp_word(value, word);
213        if (!word[0]) break;
214        if (prototype.num_lns_options < MAX_OPTS) {
215            char *x = strdup(word);
216            if (x) prototype.lns_options[prototype.num_lns_options++] = x;
217            prototype.lns_options[prototype.num_lns_options] = NULL;
218        } else {
219            break;
220        }
221    }
222    return 0;
223}
224
225/**********************************************************************
226* %FUNCTION: peer_process_option
227* %ARGUMENTS:
228*  es -- event selector
229*  name, value -- name and value of option
230* %RETURNS:
231*  0 on success, -1 on failure
232* %DESCRIPTION:
233*  Processes an option in the "peer" section
234***********************************************************************/
235static int
236peer_process_option(EventSelector *es,
237		    char const *name,
238		    char const *value)
239{
240    l2tp_peer *peer;
241
242    /* Special cases: begin and end */
243    if (!strcmp(name, "*begin*")) {
244	/* Switching in to peer context */
245	memset(&prototype, 0, sizeof(prototype));
246	prototype.mask_bits = 32;
247	prototype.validate_peer_ip = 1;
248	port = 1701;
249	return 0;
250    }
251
252    if (!strcmp(name, "*end*")) {
253	/* Validate settings */
254	uint16_t u16 = (uint16_t) port;
255	prototype.addr.sin_port = htons(u16);
256	prototype.addr.sin_family = AF_INET;
257
258	/* Allow non-authenticated tunnels
259	if (!prototype.secret_len) {
260	    l2tp_set_errmsg("No secret supplied for peer");
261	    return -1;
262	}
263	*/
264	if (!prototype.lns_ops && !prototype.lac_ops) {
265	    l2tp_set_errmsg("You must enable at least one of lns-handler or lac-handler");
266	    return -1;
267	}
268
269	/* Add the peer */
270	peer = l2tp_peer_insert(&prototype.addr);
271	if (!peer) return -1;
272
273	peer->mask_bits = prototype.mask_bits;
274	memcpy(&peer->hostname,&prototype.hostname, sizeof(prototype.hostname));
275	peer->hostname_len = prototype.hostname_len;
276	memcpy(&peer->peername,&prototype.peername, sizeof(prototype.peername));
277	peer->peername_len = prototype.peername_len;
278	memcpy(&peer->secret, &prototype.secret, MAX_SECRET_LEN);
279	peer->secret_len = prototype.secret_len;
280	peer->lns_ops = prototype.lns_ops;
281        memcpy(&peer->lns_options,&prototype.lns_options,sizeof(prototype.lns_options));
282	peer->lac_ops = prototype.lac_ops;
283        memcpy(&peer->lac_options,&prototype.lac_options,sizeof(prototype.lac_options));
284	peer->hide_avps = prototype.hide_avps;
285	peer->retain_tunnel = prototype.retain_tunnel;
286	peer->persist = prototype.persist;
287	peer->holdoff = prototype.holdoff;
288	peer->maxfail = prototype.maxfail;
289	peer->fail = 0;
290	peer->validate_peer_ip = prototype.validate_peer_ip;
291	return 0;
292    }
293
294    /* Process option */
295    return l2tp_option_set(es, name, value, peer_opts);
296}
297
298/**********************************************************************
299* %FUNCTION: peer_compute_hash
300* %ARGUMENTS:
301*  data -- a void pointer which is really a peer
302* %RETURNS:
303*  Inet address
304***********************************************************************/
305static unsigned int
306peer_compute_hash(void *data)
307{
308    unsigned int hash = (unsigned int) (((l2tp_peer *) data)->addr.sin_addr.s_addr);
309    return hash;
310}
311
312/**********************************************************************
313* %FUNCTION: peer_compare
314* %ARGUMENTS:
315*  item1 -- first peer
316*  item2 -- second peer
317* %RETURNS:
318*  0 if both peers have same ID, non-zero otherwise
319***********************************************************************/
320static int
321peer_compare(void *item1, void *item2)
322{
323    return ((l2tp_peer *) item1)->addr.sin_addr.s_addr !=
324	((l2tp_peer *) item2)->addr.sin_addr.s_addr;
325}
326
327/**********************************************************************
328* %FUNCTION: peer_init
329* %ARGUMENTS:
330*  None
331* %RETURNS:
332*  Nothing
333* %DESCRIPTION:
334*  Initializes peer hash table
335***********************************************************************/
336void
337l2tp_peer_init(void)
338{
339    hash_init(&all_peers,
340	      offsetof(l2tp_peer, hash),
341	      peer_compute_hash,
342	      peer_compare);
343    l2tp_option_register_section(&peer_option_handler);
344}
345
346/**********************************************************************
347* %FUNCTION: peer_find
348* %ARGUMENTS:
349*  addr -- IP address of peer
350*  hostname -- AVP peer hostname
351* %RETURNS:
352*  A pointer to the peer with given IP address, or NULL if not found.
353* %DESCRIPTION:
354*  Searches peer hash table for specified peer.
355***********************************************************************/
356l2tp_peer *
357l2tp_peer_find(struct sockaddr_in *addr, char const *peername)
358{
359    void *cursor;
360    l2tp_peer *peer = NULL;
361    l2tp_peer *candidate = NULL;
362    char addr1_str[16], addr2_str[16];
363
364    for (candidate = hash_start(&all_peers, &cursor);
365	 candidate ;
366	 candidate = hash_next(&all_peers, &cursor)) {
367
368	unsigned long mask = candidate->mask_bits ?
369	    htonl(0xFFFFFFFFUL << (32 - candidate->mask_bits)) : 0;
370
371	strcpy(addr1_str, inet_ntoa(addr->sin_addr));
372	strcpy(addr2_str, inet_ntoa(candidate->addr.sin_addr));
373	DBG(l2tp_db(DBG_TUNNEL, "l2tp_peer_find(%s) examining peer %s/%d\n",
374	       addr1_str, addr2_str,
375	       candidate->mask_bits));
376
377	if ((candidate->addr.sin_addr.s_addr & mask) ==
378	    (addr->sin_addr.s_addr & mask)
379	    && (!peername ||
380		!(candidate->peername[0]) ||
381		!strcmp(peername,candidate->peername))) {
382
383	    if (peer == NULL) {
384		peer = candidate;
385	    } else {
386		if (peer->mask_bits < candidate->mask_bits)
387		    peer = candidate;
388	    }
389	}
390    }
391
392    strcpy(addr1_str, inet_ntoa(addr->sin_addr));
393    if (peer != NULL)
394	strcpy(addr2_str, inet_ntoa(peer->addr.sin_addr));
395    DBG(l2tp_db(DBG_TUNNEL, "l2tp_peer_find(%s) found %s/%d\n",
396	   addr1_str,
397	   peer == NULL ? "NULL" : addr2_str,
398	   peer == NULL ? -1 : peer->mask_bits));
399
400    return peer;
401}
402
403/**********************************************************************
404* %FUNCTION: peer_insert
405* %ARGUMENTS:
406*  addr -- IP address of peer
407* %RETURNS:
408*  NULL if insert failed, pointer to new peer structure otherwise
409* %DESCRIPTION:
410*  Inserts a new peer in the all_peers table
411***********************************************************************/
412l2tp_peer *
413l2tp_peer_insert(struct sockaddr_in *addr)
414{
415    l2tp_peer *peer = malloc(sizeof(l2tp_peer));
416    if (!peer) {
417	l2tp_set_errmsg("peer_insert: Out of memory");
418	return NULL;
419    }
420    memset(peer, 0, sizeof(*peer));
421
422    peer->addr = *addr;
423    hash_insert(&all_peers, peer);
424    return peer;
425}
426