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