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