1 /***********************************************************************
5 * Code for managing L2TP sessions
7 * Copyright (C) 2001 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: session.c,v 1.1.48.1 2005/08/08 12:05:25 honor Exp $";
25 static uint16_t session_make_sid(l2tp_tunnel
*tunnel
);
26 static void session_set_state(l2tp_session
*session
, int state
);
27 static void session_send_sli(l2tp_session
*session
);
29 /* Registered LNS incoming-call handlers */
30 static l2tp_lns_handler
*lns_handlers
= NULL
;
32 /* Registered LAC handlers */
33 static l2tp_lac_handler
*lac_handlers
= NULL
;
35 static uint32_t call_serial_number
= 0;
37 static char *state_names
[] = {
38 "idle", "wait-tunnel", "wait-reply", "wait-connect", "established"
41 /**********************************************************************
42 * %FUNCTION: session_compute_hash
48 * Returns a hash value for a session
49 ***********************************************************************/
51 session_compute_hash(void *data
)
53 return (unsigned int) ((l2tp_session
*) data
)->my_id
;
57 /**********************************************************************
58 * %FUNCTION: session_compare
60 * d1, d2 -- two sessions
62 * 0 if sids are equal, non-zero otherwise
64 * Compares two sessions
65 ***********************************************************************/
67 session_compare(void *d1
, void *d2
)
69 return ((l2tp_session
*) d1
)->my_id
!= ((l2tp_session
*) d2
)->my_id
;
72 /**********************************************************************
73 * %FUNCTION: session_hash_init
79 * Initializes hash table of sessions
80 ***********************************************************************/
82 l2tp_session_hash_init(hash_table
*tab
)
84 hash_init(tab
, offsetof(l2tp_session
, hash_by_my_id
),
85 session_compute_hash
, session_compare
);
88 /**********************************************************************
89 * %FUNCTION: session_free
91 * ses -- a session to free
95 * Frees a session, closing down all resources associated with it.
96 ***********************************************************************/
98 l2tp_session_free(l2tp_session
*ses
, char const *reason
, int may_reestablish
)
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
);
106 memset(ses
, 0, sizeof(l2tp_session
));
110 /**********************************************************************
111 * %FUNCTION: session_call_lns
114 * calling_number -- calling phone number (or MAC address or whatever...)
115 * private -- private data to be stored in session structure
117 * A newly-allocated session, or NULL if session could not be created
119 * Initiates session setup. Once call is active, established() will be
121 ***********************************************************************/
123 l2tp_session_call_lns(l2tp_peer
*peer
,
124 char const *calling_number
,
131 /* Find a tunnel to the peer */
132 tunnel
= l2tp_tunnel_find_for_peer(peer
, es
);
133 if (!tunnel
) return NULL
;
135 /* Do we have call ops? */
136 if (!peer
->lac_ops
) {
137 l2tp_set_errmsg("Cannot act as LAC for peer");
141 /* Allocate session */
142 ses
= malloc(sizeof(l2tp_session
));
144 l2tp_set_errmsg("session_call_lns: out of memory");
149 memset(ses
, 0, sizeof(l2tp_session
));
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;
159 ses
->send_accm
= 0xFFFFFFFF;
160 ses
->recv_accm
= 0xFFFFFFFF;
162 /* Add it to the tunnel */
163 l2tp_tunnel_add_session(ses
);
168 /**********************************************************************
169 * %FUNCTION: session_make_sid
171 * tunnel -- an L2TP tunnel
173 * An unused random session ID
174 ***********************************************************************/
176 session_make_sid(l2tp_tunnel
*tunnel
)
180 L2TP_RANDOM_FILL(sid
);
182 if (!l2tp_tunnel_find_session(tunnel
, sid
)) return sid
;
186 /**********************************************************************
187 * %FUNCTION: session_notify_open
189 * ses -- an L2TP session
193 * Called when tunnel has been established
194 ***********************************************************************/
196 l2tp_session_notify_tunnel_open(l2tp_session
*ses
)
201 l2tp_tunnel
*tunnel
= ses
->tunnel
;
203 if (ses
->state
!= SESSION_WAIT_TUNNEL
) return;
206 DBG(l2tp_db(DBG_SESSION
, "Session %s tunnel open\n",
207 l2tp_debug_session_to_str(ses
)));
209 dgram
= l2tp_dgram_new_control(MESSAGE_ICRQ
, ses
->tunnel
->assigned_id
,
212 l2tp_set_errmsg("Could not establish session - out of memory");
213 l2tp_tunnel_delete_session(ses
, "Out of memory", 0);
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
);
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
);
229 l2tp_tunnel_xmit_control_message(tunnel
, dgram
);
231 session_set_state(ses
, SESSION_WAIT_REPLY
);
234 /**********************************************************************
235 * %FUNCTION: session_set_state
237 * session -- the session
241 ***********************************************************************/
243 session_set_state(l2tp_session
*session
, int state
)
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
;
253 /**********************************************************************
254 * %FUNCTION: session_register_lns_handler
256 * handler -- LNS handler
258 * -1 on error, 0 if all is OK
260 * Registers an LNS handler for incoming call requests
261 ***********************************************************************/
263 l2tp_session_register_lns_handler(l2tp_lns_handler
*handler
)
265 l2tp_lns_handler
*prev
= lns_handlers
;
267 if (l2tp_session_find_lns_handler(handler
->handler_name
)) {
268 l2tp_set_errmsg("LNS Handler named %s already exists",
269 handler
->handler_name
);
272 /* Add to end of handler list */
273 handler
->next
= NULL
;
275 lns_handlers
= handler
;
281 prev
->next
= handler
;
285 /**********************************************************************
286 * %FUNCTION: session_register_lac_handler
288 * handler -- LAC handler
290 * -1 on error, 0 if all is OK
292 * Registers an LAC handler for incoming call requests
293 ***********************************************************************/
295 l2tp_session_register_lac_handler(l2tp_lac_handler
*handler
)
297 l2tp_lac_handler
*prev
= lac_handlers
;
299 if (l2tp_session_find_lac_handler(handler
->handler_name
)) {
300 l2tp_set_errmsg("LAC Handler named %s already exists",
301 handler
->handler_name
);
304 /* Add to end of handler list */
305 handler
->next
= NULL
;
307 lac_handlers
= handler
;
313 prev
->next
= handler
;
317 /**********************************************************************
318 * %FUNCTION: session_send_CDN
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
327 * Sends CDN with specified result code and message.
328 ***********************************************************************/
330 l2tp_session_send_CDN(l2tp_session
*ses
,
333 char const *fmt
, ...)
337 l2tp_tunnel
*tunnel
= ses
->tunnel
;
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;
349 vsnprintf(buf
+4, 256-4, fmt
, ap
);
353 DBG(l2tp_db(DBG_SESSION
, "session_send_CDN(%s): %s\n",
354 l2tp_debug_session_to_str(ses
), buf
+4));
356 len
= 4 + strlen(buf
+4);
357 /* Build the datagram */
358 dgram
= l2tp_dgram_new_control(MESSAGE_CDN
, tunnel
->assigned_id
,
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
);
367 /* Add result code */
368 l2tp_dgram_add_avp(dgram
, tunnel
, MANDATORY
,
369 len
, VENDOR_IETF
, AVP_RESULT_CODE
, buf
);
372 session_set_state(ses
, SESSION_IDLE
);
375 l2tp_tunnel_xmit_control_message(tunnel
, dgram
);
378 l2tp_tunnel_delete_session(ses
, buf
+4, 0);
381 /**********************************************************************
382 * %FUNCTION: session_lns_handle_incoming_call
384 * tunnel -- tunnel on which ICRQ arrived
385 * sid -- assigned session ID
386 * dgram -- the ICRQ datagram
390 * Handles ICRQ. If we find an LNS handler willing to take the call,
391 * send ICRP. Otherwise, send CDN.
392 ***********************************************************************/
394 l2tp_session_lns_handle_incoming_call(l2tp_tunnel
*tunnel
,
397 char const *calling_number
)
399 l2tp_call_ops
*ops
= tunnel
->peer
->lns_ops
;
403 /* Allocate a session */
404 ses
= malloc(sizeof(l2tp_session
));
406 l2tp_set_errmsg("session_lns_handle_incoming_call: out of memory");
410 memset(ses
, 0, sizeof(l2tp_session
));
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;
420 ses
->send_accm
= 0xFFFFFFFF;
421 ses
->recv_accm
= 0xFFFFFFFF;
423 l2tp_tunnel_add_session(ses
);
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");
435 dgram
= l2tp_dgram_new_control(MESSAGE_ICRP
, ses
->tunnel
->assigned_id
,
438 /* Ugh... not much chance of this working... */
439 l2tp_session_send_CDN(ses
, RESULT_GENERAL_ERROR
, ERROR_OUT_OF_RESOURCES
,
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
);
449 /* Set session state */
450 session_set_state(ses
, SESSION_WAIT_CONNECT
);
453 l2tp_tunnel_xmit_control_message(tunnel
, dgram
);
456 /**********************************************************************
457 * %FUNCTION: session_handle_CDN
460 * dgram -- the datagram
464 * Handles a CDN by destroying session
465 ***********************************************************************/
467 l2tp_session_handle_CDN(l2tp_session
*ses
,
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);
478 uint16_t result_code
, error_code
;
480 result_code
= ((uint16_t) val
[0]) * 256 + (uint16_t) val
[1];
481 error_code
= ((uint16_t) val
[2]) * 256 + (uint16_t) val
[3];
483 msg
= (char *) &val
[4];
487 snprintf(buf
, sizeof(buf
), "Received CDN: result-code = %d, error-code = %d, message = '%.*s'", result_code
, error_code
, (int) len
-4, msg
);
489 l2tp_tunnel_delete_session(ses
, buf
, 1);
493 /**********************************************************************
494 * %FUNCTION: session_handle_ICRP
497 * dgram -- the datagram
502 ***********************************************************************/
504 l2tp_session_handle_ICRP(l2tp_session
*ses
,
512 int mandatory
, hidden
;
513 l2tp_tunnel
*tunnel
= ses
->tunnel
;
515 /* Get assigned session ID */
516 val
= l2tp_dgram_search_avp(dgram
, tunnel
, &mandatory
, &hidden
, &len
,
517 VENDOR_IETF
, AVP_ASSIGNED_SESSION_ID
);
519 l2tp_set_errmsg("No assigned session-ID in ICRP");
522 if (!l2tp_dgram_validate_avp(VENDOR_IETF
, AVP_ASSIGNED_SESSION_ID
,
524 l2tp_set_errmsg("Invalid assigned session-ID in ICRP");
528 /* Set assigned session ID */
529 u16
= ((uint16_t) val
[0]) * 256 + (uint16_t) val
[1];
532 l2tp_set_errmsg("Invalid assigned session-ID in ICRP");
536 ses
->assigned_id
= u16
;
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
]);
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());
554 dgram
= l2tp_dgram_new_control(MESSAGE_ICCN
, tunnel
->assigned_id
,
557 /* Ugh... not much chance of this working... */
558 l2tp_session_send_CDN(ses
, RESULT_GENERAL_ERROR
, ERROR_OUT_OF_RESOURCES
,
563 /* TODO: Speed, etc. are faked for now. */
567 l2tp_dgram_add_avp(dgram
, tunnel
, MANDATORY
,
568 sizeof(u32
), VENDOR_IETF
, AVP_TX_CONNECT_SPEED
, &u32
);
572 l2tp_dgram_add_avp(dgram
, tunnel
, MANDATORY
,
573 sizeof(u32
), VENDOR_IETF
, AVP_FRAMING_TYPE
, &u32
);
576 l2tp_tunnel_xmit_control_message(tunnel
, dgram
);
578 /* Set session state */
579 session_set_state(ses
, SESSION_ESTABLISHED
);
580 ses
->tunnel
->peer
->fail
= 0;
584 /**********************************************************************
585 * %FUNCTION: session_handle_ICCN
588 * dgram -- the datagram
593 ***********************************************************************/
595 l2tp_session_handle_ICCN(l2tp_session
*ses
,
599 int mandatory
, hidden
;
600 uint16_t len
, vendor
, type
;
603 l2tp_tunnel
*tunnel
= ses
->tunnel
;
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
]);
613 /* Set session state */
614 session_set_state(ses
, SESSION_ESTABLISHED
);
615 ses
->tunnel
->peer
->fail
= 0;
617 /* Pull out and examine AVP's */
619 val
= l2tp_dgram_pull_avp(dgram
, tunnel
, &mandatory
, &hidden
,
620 &len
, &vendor
, &type
, &err
);
623 l2tp_session_send_CDN(ses
, RESULT_GENERAL_ERROR
,
624 ERROR_BAD_VALUE
, "%s", l2tp_get_errmsg());
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
));
639 case AVP_SEQUENCING_REQUIRED
:
640 ses
->sequencing_required
= 1;
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");
656 /**********************************************************************
657 * %FUNCTION: session_find_lns_handler
659 * name -- name of handler
661 * Pointer to the handler if found, NULL if not
663 * Searches for an LNS handler by name
664 ***********************************************************************/
666 l2tp_session_find_lns_handler(char const *name
)
668 l2tp_lns_handler
*cur
= lns_handlers
;
670 if (!strcmp(name
, cur
->handler_name
)) return cur
;
676 /**********************************************************************
677 * %FUNCTION: session_find_lac_handler
679 * name -- name of handler
681 * Pointer to the handler if found, NULL if not
683 * Searches for an LAC handler by name
684 ***********************************************************************/
686 l2tp_session_find_lac_handler(char const *name
)
688 l2tp_lac_handler
*cur
= lac_handlers
;
690 if (!strcmp(name
, cur
->handler_name
)) return cur
;
696 /**********************************************************************
697 * %FUNCTION: l2tp_session_state_name
701 * The name of the session's state
702 ***********************************************************************/
704 l2tp_session_state_name(l2tp_session
*ses
)
706 return state_names
[ses
->state
];
709 /**********************************************************************
710 * %FUNCTION: l2tp_session_lcp_snoop
712 * ses -- L2TP session structure
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.
720 * Snoops on LCP negotiation. Used to send SLI to LAC if we're an LNS.
721 ***********************************************************************/
723 l2tp_session_lcp_snoop(l2tp_session
*ses
,
724 unsigned char const *buf
,
728 unsigned int protocol
;
732 unsigned char const *opt_data
;
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"));
744 /* Compressed protcol field */
747 protocol
= ((unsigned int) buf
[0]) * 256 + buf
[1];
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
));
757 /* If it's not LCP, do not snoop */
758 if (protocol
!= 0xc021) {
762 /* Skip protocol; go to packet data */
766 /* Unreasonably short frame?? */
767 if (len
<= 0) return;
769 /* Look for Configure-Ack or Configure-Reject code */
770 if (buf
[0] != 2 && buf
[0] != 4) return;
772 reject
= (buf
[0] == 4);
774 stated_len
= ((unsigned int) buf
[2]) * 256 + buf
[3];
776 /* Something fishy with length field? */
777 if (stated_len
> len
) return;
779 /* Skip to options */
780 len
= stated_len
- 4;
784 /* Pull off an option */
788 if (opt_len
> len
|| opt_len
< 2) break;
791 DBG(l2tp_db(DBG_SNOOP
, "Found option type %02x; len %d\n",
793 /* We are specifically interested in ACCM */
794 if (opt
== 0x02 && opt_len
== 0x06) {
796 /* ACCM negotiation REJECTED; use default */
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;
805 memcpy(&accm
, opt_data
, sizeof(accm
));
806 DBG(l2tp_db(DBG_SNOOP
, "Found ACCM of %08x (%s)\n", accm
, incoming
? "incoming" : "outgoing"));
808 ses
->recv_accm
= accm
;
809 ses
->got_recv_accm
= 1;
811 ses
->send_accm
= accm
;
812 ses
->got_send_accm
= 1;
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;
825 /**********************************************************************
826 * %FUNCTION: session_send_sli
832 * Sends an SLI message with send/receive ACCM's.
833 ***********************************************************************/
835 session_send_sli(l2tp_session
*ses
)
839 unsigned char buf
[10];
841 memcpy(buf
+2, &ses
->send_accm
, 4);
842 memcpy(buf
+6, &ses
->recv_accm
, 4);
844 dgram
= l2tp_dgram_new_control(MESSAGE_SLI
, ses
->tunnel
->assigned_id
,
849 l2tp_dgram_add_avp(dgram
, ses
->tunnel
, MANDATORY
,
850 sizeof(buf
), VENDOR_IETF
, AVP_ACCM
, buf
);
853 l2tp_tunnel_xmit_control_message(ses
->tunnel
, dgram
);