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