Annotation of embedaddon/mpd/src/l2tp_ctrl.c, revision 1.1.1.3.2.1
1.1 misho 1:
2: /*
3: * Copyright (c) 2001-2002 Packet Design, LLC.
4: * All rights reserved.
5: *
6: * Subject to the following obligations and disclaimer of warranty,
7: * use and redistribution of this software, in source or object code
8: * forms, with or without modifications are expressly permitted by
9: * Packet Design; provided, however, that:
10: *
11: * (i) Any and all reproductions of the source or object code
12: * must include the copyright notice above and the following
13: * disclaimer of warranties; and
14: * (ii) No rights are granted, in any manner or form, to use
15: * Packet Design trademarks, including the mark "PACKET DESIGN"
16: * on advertising, endorsements, or otherwise except as such
17: * appears in the above copyright notice or in the software.
18: *
19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
36: * THE POSSIBILITY OF SUCH DAMAGE.
37: *
38: * Author: Archie Cobbs <archie@freebsd.org>
39: */
40:
41: #include "ppp.h"
42: #include <netgraph.h>
43: #include <netgraph/ng_message.h>
44: #include <netgraph/ng_socket.h>
45: #include <netgraph/ng_l2tp.h>
46: #include <netgraph/ng_tee.h>
47: #include <openssl/md5.h>
48: #include "l2tp_avp.h"
49: #include "l2tp_ctrl.h"
50: #include "ngfunc.h"
51:
52: #ifndef __FreeBSD__
53: #define __printflike(x,y)
54: #endif
55:
56: #define CTRL_MEM_TYPE "ppp_l2tp_ctrl"
57: #define SESS_MEM_TYPE "ppp_l2tp_sess"
58:
59: /* Retransmit timeout parameters */
60: #define L2TP_REXMIT_MAX 8
61: #define L2TP_REXMIT_MAX_TO 10
62:
63: #define L2TP_CHALLENGE_LEN 16
64:
65: #define L2TP_CONNECT_SPEED 10000000 /* XXX hardcoded */
66: #define L2TP_FRAMING_TYPE L2TP_FRAMING_SYNC /* XXX hardcoded */
67:
68: /* Idle timeout for sending 'HELLO' message */
69: #define L2TP_IDLE_TIMEOUT 60
70:
71: /* Reply timeout for messages */
72: #define L2TP_REPLY_TIMEOUT 60
73:
74: /* Linger time for dying tunnels and sessions */
75: #define L2TP_CTRL_DEATH_TIMEOUT 11
76: #define L2TP_SESS_DEATH_TIMEOUT 11
77:
78: #define LOG_ERR LG_ERR
79: #define LOG_WARNING LG_PHYS2
80: #define LOG_NOTICE LG_PHYS2
81: #define LOG_INFO LG_PHYS3
82: #define LOG_DEBUG LG_PHYS3
83:
84: /* Control message types */
85: enum l2tp_msg_type {
86: SCCRQ =1,
87: SCCRP =2,
88: SCCCN =3,
89: StopCCN =4,
90: HELLO =6,
91: OCRQ =7,
92: OCRP =8,
93: OCCN =9,
94: ICRQ =10,
95: ICRP =11,
96: ICCN =12,
97: CDN =14,
98: WEN =15,
99: SLI =16
100: };
101:
102: /* Control connection states */
103: enum l2tp_ctrl_state {
104: CS_IDLE = 0,
105: CS_WAIT_CTL_REPLY,
106: CS_WAIT_CTL_CONNECT,
107: CS_ESTABLISHED,
108: CS_DYING
109: };
110:
111: /* Session states */
112: enum l2tp_sess_state {
113: SS_WAIT_REPLY = 1,
114: SS_WAIT_CONNECT,
115: SS_WAIT_ANSWER,
116: SS_ESTABLISHED,
117: SS_DYING
118: };
119:
120: /* Session origination */
121: enum l2tp_sess_orig {
122: ORIG_LOCAL =0,
123: ORIG_REMOTE =1
124: };
125:
126: /* Session side */
127: enum l2tp_sess_side {
128: SIDE_LNS =0,
129: SIDE_LAC =1
130: };
131:
132: /*
133: * Control message handler function types.
134: *
135: * Messages are either session-specific, or apply to the entire tunnel.
136: */
137: typedef int l2tp_ctrl_msg_handler_t(struct ppp_l2tp_ctrl *ctrl,
138: const struct ppp_l2tp_avp_list *avps,
139: struct ppp_l2tp_avp_ptrs *ptrs);
140: typedef int l2tp_sess_msg_handler_t(struct ppp_l2tp_sess *sess,
141: const struct ppp_l2tp_avp_list *avps,
142: struct ppp_l2tp_avp_ptrs *ptrs);
143:
144: /* Descriptor for one control message */
145: struct l2tp_msg_info {
146: const char *name;
147: enum l2tp_msg_type type;
148: l2tp_ctrl_msg_handler_t *ctrl_handler;
149: l2tp_sess_msg_handler_t *sess_handler;
150: int valid_states[12];
151: int valid_orig[3];
152: int valid_side[3];
153: int req_avps[AVP_MAX + 1];
154: };
155:
156: /* Control connection */
157: struct ppp_l2tp_ctrl {
158: enum l2tp_ctrl_state state; /* control state */
159: const struct ppp_l2tp_ctrl_cb *cb; /* link callbacks */
160: struct pevent_ctx *ctx; /* event context */
161: pthread_mutex_t *mutex; /* mutex */
162: ng_ID_t node_id; /* l2tp node id */
163: u_int32_t peer_id; /* peer unique id */
164: char path[32]; /* l2tp node path */
165: int csock; /* netgraph ctrl sock */
166: int dsock; /* netgraph data sock */
167: u_char *secret; /* shared secret */
168: u_int seclen; /* share secret len */
169: u_char chal[L2TP_CHALLENGE_LEN]; /* our L2TP challenge */
170: struct ng_l2tp_config config; /* netgraph node cfg. */
171: struct ghash *sessions; /* sessions */
172: struct ppp_l2tp_avp_list *avps; /* avps for SCCR[QP] */
173: struct pevent *idle_timer; /* ctrl idle timer */
174: struct pevent *reply_timer; /* reply timer */
175: struct pevent *close_timer; /* close timer */
176: struct pevent *death_timer; /* death timer */
177: struct pevent *ctrl_event; /* ctrl socket event */
178: struct pevent *data_event; /* data socket event */
179: void *link_cookie; /* opaque link cookie */
180: u_int16_t result; /* close result code */
181: u_int16_t error; /* close error code */
182: u_int32_t peer_bearer; /* peer bearer types */
183: u_int32_t peer_framing; /* peer framing types */
184: u_int active_sessions; /* # of sessns */
185: char *errmsg; /* close error msg */
186: u_char link_notified; /* link notified down */
187: u_char peer_notified; /* peer notified down */
188: u_char hide_avps; /* enable AVPs hiding */
189: char self_name[MAXHOSTNAMELEN]; /* L2TP local hostname */
190: char peer_name[MAXHOSTNAMELEN]; /* L2TP remote hostname */
191: };
192:
193: /* Session */
194: struct ppp_l2tp_sess {
195: struct ppp_l2tp_ctrl *ctrl; /* associated ctrl */
196: enum l2tp_sess_state state; /* session state */
197: enum l2tp_sess_orig orig; /* who originated it? */
198: enum l2tp_sess_side side; /* are we lac or lns? */
199: u_int32_t serial; /* call serial number */
200: struct ng_l2tp_sess_config config; /* netgraph hook cfg. */
201: struct ppp_l2tp_avp_list *my_avps; /* avps in [IO]CR[QP] */
202: struct ppp_l2tp_avp_list *peer_avps; /* avps in [IO]CCN */
203: u_int16_t session_id; /* session id */
204: u_int16_t peer_id; /* peer session id */
205: ng_ID_t node_id; /* tee node id */
206: char hook[NG_HOOKSIZ]; /* session hook name */
207: void *link_cookie; /* opaque link cookie */
208: u_int16_t result; /* close result code */
209: u_int16_t error; /* close error code */
210: char *errmsg; /* close error msg */
211: struct pevent *reply_timer; /* reply timer */
212: struct pevent *notify_timer; /* link notify timer */
213: struct pevent *close_timer; /* close timer */
214: struct pevent *death_timer; /* death timer */
215: u_char link_responded; /* link notified up */
216: u_char peer_responded; /* got icrp from lns */
217: u_char dseq_required; /* data seq. req'd */
218: u_char link_notified; /* link notified down */
219: u_char peer_notified; /* peer notified down */
220: u_char include_length; /* enable Length field in data packets */
221: u_char enable_dseq; /* enable sequence fields in data packets */
222: };
223:
224: /***
225:
226: Notes
227:
228: - "link_notified" means the link side has been notified that
229: the control connection or session has gone down.
230: - "peer_notified" means the peer has been notified that
231: the control connection or session has gone down.
232: - "link_responded" and "peer_responded" are only used for
233: outgoing calls when we are the LAC; they indicate acceptance
234: from the link side and the remote peer, respectively. Both
235: must be true before we send the OCCN.
236: - "sess->my_avps" are the AVP's included my ICRQ or OCRQ. In case
237: of ICRQ, these get overwritten by AVP's included in ICCN.
238: - "sess->peer_avps" are the AVPS included peer's ICCN or OCCN
239:
240: ***/
241:
242: /************************************************************************
243: INTERNAL FUNCTIONS
244: ************************************************************************/
245:
246: static int ppp_l2tp_ctrl_setup_1(struct ppp_l2tp_ctrl *ctrl,
1.1.1.3.2.1! misho 247: struct ppp_l2tp_avp_ptrs *ptrs,
! 248: struct ppp_l2tp_avp_list *avps);
1.1 misho 249: static int ppp_l2tp_ctrl_setup_2(struct ppp_l2tp_ctrl *ctrl,
250: struct ppp_l2tp_avp_ptrs *ptrs);
251: static void ppp_l2tp_ctrl_send(struct ppp_l2tp_ctrl *ctrl,
252: u_int16_t session_id, enum l2tp_msg_type msgtype,
253: const struct ppp_l2tp_avp_list *avps0);
254: static void ppp_l2tp_ctrl_check_reply(struct ppp_l2tp_ctrl *ctrl);
255: static void ppp_l2tp_ctrl_close(struct ppp_l2tp_ctrl *ctrl,
256: u_int16_t result, u_int16_t error, const char *errmsg);
257: static void ppp_l2tp_ctrl_death_start(struct ppp_l2tp_ctrl *ctrl);
258:
259: static struct ppp_l2tp_sess *ppp_l2tp_sess_create(struct ppp_l2tp_ctrl *ctrl,
260: enum l2tp_sess_orig orig, enum l2tp_sess_side side,
261: u_int32_t serial);
262: static void ppp_l2tp_sess_destroy(struct ppp_l2tp_sess **sessp);
263: static void ppp_l2tp_sess_close(struct ppp_l2tp_sess *sess,
264: u_int16_t result, u_int16_t error, const char *errmsg);
265: static int ppp_l2tp_sess_setup(struct ppp_l2tp_sess *sess);
266: static int ppp_l2tp_sess_check_liic(struct ppp_l2tp_sess *sess);
267: static void ppp_l2tp_sess_check_reply(struct ppp_l2tp_sess *sess);
268:
269: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_SCCRQ;
270: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_SCCRP;
271: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_SCCCN;
272: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_StopCCN;
273: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_HELLO;
274: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_OCRQ;
275: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_ICRQ;
276:
277: static l2tp_sess_msg_handler_t ppp_l2tp_handle_OCRP;
278: static l2tp_sess_msg_handler_t ppp_l2tp_handle_xCCN;
279: static l2tp_sess_msg_handler_t ppp_l2tp_handle_ICRP;
280: static l2tp_sess_msg_handler_t ppp_l2tp_handle_CDN;
281: static l2tp_sess_msg_handler_t ppp_l2tp_handle_WEN;
282: static l2tp_sess_msg_handler_t ppp_l2tp_handle_SLI;
283:
284: static pevent_handler_t ppp_l2tp_ctrl_event;
285: static pevent_handler_t ppp_l2tp_data_event;
286:
287: static pevent_handler_t ppp_l2tp_idle_timeout;
288: static pevent_handler_t ppp_l2tp_unused_timeout;
289: static pevent_handler_t ppp_l2tp_ctrl_do_close;
290: static pevent_handler_t ppp_l2tp_ctrl_death_timeout;
291:
292: static pevent_handler_t ppp_l2tp_sess_notify;
293: static pevent_handler_t ppp_l2tp_sess_do_close;
294: static pevent_handler_t ppp_l2tp_sess_death_timeout;
295:
296: static void ppp_l2tp_ctrl_dump(struct ppp_l2tp_ctrl *ctrl,
297: struct ppp_l2tp_avp_list *list, const char *fmt, ...)
298: __printflike(3, 4);
299: static const char *ppp_l2tp_ctrl_state_str(enum l2tp_ctrl_state state);
1.1.1.2 misho 300: static const char *ppp_l2tp_sess_state_str(enum l2tp_sess_state state);
1.1 misho 301: static const char *ppp_l2tp_sess_orig_str(enum l2tp_sess_orig orig);
302: static const char *ppp_l2tp_sess_side_str(enum l2tp_sess_side side);
303:
304: static ghash_hash_t ppp_l2tp_ctrl_hash;
305: static ghash_equal_t ppp_l2tp_ctrl_equal;
306:
307: static ghash_hash_t ppp_l2tp_sess_hash;
308: static ghash_equal_t ppp_l2tp_sess_equal;
309:
310: /************************************************************************
311: INTERNAL VARIABLES
312: ************************************************************************/
313:
314: /* Descriptors for each L2TP message type */
315: static const struct l2tp_msg_info ppp_l2tp_msg_info[] = {
316:
317: /* Control connection messages */
318: { "SCCRQ", SCCRQ, ppp_l2tp_handle_SCCRQ, NULL,
319: { CS_IDLE, -1 },
320: { -1 }, { -1 },
321: { AVP_PROTOCOL_VERSION, AVP_HOST_NAME,
322: AVP_FRAMING_CAPABILITIES, AVP_ASSIGNED_TUNNEL_ID, -1 } },
323: { "SCCRP", SCCRP, ppp_l2tp_handle_SCCRP, NULL,
324: { CS_WAIT_CTL_REPLY, -1 },
325: { -1 }, { -1 },
326: { AVP_PROTOCOL_VERSION, AVP_HOST_NAME,
327: AVP_FRAMING_CAPABILITIES, AVP_ASSIGNED_TUNNEL_ID, -1 } },
328: { "SCCCN", SCCCN, ppp_l2tp_handle_SCCCN, NULL,
329: { CS_WAIT_CTL_CONNECT, -1 },
330: { -1 }, { -1 },
331: { -1 } },
332: { "StopCCN", StopCCN, ppp_l2tp_handle_StopCCN, NULL,
333: { CS_IDLE, CS_WAIT_CTL_REPLY, CS_WAIT_CTL_CONNECT,
334: CS_ESTABLISHED, CS_DYING, -1 },
335: { -1 }, { -1 },
336: { AVP_ASSIGNED_TUNNEL_ID, AVP_RESULT_CODE, -1 } },
337: { "HELLO", HELLO, ppp_l2tp_handle_HELLO, NULL,
338: { CS_IDLE, CS_WAIT_CTL_REPLY, CS_WAIT_CTL_CONNECT,
339: CS_ESTABLISHED, CS_DYING, -1 },
340: { -1 }, { -1 },
341: { -1 } },
342: { "ICRQ", ICRQ, ppp_l2tp_handle_ICRQ, NULL,
343: { CS_ESTABLISHED, -1 },
344: { -1 }, { -1 },
345: { AVP_ASSIGNED_SESSION_ID, AVP_CALL_SERIAL_NUMBER, -1 } },
346: { "OCRQ", OCRQ, ppp_l2tp_handle_OCRQ, NULL,
347: { CS_ESTABLISHED, -1 },
348: { -1 }, { -1 },
349: { AVP_ASSIGNED_SESSION_ID, AVP_CALL_SERIAL_NUMBER,
350: AVP_MINIMUM_BPS, AVP_MAXIMUM_BPS, AVP_BEARER_TYPE,
351: AVP_FRAMING_TYPE, AVP_CALLED_NUMBER, -1 } },
352:
353: /* Session connection messages */
354: { "ICRP", ICRP, NULL, ppp_l2tp_handle_ICRP,
355: { SS_WAIT_REPLY, SS_DYING, -1 },
356: { ORIG_LOCAL, -1 }, { SIDE_LAC, -1 },
357: { AVP_ASSIGNED_SESSION_ID, -1 } },
358: { "OCRP", OCRP, NULL, ppp_l2tp_handle_OCRP,
359: { SS_WAIT_REPLY, SS_DYING, -1 },
360: { ORIG_LOCAL, -1 }, { SIDE_LNS, -1 },
361: { AVP_ASSIGNED_SESSION_ID, -1 } },
362: { "ICCN", ICCN, NULL, ppp_l2tp_handle_xCCN,
363: { SS_WAIT_CONNECT, SS_DYING, -1 },
364: { ORIG_REMOTE, -1 }, { SIDE_LNS, -1 },
365: { AVP_TX_CONNECT_SPEED, AVP_FRAMING_TYPE, -1 } },
366: { "OCCN", OCCN, NULL, ppp_l2tp_handle_xCCN,
367: { SS_WAIT_CONNECT, SS_DYING, -1 },
368: { ORIG_LOCAL, -1 }, { SIDE_LNS, -1 },
369: { AVP_TX_CONNECT_SPEED, AVP_FRAMING_TYPE, -1 } },
370: { "CDN", CDN, NULL, ppp_l2tp_handle_CDN,
371: { SS_WAIT_REPLY, SS_WAIT_CONNECT,
372: SS_WAIT_ANSWER, SS_ESTABLISHED, SS_DYING, -1 },
373: { ORIG_LOCAL, ORIG_REMOTE, -1 }, { SIDE_LAC, SIDE_LNS, -1 },
374: { AVP_RESULT_CODE, AVP_ASSIGNED_SESSION_ID, -1 } },
375: { "WEN", WEN, NULL, ppp_l2tp_handle_WEN,
376: { SS_ESTABLISHED, SS_DYING, -1 },
377: { ORIG_LOCAL, ORIG_REMOTE, -1 }, { SIDE_LNS, -1 },
378: { AVP_CALL_ERRORS, -1 } },
379: { "SLI", SLI, NULL, ppp_l2tp_handle_SLI,
380: { SS_ESTABLISHED, SS_DYING, -1 },
381: { ORIG_LOCAL, ORIG_REMOTE, -1 }, { SIDE_LAC, -1 },
382: { AVP_ACCM, -1 } },
1.1.1.3 misho 383: { NULL, 0, NULL, NULL, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0 }, { 0, 0 } }
1.1 misho 384: };
385:
386: /* Descriptors for each AVP */
387:
388: #define AVP_ITEM(x,h,m,min,max) \
389: { #x, ppp_l2tp_avp_decode_ ## x, 0, AVP_ ## x, h, m, min, max }
390:
391: static const struct ppp_l2tp_avp_info ppp_l2tp_avp_info_list[] = {
392: AVP_ITEM(MESSAGE_TYPE, 0, 1, 2, 2),
393: AVP_ITEM(RANDOM_VECTOR, 0, 1, 0, AVP_MAX_LENGTH),
394: AVP_ITEM(RESULT_CODE, 0, 1, 2, AVP_MAX_LENGTH),
395: AVP_ITEM(PROTOCOL_VERSION, 0, 1, 2, 2),
396: AVP_ITEM(FRAMING_CAPABILITIES, 1, 1, 4, 4),
397: AVP_ITEM(BEARER_CAPABILITIES, 1, 1, 4, 4),
398: AVP_ITEM(TIE_BREAKER, 0, 0, 8, 8),
399: AVP_ITEM(FIRMWARE_REVISION, 1, 0, 2, 2),
400: AVP_ITEM(HOST_NAME, 0, 1, 0, AVP_MAX_LENGTH),
401: AVP_ITEM(VENDOR_NAME, 1, 0, 0, AVP_MAX_LENGTH),
402: AVP_ITEM(ASSIGNED_TUNNEL_ID, 1, 1, 2, 2),
403: AVP_ITEM(RECEIVE_WINDOW_SIZE, 0, 1, 2, 2),
404: AVP_ITEM(CHALLENGE, 1, 1, 0, AVP_MAX_LENGTH),
405: AVP_ITEM(CHALLENGE_RESPONSE, 1, 1, 16, 16),
406: AVP_ITEM(CAUSE_CODE, 0, 1, 3, AVP_MAX_LENGTH),
407: AVP_ITEM(ASSIGNED_SESSION_ID, 1, 1, 2, 2),
408: AVP_ITEM(CALL_SERIAL_NUMBER, 1, 1, 4, 4),
409: AVP_ITEM(MINIMUM_BPS, 1, 1, 4, 4),
410: AVP_ITEM(MAXIMUM_BPS, 1, 1, 4, 4),
411: AVP_ITEM(BEARER_TYPE, 1, 1, 4, 4),
412: AVP_ITEM(FRAMING_TYPE, 1, 1, 4, 4),
413: AVP_ITEM(CALLED_NUMBER, 1, 1, 0, AVP_MAX_LENGTH),
414: AVP_ITEM(CALLING_NUMBER, 1, 1, 0, AVP_MAX_LENGTH),
415: AVP_ITEM(SUB_ADDRESS, 1, 1, 0, AVP_MAX_LENGTH),
416: AVP_ITEM(TX_CONNECT_SPEED, 1, 1, 4, 4),
417: AVP_ITEM(RX_CONNECT_SPEED, 1, 0, 4, 4),
418: AVP_ITEM(PHYSICAL_CHANNEL_ID, 1, 0, 4, 4),
419: AVP_ITEM(PRIVATE_GROUP_ID, 1, 0, 0, AVP_MAX_LENGTH),
420: AVP_ITEM(SEQUENCING_REQUIRED, 0, 1, 0, 0),
421: AVP_ITEM(INITIAL_RECV_CONFREQ, 1, 0, 0, AVP_MAX_LENGTH),
422: AVP_ITEM(LAST_SENT_CONFREQ, 1, 0, 0, AVP_MAX_LENGTH),
423: AVP_ITEM(LAST_RECV_CONFREQ, 1, 0, 0, AVP_MAX_LENGTH),
424: AVP_ITEM(PROXY_AUTHEN_TYPE, 1, 0, 2, 2),
425: AVP_ITEM(PROXY_AUTHEN_NAME, 1, 0, 0, AVP_MAX_LENGTH),
426: AVP_ITEM(PROXY_AUTHEN_CHALLENGE,1, 0, 0, AVP_MAX_LENGTH),
427: AVP_ITEM(PROXY_AUTHEN_ID, 1, 0, 2, 2),
428: AVP_ITEM(PROXY_AUTHEN_RESPONSE, 1, 0, 0, AVP_MAX_LENGTH),
429: AVP_ITEM(CALL_ERRORS, 1, 1, 26, 26),
430: AVP_ITEM(ACCM, 1, 1, 10, 10),
431: { NULL, NULL, 0, 0, 0, 0, 0, 0 }
432: };
433:
434: /* All control connections */
1.1.1.3 misho 435: static struct ghash *ppp_l2tp_ctrls;
1.1 misho 436:
437: static uint32_t gNextSerial = 0;
438:
439: /************************************************************************
440: PUBLIC FUNCTIONS
441: ************************************************************************/
442:
443: /*
444: * Create a new control connection.
445: */
446: struct ppp_l2tp_ctrl *
447: ppp_l2tp_ctrl_create(struct pevent_ctx *ctx, pthread_mutex_t *mutex,
448: const struct ppp_l2tp_ctrl_cb *cb,
449: u_int32_t peer_id, ng_ID_t *nodep, char *hook,
450: const struct ppp_l2tp_avp_list *avps, const void *secret, size_t seclen,
451: u_char hide_avps)
452: {
453: struct ppp_l2tp_ctrl *ctrl;
454: struct ngm_mkpeer mkpeer;
1.1.1.3 misho 455: unsigned i;
1.1 misho 456: u_int16_t value16;
1.1.1.3 misho 457: int index;
1.1 misho 458:
459: /* Init Call Serial Number */
460: if (gNextSerial == 0)
461: gNextSerial = (random() % 900) * 10000;
462:
463: /* Create global control structure hash table */
464: if (ppp_l2tp_ctrls == NULL
465: && (ppp_l2tp_ctrls = ghash_create(NULL, 0, 0, CTRL_MEM_TYPE,
466: ppp_l2tp_ctrl_hash, ppp_l2tp_ctrl_equal, NULL, NULL)) == NULL)
467: return (NULL);
468:
469: /* Create control connection */
470: ctrl = Malloc(CTRL_MEM_TYPE, sizeof(*ctrl));
471: ctrl->ctx = ctx;
472: ctrl->mutex = mutex;
473: ctrl->cb = cb;
474: ctrl->peer_id = peer_id;
475: ctrl->csock = -1;
476: ctrl->dsock = -1;
477:
478: /* Debugging */
479: Log(LOG_DEBUG, ("L2TP: %s invoked", __FUNCTION__));
480:
481: /* Select an unused, non-zero local tunnel ID */
482: while (ctrl->config.tunnel_id == 0
483: || ghash_get(ppp_l2tp_ctrls, ctrl) != NULL)
484: ctrl->config.tunnel_id = random() & 0xffff;
485:
486: /* Add control structure to hash table */
487: if (ghash_put(ppp_l2tp_ctrls, ctrl) == -1)
488: goto fail;
489:
490: /* Copy shared secret, if any */
491: if (seclen > 0)
492: ctrl->secret = Mdup(CTRL_MEM_TYPE, secret, seclen);
493: ctrl->seclen = seclen;
494: ctrl->hide_avps = hide_avps;
495:
496: /* Create sessions hash table */
497: if ((ctrl->sessions = ghash_create(NULL, 0, 0, CTRL_MEM_TYPE,
498: ppp_l2tp_sess_hash, ppp_l2tp_sess_equal, NULL, NULL)) == NULL)
499: goto fail;
500:
501: /* Create netgraph node */
502: if (NgMkSockNode(NULL, &ctrl->csock, &ctrl->dsock) == -1)
503: goto fail;
504: memset(&mkpeer, 0, sizeof(mkpeer));
505: strlcpy(mkpeer.type, NG_L2TP_NODE_TYPE, sizeof(mkpeer.type));
506: strlcpy(mkpeer.ourhook, NG_L2TP_HOOK_CTRL, sizeof(mkpeer.ourhook));
507: strlcpy(mkpeer.peerhook, NG_L2TP_HOOK_CTRL, sizeof(mkpeer.peerhook));
508: if (NgSendMsg(ctrl->csock, ".:", NGM_GENERIC_COOKIE,
509: NGM_MKPEER, &mkpeer, sizeof(mkpeer)) == -1)
510: goto fail;
511:
512: /* Get l2tp node ID */
513: if ((ctrl->node_id = NgGetNodeID(ctrl->csock, NG_L2TP_HOOK_CTRL)) == 0) {
514: Perror("L2TP: Cannot get %s node id", NG_L2TP_NODE_TYPE);
515: goto fail;
516: };
517: snprintf(ctrl->path, sizeof(ctrl->path),
518: "[%lx]:", (u_long)ctrl->node_id);
519:
520: /* Configure netgraph node with initial configuration */
521: ctrl->config.enabled = 1;
522: ctrl->config.peer_win = 1; /* we increase this later */
523: ctrl->config.rexmit_max = L2TP_REXMIT_MAX;
524: ctrl->config.rexmit_max_to = L2TP_REXMIT_MAX_TO;
525: if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_L2TP_COOKIE,
526: NGM_L2TP_SET_CONFIG, &ctrl->config, sizeof(ctrl->config)) == -1)
527: goto fail;
528:
529: /* Listen for control messages and control packets */
530: if (pevent_register(ctrl->ctx, &ctrl->ctrl_event, PEVENT_RECURRING,
531: ctrl->mutex, ppp_l2tp_ctrl_event, ctrl, PEVENT_READ,
532: ctrl->csock) == -1)
533: goto fail;
534: if (pevent_register(ctrl->ctx, &ctrl->data_event, PEVENT_RECURRING,
535: ctrl->mutex, ppp_l2tp_data_event, ctrl, PEVENT_READ,
536: ctrl->dsock) == -1)
537: goto fail;
538:
539: /* Copy initial AVP list */
540: ctrl->avps = (avps == NULL) ?
541: ppp_l2tp_avp_list_create() :
542: ppp_l2tp_avp_list_copy(avps);
543: if (ctrl->avps == NULL)
544: goto fail;
545:
546: /* Add required AVP's */
547: if (ppp_l2tp_avp_list_find(ctrl->avps,
548: 0, AVP_PROTOCOL_VERSION)== -1) {
549: const u_char pv[] = { L2TP_PROTO_VERS, L2TP_PROTO_REV };
550:
551: if (ppp_l2tp_avp_list_append(ctrl->avps, 1,
552: 0, AVP_PROTOCOL_VERSION, pv, sizeof(pv)) == -1)
553: goto fail;
554: }
555: if ((index = ppp_l2tp_avp_list_find(ctrl->avps,
556: 0, AVP_HOST_NAME)) == -1) {
557: (void)gethostname(ctrl->self_name, sizeof(ctrl->self_name) - 1);
558: ctrl->self_name[sizeof(ctrl->self_name) - 1] = '\0';
559: if (ppp_l2tp_avp_list_append(ctrl->avps, 1,
560: 0, AVP_HOST_NAME, ctrl->self_name, strlen(ctrl->self_name)) == -1)
561: goto fail;
562: } else {
1.1.1.3 misho 563: unsigned len = ctrl->avps->avps[index].vlen;
1.1 misho 564: if (len >= sizeof(ctrl->self_name))
565: len = sizeof(ctrl->self_name) - 1;
566: memcpy(ctrl->self_name, ctrl->avps->avps[index].value, len);
567: ctrl->self_name[len] = 0;
568: }
569: if (ppp_l2tp_avp_list_find(ctrl->avps,
570: 0, AVP_FRAMING_CAPABILITIES) == -1) {
571: const u_int32_t value = htonl(L2TP_FRAMING_SYNC|L2TP_FRAMING_ASYNC);
572:
573: if (ppp_l2tp_avp_list_append(ctrl->avps, 1,
574: 0, AVP_FRAMING_CAPABILITIES, &value, sizeof(value)) == -1)
575: goto fail;
576: }
577: if ((index = ppp_l2tp_avp_list_find(ctrl->avps,
578: 0, AVP_ASSIGNED_TUNNEL_ID)) != -1)
579: ppp_l2tp_avp_list_remove(ctrl->avps, index);
580: value16 = htons(ctrl->config.tunnel_id);
581: if (ppp_l2tp_avp_list_append(ctrl->avps, 1,
582: 0, AVP_ASSIGNED_TUNNEL_ID, &value16, sizeof(value16)) == -1)
583: goto fail;
584:
585: if ((index = ppp_l2tp_avp_list_find(ctrl->avps,
586: 0, AVP_CHALLENGE)) != -1)
587: ppp_l2tp_avp_list_remove(ctrl->avps, index);
588:
589: if (ctrl->secret != NULL) {
590: for (i = 0; i < sizeof(ctrl->chal); i++)
591: ctrl->chal[i] = random();
592: if (ppp_l2tp_avp_list_append(ctrl->avps, 1,
593: 0, AVP_CHALLENGE, &ctrl->chal, sizeof(ctrl->chal)) == -1)
594: goto fail;
595: }
596:
597: ctrl->state = CS_IDLE; /* wait for peer's sccrq */
598:
599: /* Expect some sort of reply */
600: ppp_l2tp_ctrl_check_reply(ctrl);
601:
602: /* Done */
603: *nodep = ctrl->node_id;
604: strlcpy(hook, NG_L2TP_HOOK_LOWER, NG_HOOKSIZ);
605: return (ctrl);
606:
607: fail:
608: /* Clean up after failure */
609: if (ctrl->csock >= 0)
610: (void)close(ctrl->csock); /* l2tp node will go away too */
611: if (ctrl->dsock >= 0)
612: (void)close(ctrl->dsock);
613: pevent_unregister(&ctrl->reply_timer);
614: pevent_unregister(&ctrl->ctrl_event);
615: pevent_unregister(&ctrl->data_event);
616: ppp_l2tp_avp_list_destroy(&ctrl->avps);
617: ghash_remove(ppp_l2tp_ctrls, ctrl);
618: ghash_destroy(&ctrl->sessions);
619: Freee(ctrl->secret);
620: Freee(ctrl);
621: if (ppp_l2tp_ctrls != NULL && ghash_size(ppp_l2tp_ctrls) == 0)
622: ghash_destroy(&ppp_l2tp_ctrls);
623: return (NULL);
624: }
625:
626: /*
627: * Create a new control connection.
628: */
629: struct ppp_l2tp_ctrl *
630: ppp_l2tp_ctrl_initiate(struct ppp_l2tp_ctrl *ctrl)
631: {
632: /* Debugging */
633: Log(LOG_DEBUG, ("L2TP: %s invoked", __FUNCTION__));
634:
635: /* Initiate connection, we're the initiator */
636: ctrl->state = CS_WAIT_CTL_REPLY;
637: ppp_l2tp_ctrl_send(ctrl, 0, SCCRQ, ctrl->avps);
638:
639: /* Expect some sort of reply */
640: ppp_l2tp_ctrl_check_reply(ctrl);
641:
642: /* Done */
643: return (ctrl);
644: }
645:
646: /*
647: * Shutdown a control connection.
648: */
649: void
650: ppp_l2tp_ctrl_shutdown(struct ppp_l2tp_ctrl *ctrl,
651: u_int16_t result, u_int16_t error, const char *errmsg)
652: {
653: /* Debugging */
654: Log(LOG_DEBUG, ("L2TP: %s invoked, ctrl=%p errmsg=\"%s\"",
655: __FUNCTION__, ctrl, errmsg));
656:
657: /* Close control connection */
658: ppp_l2tp_ctrl_close(ctrl, result, error, errmsg);
659: }
660:
661: /*
662: * Initiate a new session.
663: */
664: struct ppp_l2tp_sess *
665: ppp_l2tp_initiate(struct ppp_l2tp_ctrl *ctrl, int out,
666: u_char include_length, u_char enable_dseq,
667: const struct ppp_l2tp_avp_list *avps)
668: {
669: struct ppp_l2tp_sess *sess;
670: u_int32_t value32;
1.1.1.3 misho 671: unsigned i;
1.1 misho 672:
673: /* Debugging */
674: Log(LOG_DEBUG, ("L2TP: %s invoked, ctrl=%p out=%d", __FUNCTION__, ctrl, out));
675:
676: /* Check control connection */
677: /* XXX add support for sessions waiting for open ctrl conection */
678: if (ctrl->state != CS_ESTABLISHED) {
679: errno = ENXIO;
680: return (NULL);
681: }
682:
683: /* Verify peer supports outgoing calls */
684: if (out
685: && (ctrl->peer_bearer
686: & (L2TP_BEARER_DIGITAL|L2TP_BEARER_ANALOG)) == 0) {
687: errno = EOPNOTSUPP;
688: return (NULL);
689: }
690:
691: /* Create new session */
692: if ((sess = ppp_l2tp_sess_create(ctrl,
693: ORIG_LOCAL, out ? SIDE_LNS : SIDE_LAC,
694: gNextSerial++)) == NULL)
695: return (NULL);
696:
697: sess->include_length = include_length;
698: sess->enable_dseq = enable_dseq;
699:
700: /* Copy AVP's supplied by caller */
701: if (avps) {
702: for (i = 0; i < avps->length; i++) {
703: const struct ppp_l2tp_avp *const avp = &avps->avps[i];
704:
705: if (ppp_l2tp_avp_list_append(sess->my_avps,
706: avp->mandatory, avp->vendor, avp->type,
707: avp->value, avp->vlen) == -1)
708: goto fail;
709: }
710: }
711:
712: /* Add other AVP's required by OCRQ */
713: if (!out)
714: goto send_msg;
715: if (ppp_l2tp_avp_list_find(sess->my_avps,
716: 0, AVP_MINIMUM_BPS) == -1) {
717: value32 = htonl(0);
718: if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
719: 0, AVP_MINIMUM_BPS, &value32, sizeof(value32)) == -1)
720: goto fail;
721: }
722: if (ppp_l2tp_avp_list_find(sess->my_avps,
723: 0, AVP_MAXIMUM_BPS) == -1) {
724: value32 = htonl(0x7fffffff);
725: if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
726: 0, AVP_MAXIMUM_BPS, &value32, sizeof(value32)) == -1)
727: goto fail;
728: }
729: if (ppp_l2tp_avp_list_find(sess->my_avps,
730: 0, AVP_BEARER_TYPE) == -1) {
731: value32 = (ctrl->peer_bearer
732: & (L2TP_BEARER_DIGITAL|L2TP_BEARER_ANALOG));
733: value32 = htonl(value32);
734: if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
735: 0, AVP_BEARER_TYPE, &value32, sizeof(value32)) == -1)
736: goto fail;
737: }
738: if (ppp_l2tp_avp_list_find(sess->my_avps,
739: 0, AVP_FRAMING_TYPE) == -1) {
740: value32 = (ctrl->peer_framing
741: & (L2TP_FRAMING_SYNC|L2TP_FRAMING_ASYNC));
742: value32 = htonl(value32);
743: if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
744: 0, AVP_FRAMING_TYPE, &value32, sizeof(value32)) == -1)
745: goto fail;
746: }
747: if (ppp_l2tp_avp_list_find(sess->my_avps,
748: 0, AVP_CALLED_NUMBER) == -1) {
749: if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
750: 0, AVP_CALLED_NUMBER, NULL, 0) == -1)
751: goto fail;
752: }
753:
754: send_msg:
755: /* Send request to peer */
756: ppp_l2tp_ctrl_send(ctrl, 0, out ? OCRQ : ICRQ, sess->my_avps);
757:
758: /* Await reply from peer */
759: ppp_l2tp_sess_check_reply(sess);
760: return (sess);
761:
762: fail:
763: /* Clean up after failure */
764: ppp_l2tp_sess_destroy(&sess);
765: return (NULL);
766: }
767:
768: /*
769: * Report successful connection of a remotely initiated outgoing call
770: * or a locally initiated incoming call.
771: */
772: int
773: ppp_l2tp_connected(struct ppp_l2tp_sess *sess,
774: const struct ppp_l2tp_avp_list *avps)
775: {
776: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
777: u_int32_t value32;
1.1.1.3 misho 778: unsigned i;
1.1 misho 779:
780: /* Debugging */
781: Log(LOG_DEBUG, ("L2TP: %s invoked, sess=%p", __FUNCTION__, sess));
782:
783: /* Check control connection */
784: if (ctrl->state != CS_ESTABLISHED) {
785: Log(LOG_ERR, ("L2TP: inappropriate call to %s", __FUNCTION__));
786: errno = ENXIO;
787: return (-1);
788: }
789:
790: /* Check session state */
791: if (sess->side != SIDE_LAC
792: || !((sess->orig == ORIG_REMOTE && sess->state == SS_WAIT_ANSWER)
793: || (sess->orig == ORIG_LOCAL && sess->state == SS_WAIT_REPLY))) {
794: Log(LOG_ERR, ("L2TP: inappropriate call to %s", __FUNCTION__));
795: errno = ENOTTY;
796: return (-1);
797: }
798:
799: /* Copy AVP's supplied by caller */
800: while (sess->my_avps->length > 0)
801: ppp_l2tp_avp_list_remove(sess->my_avps, 0);
802: if (avps != NULL) {
803: for (i = 0; i < avps->length; i++) {
804: struct ppp_l2tp_avp *const avp = &avps->avps[i];
805:
806: if (ppp_l2tp_avp_list_append(sess->my_avps,
807: avp->mandatory, avp->vendor, avp->type,
808: avp->value, avp->vlen) == -1)
809: goto fail;
810: }
811: }
812:
813: /* Add other AVP's required by ICCN and OCCN */
814: if (ppp_l2tp_avp_list_find(sess->my_avps,
815: 0, AVP_TX_CONNECT_SPEED) == -1) {
816: value32 = htonl(L2TP_CONNECT_SPEED);
817: if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
818: 0, AVP_TX_CONNECT_SPEED, &value32, sizeof(value32)) == -1)
819: goto fail;
820: }
821: if (ppp_l2tp_avp_list_find(sess->my_avps,
822: 0, AVP_FRAMING_TYPE) == -1) {
823: value32 = htonl(L2TP_FRAMING_TYPE);
824: if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
825: 0, AVP_FRAMING_TYPE, &value32, sizeof(value32)) == -1)
826: goto fail;
827: }
828:
829: /* Handle incoming or outgoing call */
830: if (sess->orig == ORIG_LOCAL) {
831: sess->link_responded = 1;
832: if (ppp_l2tp_sess_check_liic(sess) == -1)
833: goto fail;
834: } else {
835: if (ppp_l2tp_sess_setup(sess) == -1)
836: goto fail;
837: ppp_l2tp_ctrl_send(ctrl, sess->peer_id, OCCN, sess->my_avps);
838: }
839:
840: /* Done */
841: return (0);
842:
843: fail:
844: /* Clean up after failure */
845: ppp_l2tp_sess_close(sess, L2TP_RESULT_ERROR,
846: L2TP_ERROR_GENERIC, strerror(errno));
847: return (-1);
848: }
849:
850: /*
851: * Terminate a session.
852: */
853: void
854: ppp_l2tp_terminate(struct ppp_l2tp_sess *sess,
855: u_int16_t result, u_int16_t error, const char *errmsg)
856: {
857: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
858:
859: /* Debugging */
860: Log(LOG_DEBUG, ("L2TP: %s invoked, sess=%p errmsg=\"%s\"",
861: __FUNCTION__, sess, errmsg != NULL ? errmsg : ""));
862:
863: /* Check control connection state */
864: if (ctrl->state == CS_DYING) {
865: sess->link_notified = 1;
866: return;
867: }
868: if (ctrl->state != CS_ESTABLISHED) {
869: Log(LOG_ERR, ("L2TP: inappropriate call to %s", __FUNCTION__));
870: return;
871: }
872:
873: /* Close connection */
874: sess->link_notified = 1;
875: ppp_l2tp_sess_close(sess, result, error, errmsg);
876: }
877:
878: /*
879: * Send SLI to peer.
880: */
881: int
882: ppp_l2tp_set_link_info(struct ppp_l2tp_sess *sess,
883: u_int32_t xmit, u_int32_t recv)
884: {
885: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
886: struct ppp_l2tp_avp_list *avps;
887: uint16_t accm[5];
888:
889: /* Only LNS should send SLI */
890: if (sess->side != SIDE_LNS)
891: return (0);
892:
893: avps = ppp_l2tp_avp_list_create();
894:
895: accm[0] = 0;
896: accm[1] = htons(xmit >> 16);
897: accm[2] = htons(xmit & 0xFFFF);
898: accm[3] = htons(recv >> 16);
899: accm[4] = htons(recv & 0xFFFF);
900: if (ppp_l2tp_avp_list_append(avps, 0,
901: 0, AVP_ACCM, &accm, sizeof(accm)) == -1) {
902: ppp_l2tp_avp_list_destroy(&avps);
903: return (-1);
904: }
905:
906: ppp_l2tp_ctrl_send(ctrl, sess->peer_id, SLI, avps);
907: ppp_l2tp_avp_list_destroy(&avps);
908: return (0);
909: }
910:
911: /*
912: * Get the link side cookie corresponding to a control connection.
913: */
914: void *
915: ppp_l2tp_ctrl_get_cookie(struct ppp_l2tp_ctrl *ctrl)
916: {
917: return (ctrl->link_cookie);
918: }
919:
920: /*
921: * Set the link side cookie corresponding to a control connection.
922: */
923: void
924: ppp_l2tp_ctrl_set_cookie(struct ppp_l2tp_ctrl *ctrl, void *cookie)
925: {
926: ctrl->link_cookie = cookie;
927: }
928:
929: /*
930: * Get the link side cookie corresponding to a session.
931: */
932: void *
933: ppp_l2tp_sess_get_cookie(struct ppp_l2tp_sess *sess)
934: {
935: return (sess->link_cookie);
936: }
937:
938: /*
939: * Set the link side cookie corresponding to a session.
940: */
941: void
942: ppp_l2tp_sess_set_cookie(struct ppp_l2tp_sess *sess, void *cookie)
943: {
944: sess->link_cookie = cookie;
945: }
946:
947: /*
948: * Get session's Call Serial Number.
949: */
950: uint32_t
951: ppp_l2tp_sess_get_serial(struct ppp_l2tp_sess *sess)
952: {
953: return(sess->serial);
954: }
955:
956: int
957: ppp_l2tp_ctrl_get_self_name(struct ppp_l2tp_ctrl *ctrl,
958: void *buf, size_t buf_len) {
959: strlcpy(buf, ctrl->self_name, buf_len);
960: return (0);
961: };
962:
963: int
964: ppp_l2tp_ctrl_get_peer_name(struct ppp_l2tp_ctrl *ctrl,
965: void *buf, size_t buf_len) {
966: strlcpy(buf, ctrl->peer_name, buf_len);
967: return (0);
968: };
969:
1.1.1.2 misho 970: char *
971: ppp_l2tp_ctrl_get_peer_name_p(struct ppp_l2tp_ctrl *ctrl) {
972: return &(ctrl->peer_name[0]);
973: };
974:
1.1 misho 975: /*
976: * Get the node path and hook name for the hook that corresponds
977: * to a control connection's L2TP frames.
978: */
979: void
980: ppp_l2tp_ctrl_get_hook(struct ppp_l2tp_ctrl *ctrl,
981: ng_ID_t *nodep, const char **hookp)
982: {
983: if (nodep != NULL)
984: *nodep = ctrl->node_id;
985: if (hookp != NULL)
986: *hookp = NG_L2TP_HOOK_LOWER;
987: }
988:
989: /*
990: * Get the node path and hook name for the hook that corresponds
991: * to a session's data packets.
992: */
993: void
994: ppp_l2tp_sess_get_hook(struct ppp_l2tp_sess *sess,
995: ng_ID_t *nodep, const char **hookp)
996: {
997: if (nodep != NULL) {
998: if (sess->node_id)
999: *nodep = sess->node_id;
1000: else
1001: *nodep = sess->ctrl->node_id;
1002: }
1003: if (hookp != NULL) {
1004: if (sess->node_id)
1005: *hookp = NG_TEE_HOOK_RIGHT;
1006: else
1007: *hookp = sess->hook;
1008: }
1009: }
1010:
1011: /*
1012: * Informs that hook has been connected and temporal tee can be shutted down.
1013: */
1014: void
1015: ppp_l2tp_sess_hooked(struct ppp_l2tp_sess *sess) {
1016: char path[32];
1017:
1018: snprintf(path, sizeof(path), "[%lx]:", (u_long)sess->node_id);
1019: (void)NgSendMsg(sess->ctrl->csock, path,
1020: NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0);
1021: sess->node_id = 0;
1022: }
1023:
1024: /************************************************************************
1025: INTERNAL FUNCTIONS: CONTROL CONNECTION
1026: ************************************************************************/
1027:
1028: /*
1029: * Extract peer information from AVP's contained in a SCCRQ or SCCRP.
1030: * This is the first part of tunnel setup.
1031: */
1032: static int
1033: ppp_l2tp_ctrl_setup_1(struct ppp_l2tp_ctrl *ctrl,
1.1.1.3.2.1! misho 1034: struct ppp_l2tp_avp_ptrs *ptrs,
! 1035: struct ppp_l2tp_avp_list *avps)
1.1 misho 1036: {
1037: /* Log */
1038: Log(LOG_INFO, ("L2TP: connected to \"%s\", version=%u.%u",
1039: ptrs->hostname->hostname, ptrs->protocol->version,
1040: ptrs->protocol->revision));
1041:
1042: /* Get peer's tunnel ID */
1043: ctrl->config.peer_id = ptrs->tunnelid->id;
1044:
1045: /* Get peer's receive window size */
1046: ctrl->config.peer_win = L2TP_DEFAULT_PEER_WIN;
1047: if (ptrs->winsize != NULL) {
1048: if (ptrs->winsize->size == 0)
1049: Log(LOG_WARNING, ("L2TP: ignoring zero recv window size AVP"));
1050: else
1051: ctrl->config.peer_win = ptrs->winsize->size;
1052: }
1053:
1054: /* Get peer's bearer and framing types */
1055: if (ptrs->bearercap != NULL) {
1056: if (ptrs->bearercap->digital)
1057: ctrl->peer_bearer |= L2TP_BEARER_DIGITAL;
1058: if (ptrs->bearercap->analog)
1059: ctrl->peer_bearer |= L2TP_BEARER_ANALOG;
1060: }
1061: if (ptrs->framingcap->sync)
1062: ctrl->peer_framing |= L2TP_FRAMING_SYNC;
1063: if (ptrs->framingcap->async)
1064: ctrl->peer_framing |= L2TP_FRAMING_ASYNC;
1065:
1066: strlcpy(ctrl->peer_name, ptrs->hostname->hostname, sizeof(ctrl->peer_name));
1067:
1068: /* Update netgraph node configuration */
1069: if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_L2TP_COOKIE,
1070: NGM_L2TP_SET_CONFIG, &ctrl->config, sizeof(ctrl->config)) == -1)
1071: return (-1);
1072:
1073: /* See if there is a challenge AVP */
1074: if (ptrs->challenge != NULL) {
1075: MD5_CTX md5ctx;
1076: u_char hash[MD5_DIGEST_LENGTH];
1077: uint8_t t;
1078:
1079: /* Make sure response was included */
1080: if (ctrl->secret == NULL) {
1081: Log(LOG_WARNING, ("L2TP: tunnel challenge received but"
1082: " no shared secret is configured"));
1083: ppp_l2tp_ctrl_close(ctrl,
1084: L2TP_RESULT_NOT_AUTH, 0, NULL);
1085: return (-1);
1086: }
1087:
1088: /* Calculate challenge response */
1089: t = (ptrs->message->mesgtype == SCCRQ)?SCCRP:SCCCN;
1090: MD5_Init(&md5ctx);
1091: MD5_Update(&md5ctx, &t, 1);
1092: MD5_Update(&md5ctx, ctrl->secret, ctrl->seclen);
1093: MD5_Update(&md5ctx, &ptrs->challenge->value, ptrs->challenge->length);
1094: MD5_Final(hash, &md5ctx);
1095:
1.1.1.3.2.1! misho 1096: if (ppp_l2tp_avp_list_append(avps, 0,
1.1 misho 1097: 0, AVP_CHALLENGE_RESPONSE, hash, sizeof(hash)) == -1)
1098: return (0);
1099: }
1100:
1101: /* Done */
1102: return (0);
1103: }
1104:
1105: /*
1106: * Extract peer information from AVP's contained in a SCCRP or SCCCN.
1107: * This is the second part of tunnel setup.
1108: */
1109: static int
1110: ppp_l2tp_ctrl_setup_2(struct ppp_l2tp_ctrl *ctrl,
1111: struct ppp_l2tp_avp_ptrs *ptrs)
1112: {
1113: /* Peer now knows our tunnel ID */
1114: ctrl->config.match_id = 1;
1115: if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_L2TP_COOKIE,
1116: NGM_L2TP_SET_CONFIG, &ctrl->config, sizeof(ctrl->config)) == -1)
1117: return (-1);
1118:
1119: /* Verify peer's challenge response */
1120: if (ctrl->secret != NULL) {
1121: MD5_CTX md5ctx;
1122: u_char hash[MD5_DIGEST_LENGTH];
1123: uint8_t t;
1124:
1125: /* Make sure response was included */
1126: if (ptrs->challengresp == NULL) {
1.1.1.2 misho 1127: Log(LOG_WARNING, ("L2TP: SCCRP/SCCCN lacks challenge response"));
1.1 misho 1128: ppp_l2tp_ctrl_close(ctrl,
1129: L2TP_RESULT_NOT_AUTH, 0, NULL);
1.1.1.2 misho 1130: return (-1);
1.1 misho 1131: }
1132:
1133: /* Calculate challenge response */
1134: t = ptrs->message->mesgtype;
1135: MD5_Init(&md5ctx);
1136: MD5_Update(&md5ctx, &t, 1);
1137: MD5_Update(&md5ctx, ctrl->secret, ctrl->seclen);
1138: MD5_Update(&md5ctx, ctrl->chal, sizeof(ctrl->chal));
1139: MD5_Final(hash, &md5ctx);
1140:
1141: /* Check challenge response */
1142: if (bcmp(hash, &ptrs->challengresp->value, sizeof(hash))) {
1143: Log(LOG_WARNING, ("L2TP: tunnel challenge/response incorrect"));
1144: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_NOT_AUTH, 0, NULL);
1145: return (-1);
1146: }
1147: }
1148:
1149: if (pevent_register(ctrl->ctx, &ctrl->death_timer, 0,
1150: ctrl->mutex, ppp_l2tp_unused_timeout, ctrl,
1151: PEVENT_TIME, gL2TPto * 1000) == -1) {
1152: Perror("L2TP: error starting unused timer");
1153: }
1154:
1155: /* Done */
1156: return (0);
1157: }
1158:
1159: /*
1160: * Create a new session.
1161: */
1162: static struct ppp_l2tp_sess *
1163: ppp_l2tp_sess_create(struct ppp_l2tp_ctrl *ctrl,
1164: enum l2tp_sess_orig orig, enum l2tp_sess_side side, u_int32_t serial)
1165: {
1166: struct ppp_l2tp_sess *sess = NULL;
1167: u_int16_t value16;
1168: u_int32_t value32;
1169:
1170: /* Create new session object */
1171: sess = Malloc(SESS_MEM_TYPE, sizeof(*sess));
1172: sess->ctrl = ctrl;
1173: sess->orig = orig;
1174: sess->side = side;
1175: sess->serial = serial;
1176: sess->state = (orig == ORIG_LOCAL) ? SS_WAIT_REPLY :
1177: (side == SIDE_LNS) ? SS_WAIT_CONNECT : SS_WAIT_ANSWER;
1178:
1179: /* Get unique session ID */
1180: while (sess->config.session_id == 0
1181: || ghash_get(ctrl->sessions, sess) != NULL)
1182: sess->config.session_id = random() & 0xffff;
1183: snprintf(sess->hook, sizeof(sess->hook),
1184: NG_L2TP_HOOK_SESSION_F, sess->config.session_id);
1185:
1186: pevent_unregister(&ctrl->death_timer);
1187: ctrl->active_sessions++;
1188:
1189: /* Add to control connection hash table */
1190: if (ghash_put(ctrl->sessions, sess) == -1) {
1191: ppp_l2tp_sess_destroy(&sess);
1192: return (NULL);
1193: }
1194:
1195: /* Create session AVP list to send to peer */
1196: sess->my_avps = ppp_l2tp_avp_list_create();
1197:
1198: /* Add assigned session ID AVP */
1199: value16 = htons(sess->config.session_id);
1200: if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
1201: 0, AVP_ASSIGNED_SESSION_ID, &value16, sizeof(value16)) == -1) {
1202: ppp_l2tp_sess_destroy(&sess);
1203: return (NULL);
1204: }
1205:
1206: if (orig == ORIG_LOCAL) {
1207: /* Add call serial number AVP */
1208: value32 = htonl(sess->serial);
1209: if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
1210: 0, AVP_CALL_SERIAL_NUMBER, &value32, sizeof(value32)) == -1) {
1211: ppp_l2tp_sess_destroy(&sess);
1212: return (NULL);
1213: }
1214: }
1215:
1216: /* Done */
1217: Log(LOG_DEBUG, ("L2TP: created new session #%u id 0x%04x orig=%s side=%s"
1218: " state=%s", sess->serial, sess->config.session_id,
1219: ppp_l2tp_sess_orig_str(sess->orig),
1220: ppp_l2tp_sess_side_str(sess->side),
1221: ppp_l2tp_sess_state_str(sess->state)));
1222: return (sess);
1223: }
1224:
1225: /*
1226: * Send a control message.
1227: */
1228: static void
1229: ppp_l2tp_ctrl_send(struct ppp_l2tp_ctrl *ctrl, u_int16_t session_id,
1230: enum l2tp_msg_type msgtype, const struct ppp_l2tp_avp_list *avps0)
1231: {
1232: struct ppp_l2tp_avp_list *avps = NULL;
1233: struct ppp_l2tp_avp *avp = NULL;
1234: u_char *data = NULL;
1235: u_int16_t value;
1236: int index;
1237: int len;
1238:
1239: /* Copy AVP list */
1240: avps = (avps0 == NULL) ? ppp_l2tp_avp_list_create()
1241: : ppp_l2tp_avp_list_copy(avps0);
1242: if (avps == NULL)
1243: goto fail;
1244:
1245: /* Remove any message type AVP in the way */
1246: if ((index = ppp_l2tp_avp_list_find(avps, 0, AVP_MESSAGE_TYPE)) != -1)
1247: ppp_l2tp_avp_list_remove(avps, index);
1248:
1249: /* Add message type AVP as first in the list */
1250: value = htons(msgtype);
1251: avp = ppp_l2tp_avp_create(1, 0, AVP_MESSAGE_TYPE, &value, sizeof(value));
1252: if (ppp_l2tp_avp_list_insert(avps, &avp, 0) == -1)
1253: goto fail;
1254:
1255: /* Encoded AVP's into a packet */
1256: if ((len = ppp_l2tp_avp_pack(ppp_l2tp_avp_info_list,
1257: avps, (ctrl->hide_avps?ctrl->secret:NULL), ctrl->seclen, NULL)) == -1)
1258: goto fail;
1259: data = Malloc(TYPED_MEM_TEMP, 2 + len);
1260: session_id = htons(session_id);
1261: memcpy(data, &session_id, 2);
1262: (void)ppp_l2tp_avp_pack(ppp_l2tp_avp_info_list,
1263: avps, (ctrl->hide_avps?ctrl->secret:NULL), ctrl->seclen, data + 2);
1264:
1265: /* Write packet */
1266: if (session_id == 0)
1267: ppp_l2tp_ctrl_dump(ctrl, avps, "L2TP: XMIT ");
1268: else {
1269: ppp_l2tp_ctrl_dump(ctrl, avps, "L2TP: XMIT(0x%04x) ",
1270: ntohs(session_id));
1271: }
1272: if (NgSendData(ctrl->dsock, NG_L2TP_HOOK_CTRL, data, 2 + len) == -1)
1273: goto fail;
1274:
1275: /* Done */
1276: goto done;
1277:
1278: fail:
1279: /* Close up shop */
1280: Perror("L2TP: error sending ctrl packet");
1281: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1282: L2TP_ERROR_GENERIC, strerror(errno));
1283:
1284: done:
1285: /* Clean up */
1286: ppp_l2tp_avp_destroy(&avp);
1287: ppp_l2tp_avp_list_destroy(&avps);
1288: Freee(data);
1289: }
1290:
1291: /*
1292: * Close a control connection gracefully, after the next context switch.
1293: */
1294: static void
1295: ppp_l2tp_ctrl_close(struct ppp_l2tp_ctrl *ctrl,
1296: u_int16_t result, u_int16_t error, const char *errmsg)
1297: {
1298: /* Sanity check */
1299: if (ctrl->state == CS_DYING)
1300: return;
1301: ctrl->state = CS_DYING;
1302:
1303: /* Save result code and error string */
1304: ctrl->result = result;
1305: ctrl->error = error;
1306: Freee(ctrl->errmsg);
1307: ctrl->errmsg = (errmsg == NULL) ? NULL : Mstrdup(CTRL_MEM_TYPE, errmsg);
1308:
1309: /* Notify peer if necessary */
1310: if (!ctrl->peer_notified) {
1311: struct ppp_l2tp_avp_list *avps = NULL;
1312: const size_t elen = (ctrl->errmsg == NULL) ?
1313: 0 : strlen(ctrl->errmsg);
1314: struct ppp_l2tp_sess *sess;
1315: struct ghash_walk walk;
1316: u_char *rbuf = NULL;
1317: u_int16_t value16;
1318:
1319: /* Create AVP list */
1320: ctrl->peer_notified = 1;
1321: avps = ppp_l2tp_avp_list_create();
1322:
1323: /* Add assigned tunnel ID AVP */
1324: value16 = htons(ctrl->config.tunnel_id);
1325: if (ppp_l2tp_avp_list_append(avps, 1, 0,
1326: AVP_ASSIGNED_TUNNEL_ID, &value16, sizeof(value16)) == -1) {
1327: Perror("L2TP: ppp_l2tp_avp_list_append");
1328: goto notify_done;
1329: }
1330:
1331: /* Add result code AVP */
1332: rbuf = Malloc(TYPED_MEM_TEMP, 4 + elen);
1333: value16 = htons(ctrl->result);
1334: memcpy(rbuf, &value16, sizeof(value16));
1335: value16 = htons(ctrl->error);
1336: memcpy(rbuf + 2, &value16, sizeof(value16));
1337: memcpy(rbuf + 4, ctrl->errmsg, elen);
1338: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_RESULT_CODE,
1339: rbuf, 4 + elen) == -1) {
1340: Perror("L2TP: ppp_l2tp_avp_list_append");
1341: goto notify_done;
1342: }
1343:
1344: /* Send StopCCN */
1345: ppp_l2tp_ctrl_send(ctrl, 0, StopCCN, avps);
1346:
1347: /* StopCCN implies closing all sessions */
1348: ghash_walk_init(ctrl->sessions, &walk);
1349: while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL)
1350: sess->peer_notified = 1;
1351:
1352: notify_done:
1353: /* Clean up */
1354: ppp_l2tp_avp_list_destroy(&avps);
1355: Freee(rbuf);
1356: }
1357:
1358: /* Stop all timers */
1359: pevent_unregister(&ctrl->idle_timer);
1360: pevent_unregister(&ctrl->reply_timer);
1361: pevent_unregister(&ctrl->close_timer);
1362: pevent_unregister(&ctrl->death_timer);
1363:
1364: /* Start timer to call ppp_l2tp_ctrl_do_close() */
1365: if (pevent_register(ctrl->ctx, &ctrl->close_timer, 0, ctrl->mutex,
1366: ppp_l2tp_ctrl_do_close, ctrl, PEVENT_TIME, 0) == -1)
1367: Perror("L2TP: error starting close timer");
1368: }
1369:
1370: /*
1371: * Close a control connection gracefully.
1372: *
1373: * We call this in a separate event thread to avoid reentrancy problems.
1374: */
1375: static void
1376: ppp_l2tp_ctrl_do_close(void *arg)
1377: {
1378: struct ppp_l2tp_ctrl *ctrl = arg;
1379: struct ppp_l2tp_sess *sess;
1380: struct ghash_walk walk;
1381:
1382: /* Remove event */
1383: pevent_unregister(&ctrl->close_timer);
1384:
1385: /* Notify link side about all sessions first */
1386: ghash_walk_init(ctrl->sessions, &walk);
1387: while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL) {
1388: if (sess->link_notified)
1389: continue;
1390: sess->link_notified = 1;
1391: sess->result = L2TP_RESULT_ERROR;
1392: sess->error = L2TP_ERROR_GENERIC;
1393: Freee(sess->errmsg);
1394: sess->errmsg = Mdup(SESS_MEM_TYPE,
1395: "control connection closing", strlen("control connection closing") + 1);
1396: (*ctrl->cb->terminated)(sess,
1397: sess->result, sess->error, sess->errmsg);
1398: }
1399:
1400: /* Now notify link side about control connection */
1401: if (!ctrl->link_notified) {
1402: ctrl->link_notified = 1;
1403: (*ctrl->cb->ctrl_terminated)(ctrl, ctrl->result, ctrl->error,
1404: (ctrl->errmsg != NULL) ? ctrl->errmsg : "");
1405: }
1406:
1407: /* If no active sessions exist, start dying */
1408: if (ctrl->active_sessions == 0) {
1409: ppp_l2tp_ctrl_death_start(ctrl);
1410: return;
1411: }
1412:
1413: /* Close all active sessions */
1414: ghash_walk_init(ctrl->sessions, &walk);
1415: while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL) {
1416: sess->peer_notified = 1; /* no need to notify peer */
1417: ppp_l2tp_sess_close(sess, L2TP_RESULT_ERROR,
1418: L2TP_ERROR_GENERIC, "control connection closing");
1419: }
1420: }
1421:
1422: /*
1423: * Notify link side that the control connection has gone away
1424: * and begin death timer.
1425: *
1426: * We rig things so that all the session death notifications happen
1427: * before the control connection notification, which happens here.
1428: */
1429: static void
1430: ppp_l2tp_ctrl_death_start(struct ppp_l2tp_ctrl *ctrl)
1431: {
1432: /* Sanity */
1433: assert(ctrl->state == CS_DYING);
1434:
1435: /* Stop timers */
1436: pevent_unregister(&ctrl->idle_timer);
1437: pevent_unregister(&ctrl->reply_timer);
1438: pevent_unregister(&ctrl->death_timer);
1439: /* close_timer must not be touched! */
1440:
1441: /* Linger for a while before going away */
1442: if (pevent_register(ctrl->ctx, &ctrl->death_timer, 0,
1443: ctrl->mutex, ppp_l2tp_ctrl_death_timeout, ctrl,
1444: PEVENT_TIME, L2TP_CTRL_DEATH_TIMEOUT * 1000) == -1)
1445: Perror("L2TP: error starting death timer");
1446: }
1447:
1448: /*
1449: * Handle idle timeout on control connection.
1450: */
1451: static void
1452: ppp_l2tp_idle_timeout(void *arg)
1453: {
1454: struct ppp_l2tp_ctrl *const ctrl = arg;
1455:
1456: /* Remove event */
1457: pevent_unregister(&ctrl->idle_timer);
1458:
1459: /* Restart idle timer */
1460: if (pevent_register(ctrl->ctx, &ctrl->idle_timer, 0,
1461: ctrl->mutex, ppp_l2tp_idle_timeout, ctrl, PEVENT_TIME,
1462: L2TP_IDLE_TIMEOUT * 1000) == -1)
1463: Perror("L2TP: error restarting idle timer");
1464:
1465: /* Send a 'hello' packet */
1466: ppp_l2tp_ctrl_send(ctrl, 0, HELLO, NULL);
1467: }
1468:
1469: /*
1470: * Handle unused timeout on control connection.
1471: */
1472: static void
1473: ppp_l2tp_unused_timeout(void *arg)
1474: {
1475: struct ppp_l2tp_ctrl *const ctrl = arg;
1476:
1477: assert(ctrl->active_sessions == 0);
1478: assert(ctrl->state != CS_DYING);
1479:
1480: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_CLEARED,
1481: 0, "no more sessions exist in this tunnel");
1482: }
1483:
1484: /*
1485: * Remove a control connection that has been dead for a while.
1486: */
1487: static void
1488: ppp_l2tp_ctrl_death_timeout(void *arg)
1489: {
1490: struct ppp_l2tp_ctrl *ctrl = arg;
1491:
1492: pevent_unregister(&ctrl->death_timer);
1493: if (*ctrl->cb->ctrl_destroyed != NULL)
1494: (*ctrl->cb->ctrl_destroyed)(ctrl);
1495: ppp_l2tp_ctrl_destroy(&ctrl);
1496: }
1497:
1498: /************************************************************************
1499: INTERNAL FUNCTIONS: SESSIONS
1500: ************************************************************************/
1501:
1502: /*
1503: * This function handles the situation of a locally initiated incoming
1504: * call, i.e., we are the LAC. Before sending the ICCN to the LNS, two
1505: * events must happen: the LNS must reply with a ICRP, and the link
1506: * side must invoke the ppp_l2tp_connected() function.
1507: */
1508: static int
1509: ppp_l2tp_sess_check_liic(struct ppp_l2tp_sess *sess)
1510: {
1511: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
1512:
1513: /* Are we ready to send ICCN yet? */
1514: if (!sess->link_responded || !sess->peer_responded)
1515: return (0);
1516:
1517: /* Set up session */
1518: if (ppp_l2tp_sess_setup(sess) == -1)
1519: return (-1);
1520:
1521: /* Now send ICCN to peer */
1522: ppp_l2tp_ctrl_send(ctrl, sess->peer_id, ICCN, sess->my_avps);
1523:
1524: /* Done */
1525: return (0);
1526: }
1527:
1528: /*
1529: * Set up a session that has reached the established state.
1530: */
1531: static int
1532: ppp_l2tp_sess_setup(struct ppp_l2tp_sess *sess)
1533: {
1534: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
1535: struct ngm_mkpeer mkpeer;
1536: char path[64];
1537:
1538: /* If link side is waiting for confirmation, schedule it */
1539: if (sess->side == SIDE_LNS || sess->orig == ORIG_LOCAL) {
1540: pevent_unregister(&sess->notify_timer);
1541: if (pevent_register(ctrl->ctx, &sess->notify_timer, 0,
1542: ctrl->mutex, ppp_l2tp_sess_notify, sess, PEVENT_TIME, 0) == -1) {
1543: Perror("L2TP: error starting notify timer");
1544: goto fail;
1545: }
1546: }
1547:
1548: /* Attach a 'tee' node so l2tp node never sees hook disconnect */
1549: memset(&mkpeer, 0, sizeof(mkpeer));
1550: strlcpy(mkpeer.type, NG_TEE_NODE_TYPE, sizeof(mkpeer.type));
1551: strlcpy(mkpeer.ourhook, sess->hook, sizeof(mkpeer.ourhook));
1552: strlcpy(mkpeer.peerhook, NG_TEE_HOOK_LEFT, sizeof(mkpeer.peerhook));
1553: if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_GENERIC_COOKIE,
1554: NGM_MKPEER, &mkpeer, sizeof(mkpeer)) == -1) {
1555: Perror("L2TP: mkpeer");
1556: goto fail;
1557: }
1558:
1559: /* Get ng_tee node ID */
1560: snprintf(path, sizeof(path), "%s.%s", NG_L2TP_HOOK_CTRL, sess->hook);
1561: if ((sess->node_id = NgGetNodeID(ctrl->csock, path)) == 0) {
1562: Perror("L2TP: Cannot get %s node id", NG_TEE_NODE_TYPE);
1563: goto fail;
1564: };
1565:
1566: /* Configure session hook */
1567: if (sess->dseq_required) {
1568: sess->config.control_dseq = sess->dseq_required;
1569: sess->config.enable_dseq = 1;
1570: } else {
1571: sess->config.control_dseq = (sess->side == SIDE_LNS)?1:0;
1572: sess->config.enable_dseq = sess->enable_dseq;
1573: }
1574: sess->config.peer_id = sess->peer_id;
1575: sess->config.include_length = sess->include_length;
1576: if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_L2TP_COOKIE,
1577: NGM_L2TP_SET_SESS_CONFIG, &sess->config,
1578: sizeof(sess->config)) == -1) {
1579: Perror("L2TP: error configuring session hook");
1580: goto fail;
1581: }
1582:
1583: /* Call is now established */
1584: sess->state = SS_ESTABLISHED;
1585: return (0);
1586:
1587: fail:
1588: /* Clean up after failure */
1589: pevent_unregister(&sess->notify_timer);
1590: return (-1);
1591: }
1592:
1593: /*
1594: * Close a session gracefully, after the next context switch.
1595: */
1596: static void
1597: ppp_l2tp_sess_close(struct ppp_l2tp_sess *sess,
1598: u_int16_t result, u_int16_t error, const char *errmsg)
1599: {
1600: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
1601:
1602: /* Sanity check */
1603: if (sess->state == SS_DYING)
1604: return;
1605: sess->state = SS_DYING;
1606:
1607: /* Save result code and error string */
1608: sess->result = result;
1609: sess->error = error;
1610: Freee(sess->errmsg);
1611: sess->errmsg = (errmsg == NULL) ? NULL : Mstrdup(SESS_MEM_TYPE, errmsg);
1612:
1613: /* Notify peer if necessary */
1614: if (!sess->peer_notified) {
1615: struct ppp_l2tp_avp_list *avps = NULL;
1616: const size_t elen = (sess->errmsg == NULL) ?
1617: 0 : strlen(sess->errmsg);
1618: u_char *rbuf = NULL;
1619: u_int16_t value16;
1620:
1621: /* Create AVP list */
1622: sess->peer_notified = 1;
1623: avps = ppp_l2tp_avp_list_create();
1624:
1625: /* Add assigned session ID AVP */
1626: value16 = htons(sess->config.session_id);
1627: if (ppp_l2tp_avp_list_append(avps, 1, 0,
1628: AVP_ASSIGNED_SESSION_ID, &value16, sizeof(value16)) == -1) {
1629: Perror("L2TP: ppp_l2tp_avp_list_append");
1630: goto notify_done;
1631: }
1632:
1633: /* Add result code AVP */
1634: rbuf = Malloc(TYPED_MEM_TEMP, 4 + elen);
1635: value16 = htons(sess->result);
1636: memcpy(rbuf, &value16, sizeof(value16));
1637: value16 = htons(sess->error);
1638: memcpy(rbuf + 2, &value16, sizeof(value16));
1639: memcpy(rbuf + 4, sess->errmsg, elen);
1640: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_RESULT_CODE,
1641: rbuf, 4 + elen) == -1) {
1642: Perror("L2TP: ppp_l2tp_avp_list_append");
1643: goto notify_done;
1644: }
1645:
1646: /* Send CDN */
1647: ppp_l2tp_ctrl_send(ctrl, sess->peer_id, CDN, avps);
1648:
1649: notify_done:
1650: /* Clean up */
1651: ppp_l2tp_avp_list_destroy(&avps);
1652: Freee(rbuf);
1653: }
1654:
1655: /* Stop all session timers */
1656: pevent_unregister(&sess->notify_timer);
1657: pevent_unregister(&sess->reply_timer);
1658: pevent_unregister(&sess->death_timer);
1659: pevent_unregister(&sess->close_timer);
1660:
1661: /* Start timer to call ppp_l2tp_sess_do_close() */
1662: if (pevent_register(ctrl->ctx, &sess->close_timer, 0,
1663: ctrl->mutex, ppp_l2tp_sess_do_close, sess, PEVENT_TIME, 0) == -1)
1664: Perror("L2TP: error starting close timer");
1665: }
1666:
1667: /*
1668: * Close a session gracefully.
1669: *
1670: * We call this in a separate event thread to avoid reentrancy problems.
1671: */
1672: static void
1673: ppp_l2tp_sess_do_close(void *arg)
1674: {
1675: struct ppp_l2tp_sess *const sess = arg;
1676: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
1677:
1678: /* Remove event */
1679: pevent_unregister(&sess->close_timer);
1680:
1681: ctrl->active_sessions--;
1682:
1683: /* Linger for a while before going away */
1684: if (pevent_register(ctrl->ctx, &sess->death_timer, 0,
1685: ctrl->mutex, ppp_l2tp_sess_death_timeout, sess, PEVENT_TIME,
1686: L2TP_SESS_DEATH_TIMEOUT * 1000) == -1)
1687: Perror("L2TP: error starting death timer");
1688:
1689: /* Notify link side about session if necessary */
1690: if (!sess->link_notified) {
1691: sess->link_notified = 1;
1692: (*ctrl->cb->terminated)(sess, sess->result, sess->error,
1693: (sess->errmsg != NULL) ? sess->errmsg : "");
1694: }
1695:
1696: /* Close control connection after last session closes */
1697: if (ctrl->active_sessions == 0) {
1698: if (ctrl->state == CS_DYING) {
1699: ppp_l2tp_ctrl_death_start(ctrl);
1700: } else if (pevent_register(ctrl->ctx, &ctrl->death_timer, 0,
1701: ctrl->mutex, ppp_l2tp_unused_timeout, ctrl,
1702: PEVENT_TIME, gL2TPto * 1000) == -1) {
1703: Perror("L2TP: error starting unused timer");
1704: }
1705: }
1706: }
1707:
1708: /*
1709: * Notify link side that a session is connected.
1710: *
1711: * We call this in a separate event thread to avoid reentrancy problems.
1712: */
1713: static void
1714: ppp_l2tp_sess_notify(void *arg)
1715: {
1716: struct ppp_l2tp_sess *const sess = arg;
1717: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
1718:
1719: pevent_unregister(&sess->notify_timer);
1720: (*ctrl->cb->connected)(sess, sess->peer_avps);
1721: }
1722:
1723: /*
1724: * Remove a session that has been dead for a while.
1725: */
1726: static void
1727: ppp_l2tp_sess_death_timeout(void *arg)
1728: {
1729: struct ppp_l2tp_sess *sess = arg;
1730:
1731: pevent_unregister(&sess->death_timer);
1732: ppp_l2tp_sess_destroy(&sess);
1733: }
1734:
1735: /************************************************************************
1736: NETGRAPH SOCKET READERS
1737: ************************************************************************/
1738:
1739: /*
1740: * Read from netgraph data socket. This is where incoming L2TP
1741: * control connection messages appear.
1742: */
1743: static void
1744: ppp_l2tp_data_event(void *arg)
1745: {
1746: struct ppp_l2tp_ctrl *const ctrl = arg;
1747: const struct l2tp_msg_info *msg_info;
1748: struct ppp_l2tp_avp_list *avps = NULL;
1749: struct ppp_l2tp_avp_ptrs *ptrs = NULL;
1750: struct ppp_l2tp_sess *sess;
1751: struct ppp_l2tp_sess key;
1752: static u_char buf[4096];
1753: u_int16_t msgtype;
1754: char ebuf[64];
1755: int len;
1.1.1.3 misho 1756: unsigned i, j;
1.1 misho 1757:
1758: /* Restart idle timer */
1759: pevent_unregister(&ctrl->idle_timer);
1760: if (pevent_register(ctrl->ctx, &ctrl->idle_timer, 0,
1761: ctrl->mutex, ppp_l2tp_idle_timeout, ctrl, PEVENT_TIME,
1762: L2TP_IDLE_TIMEOUT * 1000) == -1) {
1763: Perror("L2TP: error restarting idle timer");
1764: goto fail_errno;
1765: }
1766:
1767: /* Read packet */
1768: if ((len = read(ctrl->dsock, buf, sizeof(buf))) == -1) {
1769: Perror("L2TP: error reading ctrl hook");
1770: goto fail_errno;
1771: }
1772:
1773: /* Extract session ID */
1774: memcpy(&key.config.session_id, buf, 2);
1775: key.config.session_id = ntohs(key.config.session_id);
1776:
1777: /* Parse out AVP's */
1778: if ((avps = ppp_l2tp_avp_unpack(ppp_l2tp_avp_info_list,
1779: buf + 2, len - 2, ctrl->secret, ctrl->seclen)) == NULL) {
1780: switch (errno) {
1781: case EILSEQ:
1782: Log(LOG_ERR,
1783: ("L2TP: rec'd improperly formatted control message"));
1784: goto fail_invalid;
1785: case EAUTH:
1786: Log(LOG_ERR,
1787: ("L2TP: rec'd hidden AVP, but no shared secret"));
1788: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1789: L2TP_ERROR_GENERIC, "hidden AVP found"
1790: " but no shared secret configured");
1791: goto done;
1792: case ENOSYS:
1793: Log(LOG_ERR, ("L2TP: rec'd mandatory but unknown AVP"));
1794: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1795: L2TP_ERROR_MANDATORY, NULL);
1796: goto done;
1797: default:
1798: Perror("L2TP: error decoding control message");
1799: goto fail_errno;
1800: }
1801: }
1802:
1803: /* Debugging */
1804: if (key.config.session_id == 0)
1805: ppp_l2tp_ctrl_dump(ctrl, avps, "L2TP: RECV ");
1806: else {
1807: ppp_l2tp_ctrl_dump(ctrl, avps, "L2TP: RECV(0x%04x) ",
1808: ntohs(key.config.session_id));
1809: }
1810:
1811: /* Message type AVP must be present and first */
1812: if (avps->length == 0 || avps->avps[0].type != AVP_MESSAGE_TYPE) {
1813: Log(LOG_WARNING,
1814: ("L2TP: rec'd ctrl message lacking message type AVP"));
1815: goto fail_invalid;
1816: }
1817:
1818: /* Get message type from message type AVP */
1819: memcpy(&msgtype, avps->avps[0].value, 2);
1820: msgtype = ntohs(msgtype);
1821:
1822: /* Find descriptor for this message type */
1823: for (i = 0; ppp_l2tp_msg_info[i].name != NULL
1824: && msgtype != ppp_l2tp_msg_info[i].type; i++);
1825: if ((msg_info = &ppp_l2tp_msg_info[i])->name == NULL) {
1826: if (avps->avps[0].mandatory) {
1827: snprintf(ebuf, sizeof(ebuf), "rec'd unsupported"
1828: " but mandatory message type %u", msgtype);
1829: Log(LOG_WARNING, ("L2TP: %s", ebuf));
1830: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1831: L2TP_ERROR_BAD_VALUE, ebuf);
1832: goto done;
1833: }
1834: Log(LOG_NOTICE,
1835: ("L2TP: rec'd unknown message type %u; ignoring", msgtype));
1836: goto done; /* just ignore it */
1837: }
1838:
1839: /* Check for missing required AVP's */
1840: for (i = 0; msg_info->req_avps[i] != -1; i++) {
1841: for (j = 0; j < avps->length
1842: && avps->avps[j].type != msg_info->req_avps[i]; j++);
1843: if (j == avps->length) {
1844: snprintf(ebuf, sizeof(ebuf), "rec'd %s control"
1845: " message lacking required AVP #%u",
1846: msg_info->name, msg_info->req_avps[i]);
1847: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1848: L2TP_ERROR_BAD_VALUE, ebuf);
1849: goto done;
1850: }
1851: }
1852:
1853: /* Convert AVP's to friendly form */
1854: if ((ptrs = ppp_l2tp_avp_list2ptrs(avps)) == NULL) {
1855: Perror("L2TP: error decoding AVP list");
1856: goto fail_errno;
1857: }
1858:
1859: /* If this is a tunnel-level command, do it */
1860: if (msg_info->ctrl_handler != NULL) {
1861:
1862: /* Check for valid control connection state */
1863: for (i = 0; msg_info->valid_states[i] != -1
1.1.1.3 misho 1864: && msg_info->valid_states[i] != (int)ctrl->state; i++);
1.1 misho 1865: if (msg_info->valid_states[i] == -1) {
1866:
1867: /* Could be in CS_DYING if we just closed the tunnel */
1868: if (ctrl->state == CS_DYING) {
1869: snprintf(ebuf, sizeof(ebuf),
1870: "ignoring %s in state %s", msg_info->name,
1871: ppp_l2tp_ctrl_state_str(ctrl->state));
1872: Log(LOG_INFO, ("L2TP: %s", ebuf));
1873: goto done;
1874: }
1875:
1876: /* Log a warning message because the peer is broken */
1877: snprintf(ebuf, sizeof(ebuf),
1878: "rec'd %s in state %s", msg_info->name,
1879: ppp_l2tp_ctrl_state_str(ctrl->state));
1880: Log(LOG_WARNING, ("L2TP: %s", ebuf));
1881: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, ebuf);
1882: goto done;
1883: }
1884:
1885: /* Cancel reply timer and invoke handler */
1886: Log((msgtype == HELLO) ? LOG_DEBUG : LOG_INFO,
1887: ("L2TP: rec'd %s in state %s", msg_info->name,
1888: ppp_l2tp_ctrl_state_str(ctrl->state)));
1889: pevent_unregister(&ctrl->reply_timer);
1890: if ((*msg_info->ctrl_handler)(ctrl, avps, ptrs) == -1)
1891: goto fail_errno;
1892:
1893: /* If we're now expecting a reply, start expecting it */
1894: ppp_l2tp_ctrl_check_reply(ctrl);
1895: goto done;
1896: }
1897:
1898: /* Find associated session */
1899: if (key.config.session_id == 0) {
1900: struct ghash_walk walk;
1901:
1902: /* This should only happen with CDN messages */
1903: if (msgtype != CDN) {
1904: Log(LOG_NOTICE, ("L2TP: rec'd %s with zero session ID",
1905: msg_info->name));
1906: goto done;
1907: }
1908:
1909: /* Find session with 'reverse lookup' using peer's session ID */
1910: ghash_walk_init(ctrl->sessions, &walk);
1911: while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL
1912: && sess->peer_id != key.config.session_id);
1913: if (sess == NULL)
1914: goto done;
1915: } else if ((sess = ghash_get(ctrl->sessions, &key)) == NULL) {
1916: Log(LOG_NOTICE, ("L2TP: rec'd %s for unknown session 0x%04x",
1917: msg_info->name, key.config.session_id));
1918: goto done;
1919: }
1920:
1921: /* Check for valid session state, origination, and side */
1922: for (i = 0; msg_info->valid_states[i] != -1
1.1.1.3 misho 1923: && msg_info->valid_states[i] != (int)sess->state; i++);
1.1 misho 1924: if (msg_info->valid_states[i] == -1) {
1925: snprintf(ebuf, sizeof(ebuf), "rec'd %s in state %s",
1926: msg_info->name, ppp_l2tp_sess_state_str(sess->state));
1927: Log(LOG_WARNING, ("L2TP: %s", ebuf));
1928: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, ebuf);
1929: goto done;
1930: }
1931: for (i = 0; msg_info->valid_orig[i] != -1
1.1.1.3 misho 1932: && msg_info->valid_orig[i] != (int)sess->orig; i++);
1.1 misho 1933: if (msg_info->valid_orig[i] == -1) {
1934: snprintf(ebuf, sizeof(ebuf), "rec'd %s in state %s,"
1935: " but session originated %sly", msg_info->name,
1936: ppp_l2tp_sess_state_str(sess->state),
1937: ppp_l2tp_sess_orig_str(sess->orig));
1938: Log(LOG_WARNING, ("L2TP: %s", ebuf));
1939: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, ebuf);
1940: goto done;
1941: }
1942: for (i = 0; msg_info->valid_side[i] != -1
1.1.1.3 misho 1943: && msg_info->valid_side[i] != (int)sess->side; i++);
1.1 misho 1944: if (msg_info->valid_side[i] == -1) {
1945: snprintf(ebuf, sizeof(ebuf), "rec'd %s in state %s,"
1946: " but we are %s for this session", msg_info->name,
1947: ppp_l2tp_sess_state_str(sess->state),
1948: ppp_l2tp_sess_side_str(sess->side));
1949: Log(LOG_WARNING, ("L2TP: %s", ebuf));
1950: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, ebuf);
1951: goto done;
1952: }
1953:
1954: /* Cancel reply timer and invoke handler */
1955: Log(LOG_INFO, ("L2TP: rec'd %s in state %s",
1956: msg_info->name, ppp_l2tp_sess_state_str(sess->state)));
1957: pevent_unregister(&sess->reply_timer);
1958: if ((*msg_info->sess_handler)(sess, avps, ptrs) == -1)
1959: goto fail_errno;
1960:
1961: /* If we're now expecting a reply, start expecting it */
1962: ppp_l2tp_sess_check_reply(sess);
1963: goto done;
1964:
1965: fail_invalid:
1966: /* Fail because of a bogus message */
1967: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1968: L2TP_ERROR_BAD_VALUE, "improperly formatted control message");
1969: goto done;
1970:
1971: fail_errno:
1972: /* Fail because of a system error */
1973: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1974: L2TP_ERROR_GENERIC, strerror(errno));
1975:
1976: done:
1977: /* Clean up */
1978: ppp_l2tp_avp_list_destroy(&avps);
1979: ppp_l2tp_avp_ptrs_destroy(&ptrs);
1980: }
1981:
1982: /*
1983: * Read from netgraph control socket. This is where incoming
1984: * netgraph control messages appear.
1985: */
1986: static void
1987: ppp_l2tp_ctrl_event(void *arg)
1988: {
1989: struct ppp_l2tp_ctrl *const ctrl = arg;
1990: union {
1991: u_char buf[128];
1992: struct ng_mesg msg;
1993: } buf;
1994: struct ng_mesg *const msg = &buf.msg;
1995: char raddr[NG_PATHSIZ];
1996:
1997: /* Read netgraph control message */
1998: if (NgRecvMsg(ctrl->csock, msg, sizeof(buf), raddr) < 0) {
1999: Perror("L2TP: error reading control message");
2000: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
2001: L2TP_ERROR_GENERIC, strerror(errno));
2002: return;
2003: }
2004:
2005: /* Examine message */
2006: switch (msg->header.typecookie) {
2007: case NGM_L2TP_COOKIE:
2008: switch (msg->header.cmd) {
2009: case NGM_L2TP_ACK_FAILURE:
2010: if (ctrl->state != CS_DYING) {
2011: Log(LOG_WARNING,
2012: ("L2TP: acknowledgement timeout"));
2013: ppp_l2tp_ctrl_close(ctrl,
2014: L2TP_RESULT_CLEARED, 0, NULL);
2015: }
2016: break;
2017: default:
2018: break;
2019: }
2020: break;
2021: default:
2022: break;
2023: }
2024: }
2025:
2026: /************************************************************************
2027: INCOMING CONTROL MESSAGE HANDLERS
2028: ************************************************************************/
2029:
2030: static int
2031: ppp_l2tp_handle_SCCRQ(struct ppp_l2tp_ctrl *ctrl,
2032: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2033: {
2034: struct ppp_l2tp_ctrl *ctrl2;
2035: const u_char *tiebreaker;
2036: struct ghash_walk walk;
2037: int diff;
1.1.1.3 misho 2038: unsigned i;
1.1 misho 2039:
1.1.1.3 misho 2040: (void)avps;
1.1 misho 2041: /* See if there is an outstanding SCCRQ to this peer */
2042: ghash_walk_init(ppp_l2tp_ctrls, &walk);
2043: while ((ctrl2 = ghash_walk_next(ppp_l2tp_ctrls, &walk)) != NULL) {
2044: if (ctrl2 != ctrl
2045: && ctrl2->peer_id == ctrl->peer_id
2046: && ctrl2->state == CS_WAIT_CTL_REPLY)
2047: break;
2048: }
2049: if (ctrl2 == NULL)
2050: goto ok;
2051:
2052: /* Determine if we used a tie-breaker in our SCCRQ */
2053: for (tiebreaker = NULL, i = 0; i < ctrl2->avps->length; i++) {
2054: struct ppp_l2tp_avp *const avp = &ctrl2->avps->avps[i];
2055:
2056: if (avp->vendor == 0 && avp->type == AVP_TIE_BREAKER) {
2057: tiebreaker = avp->value;
2058: break;
2059: }
2060: }
2061:
2062: /* If neither side used a tie-breaker, allow this connection */
2063: if (tiebreaker == NULL && ptrs->tiebreaker == NULL)
2064: goto ok;
2065:
2066: /* Compare tie-breaker values to see who wins */
2067: if (tiebreaker == NULL) /* peer wins */
2068: diff = 1;
2069: else if (ptrs->tiebreaker == NULL) /* i win */
2070: diff = -1;
2071: else /* compare values */
2072: diff = memcmp(tiebreaker, &ptrs->tiebreaker->value, 8);
2073: if (diff == 0) { /* we both lose */
2074: Log(LOG_NOTICE, ("L2TP: SCCRQ tie: we both lose"));
2075: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_DUP_CTRL, 0, NULL);
2076: ppp_l2tp_ctrl_close(ctrl2, L2TP_RESULT_DUP_CTRL, 0, NULL);
2077: return (0);
2078: }
2079: if (diff > 0) { /* i win */
2080: Log(LOG_NOTICE, ("L2TP: SCCRQ tie: peer loses"));
2081: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_DUP_CTRL, 0, NULL);
2082: return (0);
2083: }
2084: Log(LOG_NOTICE, ("L2TP: SCCRQ tie: peer wins"));
2085: ppp_l2tp_ctrl_close(ctrl2, L2TP_RESULT_DUP_CTRL, 0, NULL);
2086:
2087: ok:
2088: /* Do control connection setup */
1.1.1.3.2.1! misho 2089: if (ppp_l2tp_ctrl_setup_1(ctrl, ptrs, ctrl->avps) == -1)
1.1 misho 2090: return (-1);
2091:
2092: /* Send response and update state */
2093: ctrl->state = CS_WAIT_CTL_CONNECT;
2094: ppp_l2tp_ctrl_send(ctrl, 0, SCCRP, ctrl->avps);
2095: return (0);
2096: }
2097:
2098: static int
2099: ppp_l2tp_handle_SCCRP(struct ppp_l2tp_ctrl *ctrl,
2100: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2101: {
1.1.1.3.2.1! misho 2102: struct ppp_l2tp_avp_list *avps0;
! 2103:
1.1.1.3 misho 2104: (void)avps;
1.1.1.3.2.1! misho 2105: avps0 = ppp_l2tp_avp_list_create();
! 2106:
1.1 misho 2107: /* Do control connection setup */
1.1.1.3.2.1! misho 2108: if ((ppp_l2tp_ctrl_setup_1(ctrl, ptrs, avps0) == -1) ||
! 2109: (ppp_l2tp_ctrl_setup_2(ctrl, ptrs) == -1)) {
! 2110: ppp_l2tp_avp_list_destroy(&avps0);
1.1 misho 2111: return (-1);
1.1.1.3.2.1! misho 2112: }
1.1 misho 2113:
2114: /* Send response and update state */
2115: ctrl->state = CS_ESTABLISHED;
1.1.1.3.2.1! misho 2116: ppp_l2tp_ctrl_send(ctrl, 0, SCCCN, avps0);
1.1 misho 2117: if (*ctrl->cb->ctrl_connected != NULL)
2118: (*ctrl->cb->ctrl_connected)(ctrl);
1.1.1.3.2.1! misho 2119: ppp_l2tp_avp_list_destroy(&avps0);
1.1 misho 2120: return (0);
2121: }
2122:
2123: static int
2124: ppp_l2tp_handle_SCCCN(struct ppp_l2tp_ctrl *ctrl,
2125: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2126: {
1.1.1.3 misho 2127: (void)avps;
1.1 misho 2128: /* Do control connection setup */
2129: if (ppp_l2tp_ctrl_setup_2(ctrl, ptrs) == -1)
2130: return (-1);
2131:
2132: /* Update state */
2133: ctrl->state = CS_ESTABLISHED;
2134: if (*ctrl->cb->ctrl_connected != NULL)
2135: (*ctrl->cb->ctrl_connected)(ctrl);
2136: return (0);
2137: }
2138:
2139: static int
2140: ppp_l2tp_handle_StopCCN(struct ppp_l2tp_ctrl *ctrl,
2141: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2142: {
2143: struct ppp_l2tp_sess *sess;
2144: struct ghash_walk walk;
2145:
1.1.1.3 misho 2146: (void)avps;
1.1 misho 2147: /* StopCCN implies closing all sessions */
2148: ctrl->peer_notified = 1;
2149: ghash_walk_init(ctrl->sessions, &walk);
2150: while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL)
2151: sess->peer_notified = 1;
2152:
2153: /* Close control connection */
2154: ppp_l2tp_ctrl_close(ctrl, ptrs->errresultcode->result,
2155: ptrs->errresultcode->error, ptrs->errresultcode->errmsg);
2156: return (0);
2157: }
2158:
2159: static int
2160: ppp_l2tp_handle_HELLO(struct ppp_l2tp_ctrl *ctrl,
2161: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2162: {
1.1.1.3 misho 2163: (void)avps;
2164: (void)ctrl;
2165: (void)ptrs;
1.1 misho 2166: return (0);
2167: }
2168:
2169: static int
2170: ppp_l2tp_handle_OCRQ(struct ppp_l2tp_ctrl *ctrl,
2171: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2172: {
2173: struct ppp_l2tp_sess *sess;
2174:
2175: /* Create new session */
2176: if ((sess = ppp_l2tp_sess_create(ctrl, ORIG_REMOTE, SIDE_LAC,
2177: ptrs->serialnum->serialnum)) == NULL)
2178: return (-1);
2179: sess->peer_id = ptrs->sessionid->id;
2180:
2181: /* Notify link side */
2182: (*ctrl->cb->initiated)(ctrl, sess, 1, avps, &sess->include_length, &sess->enable_dseq);
2183:
2184: if (sess->state != SS_DYING) {
2185: /* Send response */
2186: ppp_l2tp_ctrl_send(ctrl, sess->peer_id, OCRP, sess->my_avps);
2187: }
2188:
2189: /* Clean up */
2190: return (0);
2191: }
2192:
2193: static int
2194: ppp_l2tp_handle_ICRQ(struct ppp_l2tp_ctrl *ctrl,
2195: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2196: {
2197: struct ppp_l2tp_sess *sess;
2198:
2199: /* Create new session */
2200: if ((sess = ppp_l2tp_sess_create(ctrl, ORIG_REMOTE, SIDE_LNS,
2201: ptrs->serialnum->serialnum)) == NULL)
2202: return (-1);
2203: sess->peer_id = ptrs->sessionid->id;
2204:
2205: /* Notify link side */
2206: (*ctrl->cb->initiated)(ctrl, sess, 0, avps, &sess->include_length, &sess->enable_dseq);
2207:
2208: if (sess->state != SS_DYING) {
2209: /* Send response */
2210: ppp_l2tp_ctrl_send(ctrl, sess->peer_id, ICRP, sess->my_avps);
2211: ppp_l2tp_sess_check_reply(sess);
2212: }
2213:
2214: /* Clean up */
2215: return (0);
2216: }
2217:
2218: static int
2219: ppp_l2tp_handle_OCRP(struct ppp_l2tp_sess *sess,
2220: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2221: {
1.1.1.3 misho 2222: (void)avps;
1.1 misho 2223: if (sess->state == SS_DYING)
2224: return (0);
2225:
2226: sess->peer_id = ptrs->sessionid->id;
2227: sess->state = SS_WAIT_CONNECT;
2228: return (0);
2229: }
2230:
2231: static int
2232: ppp_l2tp_handle_xCCN(struct ppp_l2tp_sess *sess,
2233: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2234: {
2235: if (sess->state == SS_DYING)
2236: return (0);
2237:
2238: /* Save peer's AVP's for this session */
2239: ppp_l2tp_avp_list_destroy(&sess->peer_avps);
2240: if ((sess->peer_avps = ppp_l2tp_avp_list_copy(avps)) == NULL)
2241: return (-1);
2242:
2243: /* Set up session */
2244: sess->dseq_required = (ptrs->seqrequired != NULL);
2245: if (ppp_l2tp_sess_setup(sess) == -1)
2246: return (-1);
2247:
2248: /* Done */
2249: return (0);
2250: }
2251:
2252: static int
2253: ppp_l2tp_handle_ICRP(struct ppp_l2tp_sess *sess,
2254: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2255: {
2256: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
2257: char buf[64];
2258:
1.1.1.3 misho 2259: (void)avps;
1.1 misho 2260: if (sess->state == SS_DYING)
2261: return (0);
2262:
2263: /* Save peer ID */
2264: sess->peer_id = ptrs->sessionid->id;
2265:
2266: /* Detect duplicate ICRP's */
2267: if (sess->peer_responded) {
2268: snprintf(buf, sizeof(buf), "rec'd duplicate %s in state %s",
2269: "ICRP", ppp_l2tp_sess_state_str(sess->state));
2270: Log(LOG_WARNING, ("L2TP: %s", buf));
2271: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, buf);
2272: return (0);
2273: }
2274:
2275: /* Check status for locally initiated incoming call */
2276: sess->peer_responded = 1;
2277: if (ppp_l2tp_sess_check_liic(sess) == -1)
2278: return (-1);
2279:
2280: /* Done */
2281: return (0);
2282: }
2283:
2284: static int
2285: ppp_l2tp_handle_CDN(struct ppp_l2tp_sess *sess,
2286: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2287: {
1.1.1.3 misho 2288: (void)avps;
1.1 misho 2289: sess->peer_notified = 1;
2290: ppp_l2tp_sess_close(sess, ptrs->errresultcode->result,
2291: ptrs->errresultcode->error, ptrs->errresultcode->errmsg);
2292: return (0);
2293: }
2294:
2295: static int
2296: ppp_l2tp_handle_SLI(struct ppp_l2tp_sess *sess,
2297: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2298: {
2299: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
2300:
1.1.1.3 misho 2301: (void)avps;
1.1 misho 2302: if (sess->state == SS_DYING)
2303: return (0);
2304:
2305: if (ctrl->cb->set_link_info == NULL)
2306: return (0);
2307: (*ctrl->cb->set_link_info)(sess, ptrs->accm->xmit, ptrs->accm->recv);
2308: return (0);
2309: }
2310:
2311: static int
2312: ppp_l2tp_handle_WEN(struct ppp_l2tp_sess *sess,
2313: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2314: {
2315: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
2316:
1.1.1.3 misho 2317: (void)avps;
1.1 misho 2318: if (sess->state == SS_DYING)
2319: return (0);
2320:
2321: if (ctrl->cb->wan_error_notify == NULL)
2322: return (0);
2323: (*ctrl->cb->wan_error_notify)(sess, ptrs->callerror->crc,
2324: ptrs->callerror->frame, ptrs->callerror->overrun,
2325: ptrs->callerror->buffer, ptrs->callerror->timeout,
2326: ptrs->callerror->alignment);
2327: return (0);
2328: }
2329:
2330: /************************************************************************
2331: REPLY EXPECTORS
2332: ************************************************************************/
2333:
2334: static pevent_handler_t ppp_l2tp_ctrl_reply_timeout;
2335: static pevent_handler_t ppp_l2tp_sess_reply_timeout;
2336:
2337: static void
2338: ppp_l2tp_ctrl_check_reply(struct ppp_l2tp_ctrl *ctrl)
2339: {
2340: pevent_unregister(&ctrl->reply_timer);
2341: switch (ctrl->state) {
2342: case CS_IDLE:
2343: case CS_WAIT_CTL_REPLY:
2344: case CS_WAIT_CTL_CONNECT:
2345: if (pevent_register(ctrl->ctx, &ctrl->reply_timer, 0,
2346: ctrl->mutex, ppp_l2tp_ctrl_reply_timeout, ctrl, PEVENT_TIME,
2347: L2TP_REPLY_TIMEOUT * 1000) == -1)
2348: Perror("L2TP: error starting reply timer");
2349: break;
2350: default:
2351: break;
2352: }
2353: }
2354:
2355: static void
2356: ppp_l2tp_sess_check_reply(struct ppp_l2tp_sess *sess)
2357: {
2358: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
2359:
2360: pevent_unregister(&sess->reply_timer);
2361: switch (sess->state) {
2362: case SS_WAIT_REPLY:
2363: case SS_WAIT_CONNECT:
2364: if (pevent_register(ctrl->ctx, &sess->reply_timer, 0,
2365: ctrl->mutex, ppp_l2tp_sess_reply_timeout, sess, PEVENT_TIME,
2366: L2TP_REPLY_TIMEOUT * 1000) == -1)
2367: Perror("L2TP: error starting reply timer");
2368: break;
2369: default:
2370: break;
2371: }
2372: }
2373:
2374: static void
2375: ppp_l2tp_ctrl_reply_timeout(void *arg)
2376: {
2377: struct ppp_l2tp_ctrl *const ctrl = arg;
2378:
2379: pevent_unregister(&ctrl->reply_timer);
2380: Log(LOG_NOTICE, ("L2TP: reply timeout in state %s",
2381: ppp_l2tp_ctrl_state_str(ctrl->state)));
2382: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
2383: L2TP_ERROR_GENERIC, "expecting reply; none received");
2384: }
2385:
2386: static void
2387: ppp_l2tp_sess_reply_timeout(void *arg)
2388: {
2389: struct ppp_l2tp_sess *const sess = arg;
2390: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
2391:
2392: pevent_unregister(&sess->reply_timer);
2393: Log(LOG_NOTICE, ("L2TP: reply timeout in state %s",
2394: ppp_l2tp_sess_state_str(sess->state)));
2395: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
2396: L2TP_ERROR_GENERIC, "expecting reply; none received");
2397: }
2398:
2399: /************************************************************************
2400: CONTROL AND SESSION OBJECT DESTRUCTORS
2401: ************************************************************************/
2402:
2403: /*
2404: * Immediately destroy a control connection and all associated sessions.
2405: */
2406: void
2407: ppp_l2tp_ctrl_destroy(struct ppp_l2tp_ctrl **ctrlp)
2408: {
2409: struct ppp_l2tp_ctrl *const ctrl = *ctrlp;
2410:
2411: /* Sanity */
2412: if (ctrl == NULL)
2413: return;
2414: *ctrlp = NULL;
2415:
2416: /* Destroy all sessions */
2417: while (ghash_size(ctrl->sessions) > 0) {
2418: struct ppp_l2tp_sess *sess;
2419: struct ghash_walk walk;
2420:
2421: ghash_walk_init(ctrl->sessions, &walk);
2422: sess = ghash_walk_next(ctrl->sessions, &walk);
2423: ppp_l2tp_sess_destroy(&sess);
2424: }
2425:
2426: /* Destroy netgraph node */
2427: (void)NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL,
2428: NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0);
2429:
2430: /* Destroy control connection */
2431: ghash_remove(ppp_l2tp_ctrls, ctrl);
2432: if (ghash_size(ppp_l2tp_ctrls) == 0)
2433: ghash_destroy(&ppp_l2tp_ctrls);
2434: (void)close(ctrl->csock);
2435: (void)close(ctrl->dsock);
2436: pevent_unregister(&ctrl->reply_timer);
2437: pevent_unregister(&ctrl->close_timer);
2438: pevent_unregister(&ctrl->death_timer);
2439: pevent_unregister(&ctrl->idle_timer);
2440: pevent_unregister(&ctrl->ctrl_event);
2441: pevent_unregister(&ctrl->data_event);
2442: ppp_l2tp_avp_list_destroy(&ctrl->avps);
2443: ghash_destroy(&ctrl->sessions);
2444: Freee(ctrl->secret);
2445: Freee(ctrl->errmsg);
2446: memset(ctrl, 0, sizeof(*ctrl));
2447: Freee(ctrl);
2448: }
2449:
2450: /*
2451: * Immediately destroy a session.
2452: */
2453: static void
2454: ppp_l2tp_sess_destroy(struct ppp_l2tp_sess **sessp)
2455: {
2456: struct ppp_l2tp_sess *const sess = *sessp;
2457: struct ppp_l2tp_ctrl *ctrl;
2458: char path[32];
2459:
2460: /* Sanity */
2461: if (sess == NULL)
2462: return;
2463: *sessp = NULL;
2464:
2465: /* Destroy session */
2466: ctrl = sess->ctrl;
2467: if (sess->state != SS_DYING || sess->close_timer) {
2468: ctrl->active_sessions--;
2469: /* Close control connection after last session closes */
2470: if (ctrl->active_sessions == 0) {
2471: if (ctrl->state == CS_DYING) {
2472: ppp_l2tp_ctrl_death_start(ctrl);
2473: } else if (pevent_register(ctrl->ctx, &ctrl->death_timer, 0,
2474: ctrl->mutex, ppp_l2tp_unused_timeout, ctrl,
2475: PEVENT_TIME, gL2TPto * 1000) == -1) {
2476: Perror("L2TP: error starting unused timer");
2477: }
2478: }
2479: }
2480: ghash_remove(ctrl->sessions, sess);
2481: snprintf(path, sizeof(path), "[%lx]:", (u_long)sess->node_id);
2482: (void)NgSendMsg(ctrl->csock, path,
2483: NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0);
2484: ppp_l2tp_avp_list_destroy(&sess->my_avps);
2485: ppp_l2tp_avp_list_destroy(&sess->peer_avps);
2486: pevent_unregister(&sess->notify_timer);
2487: pevent_unregister(&sess->reply_timer);
2488: pevent_unregister(&sess->close_timer);
2489: pevent_unregister(&sess->death_timer);
2490: Freee(sess->errmsg);
2491: memset(sess, 0, sizeof(*sess));
2492: Freee(sess);
2493: }
2494:
2495: /************************************************************************
2496: HASH TABLE FUNCTIONS
2497: ************************************************************************/
2498:
2499: static int
2500: ppp_l2tp_ctrl_equal(struct ghash *g, const void *item1, const void *item2)
2501: {
2502: const struct ppp_l2tp_ctrl *const ctrl1 = item1;
2503: const struct ppp_l2tp_ctrl *const ctrl2 = item2;
2504:
1.1.1.3 misho 2505: (void)g;
1.1 misho 2506: return (ctrl1->config.tunnel_id == ctrl2->config.tunnel_id);
2507: }
2508:
2509: static u_int32_t
2510: ppp_l2tp_ctrl_hash(struct ghash *g, const void *item)
2511: {
2512: const struct ppp_l2tp_ctrl *const ctrl = item;
2513:
1.1.1.3 misho 2514: (void)g;
1.1 misho 2515: return ((u_int32_t)ctrl->config.tunnel_id);
2516: }
2517:
2518: static int
2519: ppp_l2tp_sess_equal(struct ghash *g, const void *item1, const void *item2)
2520: {
2521: const struct ppp_l2tp_sess *const sess1 = item1;
2522: const struct ppp_l2tp_sess *const sess2 = item2;
2523:
1.1.1.3 misho 2524: (void)g;
1.1 misho 2525: return (sess1->config.session_id == sess2->config.session_id);
2526: }
2527:
2528: static u_int32_t
2529: ppp_l2tp_sess_hash(struct ghash *g, const void *item)
2530: {
2531: const struct ppp_l2tp_sess *const sess = item;
2532:
1.1.1.3 misho 2533: (void)g;
1.1 misho 2534: return ((u_int32_t)sess->config.session_id);
2535: }
2536:
2537: /************************************************************************
2538: STRING CONVERTERS
2539: ************************************************************************/
2540:
2541: /*
2542: * Dump an AVP list.
2543: */
2544: static void
2545: ppp_l2tp_ctrl_dump(struct ppp_l2tp_ctrl *ctrl,
2546: struct ppp_l2tp_avp_list *avps, const char *fmt, ...)
2547: {
2548: char buf[1024];
2549: va_list args;
1.1.1.3 misho 2550: unsigned i;
2551:
2552: (void)ctrl;
2553:
2554: if ((gLogOptions & LOG_DEBUG) == 0)
2555: return;
1.1 misho 2556:
2557: va_start(args, fmt);
2558: vsnprintf(buf, sizeof(buf), fmt, args);
2559: va_end(args);
2560: for (i = 0; i < avps->length; i++) {
2561: struct ppp_l2tp_avp *const avp = &avps->avps[i];
2562: const struct ppp_l2tp_avp_info *info;
2563: int j;
2564:
2565: strlcat(buf, i > 0 ? " [" : "[", sizeof(buf));
2566: for (j = 0; (info = &ppp_l2tp_avp_info_list[j])->name != NULL
2567: && (info->vendor != avp->vendor
2568: || info->type != avp->type); j++);
2569: if (info->name != NULL) {
2570: strlcat(buf, info->name, sizeof(buf));
2571: strlcat(buf, " ", sizeof(buf));
2572: (*info->decode)(info, avp,
2573: buf + strlen(buf), sizeof(buf) - strlen(buf));
2574: } else {
2575: snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
2576: "%u:%u vlen=%u", avp->vendor, avp->type, avp->vlen);
2577: }
2578: strlcat(buf, "]", sizeof(buf));
2579: }
2580: Log(LOG_DEBUG, ("%s", buf));
2581: }
2582:
2583: static const char *
2584: ppp_l2tp_ctrl_state_str(enum l2tp_ctrl_state state)
2585: {
2586: switch (state) {
2587: case CS_IDLE:
2588: return ("idle");
2589: case CS_WAIT_CTL_REPLY:
2590: return ("wait-ctl-reply");
2591: case CS_WAIT_CTL_CONNECT:
2592: return ("wait-ctl-conn");
2593: case CS_ESTABLISHED:
2594: return ("established");
2595: case CS_DYING:
2596: return ("dying");
2597: default:
2598: return ("UNKNOWN");
2599: }
2600: }
2601:
2602: static const char *
1.1.1.2 misho 2603: ppp_l2tp_sess_state_str(enum l2tp_sess_state state)
1.1 misho 2604: {
2605: switch (state) {
2606: case SS_WAIT_REPLY:
2607: return ("wait-cs-reply");
2608: case SS_WAIT_CONNECT:
2609: return ("wait-connect");
2610: case SS_WAIT_ANSWER:
2611: return ("wait-answer");
2612: case SS_ESTABLISHED:
2613: return ("established");
2614: case SS_DYING:
2615: return ("dying");
2616: default:
2617: return ("UNKNOWN");
2618: }
2619: }
2620:
2621: static const char *
2622: ppp_l2tp_sess_orig_str(enum l2tp_sess_orig orig)
2623: {
2624: return (orig == ORIG_LOCAL ? "local" : "remote");
2625: }
2626:
2627: static const char *
2628: ppp_l2tp_sess_side_str(enum l2tp_sess_side side)
2629: {
2630: return (side == SIDE_LNS ? "LNS" : "LAC");
2631: }
2632:
2633: char *
2634: ppp_l2tp_ctrl_stats(struct ppp_l2tp_ctrl *ctrl, char *buf, size_t buf_len)
2635: {
2636: snprintf(buf, buf_len, "%s",
2637: ppp_l2tp_ctrl_state_str(ctrl->state));
2638: return (buf);
2639: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>