1 /***********************************************************************
5 * Manage lists of peers for L2TP
7 * Copyright (C) 2002 by Roaring Penguin Software Inc.
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.
14 ***********************************************************************/
16 static char const RCSID
[] =
17 "$Id: peer.c,v 1.1.48.1 2005/08/08 12:05:25 honor Exp $";
23 static hash_table all_peers
;
24 static int peer_process_option(EventSelector
*es
,
28 static l2tp_peer prototype
;
30 static option_handler peer_option_handler
= {
31 NULL
, "peer", peer_process_option
36 static int handle_secret_option(EventSelector
*es
, l2tp_opt_descriptor
*desc
, char const *value
);
37 static int handle_hostname_option(EventSelector
*es
, l2tp_opt_descriptor
*desc
, char const *value
);
38 static int handle_peername_option(EventSelector
*es
, l2tp_opt_descriptor
*desc
, char const *value
);
39 static int set_lac_handler(EventSelector
*es
, l2tp_opt_descriptor
*desc
, char const *value
);
40 static int handle_lac_option(EventSelector
*es
, l2tp_opt_descriptor
*desc
, char const *value
);
41 static int set_lns_handler(EventSelector
*es
, l2tp_opt_descriptor
*desc
, char const *value
);
42 static int handle_lns_option(EventSelector
*es
, l2tp_opt_descriptor
*desc
, char const *value
);
45 static l2tp_opt_descriptor peer_opts
[] = {
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
}
67 set_lac_handler(EventSelector
*es
,
68 l2tp_opt_descriptor
*desc
,
71 l2tp_lac_handler
*handler
= l2tp_session_find_lac_handler(value
);
73 l2tp_set_errmsg("No LAC handler named '%s'", value
);
76 prototype
.lac_ops
= handler
->call_ops
;
81 set_lns_handler(EventSelector
*es
,
82 l2tp_opt_descriptor
*desc
,
85 l2tp_lns_handler
*handler
= l2tp_session_find_lns_handler(value
);
87 l2tp_set_errmsg("No LNS handler named '%s'", value
);
90 prototype
.lns_ops
= handler
->call_ops
;
94 /**********************************************************************
95 * %FUNCTION: handle_secret_option
97 * es -- event selector
103 * Copies secret to prototype
104 ***********************************************************************/
106 handle_secret_option(EventSelector
*es
,
107 l2tp_opt_descriptor
*desc
,
110 strncpy(prototype
.secret
, value
, MAX_SECRET_LEN
);
111 prototype
.secret
[MAX_SECRET_LEN
-1] = 0;
112 prototype
.secret_len
= strlen(prototype
.secret
);
116 /**********************************************************************
117 * %FUNCTION: handle_hostname_option
119 * es -- event selector
121 * value -- the hostname
125 * Copies hostname to prototype
126 ***********************************************************************/
128 handle_hostname_option(EventSelector
*es
,
129 l2tp_opt_descriptor
*desc
,
132 strncpy(prototype
.hostname
, value
, MAX_HOSTNAME
);
133 prototype
.hostname
[MAX_HOSTNAME
-1] = 0;
134 prototype
.hostname_len
= strlen(prototype
.hostname
);
138 /**********************************************************************
139 * %FUNCTION: handle_peername_option
141 * es -- event selector
143 * value -- the hostname
147 * Copies peername to prototype
148 ***********************************************************************/
150 handle_peername_option(EventSelector
*es
,
151 l2tp_opt_descriptor
*desc
,
154 strncpy(prototype
.peername
, value
, MAX_HOSTNAME
);
155 prototype
.peername
[MAX_HOSTNAME
-1] = 0;
156 prototype
.peername_len
= strlen(prototype
.peername
);
160 /**********************************************************************
161 * %FUNCTION: handle_lac_option
163 * es -- event selector
165 * value -- the hostname
169 * Copies LAC options to prototype
170 ***********************************************************************/
172 handle_lac_option(EventSelector
*es
,
173 l2tp_opt_descriptor
*desc
,
177 while (value
&& *value
) {
178 value
= l2tp_chomp_word(value
, word
);
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
;
191 /**********************************************************************
192 * %FUNCTION: handle_lns_option
194 * es -- event selector
196 * value -- the hostname
200 * Copies LNS options to prototype
201 ***********************************************************************/
203 handle_lns_option(EventSelector
*es
,
204 l2tp_opt_descriptor
*desc
,
208 while (value
&& *value
) {
209 value
= l2tp_chomp_word(value
, word
);
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
;
222 /**********************************************************************
223 * %FUNCTION: peer_process_option
225 * es -- event selector
226 * name, value -- name and value of option
228 * 0 on success, -1 on failure
230 * Processes an option in the "peer" section
231 ***********************************************************************/
233 peer_process_option(EventSelector
*es
,
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;
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
;
255 /* Allow non-authenticated tunnels
256 if (!prototype.secret_len) {
257 l2tp_set_errmsg("No secret supplied for peer");
261 if (!prototype
.lns_ops
&& !prototype
.lac_ops
) {
262 l2tp_set_errmsg("You must enable at least one of lns-handler or lac-handler");
267 peer
= l2tp_peer_insert(&prototype
.addr
);
268 if (!peer
) return -1;
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
;
287 peer
->validate_peer_ip
= prototype
.validate_peer_ip
;
292 return l2tp_option_set(es
, name
, value
, peer_opts
);
295 /**********************************************************************
296 * %FUNCTION: peer_compute_hash
298 * data -- a void pointer which is really a peer
301 ***********************************************************************/
303 peer_compute_hash(void *data
)
305 unsigned int hash
= (unsigned int) (((l2tp_peer
*) data
)->addr
.sin_addr
.s_addr
);
309 /**********************************************************************
310 * %FUNCTION: peer_compare
312 * item1 -- first peer
313 * item2 -- second peer
315 * 0 if both peers have same ID, non-zero otherwise
316 ***********************************************************************/
318 peer_compare(void *item1
, void *item2
)
320 return ((l2tp_peer
*) item1
)->addr
.sin_addr
.s_addr
!=
321 ((l2tp_peer
*) item2
)->addr
.sin_addr
.s_addr
;
324 /**********************************************************************
325 * %FUNCTION: peer_init
331 * Initializes peer hash table
332 ***********************************************************************/
336 hash_init(&all_peers
,
337 offsetof(l2tp_peer
, hash
),
340 l2tp_option_register_section(&peer_option_handler
);
343 /**********************************************************************
344 * %FUNCTION: peer_find
346 * addr -- IP address of peer
347 * hostname -- AVP peer hostname
349 * A pointer to the peer with given IP address, or NULL if not found.
351 * Searches peer hash table for specified peer.
352 ***********************************************************************/
354 l2tp_peer_find(struct sockaddr_in
*addr
, char const *peername
)
357 l2tp_peer
*peer
= NULL
;
358 l2tp_peer
*candidate
= NULL
;
359 char addr1_str
[16], addr2_str
[16];
361 for (candidate
= hash_start(&all_peers
, &cursor
);
363 candidate
= hash_next(&all_peers
, &cursor
)) {
365 unsigned long mask
= candidate
->mask_bits
?
366 htonl(0xFFFFFFFFUL
<< (32 - candidate
->mask_bits
)) : 0;
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
));
374 if ((candidate
->addr
.sin_addr
.s_addr
& mask
) ==
375 (addr
->sin_addr
.s_addr
& mask
)
377 !(candidate
->peername
[0]) ||
378 !strcmp(peername
,candidate
->peername
))) {
383 if (peer
->mask_bits
< candidate
->mask_bits
)
389 strcpy(addr1_str
, inet_ntoa(addr
->sin_addr
));
391 strcpy(addr2_str
, inet_ntoa(peer
->addr
.sin_addr
));
392 DBG(l2tp_db(DBG_TUNNEL
, "l2tp_peer_find(%s) found %s/%d\n",
394 peer
== NULL
? "NULL" : addr2_str
,
395 peer
== NULL
? -1 : peer
->mask_bits
));
400 /**********************************************************************
401 * %FUNCTION: peer_insert
403 * addr -- IP address of peer
405 * NULL if insert failed, pointer to new peer structure otherwise
407 * Inserts a new peer in the all_peers table
408 ***********************************************************************/
410 l2tp_peer_insert(struct sockaddr_in
*addr
)
412 l2tp_peer
*peer
= malloc(sizeof(l2tp_peer
));
414 l2tp_set_errmsg("peer_insert: Out of memory");
417 memset(peer
, 0, sizeof(*peer
));
420 hash_insert(&all_peers
, peer
);