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