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