Annotation of embedaddon/mpd/src/l2tp_ctrl.c, revision 1.1.1.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,
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);
299: static const char *ppp_l2tp_sess_state_str(enum l2tp_ctrl_state state);
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:
968: /*
969: * Get the node path and hook name for the hook that corresponds
970: * to a control connection's L2TP frames.
971: */
972: void
973: ppp_l2tp_ctrl_get_hook(struct ppp_l2tp_ctrl *ctrl,
974: ng_ID_t *nodep, const char **hookp)
975: {
976: if (nodep != NULL)
977: *nodep = ctrl->node_id;
978: if (hookp != NULL)
979: *hookp = NG_L2TP_HOOK_LOWER;
980: }
981:
982: /*
983: * Get the node path and hook name for the hook that corresponds
984: * to a session's data packets.
985: */
986: void
987: ppp_l2tp_sess_get_hook(struct ppp_l2tp_sess *sess,
988: ng_ID_t *nodep, const char **hookp)
989: {
990: if (nodep != NULL) {
991: if (sess->node_id)
992: *nodep = sess->node_id;
993: else
994: *nodep = sess->ctrl->node_id;
995: }
996: if (hookp != NULL) {
997: if (sess->node_id)
998: *hookp = NG_TEE_HOOK_RIGHT;
999: else
1000: *hookp = sess->hook;
1001: }
1002: }
1003:
1004: /*
1005: * Informs that hook has been connected and temporal tee can be shutted down.
1006: */
1007: void
1008: ppp_l2tp_sess_hooked(struct ppp_l2tp_sess *sess) {
1009: char path[32];
1010:
1011: snprintf(path, sizeof(path), "[%lx]:", (u_long)sess->node_id);
1012: (void)NgSendMsg(sess->ctrl->csock, path,
1013: NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0);
1014: sess->node_id = 0;
1015: }
1016:
1017: /************************************************************************
1018: INTERNAL FUNCTIONS: CONTROL CONNECTION
1019: ************************************************************************/
1020:
1021: /*
1022: * Extract peer information from AVP's contained in a SCCRQ or SCCRP.
1023: * This is the first part of tunnel setup.
1024: */
1025: static int
1026: ppp_l2tp_ctrl_setup_1(struct ppp_l2tp_ctrl *ctrl,
1027: struct ppp_l2tp_avp_ptrs *ptrs)
1028: {
1029: /* Log */
1030: Log(LOG_INFO, ("L2TP: connected to \"%s\", version=%u.%u",
1031: ptrs->hostname->hostname, ptrs->protocol->version,
1032: ptrs->protocol->revision));
1033:
1034: /* Get peer's tunnel ID */
1035: ctrl->config.peer_id = ptrs->tunnelid->id;
1036:
1037: /* Get peer's receive window size */
1038: ctrl->config.peer_win = L2TP_DEFAULT_PEER_WIN;
1039: if (ptrs->winsize != NULL) {
1040: if (ptrs->winsize->size == 0)
1041: Log(LOG_WARNING, ("L2TP: ignoring zero recv window size AVP"));
1042: else
1043: ctrl->config.peer_win = ptrs->winsize->size;
1044: }
1045:
1046: /* Get peer's bearer and framing types */
1047: if (ptrs->bearercap != NULL) {
1048: if (ptrs->bearercap->digital)
1049: ctrl->peer_bearer |= L2TP_BEARER_DIGITAL;
1050: if (ptrs->bearercap->analog)
1051: ctrl->peer_bearer |= L2TP_BEARER_ANALOG;
1052: }
1053: if (ptrs->framingcap->sync)
1054: ctrl->peer_framing |= L2TP_FRAMING_SYNC;
1055: if (ptrs->framingcap->async)
1056: ctrl->peer_framing |= L2TP_FRAMING_ASYNC;
1057:
1058: strlcpy(ctrl->peer_name, ptrs->hostname->hostname, sizeof(ctrl->peer_name));
1059:
1060: /* Update netgraph node configuration */
1061: if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_L2TP_COOKIE,
1062: NGM_L2TP_SET_CONFIG, &ctrl->config, sizeof(ctrl->config)) == -1)
1063: return (-1);
1064:
1065: /* See if there is a challenge AVP */
1066: if (ptrs->challenge != NULL) {
1067: MD5_CTX md5ctx;
1068: u_char hash[MD5_DIGEST_LENGTH];
1069: uint8_t t;
1070:
1071: /* Make sure response was included */
1072: if (ctrl->secret == NULL) {
1073: Log(LOG_WARNING, ("L2TP: tunnel challenge received but"
1074: " no shared secret is configured"));
1075: ppp_l2tp_ctrl_close(ctrl,
1076: L2TP_RESULT_NOT_AUTH, 0, NULL);
1077: return (-1);
1078: }
1079:
1080: /* Calculate challenge response */
1081: t = (ptrs->message->mesgtype == SCCRQ)?SCCRP:SCCCN;
1082: MD5_Init(&md5ctx);
1083: MD5_Update(&md5ctx, &t, 1);
1084: MD5_Update(&md5ctx, ctrl->secret, ctrl->seclen);
1085: MD5_Update(&md5ctx, &ptrs->challenge->value, ptrs->challenge->length);
1086: MD5_Final(hash, &md5ctx);
1087:
1088: if (ppp_l2tp_avp_list_append(ctrl->avps, 0,
1089: 0, AVP_CHALLENGE_RESPONSE, hash, sizeof(hash)) == -1)
1090: return (0);
1091: }
1092:
1093: /* Done */
1094: return (0);
1095: }
1096:
1097: /*
1098: * Extract peer information from AVP's contained in a SCCRP or SCCCN.
1099: * This is the second part of tunnel setup.
1100: */
1101: static int
1102: ppp_l2tp_ctrl_setup_2(struct ppp_l2tp_ctrl *ctrl,
1103: struct ppp_l2tp_avp_ptrs *ptrs)
1104: {
1105: /* Peer now knows our tunnel ID */
1106: ctrl->config.match_id = 1;
1107: if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_L2TP_COOKIE,
1108: NGM_L2TP_SET_CONFIG, &ctrl->config, sizeof(ctrl->config)) == -1)
1109: return (-1);
1110:
1111: /* Verify peer's challenge response */
1112: if (ctrl->secret != NULL) {
1113: MD5_CTX md5ctx;
1114: u_char hash[MD5_DIGEST_LENGTH];
1115: uint8_t t;
1116:
1117: /* Make sure response was included */
1118: if (ptrs->challengresp == NULL) {
1119: Log(LOG_WARNING, ("L2TP: SCCRP lacks challenge response"));
1120: ppp_l2tp_ctrl_close(ctrl,
1121: L2TP_RESULT_NOT_AUTH, 0, NULL);
1122: return (0);
1123: }
1124:
1125: /* Calculate challenge response */
1126: t = ptrs->message->mesgtype;
1127: MD5_Init(&md5ctx);
1128: MD5_Update(&md5ctx, &t, 1);
1129: MD5_Update(&md5ctx, ctrl->secret, ctrl->seclen);
1130: MD5_Update(&md5ctx, ctrl->chal, sizeof(ctrl->chal));
1131: MD5_Final(hash, &md5ctx);
1132:
1133: /* Check challenge response */
1134: if (bcmp(hash, &ptrs->challengresp->value, sizeof(hash))) {
1135: Log(LOG_WARNING, ("L2TP: tunnel challenge/response incorrect"));
1136: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_NOT_AUTH, 0, NULL);
1137: return (-1);
1138: }
1139: }
1140:
1141: if (pevent_register(ctrl->ctx, &ctrl->death_timer, 0,
1142: ctrl->mutex, ppp_l2tp_unused_timeout, ctrl,
1143: PEVENT_TIME, gL2TPto * 1000) == -1) {
1144: Perror("L2TP: error starting unused timer");
1145: }
1146:
1147: /* Done */
1148: return (0);
1149: }
1150:
1151: /*
1152: * Create a new session.
1153: */
1154: static struct ppp_l2tp_sess *
1155: ppp_l2tp_sess_create(struct ppp_l2tp_ctrl *ctrl,
1156: enum l2tp_sess_orig orig, enum l2tp_sess_side side, u_int32_t serial)
1157: {
1158: struct ppp_l2tp_sess *sess = NULL;
1159: u_int16_t value16;
1160: u_int32_t value32;
1161:
1162: /* Create new session object */
1163: sess = Malloc(SESS_MEM_TYPE, sizeof(*sess));
1164: sess->ctrl = ctrl;
1165: sess->orig = orig;
1166: sess->side = side;
1167: sess->serial = serial;
1168: sess->state = (orig == ORIG_LOCAL) ? SS_WAIT_REPLY :
1169: (side == SIDE_LNS) ? SS_WAIT_CONNECT : SS_WAIT_ANSWER;
1170:
1171: /* Get unique session ID */
1172: while (sess->config.session_id == 0
1173: || ghash_get(ctrl->sessions, sess) != NULL)
1174: sess->config.session_id = random() & 0xffff;
1175: snprintf(sess->hook, sizeof(sess->hook),
1176: NG_L2TP_HOOK_SESSION_F, sess->config.session_id);
1177:
1178: pevent_unregister(&ctrl->death_timer);
1179: ctrl->active_sessions++;
1180:
1181: /* Add to control connection hash table */
1182: if (ghash_put(ctrl->sessions, sess) == -1) {
1183: ppp_l2tp_sess_destroy(&sess);
1184: return (NULL);
1185: }
1186:
1187: /* Create session AVP list to send to peer */
1188: sess->my_avps = ppp_l2tp_avp_list_create();
1189:
1190: /* Add assigned session ID AVP */
1191: value16 = htons(sess->config.session_id);
1192: if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
1193: 0, AVP_ASSIGNED_SESSION_ID, &value16, sizeof(value16)) == -1) {
1194: ppp_l2tp_sess_destroy(&sess);
1195: return (NULL);
1196: }
1197:
1198: if (orig == ORIG_LOCAL) {
1199: /* Add call serial number AVP */
1200: value32 = htonl(sess->serial);
1201: if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
1202: 0, AVP_CALL_SERIAL_NUMBER, &value32, sizeof(value32)) == -1) {
1203: ppp_l2tp_sess_destroy(&sess);
1204: return (NULL);
1205: }
1206: }
1207:
1208: /* Done */
1209: Log(LOG_DEBUG, ("L2TP: created new session #%u id 0x%04x orig=%s side=%s"
1210: " state=%s", sess->serial, sess->config.session_id,
1211: ppp_l2tp_sess_orig_str(sess->orig),
1212: ppp_l2tp_sess_side_str(sess->side),
1213: ppp_l2tp_sess_state_str(sess->state)));
1214: return (sess);
1215: }
1216:
1217: /*
1218: * Send a control message.
1219: */
1220: static void
1221: ppp_l2tp_ctrl_send(struct ppp_l2tp_ctrl *ctrl, u_int16_t session_id,
1222: enum l2tp_msg_type msgtype, const struct ppp_l2tp_avp_list *avps0)
1223: {
1224: struct ppp_l2tp_avp_list *avps = NULL;
1225: struct ppp_l2tp_avp *avp = NULL;
1226: u_char *data = NULL;
1227: u_int16_t value;
1228: int index;
1229: int len;
1230:
1231: /* Copy AVP list */
1232: avps = (avps0 == NULL) ? ppp_l2tp_avp_list_create()
1233: : ppp_l2tp_avp_list_copy(avps0);
1234: if (avps == NULL)
1235: goto fail;
1236:
1237: /* Remove any message type AVP in the way */
1238: if ((index = ppp_l2tp_avp_list_find(avps, 0, AVP_MESSAGE_TYPE)) != -1)
1239: ppp_l2tp_avp_list_remove(avps, index);
1240:
1241: /* Add message type AVP as first in the list */
1242: value = htons(msgtype);
1243: avp = ppp_l2tp_avp_create(1, 0, AVP_MESSAGE_TYPE, &value, sizeof(value));
1244: if (ppp_l2tp_avp_list_insert(avps, &avp, 0) == -1)
1245: goto fail;
1246:
1247: /* Encoded AVP's into a packet */
1248: if ((len = ppp_l2tp_avp_pack(ppp_l2tp_avp_info_list,
1249: avps, (ctrl->hide_avps?ctrl->secret:NULL), ctrl->seclen, NULL)) == -1)
1250: goto fail;
1251: data = Malloc(TYPED_MEM_TEMP, 2 + len);
1252: session_id = htons(session_id);
1253: memcpy(data, &session_id, 2);
1254: (void)ppp_l2tp_avp_pack(ppp_l2tp_avp_info_list,
1255: avps, (ctrl->hide_avps?ctrl->secret:NULL), ctrl->seclen, data + 2);
1256:
1257: /* Write packet */
1258: if (session_id == 0)
1259: ppp_l2tp_ctrl_dump(ctrl, avps, "L2TP: XMIT ");
1260: else {
1261: ppp_l2tp_ctrl_dump(ctrl, avps, "L2TP: XMIT(0x%04x) ",
1262: ntohs(session_id));
1263: }
1264: if (NgSendData(ctrl->dsock, NG_L2TP_HOOK_CTRL, data, 2 + len) == -1)
1265: goto fail;
1266:
1267: /* Done */
1268: goto done;
1269:
1270: fail:
1271: /* Close up shop */
1272: Perror("L2TP: error sending ctrl packet");
1273: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1274: L2TP_ERROR_GENERIC, strerror(errno));
1275:
1276: done:
1277: /* Clean up */
1278: ppp_l2tp_avp_destroy(&avp);
1279: ppp_l2tp_avp_list_destroy(&avps);
1280: Freee(data);
1281: }
1282:
1283: /*
1284: * Close a control connection gracefully, after the next context switch.
1285: */
1286: static void
1287: ppp_l2tp_ctrl_close(struct ppp_l2tp_ctrl *ctrl,
1288: u_int16_t result, u_int16_t error, const char *errmsg)
1289: {
1290: /* Sanity check */
1291: if (ctrl->state == CS_DYING)
1292: return;
1293: ctrl->state = CS_DYING;
1294:
1295: /* Save result code and error string */
1296: ctrl->result = result;
1297: ctrl->error = error;
1298: Freee(ctrl->errmsg);
1299: ctrl->errmsg = (errmsg == NULL) ? NULL : Mstrdup(CTRL_MEM_TYPE, errmsg);
1300:
1301: /* Notify peer if necessary */
1302: if (!ctrl->peer_notified) {
1303: struct ppp_l2tp_avp_list *avps = NULL;
1304: const size_t elen = (ctrl->errmsg == NULL) ?
1305: 0 : strlen(ctrl->errmsg);
1306: struct ppp_l2tp_sess *sess;
1307: struct ghash_walk walk;
1308: u_char *rbuf = NULL;
1309: u_int16_t value16;
1310:
1311: /* Create AVP list */
1312: ctrl->peer_notified = 1;
1313: avps = ppp_l2tp_avp_list_create();
1314:
1315: /* Add assigned tunnel ID AVP */
1316: value16 = htons(ctrl->config.tunnel_id);
1317: if (ppp_l2tp_avp_list_append(avps, 1, 0,
1318: AVP_ASSIGNED_TUNNEL_ID, &value16, sizeof(value16)) == -1) {
1319: Perror("L2TP: ppp_l2tp_avp_list_append");
1320: goto notify_done;
1321: }
1322:
1323: /* Add result code AVP */
1324: rbuf = Malloc(TYPED_MEM_TEMP, 4 + elen);
1325: value16 = htons(ctrl->result);
1326: memcpy(rbuf, &value16, sizeof(value16));
1327: value16 = htons(ctrl->error);
1328: memcpy(rbuf + 2, &value16, sizeof(value16));
1329: memcpy(rbuf + 4, ctrl->errmsg, elen);
1330: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_RESULT_CODE,
1331: rbuf, 4 + elen) == -1) {
1332: Perror("L2TP: ppp_l2tp_avp_list_append");
1333: goto notify_done;
1334: }
1335:
1336: /* Send StopCCN */
1337: ppp_l2tp_ctrl_send(ctrl, 0, StopCCN, avps);
1338:
1339: /* StopCCN implies closing all sessions */
1340: ghash_walk_init(ctrl->sessions, &walk);
1341: while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL)
1342: sess->peer_notified = 1;
1343:
1344: notify_done:
1345: /* Clean up */
1346: ppp_l2tp_avp_list_destroy(&avps);
1347: Freee(rbuf);
1348: }
1349:
1350: /* Stop all timers */
1351: pevent_unregister(&ctrl->idle_timer);
1352: pevent_unregister(&ctrl->reply_timer);
1353: pevent_unregister(&ctrl->close_timer);
1354: pevent_unregister(&ctrl->death_timer);
1355:
1356: /* Start timer to call ppp_l2tp_ctrl_do_close() */
1357: if (pevent_register(ctrl->ctx, &ctrl->close_timer, 0, ctrl->mutex,
1358: ppp_l2tp_ctrl_do_close, ctrl, PEVENT_TIME, 0) == -1)
1359: Perror("L2TP: error starting close timer");
1360: }
1361:
1362: /*
1363: * Close a control connection gracefully.
1364: *
1365: * We call this in a separate event thread to avoid reentrancy problems.
1366: */
1367: static void
1368: ppp_l2tp_ctrl_do_close(void *arg)
1369: {
1370: struct ppp_l2tp_ctrl *ctrl = arg;
1371: struct ppp_l2tp_sess *sess;
1372: struct ghash_walk walk;
1373:
1374: /* Remove event */
1375: pevent_unregister(&ctrl->close_timer);
1376:
1377: /* Notify link side about all sessions first */
1378: ghash_walk_init(ctrl->sessions, &walk);
1379: while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL) {
1380: if (sess->link_notified)
1381: continue;
1382: sess->link_notified = 1;
1383: sess->result = L2TP_RESULT_ERROR;
1384: sess->error = L2TP_ERROR_GENERIC;
1385: Freee(sess->errmsg);
1386: sess->errmsg = Mdup(SESS_MEM_TYPE,
1387: "control connection closing", strlen("control connection closing") + 1);
1388: (*ctrl->cb->terminated)(sess,
1389: sess->result, sess->error, sess->errmsg);
1390: }
1391:
1392: /* Now notify link side about control connection */
1393: if (!ctrl->link_notified) {
1394: ctrl->link_notified = 1;
1395: (*ctrl->cb->ctrl_terminated)(ctrl, ctrl->result, ctrl->error,
1396: (ctrl->errmsg != NULL) ? ctrl->errmsg : "");
1397: }
1398:
1399: /* If no active sessions exist, start dying */
1400: if (ctrl->active_sessions == 0) {
1401: ppp_l2tp_ctrl_death_start(ctrl);
1402: return;
1403: }
1404:
1405: /* Close all active sessions */
1406: ghash_walk_init(ctrl->sessions, &walk);
1407: while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL) {
1408: sess->peer_notified = 1; /* no need to notify peer */
1409: ppp_l2tp_sess_close(sess, L2TP_RESULT_ERROR,
1410: L2TP_ERROR_GENERIC, "control connection closing");
1411: }
1412: }
1413:
1414: /*
1415: * Notify link side that the control connection has gone away
1416: * and begin death timer.
1417: *
1418: * We rig things so that all the session death notifications happen
1419: * before the control connection notification, which happens here.
1420: */
1421: static void
1422: ppp_l2tp_ctrl_death_start(struct ppp_l2tp_ctrl *ctrl)
1423: {
1424: /* Sanity */
1425: assert(ctrl->state == CS_DYING);
1426:
1427: /* Stop timers */
1428: pevent_unregister(&ctrl->idle_timer);
1429: pevent_unregister(&ctrl->reply_timer);
1430: pevent_unregister(&ctrl->death_timer);
1431: /* close_timer must not be touched! */
1432:
1433: /* Linger for a while before going away */
1434: if (pevent_register(ctrl->ctx, &ctrl->death_timer, 0,
1435: ctrl->mutex, ppp_l2tp_ctrl_death_timeout, ctrl,
1436: PEVENT_TIME, L2TP_CTRL_DEATH_TIMEOUT * 1000) == -1)
1437: Perror("L2TP: error starting death timer");
1438: }
1439:
1440: /*
1441: * Handle idle timeout on control connection.
1442: */
1443: static void
1444: ppp_l2tp_idle_timeout(void *arg)
1445: {
1446: struct ppp_l2tp_ctrl *const ctrl = arg;
1447:
1448: /* Remove event */
1449: pevent_unregister(&ctrl->idle_timer);
1450:
1451: /* Restart idle timer */
1452: if (pevent_register(ctrl->ctx, &ctrl->idle_timer, 0,
1453: ctrl->mutex, ppp_l2tp_idle_timeout, ctrl, PEVENT_TIME,
1454: L2TP_IDLE_TIMEOUT * 1000) == -1)
1455: Perror("L2TP: error restarting idle timer");
1456:
1457: /* Send a 'hello' packet */
1458: ppp_l2tp_ctrl_send(ctrl, 0, HELLO, NULL);
1459: }
1460:
1461: /*
1462: * Handle unused timeout on control connection.
1463: */
1464: static void
1465: ppp_l2tp_unused_timeout(void *arg)
1466: {
1467: struct ppp_l2tp_ctrl *const ctrl = arg;
1468:
1469: assert(ctrl->active_sessions == 0);
1470: assert(ctrl->state != CS_DYING);
1471:
1472: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_CLEARED,
1473: 0, "no more sessions exist in this tunnel");
1474: }
1475:
1476: /*
1477: * Remove a control connection that has been dead for a while.
1478: */
1479: static void
1480: ppp_l2tp_ctrl_death_timeout(void *arg)
1481: {
1482: struct ppp_l2tp_ctrl *ctrl = arg;
1483:
1484: pevent_unregister(&ctrl->death_timer);
1485: if (*ctrl->cb->ctrl_destroyed != NULL)
1486: (*ctrl->cb->ctrl_destroyed)(ctrl);
1487: ppp_l2tp_ctrl_destroy(&ctrl);
1488: }
1489:
1490: /************************************************************************
1491: INTERNAL FUNCTIONS: SESSIONS
1492: ************************************************************************/
1493:
1494: /*
1495: * This function handles the situation of a locally initiated incoming
1496: * call, i.e., we are the LAC. Before sending the ICCN to the LNS, two
1497: * events must happen: the LNS must reply with a ICRP, and the link
1498: * side must invoke the ppp_l2tp_connected() function.
1499: */
1500: static int
1501: ppp_l2tp_sess_check_liic(struct ppp_l2tp_sess *sess)
1502: {
1503: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
1504:
1505: /* Are we ready to send ICCN yet? */
1506: if (!sess->link_responded || !sess->peer_responded)
1507: return (0);
1508:
1509: /* Set up session */
1510: if (ppp_l2tp_sess_setup(sess) == -1)
1511: return (-1);
1512:
1513: /* Now send ICCN to peer */
1514: ppp_l2tp_ctrl_send(ctrl, sess->peer_id, ICCN, sess->my_avps);
1515:
1516: /* Done */
1517: return (0);
1518: }
1519:
1520: /*
1521: * Set up a session that has reached the established state.
1522: */
1523: static int
1524: ppp_l2tp_sess_setup(struct ppp_l2tp_sess *sess)
1525: {
1526: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
1527: struct ngm_mkpeer mkpeer;
1528: char path[64];
1529:
1530: /* If link side is waiting for confirmation, schedule it */
1531: if (sess->side == SIDE_LNS || sess->orig == ORIG_LOCAL) {
1532: pevent_unregister(&sess->notify_timer);
1533: if (pevent_register(ctrl->ctx, &sess->notify_timer, 0,
1534: ctrl->mutex, ppp_l2tp_sess_notify, sess, PEVENT_TIME, 0) == -1) {
1535: Perror("L2TP: error starting notify timer");
1536: goto fail;
1537: }
1538: }
1539:
1540: /* Attach a 'tee' node so l2tp node never sees hook disconnect */
1541: memset(&mkpeer, 0, sizeof(mkpeer));
1542: strlcpy(mkpeer.type, NG_TEE_NODE_TYPE, sizeof(mkpeer.type));
1543: strlcpy(mkpeer.ourhook, sess->hook, sizeof(mkpeer.ourhook));
1544: strlcpy(mkpeer.peerhook, NG_TEE_HOOK_LEFT, sizeof(mkpeer.peerhook));
1545: if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_GENERIC_COOKIE,
1546: NGM_MKPEER, &mkpeer, sizeof(mkpeer)) == -1) {
1547: Perror("L2TP: mkpeer");
1548: goto fail;
1549: }
1550:
1551: /* Get ng_tee node ID */
1552: snprintf(path, sizeof(path), "%s.%s", NG_L2TP_HOOK_CTRL, sess->hook);
1553: if ((sess->node_id = NgGetNodeID(ctrl->csock, path)) == 0) {
1554: Perror("L2TP: Cannot get %s node id", NG_TEE_NODE_TYPE);
1555: goto fail;
1556: };
1557:
1558: /* Configure session hook */
1559: if (sess->dseq_required) {
1560: sess->config.control_dseq = sess->dseq_required;
1561: sess->config.enable_dseq = 1;
1562: } else {
1563: sess->config.control_dseq = (sess->side == SIDE_LNS)?1:0;
1564: sess->config.enable_dseq = sess->enable_dseq;
1565: }
1566: sess->config.peer_id = sess->peer_id;
1567: sess->config.include_length = sess->include_length;
1568: if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_L2TP_COOKIE,
1569: NGM_L2TP_SET_SESS_CONFIG, &sess->config,
1570: sizeof(sess->config)) == -1) {
1571: Perror("L2TP: error configuring session hook");
1572: goto fail;
1573: }
1574:
1575: /* Call is now established */
1576: sess->state = SS_ESTABLISHED;
1577: return (0);
1578:
1579: fail:
1580: /* Clean up after failure */
1581: pevent_unregister(&sess->notify_timer);
1582: return (-1);
1583: }
1584:
1585: /*
1586: * Close a session gracefully, after the next context switch.
1587: */
1588: static void
1589: ppp_l2tp_sess_close(struct ppp_l2tp_sess *sess,
1590: u_int16_t result, u_int16_t error, const char *errmsg)
1591: {
1592: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
1593:
1594: /* Sanity check */
1595: if (sess->state == SS_DYING)
1596: return;
1597: sess->state = SS_DYING;
1598:
1599: /* Save result code and error string */
1600: sess->result = result;
1601: sess->error = error;
1602: Freee(sess->errmsg);
1603: sess->errmsg = (errmsg == NULL) ? NULL : Mstrdup(SESS_MEM_TYPE, errmsg);
1604:
1605: /* Notify peer if necessary */
1606: if (!sess->peer_notified) {
1607: struct ppp_l2tp_avp_list *avps = NULL;
1608: const size_t elen = (sess->errmsg == NULL) ?
1609: 0 : strlen(sess->errmsg);
1610: u_char *rbuf = NULL;
1611: u_int16_t value16;
1612:
1613: /* Create AVP list */
1614: sess->peer_notified = 1;
1615: avps = ppp_l2tp_avp_list_create();
1616:
1617: /* Add assigned session ID AVP */
1618: value16 = htons(sess->config.session_id);
1619: if (ppp_l2tp_avp_list_append(avps, 1, 0,
1620: AVP_ASSIGNED_SESSION_ID, &value16, sizeof(value16)) == -1) {
1621: Perror("L2TP: ppp_l2tp_avp_list_append");
1622: goto notify_done;
1623: }
1624:
1625: /* Add result code AVP */
1626: rbuf = Malloc(TYPED_MEM_TEMP, 4 + elen);
1627: value16 = htons(sess->result);
1628: memcpy(rbuf, &value16, sizeof(value16));
1629: value16 = htons(sess->error);
1630: memcpy(rbuf + 2, &value16, sizeof(value16));
1631: memcpy(rbuf + 4, sess->errmsg, elen);
1632: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_RESULT_CODE,
1633: rbuf, 4 + elen) == -1) {
1634: Perror("L2TP: ppp_l2tp_avp_list_append");
1635: goto notify_done;
1636: }
1637:
1638: /* Send CDN */
1639: ppp_l2tp_ctrl_send(ctrl, sess->peer_id, CDN, avps);
1640:
1641: notify_done:
1642: /* Clean up */
1643: ppp_l2tp_avp_list_destroy(&avps);
1644: Freee(rbuf);
1645: }
1646:
1647: /* Stop all session timers */
1648: pevent_unregister(&sess->notify_timer);
1649: pevent_unregister(&sess->reply_timer);
1650: pevent_unregister(&sess->death_timer);
1651: pevent_unregister(&sess->close_timer);
1652:
1653: /* Start timer to call ppp_l2tp_sess_do_close() */
1654: if (pevent_register(ctrl->ctx, &sess->close_timer, 0,
1655: ctrl->mutex, ppp_l2tp_sess_do_close, sess, PEVENT_TIME, 0) == -1)
1656: Perror("L2TP: error starting close timer");
1657: }
1658:
1659: /*
1660: * Close a session gracefully.
1661: *
1662: * We call this in a separate event thread to avoid reentrancy problems.
1663: */
1664: static void
1665: ppp_l2tp_sess_do_close(void *arg)
1666: {
1667: struct ppp_l2tp_sess *const sess = arg;
1668: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
1669:
1670: /* Remove event */
1671: pevent_unregister(&sess->close_timer);
1672:
1673: ctrl->active_sessions--;
1674:
1675: /* Linger for a while before going away */
1676: if (pevent_register(ctrl->ctx, &sess->death_timer, 0,
1677: ctrl->mutex, ppp_l2tp_sess_death_timeout, sess, PEVENT_TIME,
1678: L2TP_SESS_DEATH_TIMEOUT * 1000) == -1)
1679: Perror("L2TP: error starting death timer");
1680:
1681: /* Notify link side about session if necessary */
1682: if (!sess->link_notified) {
1683: sess->link_notified = 1;
1684: (*ctrl->cb->terminated)(sess, sess->result, sess->error,
1685: (sess->errmsg != NULL) ? sess->errmsg : "");
1686: }
1687:
1688: /* Close control connection after last session closes */
1689: if (ctrl->active_sessions == 0) {
1690: if (ctrl->state == CS_DYING) {
1691: ppp_l2tp_ctrl_death_start(ctrl);
1692: } else if (pevent_register(ctrl->ctx, &ctrl->death_timer, 0,
1693: ctrl->mutex, ppp_l2tp_unused_timeout, ctrl,
1694: PEVENT_TIME, gL2TPto * 1000) == -1) {
1695: Perror("L2TP: error starting unused timer");
1696: }
1697: }
1698: }
1699:
1700: /*
1701: * Notify link side that a session is connected.
1702: *
1703: * We call this in a separate event thread to avoid reentrancy problems.
1704: */
1705: static void
1706: ppp_l2tp_sess_notify(void *arg)
1707: {
1708: struct ppp_l2tp_sess *const sess = arg;
1709: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
1710:
1711: pevent_unregister(&sess->notify_timer);
1712: (*ctrl->cb->connected)(sess, sess->peer_avps);
1713: }
1714:
1715: /*
1716: * Remove a session that has been dead for a while.
1717: */
1718: static void
1719: ppp_l2tp_sess_death_timeout(void *arg)
1720: {
1721: struct ppp_l2tp_sess *sess = arg;
1722:
1723: pevent_unregister(&sess->death_timer);
1724: ppp_l2tp_sess_destroy(&sess);
1725: }
1726:
1727: /************************************************************************
1728: NETGRAPH SOCKET READERS
1729: ************************************************************************/
1730:
1731: /*
1732: * Read from netgraph data socket. This is where incoming L2TP
1733: * control connection messages appear.
1734: */
1735: static void
1736: ppp_l2tp_data_event(void *arg)
1737: {
1738: struct ppp_l2tp_ctrl *const ctrl = arg;
1739: const struct l2tp_msg_info *msg_info;
1740: struct ppp_l2tp_avp_list *avps = NULL;
1741: struct ppp_l2tp_avp_ptrs *ptrs = NULL;
1742: struct ppp_l2tp_sess *sess;
1743: struct ppp_l2tp_sess key;
1744: static u_char buf[4096];
1745: u_int16_t msgtype;
1746: char ebuf[64];
1747: int len;
1748: int i;
1749: int j;
1750:
1751: /* Restart idle timer */
1752: pevent_unregister(&ctrl->idle_timer);
1753: if (pevent_register(ctrl->ctx, &ctrl->idle_timer, 0,
1754: ctrl->mutex, ppp_l2tp_idle_timeout, ctrl, PEVENT_TIME,
1755: L2TP_IDLE_TIMEOUT * 1000) == -1) {
1756: Perror("L2TP: error restarting idle timer");
1757: goto fail_errno;
1758: }
1759:
1760: /* Read packet */
1761: if ((len = read(ctrl->dsock, buf, sizeof(buf))) == -1) {
1762: Perror("L2TP: error reading ctrl hook");
1763: goto fail_errno;
1764: }
1765:
1766: /* Extract session ID */
1767: memcpy(&key.config.session_id, buf, 2);
1768: key.config.session_id = ntohs(key.config.session_id);
1769:
1770: /* Parse out AVP's */
1771: if ((avps = ppp_l2tp_avp_unpack(ppp_l2tp_avp_info_list,
1772: buf + 2, len - 2, ctrl->secret, ctrl->seclen)) == NULL) {
1773: switch (errno) {
1774: case EILSEQ:
1775: Log(LOG_ERR,
1776: ("L2TP: rec'd improperly formatted control message"));
1777: goto fail_invalid;
1778: case EAUTH:
1779: Log(LOG_ERR,
1780: ("L2TP: rec'd hidden AVP, but no shared secret"));
1781: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1782: L2TP_ERROR_GENERIC, "hidden AVP found"
1783: " but no shared secret configured");
1784: goto done;
1785: case ENOSYS:
1786: Log(LOG_ERR, ("L2TP: rec'd mandatory but unknown AVP"));
1787: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1788: L2TP_ERROR_MANDATORY, NULL);
1789: goto done;
1790: default:
1791: Perror("L2TP: error decoding control message");
1792: goto fail_errno;
1793: }
1794: }
1795:
1796: /* Debugging */
1797: if (key.config.session_id == 0)
1798: ppp_l2tp_ctrl_dump(ctrl, avps, "L2TP: RECV ");
1799: else {
1800: ppp_l2tp_ctrl_dump(ctrl, avps, "L2TP: RECV(0x%04x) ",
1801: ntohs(key.config.session_id));
1802: }
1803:
1804: /* Message type AVP must be present and first */
1805: if (avps->length == 0 || avps->avps[0].type != AVP_MESSAGE_TYPE) {
1806: Log(LOG_WARNING,
1807: ("L2TP: rec'd ctrl message lacking message type AVP"));
1808: goto fail_invalid;
1809: }
1810:
1811: /* Get message type from message type AVP */
1812: memcpy(&msgtype, avps->avps[0].value, 2);
1813: msgtype = ntohs(msgtype);
1814:
1815: /* Find descriptor for this message type */
1816: for (i = 0; ppp_l2tp_msg_info[i].name != NULL
1817: && msgtype != ppp_l2tp_msg_info[i].type; i++);
1818: if ((msg_info = &ppp_l2tp_msg_info[i])->name == NULL) {
1819: if (avps->avps[0].mandatory) {
1820: snprintf(ebuf, sizeof(ebuf), "rec'd unsupported"
1821: " but mandatory message type %u", msgtype);
1822: Log(LOG_WARNING, ("L2TP: %s", ebuf));
1823: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1824: L2TP_ERROR_BAD_VALUE, ebuf);
1825: goto done;
1826: }
1827: Log(LOG_NOTICE,
1828: ("L2TP: rec'd unknown message type %u; ignoring", msgtype));
1829: goto done; /* just ignore it */
1830: }
1831:
1832: /* Check for missing required AVP's */
1833: for (i = 0; msg_info->req_avps[i] != -1; i++) {
1834: for (j = 0; j < avps->length
1835: && avps->avps[j].type != msg_info->req_avps[i]; j++);
1836: if (j == avps->length) {
1837: snprintf(ebuf, sizeof(ebuf), "rec'd %s control"
1838: " message lacking required AVP #%u",
1839: msg_info->name, msg_info->req_avps[i]);
1840: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1841: L2TP_ERROR_BAD_VALUE, ebuf);
1842: goto done;
1843: }
1844: }
1845:
1846: /* Convert AVP's to friendly form */
1847: if ((ptrs = ppp_l2tp_avp_list2ptrs(avps)) == NULL) {
1848: Perror("L2TP: error decoding AVP list");
1849: goto fail_errno;
1850: }
1851:
1852: /* If this is a tunnel-level command, do it */
1853: if (msg_info->ctrl_handler != NULL) {
1854:
1855: /* Check for valid control connection state */
1856: for (i = 0; msg_info->valid_states[i] != -1
1857: && msg_info->valid_states[i] != ctrl->state; i++);
1858: if (msg_info->valid_states[i] == -1) {
1859:
1860: /* Could be in CS_DYING if we just closed the tunnel */
1861: if (ctrl->state == CS_DYING) {
1862: snprintf(ebuf, sizeof(ebuf),
1863: "ignoring %s in state %s", msg_info->name,
1864: ppp_l2tp_ctrl_state_str(ctrl->state));
1865: Log(LOG_INFO, ("L2TP: %s", ebuf));
1866: goto done;
1867: }
1868:
1869: /* Log a warning message because the peer is broken */
1870: snprintf(ebuf, sizeof(ebuf),
1871: "rec'd %s in state %s", msg_info->name,
1872: ppp_l2tp_ctrl_state_str(ctrl->state));
1873: Log(LOG_WARNING, ("L2TP: %s", ebuf));
1874: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, ebuf);
1875: goto done;
1876: }
1877:
1878: /* Cancel reply timer and invoke handler */
1879: Log((msgtype == HELLO) ? LOG_DEBUG : LOG_INFO,
1880: ("L2TP: rec'd %s in state %s", msg_info->name,
1881: ppp_l2tp_ctrl_state_str(ctrl->state)));
1882: pevent_unregister(&ctrl->reply_timer);
1883: if ((*msg_info->ctrl_handler)(ctrl, avps, ptrs) == -1)
1884: goto fail_errno;
1885:
1886: /* If we're now expecting a reply, start expecting it */
1887: ppp_l2tp_ctrl_check_reply(ctrl);
1888: goto done;
1889: }
1890:
1891: /* Find associated session */
1892: if (key.config.session_id == 0) {
1893: struct ghash_walk walk;
1894:
1895: /* This should only happen with CDN messages */
1896: if (msgtype != CDN) {
1897: Log(LOG_NOTICE, ("L2TP: rec'd %s with zero session ID",
1898: msg_info->name));
1899: goto done;
1900: }
1901:
1902: /* Find session with 'reverse lookup' using peer's session ID */
1903: ghash_walk_init(ctrl->sessions, &walk);
1904: while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL
1905: && sess->peer_id != key.config.session_id);
1906: if (sess == NULL)
1907: goto done;
1908: } else if ((sess = ghash_get(ctrl->sessions, &key)) == NULL) {
1909: Log(LOG_NOTICE, ("L2TP: rec'd %s for unknown session 0x%04x",
1910: msg_info->name, key.config.session_id));
1911: goto done;
1912: }
1913:
1914: /* Check for valid session state, origination, and side */
1915: for (i = 0; msg_info->valid_states[i] != -1
1916: && msg_info->valid_states[i] != sess->state; i++);
1917: if (msg_info->valid_states[i] == -1) {
1918: snprintf(ebuf, sizeof(ebuf), "rec'd %s in state %s",
1919: msg_info->name, ppp_l2tp_sess_state_str(sess->state));
1920: Log(LOG_WARNING, ("L2TP: %s", ebuf));
1921: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, ebuf);
1922: goto done;
1923: }
1924: for (i = 0; msg_info->valid_orig[i] != -1
1925: && msg_info->valid_orig[i] != sess->orig; i++);
1926: if (msg_info->valid_orig[i] == -1) {
1927: snprintf(ebuf, sizeof(ebuf), "rec'd %s in state %s,"
1928: " but session originated %sly", msg_info->name,
1929: ppp_l2tp_sess_state_str(sess->state),
1930: ppp_l2tp_sess_orig_str(sess->orig));
1931: Log(LOG_WARNING, ("L2TP: %s", ebuf));
1932: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, ebuf);
1933: goto done;
1934: }
1935: for (i = 0; msg_info->valid_side[i] != -1
1936: && msg_info->valid_side[i] != sess->side; i++);
1937: if (msg_info->valid_side[i] == -1) {
1938: snprintf(ebuf, sizeof(ebuf), "rec'd %s in state %s,"
1939: " but we are %s for this session", msg_info->name,
1940: ppp_l2tp_sess_state_str(sess->state),
1941: ppp_l2tp_sess_side_str(sess->side));
1942: Log(LOG_WARNING, ("L2TP: %s", ebuf));
1943: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, ebuf);
1944: goto done;
1945: }
1946:
1947: /* Cancel reply timer and invoke handler */
1948: Log(LOG_INFO, ("L2TP: rec'd %s in state %s",
1949: msg_info->name, ppp_l2tp_sess_state_str(sess->state)));
1950: pevent_unregister(&sess->reply_timer);
1951: if ((*msg_info->sess_handler)(sess, avps, ptrs) == -1)
1952: goto fail_errno;
1953:
1954: /* If we're now expecting a reply, start expecting it */
1955: ppp_l2tp_sess_check_reply(sess);
1956: goto done;
1957:
1958: fail_invalid:
1959: /* Fail because of a bogus message */
1960: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1961: L2TP_ERROR_BAD_VALUE, "improperly formatted control message");
1962: goto done;
1963:
1964: fail_errno:
1965: /* Fail because of a system error */
1966: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1967: L2TP_ERROR_GENERIC, strerror(errno));
1968:
1969: done:
1970: /* Clean up */
1971: ppp_l2tp_avp_list_destroy(&avps);
1972: ppp_l2tp_avp_ptrs_destroy(&ptrs);
1973: }
1974:
1975: /*
1976: * Read from netgraph control socket. This is where incoming
1977: * netgraph control messages appear.
1978: */
1979: static void
1980: ppp_l2tp_ctrl_event(void *arg)
1981: {
1982: struct ppp_l2tp_ctrl *const ctrl = arg;
1983: union {
1984: u_char buf[128];
1985: struct ng_mesg msg;
1986: } buf;
1987: struct ng_mesg *const msg = &buf.msg;
1988: char raddr[NG_PATHSIZ];
1989:
1990: /* Read netgraph control message */
1991: if (NgRecvMsg(ctrl->csock, msg, sizeof(buf), raddr) < 0) {
1992: Perror("L2TP: error reading control message");
1993: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
1994: L2TP_ERROR_GENERIC, strerror(errno));
1995: return;
1996: }
1997:
1998: /* Examine message */
1999: switch (msg->header.typecookie) {
2000: case NGM_L2TP_COOKIE:
2001: switch (msg->header.cmd) {
2002: case NGM_L2TP_ACK_FAILURE:
2003: if (ctrl->state != CS_DYING) {
2004: Log(LOG_WARNING,
2005: ("L2TP: acknowledgement timeout"));
2006: ppp_l2tp_ctrl_close(ctrl,
2007: L2TP_RESULT_CLEARED, 0, NULL);
2008: }
2009: break;
2010: default:
2011: break;
2012: }
2013: break;
2014: default:
2015: break;
2016: }
2017: }
2018:
2019: /************************************************************************
2020: INCOMING CONTROL MESSAGE HANDLERS
2021: ************************************************************************/
2022:
2023: static int
2024: ppp_l2tp_handle_SCCRQ(struct ppp_l2tp_ctrl *ctrl,
2025: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2026: {
2027: struct ppp_l2tp_ctrl *ctrl2;
2028: const u_char *tiebreaker;
2029: struct ghash_walk walk;
2030: int diff;
2031: int i;
2032:
2033: /* See if there is an outstanding SCCRQ to this peer */
2034: ghash_walk_init(ppp_l2tp_ctrls, &walk);
2035: while ((ctrl2 = ghash_walk_next(ppp_l2tp_ctrls, &walk)) != NULL) {
2036: if (ctrl2 != ctrl
2037: && ctrl2->peer_id == ctrl->peer_id
2038: && ctrl2->state == CS_WAIT_CTL_REPLY)
2039: break;
2040: }
2041: if (ctrl2 == NULL)
2042: goto ok;
2043:
2044: /* Determine if we used a tie-breaker in our SCCRQ */
2045: for (tiebreaker = NULL, i = 0; i < ctrl2->avps->length; i++) {
2046: struct ppp_l2tp_avp *const avp = &ctrl2->avps->avps[i];
2047:
2048: if (avp->vendor == 0 && avp->type == AVP_TIE_BREAKER) {
2049: tiebreaker = avp->value;
2050: break;
2051: }
2052: }
2053:
2054: /* If neither side used a tie-breaker, allow this connection */
2055: if (tiebreaker == NULL && ptrs->tiebreaker == NULL)
2056: goto ok;
2057:
2058: /* Compare tie-breaker values to see who wins */
2059: if (tiebreaker == NULL) /* peer wins */
2060: diff = 1;
2061: else if (ptrs->tiebreaker == NULL) /* i win */
2062: diff = -1;
2063: else /* compare values */
2064: diff = memcmp(tiebreaker, &ptrs->tiebreaker->value, 8);
2065: if (diff == 0) { /* we both lose */
2066: Log(LOG_NOTICE, ("L2TP: SCCRQ tie: we both lose"));
2067: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_DUP_CTRL, 0, NULL);
2068: ppp_l2tp_ctrl_close(ctrl2, L2TP_RESULT_DUP_CTRL, 0, NULL);
2069: return (0);
2070: }
2071: if (diff > 0) { /* i win */
2072: Log(LOG_NOTICE, ("L2TP: SCCRQ tie: peer loses"));
2073: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_DUP_CTRL, 0, NULL);
2074: return (0);
2075: }
2076: Log(LOG_NOTICE, ("L2TP: SCCRQ tie: peer wins"));
2077: ppp_l2tp_ctrl_close(ctrl2, L2TP_RESULT_DUP_CTRL, 0, NULL);
2078:
2079: ok:
2080: /* Do control connection setup */
2081: if (ppp_l2tp_ctrl_setup_1(ctrl, ptrs) == -1)
2082: return (-1);
2083:
2084: /* Send response and update state */
2085: ctrl->state = CS_WAIT_CTL_CONNECT;
2086: ppp_l2tp_ctrl_send(ctrl, 0, SCCRP, ctrl->avps);
2087: return (0);
2088: }
2089:
2090: static int
2091: ppp_l2tp_handle_SCCRP(struct ppp_l2tp_ctrl *ctrl,
2092: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2093: {
2094: /* Do control connection setup */
2095: if (ppp_l2tp_ctrl_setup_1(ctrl, ptrs) == -1)
2096: return (-1);
2097: if (ppp_l2tp_ctrl_setup_2(ctrl, ptrs) == -1)
2098: return (-1);
2099:
2100: /* Send response and update state */
2101: ctrl->state = CS_ESTABLISHED;
2102: ppp_l2tp_ctrl_send(ctrl, 0, SCCCN, ctrl->avps);
2103: if (*ctrl->cb->ctrl_connected != NULL)
2104: (*ctrl->cb->ctrl_connected)(ctrl);
2105: return (0);
2106: }
2107:
2108: static int
2109: ppp_l2tp_handle_SCCCN(struct ppp_l2tp_ctrl *ctrl,
2110: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2111: {
2112: /* Do control connection setup */
2113: if (ppp_l2tp_ctrl_setup_2(ctrl, ptrs) == -1)
2114: return (-1);
2115:
2116: /* Update state */
2117: ctrl->state = CS_ESTABLISHED;
2118: if (*ctrl->cb->ctrl_connected != NULL)
2119: (*ctrl->cb->ctrl_connected)(ctrl);
2120: return (0);
2121: }
2122:
2123: static int
2124: ppp_l2tp_handle_StopCCN(struct ppp_l2tp_ctrl *ctrl,
2125: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2126: {
2127: struct ppp_l2tp_sess *sess;
2128: struct ghash_walk walk;
2129:
2130: /* StopCCN implies closing all sessions */
2131: ctrl->peer_notified = 1;
2132: ghash_walk_init(ctrl->sessions, &walk);
2133: while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL)
2134: sess->peer_notified = 1;
2135:
2136: /* Close control connection */
2137: ppp_l2tp_ctrl_close(ctrl, ptrs->errresultcode->result,
2138: ptrs->errresultcode->error, ptrs->errresultcode->errmsg);
2139: return (0);
2140: }
2141:
2142: static int
2143: ppp_l2tp_handle_HELLO(struct ppp_l2tp_ctrl *ctrl,
2144: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2145: {
2146: return (0);
2147: }
2148:
2149: static int
2150: ppp_l2tp_handle_OCRQ(struct ppp_l2tp_ctrl *ctrl,
2151: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2152: {
2153: struct ppp_l2tp_sess *sess;
2154:
2155: /* Create new session */
2156: if ((sess = ppp_l2tp_sess_create(ctrl, ORIG_REMOTE, SIDE_LAC,
2157: ptrs->serialnum->serialnum)) == NULL)
2158: return (-1);
2159: sess->peer_id = ptrs->sessionid->id;
2160:
2161: /* Notify link side */
2162: (*ctrl->cb->initiated)(ctrl, sess, 1, avps, &sess->include_length, &sess->enable_dseq);
2163:
2164: if (sess->state != SS_DYING) {
2165: /* Send response */
2166: ppp_l2tp_ctrl_send(ctrl, sess->peer_id, OCRP, sess->my_avps);
2167: }
2168:
2169: /* Clean up */
2170: return (0);
2171: }
2172:
2173: static int
2174: ppp_l2tp_handle_ICRQ(struct ppp_l2tp_ctrl *ctrl,
2175: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2176: {
2177: struct ppp_l2tp_sess *sess;
2178:
2179: /* Create new session */
2180: if ((sess = ppp_l2tp_sess_create(ctrl, ORIG_REMOTE, SIDE_LNS,
2181: ptrs->serialnum->serialnum)) == NULL)
2182: return (-1);
2183: sess->peer_id = ptrs->sessionid->id;
2184:
2185: /* Notify link side */
2186: (*ctrl->cb->initiated)(ctrl, sess, 0, avps, &sess->include_length, &sess->enable_dseq);
2187:
2188: if (sess->state != SS_DYING) {
2189: /* Send response */
2190: ppp_l2tp_ctrl_send(ctrl, sess->peer_id, ICRP, sess->my_avps);
2191: ppp_l2tp_sess_check_reply(sess);
2192: }
2193:
2194: /* Clean up */
2195: return (0);
2196: }
2197:
2198: static int
2199: ppp_l2tp_handle_OCRP(struct ppp_l2tp_sess *sess,
2200: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2201: {
2202: if (sess->state == SS_DYING)
2203: return (0);
2204:
2205: sess->peer_id = ptrs->sessionid->id;
2206: sess->state = SS_WAIT_CONNECT;
2207: return (0);
2208: }
2209:
2210: static int
2211: ppp_l2tp_handle_xCCN(struct ppp_l2tp_sess *sess,
2212: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2213: {
2214: if (sess->state == SS_DYING)
2215: return (0);
2216:
2217: /* Save peer's AVP's for this session */
2218: ppp_l2tp_avp_list_destroy(&sess->peer_avps);
2219: if ((sess->peer_avps = ppp_l2tp_avp_list_copy(avps)) == NULL)
2220: return (-1);
2221:
2222: /* Set up session */
2223: sess->dseq_required = (ptrs->seqrequired != NULL);
2224: if (ppp_l2tp_sess_setup(sess) == -1)
2225: return (-1);
2226:
2227: /* Done */
2228: return (0);
2229: }
2230:
2231: static int
2232: ppp_l2tp_handle_ICRP(struct ppp_l2tp_sess *sess,
2233: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2234: {
2235: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
2236: char buf[64];
2237:
2238: if (sess->state == SS_DYING)
2239: return (0);
2240:
2241: /* Save peer ID */
2242: sess->peer_id = ptrs->sessionid->id;
2243:
2244: /* Detect duplicate ICRP's */
2245: if (sess->peer_responded) {
2246: snprintf(buf, sizeof(buf), "rec'd duplicate %s in state %s",
2247: "ICRP", ppp_l2tp_sess_state_str(sess->state));
2248: Log(LOG_WARNING, ("L2TP: %s", buf));
2249: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, buf);
2250: return (0);
2251: }
2252:
2253: /* Check status for locally initiated incoming call */
2254: sess->peer_responded = 1;
2255: if (ppp_l2tp_sess_check_liic(sess) == -1)
2256: return (-1);
2257:
2258: /* Done */
2259: return (0);
2260: }
2261:
2262: static int
2263: ppp_l2tp_handle_CDN(struct ppp_l2tp_sess *sess,
2264: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2265: {
2266: sess->peer_notified = 1;
2267: ppp_l2tp_sess_close(sess, ptrs->errresultcode->result,
2268: ptrs->errresultcode->error, ptrs->errresultcode->errmsg);
2269: return (0);
2270: }
2271:
2272: static int
2273: ppp_l2tp_handle_SLI(struct ppp_l2tp_sess *sess,
2274: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2275: {
2276: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
2277:
2278: if (sess->state == SS_DYING)
2279: return (0);
2280:
2281: if (ctrl->cb->set_link_info == NULL)
2282: return (0);
2283: (*ctrl->cb->set_link_info)(sess, ptrs->accm->xmit, ptrs->accm->recv);
2284: return (0);
2285: }
2286:
2287: static int
2288: ppp_l2tp_handle_WEN(struct ppp_l2tp_sess *sess,
2289: const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
2290: {
2291: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
2292:
2293: if (sess->state == SS_DYING)
2294: return (0);
2295:
2296: if (ctrl->cb->wan_error_notify == NULL)
2297: return (0);
2298: (*ctrl->cb->wan_error_notify)(sess, ptrs->callerror->crc,
2299: ptrs->callerror->frame, ptrs->callerror->overrun,
2300: ptrs->callerror->buffer, ptrs->callerror->timeout,
2301: ptrs->callerror->alignment);
2302: return (0);
2303: }
2304:
2305: /************************************************************************
2306: REPLY EXPECTORS
2307: ************************************************************************/
2308:
2309: static pevent_handler_t ppp_l2tp_ctrl_reply_timeout;
2310: static pevent_handler_t ppp_l2tp_sess_reply_timeout;
2311:
2312: static void
2313: ppp_l2tp_ctrl_check_reply(struct ppp_l2tp_ctrl *ctrl)
2314: {
2315: pevent_unregister(&ctrl->reply_timer);
2316: switch (ctrl->state) {
2317: case CS_IDLE:
2318: case CS_WAIT_CTL_REPLY:
2319: case CS_WAIT_CTL_CONNECT:
2320: if (pevent_register(ctrl->ctx, &ctrl->reply_timer, 0,
2321: ctrl->mutex, ppp_l2tp_ctrl_reply_timeout, ctrl, PEVENT_TIME,
2322: L2TP_REPLY_TIMEOUT * 1000) == -1)
2323: Perror("L2TP: error starting reply timer");
2324: break;
2325: default:
2326: break;
2327: }
2328: }
2329:
2330: static void
2331: ppp_l2tp_sess_check_reply(struct ppp_l2tp_sess *sess)
2332: {
2333: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
2334:
2335: pevent_unregister(&sess->reply_timer);
2336: switch (sess->state) {
2337: case SS_WAIT_REPLY:
2338: case SS_WAIT_CONNECT:
2339: if (pevent_register(ctrl->ctx, &sess->reply_timer, 0,
2340: ctrl->mutex, ppp_l2tp_sess_reply_timeout, sess, PEVENT_TIME,
2341: L2TP_REPLY_TIMEOUT * 1000) == -1)
2342: Perror("L2TP: error starting reply timer");
2343: break;
2344: default:
2345: break;
2346: }
2347: }
2348:
2349: static void
2350: ppp_l2tp_ctrl_reply_timeout(void *arg)
2351: {
2352: struct ppp_l2tp_ctrl *const ctrl = arg;
2353:
2354: pevent_unregister(&ctrl->reply_timer);
2355: Log(LOG_NOTICE, ("L2TP: reply timeout in state %s",
2356: ppp_l2tp_ctrl_state_str(ctrl->state)));
2357: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
2358: L2TP_ERROR_GENERIC, "expecting reply; none received");
2359: }
2360:
2361: static void
2362: ppp_l2tp_sess_reply_timeout(void *arg)
2363: {
2364: struct ppp_l2tp_sess *const sess = arg;
2365: struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
2366:
2367: pevent_unregister(&sess->reply_timer);
2368: Log(LOG_NOTICE, ("L2TP: reply timeout in state %s",
2369: ppp_l2tp_sess_state_str(sess->state)));
2370: ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
2371: L2TP_ERROR_GENERIC, "expecting reply; none received");
2372: }
2373:
2374: /************************************************************************
2375: CONTROL AND SESSION OBJECT DESTRUCTORS
2376: ************************************************************************/
2377:
2378: /*
2379: * Immediately destroy a control connection and all associated sessions.
2380: */
2381: void
2382: ppp_l2tp_ctrl_destroy(struct ppp_l2tp_ctrl **ctrlp)
2383: {
2384: struct ppp_l2tp_ctrl *const ctrl = *ctrlp;
2385:
2386: /* Sanity */
2387: if (ctrl == NULL)
2388: return;
2389: *ctrlp = NULL;
2390:
2391: /* Destroy all sessions */
2392: while (ghash_size(ctrl->sessions) > 0) {
2393: struct ppp_l2tp_sess *sess;
2394: struct ghash_walk walk;
2395:
2396: ghash_walk_init(ctrl->sessions, &walk);
2397: sess = ghash_walk_next(ctrl->sessions, &walk);
2398: ppp_l2tp_sess_destroy(&sess);
2399: }
2400:
2401: /* Destroy netgraph node */
2402: (void)NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL,
2403: NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0);
2404:
2405: /* Destroy control connection */
2406: ghash_remove(ppp_l2tp_ctrls, ctrl);
2407: if (ghash_size(ppp_l2tp_ctrls) == 0)
2408: ghash_destroy(&ppp_l2tp_ctrls);
2409: (void)close(ctrl->csock);
2410: (void)close(ctrl->dsock);
2411: pevent_unregister(&ctrl->reply_timer);
2412: pevent_unregister(&ctrl->close_timer);
2413: pevent_unregister(&ctrl->death_timer);
2414: pevent_unregister(&ctrl->idle_timer);
2415: pevent_unregister(&ctrl->ctrl_event);
2416: pevent_unregister(&ctrl->data_event);
2417: ppp_l2tp_avp_list_destroy(&ctrl->avps);
2418: ghash_destroy(&ctrl->sessions);
2419: Freee(ctrl->secret);
2420: Freee(ctrl->errmsg);
2421: memset(ctrl, 0, sizeof(*ctrl));
2422: Freee(ctrl);
2423: }
2424:
2425: /*
2426: * Immediately destroy a session.
2427: */
2428: static void
2429: ppp_l2tp_sess_destroy(struct ppp_l2tp_sess **sessp)
2430: {
2431: struct ppp_l2tp_sess *const sess = *sessp;
2432: struct ppp_l2tp_ctrl *ctrl;
2433: char path[32];
2434:
2435: /* Sanity */
2436: if (sess == NULL)
2437: return;
2438: *sessp = NULL;
2439:
2440: /* Destroy session */
2441: ctrl = sess->ctrl;
2442: if (sess->state != SS_DYING || sess->close_timer) {
2443: ctrl->active_sessions--;
2444: /* Close control connection after last session closes */
2445: if (ctrl->active_sessions == 0) {
2446: if (ctrl->state == CS_DYING) {
2447: ppp_l2tp_ctrl_death_start(ctrl);
2448: } else if (pevent_register(ctrl->ctx, &ctrl->death_timer, 0,
2449: ctrl->mutex, ppp_l2tp_unused_timeout, ctrl,
2450: PEVENT_TIME, gL2TPto * 1000) == -1) {
2451: Perror("L2TP: error starting unused timer");
2452: }
2453: }
2454: }
2455: ghash_remove(ctrl->sessions, sess);
2456: snprintf(path, sizeof(path), "[%lx]:", (u_long)sess->node_id);
2457: (void)NgSendMsg(ctrl->csock, path,
2458: NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0);
2459: ppp_l2tp_avp_list_destroy(&sess->my_avps);
2460: ppp_l2tp_avp_list_destroy(&sess->peer_avps);
2461: pevent_unregister(&sess->notify_timer);
2462: pevent_unregister(&sess->reply_timer);
2463: pevent_unregister(&sess->close_timer);
2464: pevent_unregister(&sess->death_timer);
2465: Freee(sess->errmsg);
2466: memset(sess, 0, sizeof(*sess));
2467: Freee(sess);
2468: }
2469:
2470: /************************************************************************
2471: HASH TABLE FUNCTIONS
2472: ************************************************************************/
2473:
2474: static int
2475: ppp_l2tp_ctrl_equal(struct ghash *g, const void *item1, const void *item2)
2476: {
2477: const struct ppp_l2tp_ctrl *const ctrl1 = item1;
2478: const struct ppp_l2tp_ctrl *const ctrl2 = item2;
2479:
2480: return (ctrl1->config.tunnel_id == ctrl2->config.tunnel_id);
2481: }
2482:
2483: static u_int32_t
2484: ppp_l2tp_ctrl_hash(struct ghash *g, const void *item)
2485: {
2486: const struct ppp_l2tp_ctrl *const ctrl = item;
2487:
2488: return ((u_int32_t)ctrl->config.tunnel_id);
2489: }
2490:
2491: static int
2492: ppp_l2tp_sess_equal(struct ghash *g, const void *item1, const void *item2)
2493: {
2494: const struct ppp_l2tp_sess *const sess1 = item1;
2495: const struct ppp_l2tp_sess *const sess2 = item2;
2496:
2497: return (sess1->config.session_id == sess2->config.session_id);
2498: }
2499:
2500: static u_int32_t
2501: ppp_l2tp_sess_hash(struct ghash *g, const void *item)
2502: {
2503: const struct ppp_l2tp_sess *const sess = item;
2504:
2505: return ((u_int32_t)sess->config.session_id);
2506: }
2507:
2508: /************************************************************************
2509: STRING CONVERTERS
2510: ************************************************************************/
2511:
2512: /*
2513: * Dump an AVP list.
2514: */
2515: static void
2516: ppp_l2tp_ctrl_dump(struct ppp_l2tp_ctrl *ctrl,
2517: struct ppp_l2tp_avp_list *avps, const char *fmt, ...)
2518: {
2519: char buf[1024];
2520: va_list args;
2521: int i;
2522:
2523: va_start(args, fmt);
2524: vsnprintf(buf, sizeof(buf), fmt, args);
2525: va_end(args);
2526: for (i = 0; i < avps->length; i++) {
2527: struct ppp_l2tp_avp *const avp = &avps->avps[i];
2528: const struct ppp_l2tp_avp_info *info;
2529: int j;
2530:
2531: strlcat(buf, i > 0 ? " [" : "[", sizeof(buf));
2532: for (j = 0; (info = &ppp_l2tp_avp_info_list[j])->name != NULL
2533: && (info->vendor != avp->vendor
2534: || info->type != avp->type); j++);
2535: if (info->name != NULL) {
2536: strlcat(buf, info->name, sizeof(buf));
2537: strlcat(buf, " ", sizeof(buf));
2538: (*info->decode)(info, avp,
2539: buf + strlen(buf), sizeof(buf) - strlen(buf));
2540: } else {
2541: snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
2542: "%u:%u vlen=%u", avp->vendor, avp->type, avp->vlen);
2543: }
2544: strlcat(buf, "]", sizeof(buf));
2545: }
2546: Log(LOG_DEBUG, ("%s", buf));
2547: }
2548:
2549: static const char *
2550: ppp_l2tp_ctrl_state_str(enum l2tp_ctrl_state state)
2551: {
2552: switch (state) {
2553: case CS_IDLE:
2554: return ("idle");
2555: case CS_WAIT_CTL_REPLY:
2556: return ("wait-ctl-reply");
2557: case CS_WAIT_CTL_CONNECT:
2558: return ("wait-ctl-conn");
2559: case CS_ESTABLISHED:
2560: return ("established");
2561: case CS_DYING:
2562: return ("dying");
2563: default:
2564: return ("UNKNOWN");
2565: }
2566: }
2567:
2568: static const char *
2569: ppp_l2tp_sess_state_str(enum l2tp_ctrl_state state)
2570: {
2571: switch (state) {
2572: case SS_WAIT_REPLY:
2573: return ("wait-cs-reply");
2574: case SS_WAIT_CONNECT:
2575: return ("wait-connect");
2576: case SS_WAIT_ANSWER:
2577: return ("wait-answer");
2578: case SS_ESTABLISHED:
2579: return ("established");
2580: case SS_DYING:
2581: return ("dying");
2582: default:
2583: return ("UNKNOWN");
2584: }
2585: }
2586:
2587: static const char *
2588: ppp_l2tp_sess_orig_str(enum l2tp_sess_orig orig)
2589: {
2590: return (orig == ORIG_LOCAL ? "local" : "remote");
2591: }
2592:
2593: static const char *
2594: ppp_l2tp_sess_side_str(enum l2tp_sess_side side)
2595: {
2596: return (side == SIDE_LNS ? "LNS" : "LAC");
2597: }
2598:
2599: char *
2600: ppp_l2tp_ctrl_stats(struct ppp_l2tp_ctrl *ctrl, char *buf, size_t buf_len)
2601: {
2602: snprintf(buf, buf_len, "%s",
2603: ppp_l2tp_ctrl_state_str(ctrl->state));
2604: return (buf);
2605: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>