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