Annotation of embedaddon/libpdel/ppp/ppp_l2tp_server.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_engine.h"
44: #include "ppp/ppp_fsm_option.h"
45: #include "ppp/ppp_auth.h"
46: #include "ppp/ppp_lcp.h"
47: #include "ppp/ppp_link.h"
48: #include "ppp/ppp_channel.h"
49: #include "ppp/ppp_l2tp_avp.h"
50: #include "ppp/ppp_l2tp_server.h"
51: #include "ppp/ppp_l2tp_ctrl.h"
52:
53: #include <net/ethernet.h>
54: #include <netinet/in_systm.h>
55: #include <netinet/ip.h>
56: #include <netinet/udp.h>
57:
58: #include <netgraph/ng_ksocket.h>
59:
60: #define L2TP_MTYPE "ppp_l2tp"
61: #define L2TP_OUTPUT_MTYPE "ppp_l2tp.output"
62: #define L2TP_DEVICE_MTYPE "ppp_l2tp.device"
63: #define L2TP_PEER_MTYPE "ppp_l2tp.peer"
64:
65: /* Win2k is too stupid to handle changing the UDP port */
66: #define L2TP_CHANGE_PORT 0
67:
68: #if 0 /* win2k seems to require at least 1500 */
69: #define L2TP_MRU \
70: (ETHER_MAX_LEN /* standard ethernet frame */ \
71: - ETHER_CRC_LEN /* ethernet crc */ \
72: - ETHER_HDR_LEN /* ethernet header */ \
73: - sizeof(struct ip) /* ip header */ \
74: - sizeof(struct udp) /* udp header */ \
75: - 10 /* l2tp header */
76: - 2) /* ppp protocol field */
77: #else
78: #define L2TP_MRU LCP_DEFAULT_MRU
79: #endif
80:
81: #define L2TP_MRRU LCP_DEFAULT_MRRU
82:
83: /* L2TP server info */
84: struct ppp_l2tp_server {
85: struct ppp_l2tp_server_info info; /* client info */
86: struct ppp_log *log; /* ppp log */
87: struct ppp_engine *engine; /* ppp engine */
88: struct ghash *peers; /* active peers */
89: struct pevent_ctx *ev_ctx; /* event context */
90: pthread_mutex_t *mutex; /* mutex */
91: struct in_addr ip; /* server ip address */
92: u_int16_t port; /* server udp port */
93: int sock; /* udp listen socket */
94: struct pevent *sock_event; /* event context */
95: };
96:
97: /* We keep one of these for each control connection */
98: struct ppp_l2tp_peer {
99: struct ppp_l2tp_server *s; /* pointer to server */
100: struct ppp_l2tp_ctrl *ctrl; /* ctrl connection */
101: void *carg; /* client callbck arg */
102: struct ppp_l2tp_sess *sess; /* l2tp session */
103: struct ppp_channel *chan; /* pointer to channel */
104: struct ppp_auth_config auth; /* auth config */
105: char node[32]; /* node path */
106: char hook[NG_HOOKSIZ]; /* node hook */
107: char logname[32]; /* peer logname */
108: struct in_addr ip; /* peer ip address */
109: u_int16_t port; /* peer port */
110: u_char closed; /* closed by client */
111: };
112:
113: /* L2TP control callbacks */
114: static ppp_l2tp_ctrl_terminated_t ppp_l2tp_server_ctrl_terminated;
115: static ppp_l2tp_initiated_t ppp_l2tp_server_initiated;
116: static ppp_l2tp_connected_t ppp_l2tp_server_connected;
117: static ppp_l2tp_terminated_t ppp_l2tp_server_terminated;
118:
119: static const struct ppp_l2tp_ctrl_cb ppp_l2tp_server_ctrl_cb = {
120: ppp_l2tp_server_ctrl_terminated,
121: ppp_l2tp_server_initiated,
122: ppp_l2tp_server_connected,
123: ppp_l2tp_server_terminated,
124: NULL,
125: NULL,
126: };
127:
128: /* Device methods */
129: static ppp_channel_open_t ppp_l2tp_server_device_open;
130: static ppp_channel_close_t ppp_l2tp_server_device_close;
131: static ppp_channel_destroy_t ppp_l2tp_server_device_destroy;
132: static ppp_channel_free_output_t ppp_l2tp_server_device_free_output;
133: static ppp_channel_set_link_info_t ppp_l2tp_server_device_set_link_info;
134: static ppp_channel_get_origination_t ppp_l2tp_server_device_get_origination;
135: static ppp_channel_get_node_t ppp_l2tp_server_device_get_node;
136: static ppp_channel_get_hook_t ppp_l2tp_server_device_get_hook;
137: static ppp_channel_is_async_t ppp_l2tp_server_device_is_async;
138: static ppp_channel_get_mtu_t ppp_l2tp_server_device_get_mtu;
139: static ppp_channel_get_acfcomp_t ppp_l2tp_server_device_get_acfcomp;
140: static ppp_channel_get_pfcomp_t ppp_l2tp_server_device_get_pfcomp;
141:
142: static struct ppp_channel_meth ppp_l2tp_server_device_meth = {
143: ppp_l2tp_server_device_open,
144: ppp_l2tp_server_device_close,
145: ppp_l2tp_server_device_destroy,
146: ppp_l2tp_server_device_free_output,
147: ppp_l2tp_server_device_set_link_info,
148: ppp_l2tp_server_device_get_origination,
149: ppp_l2tp_server_device_get_node,
150: ppp_l2tp_server_device_get_hook,
151: ppp_l2tp_server_device_is_async,
152: ppp_l2tp_server_device_get_mtu,
153: ppp_l2tp_server_device_get_acfcomp,
154: ppp_l2tp_server_device_get_pfcomp,
155: };
156:
157: /* Other internal functions */
158: static int ppp_l2tp_server_new_sess(struct ppp_l2tp_peer *peer,
159: struct ppp_l2tp_sess *sess);
160: static void ppp_l2tp_server_destroy(struct ppp_l2tp_server **sp);
161: static void ppp_l2tp_server_peer_destroy(struct ppp_l2tp_peer **peerp);
162: static void ppp_l2tp_server_device_output(struct ppp_l2tp_peer *peer,
163: enum ppp_channeloutput type, ...);
164: static void ppp_l2tp_server_close_client(struct ppp_l2tp_peer *peer);
165:
166: static pevent_handler_t ppp_l2tp_server_sock_event;
167:
168: static const int one = 1;
169:
170: /* Macro for logging */
171: #define LOG(sev, fmt, args...) PPP_LOG(s->log, sev, fmt , ## args)
172:
173: /***********************************************************************
174: PUBLIC FUNCTIONS
175: ***********************************************************************/
176:
177: /*
178: * Start the L2TP server associated with a ppp engine.
179: */
180: int
181: ppp_l2tp_server_start(struct ppp_engine *engine,
182: const struct ppp_l2tp_server_info *info,
183: struct in_addr ip, u_int16_t port, u_int max_conn)
184: {
185: struct ppp_log *const elog = ppp_engine_get_log(engine);
186: struct sockaddr_in sin;
187: struct ppp_l2tp_server *s;
188:
189: /* Sanity */
190: if (engine == NULL || info->arg == NULL) {
191: errno = EINVAL;
192: return (-1);
193: }
194:
195: /* See if server already exists */
196: if ((s = ppp_engine_get_l2tp_server(engine)) != NULL) {
197: errno = EALREADY;
198: return (-1);
199: }
200:
201: /* Create new server */
202: if ((s = MALLOC(L2TP_MTYPE, sizeof(*s))) == NULL)
203: return (-1);
204: memset(s, 0, sizeof(*s));
205: s->engine = engine;
206: s->ev_ctx = ppp_engine_get_ev_ctx(engine);
207: s->mutex = ppp_engine_get_mutex(engine);
208: s->sock = -1;
209: s->log = ppp_log_dup(elog);
210: s->info = *info;
211: s->ip = ip;
212: s->port = (port != 0) ? port : L2TP_PORT;
213:
214: /* Create control connection hash table */
215: if ((s->peers = ghash_create(s, 0, 0,
216: L2TP_MTYPE, NULL, NULL, NULL, NULL)) == NULL) {
217: ppp_log_put(elog, LOG_ERR, "ghash_create: %m");
218: goto fail;
219: }
220:
221: /* Setup UDP socket that listens for new connections */
222: if ((s->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
223: ppp_log_put(elog, LOG_ERR, "socket: %m");
224: goto fail;
225: }
226: if (setsockopt(s->sock, SOL_SOCKET,
227: SO_REUSEADDR, &one, sizeof(one)) == -1) {
228: ppp_log_put(elog, LOG_ERR, "setsockopt: %m");
229: goto fail;
230: }
231: if (setsockopt(s->sock, SOL_SOCKET,
232: SO_REUSEPORT, &one, sizeof(one)) == -1) {
233: ppp_log_put(elog, LOG_ERR, "setsockopt: %m");
234: goto fail;
235: }
236: memset(&sin, 0, sizeof(sin));
237: #ifndef __linux__
238: sin.sin_len = sizeof(sin);
239: #endif
240: sin.sin_family = AF_INET;
241: sin.sin_addr = ip;
242: sin.sin_port = htons(s->port);
243: if (bind(s->sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
244: ppp_log_put(elog, LOG_ERR, "bind: %m");
245: goto fail;
246: }
247: if (pevent_register(s->ev_ctx, &s->sock_event, PEVENT_RECURRING,
248: s->mutex, ppp_l2tp_server_sock_event, s, PEVENT_READ,
249: s->sock) == -1) {
250: ppp_log_put(elog, LOG_ERR, "pevent_register: %m");
251: goto fail;
252: }
253:
254: /* Done */
255: ppp_engine_set_l2tp_server(engine, s);
256: return (0);
257:
258: fail:
259: /* Clean up after failure */
260: pevent_unregister(&s->sock_event);
261: if (s->sock != -1)
262: close(s->sock);
263: ghash_destroy(&s->peers);
264: FREE(L2TP_MTYPE, s);
265: return (-1);
266: }
267:
268: /*
269: * Stop the L2TP server associated with a ppp engine.
270: *
271: * We can't completely destroy it, because there may be L2TP devices
272: * in use by ppp_link's that still exist. The ppp_link's are responsible
273: * for destroying their devices, not us.
274: */
275: void
276: ppp_l2tp_server_stop(struct ppp_engine *engine)
277: {
278: struct ppp_l2tp_server *s;
279:
280: /* Get and clear L2TP server */
281: if ((s = ppp_engine_get_l2tp_server(engine)) == NULL)
282: return;
283: ppp_engine_set_l2tp_server(s->engine, NULL);
284:
285: /* Stop accepting new connections */
286: pevent_unregister(&s->sock_event);
287: (void)close(s->sock);
288: s->sock = -1;
289:
290: /* If there are no control connections, clean up now */
291: if (ghash_size(s->peers) == 0) {
292: ppp_l2tp_server_destroy(&s);
293: return;
294: }
295:
296: /* Destroy all control connections */
297: while (1) {
298: struct ppp_l2tp_peer *peer;
299: struct ghash_walk walk;
300:
301: ghash_walk_init(s->peers, &walk);
302: while ((peer = ghash_walk_next(s->peers, &walk)) != NULL) {
303:
304: /*
305: * Destroy control connection and session (if any).
306: * We do a 'close' before the 'destroy' to cause at
307: * least one StopCCN packet to be generated, in an
308: * attempt to be a little nicer to the peer.
309: */
310: if (peer->ctrl != NULL) {
311: ppp_l2tp_ctrl_shutdown(peer->ctrl,
312: L2TP_RESULT_SHUTDOWN, 0, NULL);
313: ppp_l2tp_ctrl_destroy(&peer->ctrl);
314: peer->sess = NULL;
315: }
316:
317: /* Notify client side peer is gone */
318: ppp_l2tp_server_close_client(peer);
319:
320: /* Destroy peer if it has no more references */
321: if (peer->chan == NULL) {
322: ppp_l2tp_server_peer_destroy(&peer);
323: break; /* restart; walk is invalid */
324: }
325: }
326: if (peer == NULL)
327: break;
328: }
329: }
330:
331: /*
332: * Destroy the L2TP server object.
333: */
334: static void
335: ppp_l2tp_server_destroy(struct ppp_l2tp_server **sp)
336: {
337: struct ppp_l2tp_server *const s = *sp;
338:
339: /* Sanity */
340: if (s == NULL)
341: return;
342: *sp = NULL;
343:
344: /* Deallocate */
345: assert(ghash_size(s->peers) == 0);
346: pevent_unregister(&s->sock_event);
347: (void)close(s->sock);
348: ghash_destroy(&s->peers);
349: ppp_log_close(&s->log);
350: FREE(L2TP_MTYPE, s);
351: }
352:
353: /*
354: * Close a L2TP connection.
355: */
356: void
357: ppp_l2tp_server_close(struct ppp_engine *engine, struct ppp_l2tp_peer **peerp)
358: {
359: struct ppp_l2tp_peer *const peer = *peerp;
360:
361: if (peer == NULL)
362: return;
363: *peerp = NULL;
364: peer->carg = NULL; /* don't call client 'destroy' method */
365: if (peer->chan != NULL)
366: ppp_l2tp_server_device_close(peer->chan);
367: }
368:
369: /*
370: * Get the client handle for the L2TP channel associated with a device.
371: */
372: void *
373: ppp_l2tp_server_get_client_info(struct ppp_channel *chan)
374: {
375: struct ppp_l2tp_peer *const peer = chan->priv;
376:
377: if (chan->meth != &ppp_l2tp_server_device_meth) {
378: errno = EINVAL;
379: return (NULL);
380: }
381: if (peer->carg == NULL)
382: errno = ENXIO;
383: return (peer->carg);
384: }
385:
386: /***********************************************************************
387: L2TP CONTROL CALLBACKS
388: ***********************************************************************/
389:
390: /*
391: * This is called when a control connection is terminated for any reason
392: * other than a call ppp_l2tp_ctrl_destroy().
393: */
394: static void
395: ppp_l2tp_server_ctrl_terminated(struct ppp_l2tp_ctrl *ctrl,
396: u_int16_t result, u_int16_t error, const char *errmsg)
397: {
398: struct ppp_l2tp_peer *peer = ppp_l2tp_ctrl_get_cookie(ctrl);
399: struct ppp_l2tp_server *const s = peer->s;
400:
401: /* Debugging */
402: LOG(LOG_DEBUG, "%s: invoked ctrl=%p errmsg=\"%s\"",
403: __FUNCTION__, ctrl, errmsg);
404:
405: /* Notify client side peer is gone */
406: ppp_l2tp_server_close_client(peer);
407:
408: /* There should be no session */
409: assert(peer->sess == NULL);
410: peer->ctrl = NULL;
411:
412: /* Destroy peer if it has no more references */
413: if (peer->chan == NULL)
414: ppp_l2tp_server_peer_destroy(&peer);
415: }
416:
417: /*
418: * This callback is used to report the peer's initiating a new incoming
419: * or outgoing call.
420: */
421: static void
422: ppp_l2tp_server_initiated(struct ppp_l2tp_ctrl *ctrl,
423: struct ppp_l2tp_sess *sess, int out,
424: const struct ppp_l2tp_avp_list *avps)
425: {
426: struct ppp_l2tp_peer *const peer = ppp_l2tp_ctrl_get_cookie(ctrl);
427: struct ppp_l2tp_server *const s = peer->s;
428:
429: /* Debugging */
430: LOG(LOG_DEBUG, "%s: invoked ctrl=%p sess=%p out=%d",
431: __FUNCTION__, ctrl, sess, out);
432:
433: /* If call is incoming, wait for peer to reply */
434: if (!out) {
435: ppp_l2tp_sess_set_cookie(sess, peer);
436: return;
437: }
438:
439: /* Accept call */
440: if (ppp_l2tp_server_new_sess(peer, sess) == -1) {
441: ppp_l2tp_terminate(sess, L2TP_RESULT_ERROR,
442: L2TP_ERROR_GENERIC, strerror(errno));
443: return;
444: }
445:
446: /* Notify control code */
447: ppp_l2tp_connected(sess, NULL);
448: }
449:
450: /*
451: * This callback is used to report successful connection of a remotely
452: * initiated incoming call (see ppp_l2tp_initiated_t) or a locally initiated
453: * outgoing call (see ppp_l2tp_initiate()).
454: */
455: static void
456: ppp_l2tp_server_connected(struct ppp_l2tp_sess *sess,
457: const struct ppp_l2tp_avp_list *avps)
458: {
459: struct ppp_l2tp_peer *const peer = ppp_l2tp_sess_get_cookie(sess);
460: struct ppp_l2tp_server *const s = peer->s;
461:
462: /* Debugging */
463: LOG(LOG_DEBUG, "%s: invoked sess=%p", __FUNCTION__, sess);
464:
465: /* Accept call */
466: if (ppp_l2tp_server_new_sess(peer, sess) == -1) {
467: ppp_l2tp_terminate(sess, L2TP_RESULT_ERROR,
468: L2TP_ERROR_GENERIC, strerror(errno));
469: return;
470: }
471: }
472:
473: /*
474: * This callback is called when any call, whether successfully connected
475: * or not, is terminated for any reason other than explict termination
476: * from the link side (via a call to either ppp_l2tp_terminate() or
477: * ppp_l2tp_ctrl_destroy()).
478: */
479: static void
480: ppp_l2tp_server_terminated(struct ppp_l2tp_sess *sess,
481: u_int16_t result, u_int16_t error, const char *errmsg)
482: {
483: struct ppp_l2tp_peer *const peer = ppp_l2tp_sess_get_cookie(sess);
484: struct ppp_l2tp_server *const s = peer->s;
485: char buf[128];
486:
487: /* Debugging */
488: LOG(LOG_DEBUG, "%s: invoked sess=%p", __FUNCTION__, sess);
489:
490: /* Sanity */
491: assert(peer->sess == NULL || peer->sess == sess);
492: assert(peer->ctrl != NULL);
493:
494: /* Control side is notifying us session is down */
495: peer->sess = NULL;
496: snprintf(buf, sizeof(buf), "result=%u error=%u errmsg=\"%s\"",
497: result, error, (errmsg != NULL) ? errmsg : "");
498: LOG(LOG_INFO, "call from %s terminated: %s", peer->logname, buf);
499:
500: /* Notify client side peer is gone */
501: ppp_l2tp_server_close_client(peer);
502:
503: /* Notify PPP stack session is down */
504: if (peer->chan != NULL) {
505: ppp_l2tp_server_device_output(peer,
506: PPP_CHANNEL_OUTPUT_DOWN_FATAL,
507: (errmsg != NULL) ? errmsg : "administratively closed");
508: }
509: }
510:
511: /***********************************************************************
512: INTERNAL FUNCTIONS
513: ***********************************************************************/
514:
515: /*
516: * Read an incoming packet that might be a new L2TP connection.
517: */
518: static void
519: ppp_l2tp_server_sock_event(void *arg)
520: {
521: struct ppp_l2tp_server *const s = arg;
522: struct ppp_l2tp_avp_list *avps = NULL;
523: struct ppp_l2tp_peer *peer = NULL;
524: #if !L2TP_CHANGE_PORT
525: union {
526: u_char buf[sizeof(struct ng_ksocket_sockopt) + sizeof(int)];
527: struct ng_ksocket_sockopt sockopt;
528: } sockopt_buf;
529: struct ng_ksocket_sockopt *const sockopt = &sockopt_buf.sockopt;
530: #endif
531: struct ppp_log *log = NULL;
532: struct ngm_connect connect;
533: struct ngm_rmhook rmhook;
534: struct ngm_mkpeer mkpeer;
535: struct sockaddr_in peer_sin;
536: struct sockaddr_in sin;
537: const size_t bufsize = 8192;
538: u_int16_t *buf = NULL;
539: char hook[NG_HOOKSIZ];
540: socklen_t sin_len;
541: char namebuf[64];
542: ng_ID_t node_id;
543: int csock = -1;
544: int dsock = -1;
545: int len;
546:
547: /* Allocate buffer */
548: if ((buf = MALLOC(TYPED_MEM_TEMP, bufsize)) == NULL) {
549: LOG(LOG_ERR, "malloc: %m");
550: goto fail;
551: }
552:
553: /* Read packet */
554: sin_len = sizeof(peer_sin);
555: if ((len = recvfrom(s->sock, buf, bufsize, 0,
556: (struct sockaddr *)&peer_sin, &sin_len)) == -1) {
557: LOG(LOG_ERR, "recvfrom: %m");
558: goto fail;
559: }
560:
561: /* Drop it if it's not an initial L2TP packet */
562: if (len < 12)
563: goto fail;
564: if ((ntohs(buf[0]) & 0xcb0f) != 0xc802 || ntohs(buf[1]) < 12
565: || buf[2] != 0 || buf[3] != 0 || buf[4] != 0 || buf[5] != 0)
566: goto fail;
567:
568: /* Create a new peer */
569: if ((peer = MALLOC(L2TP_PEER_MTYPE, sizeof(*peer))) == NULL) {
570: LOG(LOG_ERR, "malloc: %m");
571: return;
572: }
573: memset(peer, 0, sizeof(*peer));
574: peer->s = s;
575: peer->ip = peer_sin.sin_addr;
576: peer->port = ntohs(peer_sin.sin_port);
577:
578: /* Check with client library */
579: snprintf(peer->logname, sizeof(peer->logname), "%s:%u",
580: inet_ntoa(peer_sin.sin_addr), ntohs(peer_sin.sin_port));
581: if ((peer->carg = (*s->info.admit)(s->info.arg, peer,
582: peer->ip, peer->port, &peer->auth, peer->logname,
583: sizeof(peer->logname))) == NULL)
584: goto fail;
585:
586: /* Create vendor name AVP */
587: if (s->info.vendor != NULL) {
588: if ((avps = ppp_l2tp_avp_list_create()) == NULL) {
589: LOG(LOG_ERR, "%s: %m", "ppp_l2tp_avp_list_create");
590: goto fail;
591: }
592: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_VENDOR_NAME,
593: s->info.vendor, strlen(s->info.vendor)) == -1) {
594: LOG(LOG_ERR, "%s: %m", "ppp_l2tp_avp_list_append");
595: goto fail;
596: }
597: }
598:
599: /* Create a log for the control connection */
600: if ((log = ppp_log_prefix(s->log, "%s: ", peer->logname)) == NULL) {
601: LOG(LOG_ERR, "%s: %m", "ppp_log_prefix");
602: goto fail;
603: }
604:
605: /* Create a new control connection */
606: if ((peer->ctrl = ppp_l2tp_ctrl_create(s->ev_ctx, s->mutex,
607: &ppp_l2tp_server_ctrl_cb, log, 0, ntohl(peer_sin.sin_addr.s_addr),
608: &node_id, hook, avps, NULL, 0)) == NULL) {
609: LOG(LOG_ERR, "%s: %m", "ppp_l2tp_ctrl_create");
610: goto fail;
611: }
612: ppp_l2tp_ctrl_set_cookie(peer->ctrl, peer);
613: log = NULL; /* log is consumed by control connection */
614:
615: /* Get a temporary netgraph socket node */
616: if (NgMkSockNode(NULL, &csock, &dsock) == -1) {
617: LOG(LOG_ERR, "%s: %m", "NgMkSockNode");
618: goto fail;
619: }
620:
621: /* Connect to l2tp netgraph node "lower" hook */
622: snprintf(namebuf, sizeof(namebuf), "[%lx]:", (u_long)node_id);
623: memset(&connect, 0, sizeof(connect));
624: strlcpy(connect.path, namebuf, sizeof(connect.path));
625: strlcpy(connect.ourhook, hook, sizeof(connect.ourhook));
626: strlcpy(connect.peerhook, hook, sizeof(connect.peerhook));
627: if (NgSendMsg(csock, ".", NGM_GENERIC_COOKIE,
628: NGM_CONNECT, &connect, sizeof(connect)) == -1) {
629: LOG(LOG_ERR, "%s: %m", "connect");
630: goto fail;
631: }
632:
633: /* Write the received packet to the node */
634: if (NgSendData(dsock, hook, (u_char *)buf, len) == -1) {
635: LOG(LOG_ERR, "%s: %m", "NgSendData");
636: goto fail;
637: }
638:
639: /* Disconnect from netgraph node "lower" hook */
640: memset(&rmhook, 0, sizeof(rmhook));
641: strlcpy(rmhook.ourhook, hook, sizeof(rmhook.ourhook));
642: if (NgSendMsg(csock, ".", NGM_GENERIC_COOKIE,
643: NGM_RMHOOK, &rmhook, sizeof(rmhook)) == -1) {
644: LOG(LOG_ERR, "%s: %m", "rmhook");
645: goto fail;
646: }
647:
648: /* Attach a new UDP socket to "lower" hook */
649: memset(&mkpeer, 0, sizeof(mkpeer));
650: strlcpy(mkpeer.type, NG_KSOCKET_NODE_TYPE, sizeof(mkpeer.type));
651: strlcpy(mkpeer.ourhook, hook, sizeof(mkpeer.ourhook));
652: strlcpy(mkpeer.peerhook, "inet/dgram/udp", sizeof(mkpeer.peerhook));
653: if (NgSendMsg(csock, namebuf, NGM_GENERIC_COOKIE,
654: NGM_MKPEER, &mkpeer, sizeof(mkpeer)) == -1) {
655: LOG(LOG_ERR, "%s: %m", "mkpeer");
656: goto fail;
657: }
658:
659: /* Point name at ksocket node */
660: strlcat(namebuf, hook, sizeof(namebuf));
661:
662: #if !L2TP_CHANGE_PORT
663: /* Make UDP port reusable */
664: memset(&sockopt_buf, 0, sizeof(sockopt_buf));
665: sockopt->level = SOL_SOCKET;
666: sockopt->name = SO_REUSEADDR;
667: memcpy(sockopt->value, &one, sizeof(int));
668: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
669: NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
670: LOG(LOG_ERR, "%s: %m", "setsockopt");
671: goto fail;
672: }
673: sockopt->name = SO_REUSEPORT;
674: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
675: NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
676: LOG(LOG_ERR, "%s: %m", "setsockopt");
677: goto fail;
678: }
679: #endif
680:
681: /* Bind socket to a new port */
682: memset(&sin, 0, sizeof(sin));
683: #ifndef __linux__
684: sin.sin_len = sizeof(sin);
685: #endif
686: sin.sin_family = AF_INET;
687: sin.sin_addr = s->ip;
688: #if L2TP_CHANGE_PORT
689: sin.sin_port = 0; /* "choose any free port" */
690: #else
691: sin.sin_port = htons(s->port);
692: #endif
693: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
694: NGM_KSOCKET_BIND, &sin, sizeof(sin)) == -1) {
695: LOG(LOG_ERR, "%s: %m", "bind");
696: goto fail;
697: }
698:
699: #if L2TP_CHANGE_PORT
700: /* Set up reverse NAT mapping for the new port */
701: if (s->info.natmap != NULL) {
702: struct ng_mesg *const reply = (struct ng_mesg *)buf;
703: struct sockaddr_in *const self_sin
704: = (struct sockaddr_in *)reply->data;
705:
706: /* Get kernel-assigned UDP port number */
707: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
708: NGM_KSOCKET_GETNAME, NULL, 0) == -1) {
709: LOG(LOG_ERR, "%s: %m", "getsockname");
710: goto fail;
711: }
712: if (NgRecvMsg(csock, reply, bufsize, NULL) == -1) {
713: LOG(LOG_ERR, "%s: %m", "recvmsg");
714: goto fail;
715: }
716: if ((*s->info.natmap)(s->info.arg, self_sin->sin_addr,
717: ntohs(self_sin->sin_port), s->port, peer_sin.sin_addr,
718: ntohs(peer_sin.sin_port)) == -1) {
719: LOG(LOG_ERR, "%s: %m", "can't reverse NAT map");
720: goto fail;
721: }
722: }
723: #endif
724:
725: /* Connect socket to remote peer's IP and port */
726: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
727: NGM_KSOCKET_CONNECT, &peer_sin, sizeof(peer_sin)) == -1
728: && errno != EINPROGRESS) {
729: LOG(LOG_ERR, "%s: %m", "connect");
730: goto fail;
731: }
732:
733: /* Add peer to our hash table */
734: if (ghash_put(s->peers, peer) == -1) {
735: LOG(LOG_ERR, "%s: %m", "ghash_put");
736: goto fail;
737: }
738:
739: /* Clean up and return */
740: ppp_l2tp_avp_list_destroy(&avps);
741: (void)close(csock);
742: (void)close(dsock);
743: FREE(TYPED_MEM_TEMP, buf);
744: return;
745:
746: fail:
747: /* Clean up after failure */
748: if (csock != -1)
749: (void)close(csock);
750: if (dsock != -1)
751: (void)close(dsock);
752: if (peer != NULL) {
753: ppp_l2tp_server_close_client(peer);
754: ppp_l2tp_ctrl_destroy(&peer->ctrl);
755: FREE(L2TP_PEER_MTYPE, peer);
756: }
757: ppp_l2tp_avp_list_destroy(&avps);
758: ppp_log_close(&log);
759: FREE(TYPED_MEM_TEMP, buf);
760: }
761:
762: /*
763: * Create a new L2TP peer object corresponding to a L2TP channel
764: * and start up a new PPP link/bundle.
765: */
766: static int
767: ppp_l2tp_server_new_sess(struct ppp_l2tp_peer *peer, struct ppp_l2tp_sess *sess)
768: {
769: struct ppp_l2tp_server *const s = peer->s;
770: struct ppp_link_config link_config;
771: struct ppp_log *log = NULL;
772: const char *hook;
773: ng_ID_t node_id;
774: int esave;
775:
776: /* We allow only one session per control connection */
777: if (peer->sess != NULL) {
778: errno = EALREADY;
779: return (-1);
780: }
781:
782: /* Get this link's node and hook */
783: ppp_l2tp_sess_get_hook(sess, &node_id, &hook);
784: snprintf(peer->node, sizeof(peer->node), "[%lx]:", (u_long)node_id);
785: strlcpy(peer->hook, hook, sizeof(peer->hook));
786:
787: /* Create a new PPP device for this session */
788: if ((peer->chan = MALLOC(L2TP_DEVICE_MTYPE,
789: sizeof(*peer->chan))) == NULL) {
790: LOG(LOG_ERR, "can't allocate new channel: %m");
791: goto fail;
792: }
793: memset(peer->chan, 0, sizeof(*peer->chan));
794: peer->chan->meth = &ppp_l2tp_server_device_meth;
795: peer->chan->priv = peer;
796:
797: /* Create device output message port */
798: if ((peer->chan->outport
799: = mesg_port_create("ppp_l2tp_server")) == NULL) {
800: LOG(LOG_ERR, "can't create mesg_port: %m");
801: goto fail;
802: }
803:
804: /* Create log for the new PPP link by prefixing the engine's log */
805: if ((log = ppp_engine_get_log(s->engine)) != NULL
806: && (log = ppp_log_prefix(log, "%s: ", peer->logname)) == NULL) {
807: LOG(LOG_ERR, "can't create link log: %m");
808: goto fail;
809: }
810:
811: /* Configure the new PPP link */
812: memset(&link_config, 0, sizeof(link_config));
813: link_config.auth = peer->auth;
814: link_config.max_self_mru = L2TP_MRU;
815: link_config.max_self_mrru = L2TP_MRRU;
816: link_config.multilink = 1;
817: link_config.eid.class = PPP_EID_CLASS_IP;
818: link_config.eid.length = sizeof(s->ip);
819: memcpy(link_config.eid.value, &s->ip, sizeof(s->ip));
820:
821: /* Add new link to the PPP engine */
822: if (ppp_link_create(s->engine, peer->chan, &link_config, log) == -1) {
823: LOG(LOG_ERR, "can't create link: %m");
824: goto fail;
825: }
826: log = NULL;
827:
828: /* Notify PPP engine link is up */
829: ppp_l2tp_server_device_output(peer, PPP_CHANNEL_OUTPUT_UP);
830:
831: /* Done */
832: peer->sess = sess;
833: return (0);
834:
835: fail:
836: /* Clean up after failure */
837: esave = errno;
838: ppp_log_close(&log);
839: if (peer->chan != NULL) {
840: if (peer->chan->outport != NULL)
841: mesg_port_destroy(&peer->chan->outport);
842: FREE(L2TP_DEVICE_MTYPE, peer->chan);
843: }
844: errno = esave;
845: return (-1);
846: }
847:
848: /*
849: * Output indication from the device.
850: */
851: static void
852: ppp_l2tp_server_device_output(struct ppp_l2tp_peer *peer,
853: enum ppp_channeloutput type, ...)
854: {
855: struct ppp_l2tp_server *const s = peer->s;
856: struct ppp_channel_output *output;
857:
858: /* Get output object */
859: if ((output = MALLOC(L2TP_OUTPUT_MTYPE, sizeof(*output))) == NULL) {
860: LOG(LOG_ERR, "can't create l2tp output: %m");
861: return;
862: }
863: memset(output, 0, sizeof(*output));
864: output->type = type;
865:
866: /* Get extra args */
867: switch (output->type) {
868: case PPP_CHANNEL_OUTPUT_DOWN_FATAL:
869: case PPP_CHANNEL_OUTPUT_DOWN_NONFATAL:
870: {
871: const char *msg;
872: va_list args;
873:
874: /* Get string message */
875: va_start(args, type);
876: msg = va_arg(args, const char *);
877: va_end(args);
878: if ((output->info = STRDUP(L2TP_OUTPUT_MTYPE, msg)) == NULL) {
879: LOG(LOG_ERR, "can't create l2tp output: %m");
880: FREE(L2TP_OUTPUT_MTYPE, output);
881: return;
882: }
883: break;
884: }
885: case PPP_CHANNEL_OUTPUT_UP:
886: break;
887: }
888:
889: /* Send message */
890: if (mesg_port_put(peer->chan->outport, output) == -1) {
891: LOG(LOG_ERR, "can't send l2tp output: %m");
892: ppp_l2tp_server_device_free_output(peer->chan, output);
893: return;
894: }
895: }
896:
897: /*
898: * Notify client code that connection is gone.
899: * Make sure that we only do this once however.
900: */
901: static void
902: ppp_l2tp_server_close_client(struct ppp_l2tp_peer *peer)
903: {
904: struct ppp_l2tp_server *const s = peer->s;
905: void *const peer_carg = peer->carg;
906:
907: if (peer_carg == NULL)
908: return;
909: peer->carg = NULL;
910: (*s->info.destroy)(s->info.arg, peer_carg);
911: }
912:
913: /*
914: * Destroy a peer.
915: */
916: static void
917: ppp_l2tp_server_peer_destroy(struct ppp_l2tp_peer **peerp)
918: {
919: struct ppp_l2tp_peer *peer = *peerp;
920: struct ppp_l2tp_server *s;
921:
922: /* Sanity checks */
923: if (peer == NULL)
924: return;
925: *peerp = NULL;
926: assert(peer->ctrl == NULL);
927: assert(peer->sess == NULL);
928: assert(peer->chan == NULL);
929:
930: /* Destroy peer */
931: s = peer->s;
932: ghash_remove(s->peers, peer);
933: FREE(L2TP_PEER_MTYPE, peer);
934:
935: /* Destroy server if shutting down and no more peers left */
936: if (s->sock == -1 && ghash_size(s->peers) == 0)
937: ppp_l2tp_server_destroy(&s);
938: }
939:
940: /***********************************************************************
941: L2TP DEVICE METHODS
942: ***********************************************************************/
943:
944: static void
945: ppp_l2tp_server_device_open(struct ppp_channel *chan)
946: {
947: return;
948: }
949:
950: static void
951: ppp_l2tp_server_device_close(struct ppp_channel *chan)
952: {
953: struct ppp_l2tp_peer *const peer = chan->priv;
954: struct ppp_l2tp_server *const s = peer->s;
955:
956: /* Logging */
957: if (!peer->closed) {
958: LOG(LOG_INFO, "closing L2TP connection with %s", peer->logname);
959: peer->closed = 1;
960: }
961:
962: /* Terminate the L2TP channel */
963: if (peer->sess != NULL) {
964: ppp_l2tp_terminate(peer->sess, L2TP_RESULT_ADMIN, 0, NULL);
965: peer->sess = NULL;
966: }
967:
968: /* Notify upper layers link is down */
969: ppp_l2tp_server_device_output(peer,
970: PPP_CHANNEL_OUTPUT_DOWN_FATAL, "administratively closed");
971: }
972:
973: static void
974: ppp_l2tp_server_device_destroy(struct ppp_channel **chanp)
975: {
976: struct ppp_channel *const chan = *chanp;
977: struct ppp_channel_output *output;
978: struct ppp_l2tp_peer *peer;
979: struct ppp_l2tp_server *s;
980:
981: /* Sanity */
982: if (chan == NULL)
983: return;
984: *chanp = NULL;
985: peer = chan->priv;
986: assert(peer->chan == chan);
987: s = peer->s;
988:
989: /* Close client code's side of the device */
990: ppp_l2tp_server_close_client(peer);
991:
992: /* Terminate the L2TP channel */
993: if (peer->sess != NULL) {
994: ppp_l2tp_terminate(peer->sess, L2TP_RESULT_ADMIN, 0, NULL);
995: peer->sess = NULL;
996: }
997:
998: /* Destroy the device object */
999: while ((output = mesg_port_get(chan->outport, 0)) != NULL)
1000: ppp_l2tp_server_device_free_output(chan, output);
1001: mesg_port_destroy(&chan->outport);
1002: FREE(L2TP_DEVICE_MTYPE, chan);
1003: peer->chan = NULL;
1004:
1005: /* Destroy peer if it has no more references */
1006: if (peer->ctrl == NULL)
1007: ppp_l2tp_server_peer_destroy(&peer);
1008: }
1009:
1010: static void
1011: ppp_l2tp_server_device_free_output(struct ppp_channel *chan,
1012: struct ppp_channel_output *output)
1013: {
1014: FREE(L2TP_OUTPUT_MTYPE, output->info);
1015: FREE(L2TP_OUTPUT_MTYPE, output);
1016: }
1017:
1018: static void
1019: ppp_l2tp_server_device_set_link_info(struct ppp_channel *chan, u_int32_t accm)
1020: {
1021: /* XXX implement me? */
1022: }
1023:
1024: static int
1025: ppp_l2tp_server_device_get_origination(struct ppp_channel *chan)
1026: {
1027: return (PPP_PEER); /* we don't initiate any calls ourself */
1028: }
1029:
1030: static const char *
1031: ppp_l2tp_server_device_get_node(struct ppp_channel *chan)
1032: {
1033: struct ppp_l2tp_peer *const peer = chan->priv;
1034:
1035: return (peer->node);
1036: }
1037:
1038: static const char *
1039: ppp_l2tp_server_device_get_hook(struct ppp_channel *chan)
1040: {
1041: struct ppp_l2tp_peer *const peer = chan->priv;
1042:
1043: return (peer->hook);
1044: }
1045:
1046: static int
1047: ppp_l2tp_server_device_is_async(struct ppp_channel *chan)
1048: {
1049: return (0);
1050: }
1051:
1052: static u_int
1053: ppp_l2tp_server_device_get_mtu(struct ppp_channel *chan)
1054: {
1055: return (L2TP_MRU);
1056: }
1057:
1058: static int
1059: ppp_l2tp_server_device_get_acfcomp(struct ppp_channel *chan)
1060: {
1061: return (1);
1062: }
1063:
1064: static int
1065: ppp_l2tp_server_device_get_pfcomp(struct ppp_channel *chan)
1066: {
1067: return (1);
1068: }
1069:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>