1/*********************************************************************** 2* 3* session.c 4* 5* Code for managing L2TP sessions 6* 7* Copyright (C) 2001 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: session.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#include <stdarg.h> 23#include <stdio.h> 24 25static uint16_t session_make_sid(l2tp_tunnel *tunnel); 26static void session_set_state(l2tp_session *session, int state); 27static void session_send_sli(l2tp_session *session); 28 29/* Registered LNS incoming-call handlers */ 30static l2tp_lns_handler *lns_handlers = NULL; 31 32/* Registered LAC handlers */ 33static l2tp_lac_handler *lac_handlers = NULL; 34 35static uint32_t call_serial_number = 0; 36 37static char *state_names[] = { 38 "idle", "wait-tunnel", "wait-reply", "wait-connect", "established" 39}; 40 41/********************************************************************** 42* %FUNCTION: session_compute_hash 43* %ARGUMENTS: 44* data -- a session 45* %RETURNS: 46* The session ID 47* %DESCRIPTION: 48* Returns a hash value for a session 49***********************************************************************/ 50static unsigned int 51session_compute_hash(void *data) 52{ 53 return (unsigned int) ((l2tp_session *) data)->my_id; 54} 55 56 57/********************************************************************** 58* %FUNCTION: session_compare 59* %ARGUMENTS: 60* d1, d2 -- two sessions 61* %RETURNS: 62* 0 if sids are equal, non-zero otherwise 63* %DESCRIPTION: 64* Compares two sessions 65***********************************************************************/ 66static int 67session_compare(void *d1, void *d2) 68{ 69 return ((l2tp_session *) d1)->my_id != ((l2tp_session *) d2)->my_id; 70} 71 72/********************************************************************** 73* %FUNCTION: session_hash_init 74* %ARGUMENTS: 75* tab -- hash table 76* %RETURNS: 77* Nothing 78* %DESCRIPTION: 79* Initializes hash table of sessions 80***********************************************************************/ 81void 82l2tp_session_hash_init(hash_table *tab) 83{ 84 hash_init(tab, offsetof(l2tp_session, hash_by_my_id), 85 session_compute_hash, session_compare); 86} 87 88/********************************************************************** 89* %FUNCTION: session_free 90* %ARGUMENTS: 91* ses -- a session to free 92* %RETURNS: 93* Nothing 94* %DESCRIPTION: 95* Frees a session, closing down all resources associated with it. 96***********************************************************************/ 97void 98l2tp_session_free(l2tp_session *ses, char const *reason, int may_reestablish) 99{ 100 session_set_state(ses, SESSION_IDLE); 101 DBG(l2tp_db(DBG_SESSION, "session_free(%s) %s\n", 102 l2tp_debug_session_to_str(ses), reason)); 103 if (ses->call_ops && ses->call_ops->close) { 104 ses->call_ops->close(ses, reason, may_reestablish); 105 } 106 memset(ses, 0, sizeof(l2tp_session)); 107 free(ses); 108} 109 110/********************************************************************** 111* %FUNCTION: session_call_lns 112* %ARGUMENTS: 113* peer -- L2TP peer 114* calling_number -- calling phone number (or MAC address or whatever...) 115* private -- private data to be stored in session structure 116* %RETURNS: 117* A newly-allocated session, or NULL if session could not be created 118* %DESCRIPTION: 119* Initiates session setup. Once call is active, established() will be 120* called. 121***********************************************************************/ 122l2tp_session * 123l2tp_session_call_lns(l2tp_peer *peer, 124 char const *calling_number, 125 EventSelector *es, 126 void *private) 127{ 128 l2tp_session *ses; 129 l2tp_tunnel *tunnel; 130 131 /* Find a tunnel to the peer */ 132 tunnel = l2tp_tunnel_find_for_peer(peer, es); 133 if (!tunnel) return NULL; 134 135 /* Do we have call ops? */ 136 if (!peer->lac_ops) { 137 l2tp_set_errmsg("Cannot act as LAC for peer"); 138 return NULL; 139 } 140 141 /* Allocate session */ 142 ses = malloc(sizeof(l2tp_session)); 143 if (!ses) { 144 l2tp_set_errmsg("session_call_lns: out of memory"); 145 return NULL; 146 } 147 148 /* Init fields */ 149 memset(ses, 0, sizeof(l2tp_session)); 150 ses->we_are_lac = 1; 151 ses->tunnel = tunnel; 152 ses->my_id = session_make_sid(tunnel); 153 ses->call_ops = peer->lac_ops; 154 ses->state = SESSION_WAIT_TUNNEL; 155 strncpy(ses->calling_number, calling_number, MAX_HOSTNAME); 156 ses->calling_number[MAX_HOSTNAME-1] = 0; 157 ses->private = private; 158 ses->snooping = 1; 159 ses->send_accm = 0xFFFFFFFF; 160 ses->recv_accm = 0xFFFFFFFF; 161 162 /* Add it to the tunnel */ 163 l2tp_tunnel_add_session(ses); 164 165 return ses; 166} 167 168/********************************************************************** 169* %FUNCTION: session_make_sid 170* %ARGUMENTS: 171* tunnel -- an L2TP tunnel 172* %RETURNS: 173* An unused random session ID 174***********************************************************************/ 175static uint16_t 176session_make_sid(l2tp_tunnel *tunnel) 177{ 178 uint16_t sid; 179 while(1) { 180 L2TP_RANDOM_FILL(sid); 181 if (!sid) continue; 182 if (!l2tp_tunnel_find_session(tunnel, sid)) return sid; 183 } 184} 185 186/********************************************************************** 187* %FUNCTION: session_notify_open 188* %ARGUMENTS: 189* ses -- an L2TP session 190* %RETURNS: 191* Nothing 192* %DESCRIPTION: 193* Called when tunnel has been established 194***********************************************************************/ 195void 196l2tp_session_notify_tunnel_open(l2tp_session *ses) 197{ 198 uint16_t u16; 199 uint32_t u32; 200 l2tp_dgram *dgram; 201 l2tp_tunnel *tunnel = ses->tunnel; 202 203 if (ses->state != SESSION_WAIT_TUNNEL) return; 204 205 /* Send ICRQ */ 206 DBG(l2tp_db(DBG_SESSION, "Session %s tunnel open\n", 207 l2tp_debug_session_to_str(ses))); 208 209 dgram = l2tp_dgram_new_control(MESSAGE_ICRQ, ses->tunnel->assigned_id, 210 0); 211 if (!dgram) { 212 l2tp_set_errmsg("Could not establish session - out of memory"); 213 l2tp_tunnel_delete_session(ses, "Out of memory", 0); 214 return; 215 } 216 217 /* assigned session ID */ 218 u16 = htons(ses->my_id); 219 l2tp_dgram_add_avp(dgram, tunnel, MANDATORY, 220 sizeof(u16), VENDOR_IETF, AVP_ASSIGNED_SESSION_ID, &u16); 221 222 /* Call serial number */ 223 u32 = htonl(call_serial_number); 224 call_serial_number++; 225 l2tp_dgram_add_avp(dgram, tunnel, MANDATORY, 226 sizeof(u32), VENDOR_IETF, AVP_CALL_SERIAL_NUMBER, &u32); 227 228 /* Ship it out */ 229 l2tp_tunnel_xmit_control_message(tunnel, dgram); 230 231 session_set_state(ses, SESSION_WAIT_REPLY); 232} 233 234/********************************************************************** 235* %FUNCTION: session_set_state 236* %ARGUMENTS: 237* session -- the session 238* state -- new state 239* %RETURNS: 240* Nothing 241***********************************************************************/ 242static void 243session_set_state(l2tp_session *session, int state) 244{ 245 if (state == session->state) return; 246 DBG(l2tp_db(DBG_SESSION, "session(%s) state %s -> %s\n", 247 l2tp_debug_session_to_str(session), 248 state_names[session->state], 249 state_names[state])); 250 session->state = state; 251} 252 253/********************************************************************** 254* %FUNCTION: session_register_lns_handler 255* %ARGUMENTS: 256* handler -- LNS handler 257* %RETURNS: 258* -1 on error, 0 if all is OK 259* %DESCRIPTION: 260* Registers an LNS handler for incoming call requests 261***********************************************************************/ 262int 263l2tp_session_register_lns_handler(l2tp_lns_handler *handler) 264{ 265 l2tp_lns_handler *prev = lns_handlers; 266 267 if (l2tp_session_find_lns_handler(handler->handler_name)) { 268 l2tp_set_errmsg("LNS Handler named %s already exists", 269 handler->handler_name); 270 return -1; 271 } 272 /* Add to end of handler list */ 273 handler->next = NULL; 274 if (!prev) { 275 lns_handlers = handler; 276 return 0; 277 } 278 while (prev->next) { 279 prev = prev->next; 280 } 281 prev->next = handler; 282 return 0; 283} 284 285/********************************************************************** 286* %FUNCTION: session_register_lac_handler 287* %ARGUMENTS: 288* handler -- LAC handler 289* %RETURNS: 290* -1 on error, 0 if all is OK 291* %DESCRIPTION: 292* Registers an LAC handler for incoming call requests 293***********************************************************************/ 294int 295l2tp_session_register_lac_handler(l2tp_lac_handler *handler) 296{ 297 l2tp_lac_handler *prev = lac_handlers; 298 299 if (l2tp_session_find_lac_handler(handler->handler_name)) { 300 l2tp_set_errmsg("LAC Handler named %s already exists", 301 handler->handler_name); 302 return -1; 303 } 304 /* Add to end of handler list */ 305 handler->next = NULL; 306 if (!prev) { 307 lac_handlers = handler; 308 return 0; 309 } 310 while (prev->next) { 311 prev = prev->next; 312 } 313 prev->next = handler; 314 return 0; 315} 316 317/********************************************************************** 318* %FUNCTION: session_send_CDN 319* %ARGUMENTS: 320* ses -- which session to terminate 321* result_code -- result code 322* error_code -- error code 323* fmt -- printf-style format string for error message 324* %RETURNS: 325* Nothing 326* %DESCRIPTION: 327* Sends CDN with specified result code and message. 328***********************************************************************/ 329void 330l2tp_session_send_CDN(l2tp_session *ses, 331 int result_code, 332 int error_code, 333 char const *fmt, ...) 334{ 335 char buf[256]; 336 va_list ap; 337 l2tp_tunnel *tunnel = ses->tunnel; 338 uint16_t len; 339 l2tp_dgram *dgram; 340 uint16_t u16; 341 342 /* Build the buffer for the result-code AVP */ 343 buf[0] = result_code / 256; 344 buf[1] = result_code & 255; 345 buf[2] = error_code / 256; 346 buf[3] = error_code & 255; 347 348 va_start(ap, fmt); 349 vsnprintf(buf+4, 256-4, fmt, ap); 350 buf[255] = 0; 351 va_end(ap); 352 353 DBG(l2tp_db(DBG_SESSION, "session_send_CDN(%s): %s\n", 354 l2tp_debug_session_to_str(ses), buf+4)); 355 356 len = 4 + strlen(buf+4); 357 /* Build the datagram */ 358 dgram = l2tp_dgram_new_control(MESSAGE_CDN, tunnel->assigned_id, 359 ses->assigned_id); 360 if (!dgram) return; 361 362 /* Add assigned session ID */ 363 u16 = htons(ses->my_id); 364 l2tp_dgram_add_avp(dgram, tunnel, MANDATORY, 365 sizeof(u16), VENDOR_IETF, AVP_ASSIGNED_SESSION_ID, &u16); 366 367 /* Add result code */ 368 l2tp_dgram_add_avp(dgram, tunnel, MANDATORY, 369 len, VENDOR_IETF, AVP_RESULT_CODE, buf); 370 371 /* TODO: Clean up */ 372 session_set_state(ses, SESSION_IDLE); 373 374 /* Ship it out */ 375 l2tp_tunnel_xmit_control_message(tunnel, dgram); 376 377 /* Free session */ 378 l2tp_tunnel_delete_session(ses, buf+4, 0); 379} 380 381/********************************************************************** 382* %FUNCTION: session_lns_handle_incoming_call 383* %ARGUMENTS: 384* tunnel -- tunnel on which ICRQ arrived 385* sid -- assigned session ID 386* dgram -- the ICRQ datagram 387* %RETURNS: 388* Nothing 389* %DESCRIPTION: 390* Handles ICRQ. If we find an LNS handler willing to take the call, 391* send ICRP. Otherwise, send CDN. 392***********************************************************************/ 393void 394l2tp_session_lns_handle_incoming_call(l2tp_tunnel *tunnel, 395 uint16_t sid, 396 l2tp_dgram *dgram, 397 char const *calling_number) 398{ 399 l2tp_call_ops *ops = tunnel->peer->lns_ops; 400 l2tp_session *ses; 401 uint16_t u16; 402 403 /* Allocate a session */ 404 ses = malloc(sizeof(l2tp_session)); 405 if (!ses) { 406 l2tp_set_errmsg("session_lns_handle_incoming_call: out of memory"); 407 return; 408 } 409 /* Init fields */ 410 memset(ses, 0, sizeof(l2tp_session)); 411 ses->we_are_lac = 0; 412 ses->tunnel = tunnel; 413 ses->my_id = session_make_sid(tunnel); 414 ses->assigned_id = sid; 415 ses->state = SESSION_IDLE; 416 strncpy(ses->calling_number, calling_number, MAX_HOSTNAME); 417 ses->calling_number[MAX_HOSTNAME-1] = 0; 418 ses->private = NULL; 419 ses->snooping = 1; 420 ses->send_accm = 0xFFFFFFFF; 421 ses->recv_accm = 0xFFFFFFFF; 422 423 l2tp_tunnel_add_session(ses); 424 425 if (!ops || !ops->establish) { 426 l2tp_session_send_CDN(ses, RESULT_GENERAL_ERROR, 427 ERROR_OUT_OF_RESOURCES, 428 "No LNS handler willing to accept call"); 429 return; 430 } 431 432 ses->call_ops = ops; 433 434 /* Send ICRP */ 435 dgram = l2tp_dgram_new_control(MESSAGE_ICRP, ses->tunnel->assigned_id, 436 ses->assigned_id); 437 if (!dgram) { 438 /* Ugh... not much chance of this working... */ 439 l2tp_session_send_CDN(ses, RESULT_GENERAL_ERROR, ERROR_OUT_OF_RESOURCES, 440 "Out of memory"); 441 return; 442 } 443 444 /* Add assigned session ID */ 445 u16 = htons(ses->my_id); 446 l2tp_dgram_add_avp(dgram, tunnel, MANDATORY, 447 sizeof(u16), VENDOR_IETF, AVP_ASSIGNED_SESSION_ID, &u16); 448 449 /* Set session state */ 450 session_set_state(ses, SESSION_WAIT_CONNECT); 451 452 /* Ship ICRP */ 453 l2tp_tunnel_xmit_control_message(tunnel, dgram); 454} 455 456/********************************************************************** 457* %FUNCTION: session_handle_CDN 458* %ARGUMENTS: 459* ses -- the session 460* dgram -- the datagram 461* %RETURNS: 462* Nothing 463* %DESCRIPTION: 464* Handles a CDN by destroying session 465***********************************************************************/ 466void 467l2tp_session_handle_CDN(l2tp_session *ses, 468 l2tp_dgram *dgram) 469{ 470 char buf[1024]; 471 unsigned char *val; 472 uint16_t len; 473 val = l2tp_dgram_search_avp(dgram, ses->tunnel, NULL, NULL, &len, 474 VENDOR_IETF, AVP_RESULT_CODE); 475 if (!val || len < 4) { 476 l2tp_tunnel_delete_session(ses, "Received CDN", 1); 477 } else { 478 uint16_t result_code, error_code; 479 char *msg; 480 result_code = ((uint16_t) val[0]) * 256 + (uint16_t) val[1]; 481 error_code = ((uint16_t) val[2]) * 256 + (uint16_t) val[3]; 482 if (len > 4) { 483 msg = (char *) &val[4]; 484 } else { 485 msg = ""; 486 } 487 snprintf(buf, sizeof(buf), "Received CDN: result-code = %d, error-code = %d, message = '%.*s'", result_code, error_code, (int) len-4, msg); 488 buf[1023] = 0; 489 l2tp_tunnel_delete_session(ses, buf, 1); 490 } 491} 492 493/********************************************************************** 494* %FUNCTION: session_handle_ICRP 495* %ARGUMENTS: 496* ses -- the session 497* dgram -- the datagram 498* %RETURNS: 499* Nothing 500* %DESCRIPTION: 501* Handles an ICRP 502***********************************************************************/ 503void 504l2tp_session_handle_ICRP(l2tp_session *ses, 505 l2tp_dgram *dgram) 506{ 507 uint16_t u16; 508 unsigned char *val; 509 uint16_t len; 510 uint32_t u32; 511 512 int mandatory, hidden; 513 l2tp_tunnel *tunnel = ses->tunnel; 514 515 /* Get assigned session ID */ 516 val = l2tp_dgram_search_avp(dgram, tunnel, &mandatory, &hidden, &len, 517 VENDOR_IETF, AVP_ASSIGNED_SESSION_ID); 518 if (!val) { 519 l2tp_set_errmsg("No assigned session-ID in ICRP"); 520 return; 521 } 522 if (!l2tp_dgram_validate_avp(VENDOR_IETF, AVP_ASSIGNED_SESSION_ID, 523 len, mandatory)) { 524 l2tp_set_errmsg("Invalid assigned session-ID in ICRP"); 525 return; 526 } 527 528 /* Set assigned session ID */ 529 u16 = ((uint16_t) val[0]) * 256 + (uint16_t) val[1]; 530 531 if (!u16) { 532 l2tp_set_errmsg("Invalid assigned session-ID in ICRP"); 533 return; 534 } 535 536 ses->assigned_id = u16; 537 538 /* If state is not WAIT_REPLY, fubar */ 539 if (ses->state != SESSION_WAIT_REPLY) { 540 l2tp_session_send_CDN(ses, RESULT_FSM_ERROR, 0, "Received ICRP for session in state %s", state_names[ses->state]); 541 return; 542 } 543 544 /* Tell PPP code that call has been established */ 545 if (ses->call_ops && ses->call_ops->establish) { 546 if (ses->call_ops->establish(ses) < 0) { 547 l2tp_session_send_CDN(ses, RESULT_GENERAL_ERROR, ERROR_VENDOR_SPECIFIC, 548 "%s", l2tp_get_errmsg()); 549 return; 550 } 551 } 552 553 /* Send ICCN */ 554 dgram = l2tp_dgram_new_control(MESSAGE_ICCN, tunnel->assigned_id, 555 ses->assigned_id); 556 if (!dgram) { 557 /* Ugh... not much chance of this working... */ 558 l2tp_session_send_CDN(ses, RESULT_GENERAL_ERROR, ERROR_OUT_OF_RESOURCES, 559 "Out of memory"); 560 return; 561 } 562 563 /* TODO: Speed, etc. are faked for now. */ 564 565 /* Connect speed */ 566 u32 = htonl(57600); 567 l2tp_dgram_add_avp(dgram, tunnel, MANDATORY, 568 sizeof(u32), VENDOR_IETF, AVP_TX_CONNECT_SPEED, &u32); 569 570 /* Framing Type */ 571 u32 = htonl(1); 572 l2tp_dgram_add_avp(dgram, tunnel, MANDATORY, 573 sizeof(u32), VENDOR_IETF, AVP_FRAMING_TYPE, &u32); 574 575 /* Ship it out */ 576 l2tp_tunnel_xmit_control_message(tunnel, dgram); 577 578 /* Set session state */ 579 session_set_state(ses, SESSION_ESTABLISHED); 580 ses->tunnel->peer->fail = 0; 581 582} 583 584/********************************************************************** 585* %FUNCTION: session_handle_ICCN 586* %ARGUMENTS: 587* ses -- the session 588* dgram -- the datagram 589* %RETURNS: 590* Nothing 591* %DESCRIPTION: 592* Handles an ICCN 593***********************************************************************/ 594void 595l2tp_session_handle_ICCN(l2tp_session *ses, 596 l2tp_dgram *dgram) 597{ 598 unsigned char *val; 599 int mandatory, hidden; 600 uint16_t len, vendor, type; 601 int err = 0; 602 603 l2tp_tunnel *tunnel = ses->tunnel; 604 605 /* If state is not WAIT_CONNECT, fubar */ 606 if (ses->state != SESSION_WAIT_CONNECT) { 607 l2tp_session_send_CDN(ses, RESULT_FSM_ERROR, 0, 608 "Received ICCN for session in state %s", 609 state_names[ses->state]); 610 return; 611 } 612 613 /* Set session state */ 614 session_set_state(ses, SESSION_ESTABLISHED); 615 ses->tunnel->peer->fail = 0; 616 617 /* Pull out and examine AVP's */ 618 while(1) { 619 val = l2tp_dgram_pull_avp(dgram, tunnel, &mandatory, &hidden, 620 &len, &vendor, &type, &err); 621 if (!val) { 622 if (err) { 623 l2tp_session_send_CDN(ses, RESULT_GENERAL_ERROR, 624 ERROR_BAD_VALUE, "%s", l2tp_get_errmsg()); 625 return; 626 } 627 break; 628 } 629 if (vendor != VENDOR_IETF) { 630 if (!mandatory) continue; 631 l2tp_session_send_CDN(ses, RESULT_GENERAL_ERROR, 632 ERROR_UNKNOWN_AVP_WITH_M_BIT, 633 "Unknown mandatory attribute (vendor=%d, type=%d) in %s", 634 (int) vendor, (int) type, 635 l2tp_debug_avp_type_to_str(dgram->msg_type)); 636 return; 637 } 638 switch(type) { 639 case AVP_SEQUENCING_REQUIRED: 640 ses->sequencing_required = 1; 641 break; 642 } 643 644 } 645 646 /* Start the call */ 647 if (ses->call_ops->establish(ses) < 0) { 648 l2tp_session_send_CDN(ses, RESULT_GENERAL_ERROR, 649 ERROR_OUT_OF_RESOURCES, 650 "No LNS handler willing to accept call"); 651 return; 652 } 653 654} 655 656/********************************************************************** 657* %FUNCTION: session_find_lns_handler 658* %ARGUMENTS: 659* name -- name of handler 660* %RETURNS: 661* Pointer to the handler if found, NULL if not 662* %DESCRIPTION: 663* Searches for an LNS handler by name 664***********************************************************************/ 665l2tp_lns_handler * 666l2tp_session_find_lns_handler(char const *name) 667{ 668 l2tp_lns_handler *cur = lns_handlers; 669 while(cur) { 670 if (!strcmp(name, cur->handler_name)) return cur; 671 cur = cur->next; 672 } 673 return NULL; 674} 675 676/********************************************************************** 677* %FUNCTION: session_find_lac_handler 678* %ARGUMENTS: 679* name -- name of handler 680* %RETURNS: 681* Pointer to the handler if found, NULL if not 682* %DESCRIPTION: 683* Searches for an LAC handler by name 684***********************************************************************/ 685l2tp_lac_handler * 686l2tp_session_find_lac_handler(char const *name) 687{ 688 l2tp_lac_handler *cur = lac_handlers; 689 while(cur) { 690 if (!strcmp(name, cur->handler_name)) return cur; 691 cur = cur->next; 692 } 693 return NULL; 694} 695 696/********************************************************************** 697* %FUNCTION: l2tp_session_state_name 698* %ARGUMENTS: 699* ses -- the session 700* %RETURNS: 701* The name of the session's state 702***********************************************************************/ 703char const * 704l2tp_session_state_name(l2tp_session *ses) 705{ 706 return state_names[ses->state]; 707} 708 709/********************************************************************** 710* %FUNCTION: l2tp_session_lcp_snoop 711* %ARGUMENTS: 712* ses -- L2TP session structure 713* buf -- PPP frame 714* len -- length of PPP frame 715* incoming -- if 1, frame is coming from L2TP tunnel. If 0, frame is 716* going to L2TP tunnel. 717* %RETURNS: 718* Nothing 719* %DESCRIPTION: 720* Snoops on LCP negotiation. Used to send SLI to LAC if we're an LNS. 721***********************************************************************/ 722void 723l2tp_session_lcp_snoop(l2tp_session *ses, 724 unsigned char const *buf, 725 int len, 726 int incoming) 727{ 728 unsigned int protocol; 729 int stated_len; 730 int opt, opt_len; 731 int reject; 732 unsigned char const *opt_data; 733 uint32_t accm; 734 735 /* If we are LAC, do not snoop */ 736 if (ses->we_are_lac) { 737 DBG(l2tp_db(DBG_SNOOP, "Turning off snooping: We are LAC.\n")); 738 ses->snooping = 0; 739 return; 740 } 741 742 /* Get protocol */ 743 if (buf[0] & 0x01) { 744 /* Compressed protcol field */ 745 protocol = buf[0]; 746 } else { 747 protocol = ((unsigned int) buf[0]) * 256 + buf[1]; 748 } 749 750 /* If it's a network protocol, stop snooping */ 751 if (protocol <= 0x3fff) { 752 DBG(l2tp_db(DBG_SNOOP, "Turning off snooping: Network protocol %04x found.\n", protocol)); 753 ses->snooping = 0; 754 return; 755 } 756 757 /* If it's not LCP, do not snoop */ 758 if (protocol != 0xc021) { 759 return; 760 } 761 762 /* Skip protocol; go to packet data */ 763 buf += 2; 764 len -= 2; 765 766 /* Unreasonably short frame?? */ 767 if (len <= 0) return; 768 769 /* Look for Configure-Ack or Configure-Reject code */ 770 if (buf[0] != 2 && buf[0] != 4) return; 771 772 reject = (buf[0] == 4); 773 774 stated_len = ((unsigned int) buf[2]) * 256 + buf[3]; 775 776 /* Something fishy with length field? */ 777 if (stated_len > len) return; 778 779 /* Skip to options */ 780 len = stated_len - 4; 781 buf += 4; 782 783 while (len > 0) { 784 /* Pull off an option */ 785 opt = buf[0]; 786 opt_len = buf[1]; 787 opt_data = &buf[2]; 788 if (opt_len > len || opt_len < 2) break; 789 len -= opt_len; 790 buf += opt_len; 791 DBG(l2tp_db(DBG_SNOOP, "Found option type %02x; len %d\n", 792 opt, opt_len)); 793 /* We are specifically interested in ACCM */ 794 if (opt == 0x02 && opt_len == 0x06) { 795 if (reject) { 796 /* ACCM negotiation REJECTED; use default */ 797 accm = 0xFFFFFFFF; 798 DBG(l2tp_db(DBG_SNOOP, "Rejected ACCM negotiation; defaulting (%s)\n", incoming ? "incoming" : "outgoing")); 799 /* ??? Is this right? */ 800 ses->recv_accm = accm; 801 ses->send_accm = accm; 802 ses->got_recv_accm = 1; 803 ses->got_send_accm = 1; 804 } else { 805 memcpy(&accm, opt_data, sizeof(accm)); 806 DBG(l2tp_db(DBG_SNOOP, "Found ACCM of %08x (%s)\n", accm, incoming ? "incoming" : "outgoing")); 807 if (incoming) { 808 ses->recv_accm = accm; 809 ses->got_recv_accm = 1; 810 } else { 811 ses->send_accm = accm; 812 ses->got_send_accm = 1; 813 } 814 } 815 816 if (ses->got_recv_accm && ses->got_send_accm) { 817 DBG(l2tp_db(DBG_SNOOP, "Sending SLI: Send ACCM = %08x; Receive ACCM = %08x\n", ses->send_accm, ses->recv_accm)); 818 session_send_sli(ses); 819 ses->got_recv_accm = 0; 820 ses->got_send_accm = 0; 821 } 822 } 823 } 824} 825/********************************************************************** 826* %FUNCTION: session_send_sli 827* %ARGUMENTS: 828* ses -- the session 829* %RETURNS: 830* Nothing 831* %DESCRIPTION: 832* Sends an SLI message with send/receive ACCM's. 833***********************************************************************/ 834void 835session_send_sli(l2tp_session *ses) 836{ 837 l2tp_dgram *dgram; 838 839 unsigned char buf[10]; 840 memset(buf, 0, 2); 841 memcpy(buf+2, &ses->send_accm, 4); 842 memcpy(buf+6, &ses->recv_accm, 4); 843 844 dgram = l2tp_dgram_new_control(MESSAGE_SLI, ses->tunnel->assigned_id, 845 ses->assigned_id); 846 if (!dgram) return; 847 848 /* Add ACCM */ 849 l2tp_dgram_add_avp(dgram, ses->tunnel, MANDATORY, 850 sizeof(buf), VENDOR_IETF, AVP_ACCM, buf); 851 852 /* Ship it out */ 853 l2tp_tunnel_xmit_control_message(ses->tunnel, dgram); 854 ses->sent_sli = 1; 855} 856