1 /* pppol2tp.c - pppd plugin to implement PPPoL2TP protocol
2 * for Linux using kernel pppol2tp support.
4 * Requires kernel pppol2tp driver which is integrated into the kernel
5 * from 2.6.23 onwards. For earlier kernels, a version can be obtained
6 * from the OpenL2TP project at
7 * http://www.sourceforge.net/projects/openl2tp/
9 * Original by Martijn van Oosterhout <kleptog@svana.org>
10 * Modified by jchapman@katalix.com
12 * Heavily based upon pppoatm.c: original notice follows
14 * Copyright 2000 Mitchell Blank Jr.
15 * Based in part on work from Jens Axboe and Paul Mackerras.
16 * Updated to ppp-2.4.1 by Bernhard Kaindl
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version
21 * 2 of the License, or (at your option) any later version.
28 #include "pathnames.h"
35 #include <sys/ioctl.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
39 #include <linux/version.h>
40 #include <linux/sockios.h>
42 /* should be defined in sys/types.h */
43 #define aligned_u64 unsigned long long __attribute__((aligned(8)))
45 #include <linux/types.h>
46 #include <linux/if_ether.h>
47 #include <linux/ppp_defs.h>
48 #include <linux/if_ppp.h>
49 #include <linux/if_pppox.h>
50 #include <linux/if_pppol2tp.h>
52 /* should be added to system's socket.h... */
54 #define SOL_PPPOL2TP 273
57 const char pppd_version[] = VERSION;
59 static int setdevname_pppol2tp(char **argv);
61 static int pppol2tp_fd = -1;
62 static char *pppol2tp_fd_str;
63 static bool pppol2tp_lns_mode = 0;
64 static bool pppol2tp_recv_seq = 0;
65 static bool pppol2tp_send_seq = 0;
66 static int pppol2tp_debug_mask = 0;
67 static int pppol2tp_reorder_timeout = 0;
68 static char pppol2tp_ifname[32] = { 0, };
69 int pppol2tp_tunnel_id = 0;
70 int pppol2tp_session_id = 0;
72 static int device_got_set = 0;
73 struct channel pppol2tp_channel;
75 static void (*old_snoop_recv_hook)(unsigned char *p, int len) = NULL;
76 static void (*old_snoop_send_hook)(unsigned char *p, int len) = NULL;
78 /* Hook provided to allow other plugins to handle ACCM changes */
79 void (*pppol2tp_send_accm_hook)(int tunnel_id, int session_id,
80 uint32_t send_accm, uint32_t recv_accm) = NULL;
82 /* Hook provided to allow other plugins to handle IP up/down */
83 void (*pppol2tp_ip_updown_hook)(int tunnel_id, int session_id, int up) = NULL;
85 static option_t pppol2tp_options[] = {
86 { "pppol2tp", o_special, &setdevname_pppol2tp,
87 "FD for PPPoL2TP socket", OPT_DEVNAM | OPT_A2STRVAL,
89 { "pppol2tp_lns_mode", o_bool, &pppol2tp_lns_mode,
90 "PPPoL2TP LNS behavior. Default off.",
91 OPT_PRIO | OPRIO_CFGFILE },
92 { "pppol2tp_send_seq", o_bool, &pppol2tp_send_seq,
93 "PPPoL2TP enable sequence numbers in transmitted data packets. "
95 OPT_PRIO | OPRIO_CFGFILE },
96 { "pppol2tp_recv_seq", o_bool, &pppol2tp_recv_seq,
97 "PPPoL2TP enforce sequence numbers in received data packets. "
99 OPT_PRIO | OPRIO_CFGFILE },
100 { "pppol2tp_reorderto", o_int, &pppol2tp_reorder_timeout,
101 "PPPoL2TP data packet reorder timeout. Default 0 (no reordering).",
103 { "pppol2tp_debug_mask", o_int, &pppol2tp_debug_mask,
104 "PPPoL2TP debug mask. Default: no debug.",
106 { "pppol2tp_ifname", o_string, &pppol2tp_ifname,
107 "Set interface name of PPP interface",
108 OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, 16 },
109 { "pppol2tp_tunnel_id", o_int, &pppol2tp_tunnel_id,
110 "PPPoL2TP tunnel_id.",
112 { "pppol2tp_session_id", o_int, &pppol2tp_session_id,
113 "PPPoL2TP session_id.",
118 static int setdevname_pppol2tp(char **argv)
122 struct sockaddr pppol2tp;
127 int tmp_len = sizeof(tmp);
132 if (!int_option(*argv, &pppol2tp_fd))
135 if(getsockname(pppol2tp_fd, (struct sockaddr *)&s, &len) < 0) {
136 fatal("Given FD for PPPoL2TP socket invalid (%s)",
139 if(s.pppol2tp.sa_family != AF_PPPOX) {
140 fatal("Socket of not a PPPoX socket");
143 /* Do a test getsockopt() to ensure that the kernel has the necessary
146 if (getsockopt(pppol2tp_fd, SOL_PPPOL2TP, PPPOL2TP_SO_DEBUG,
147 &tmp, &tmp_len) < 0) {
148 fatal("PPPoL2TP kernel driver not installed");
151 pppol2tp_fd_str = strdup(*argv);
152 if (pppol2tp_fd_str == NULL)
155 /* Setup option defaults. Compression options are disabled! */
159 lcp_allowoptions[0].neg_accompression = 1;
160 lcp_wantoptions[0].neg_accompression = 0;
162 lcp_allowoptions[0].neg_pcompression = 1;
163 lcp_wantoptions[0].neg_pcompression = 0;
165 ccp_allowoptions[0].deflate = 0;
166 ccp_wantoptions[0].deflate = 0;
168 ipcp_allowoptions[0].neg_vj = 0;
169 ipcp_wantoptions[0].neg_vj = 0;
171 ccp_allowoptions[0].bsd_compress = 0;
172 ccp_wantoptions[0].bsd_compress = 0;
174 the_channel = &pppol2tp_channel;
180 static int connect_pppol2tp(void)
182 if(pppol2tp_fd == -1) {
183 fatal("No PPPoL2TP FD specified");
189 static void disconnect_pppol2tp(void)
191 if (pppol2tp_fd >= 0) {
197 static void send_config_pppol2tp(int mtu,
209 if (pppol2tp_ifname[0]) {
213 fd = socket(AF_INET, SOCK_DGRAM, 0);
215 memset (&ifr, '\0', sizeof (ifr));
216 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
217 strlcpy(ifr.ifr_newname, pppol2tp_ifname,
218 sizeof(ifr.ifr_name));
219 ioctl(fd, SIOCSIFNAME, (caddr_t) &ifr);
220 strlcpy(ifname, pppol2tp_ifname, 32);
221 if (pppol2tp_debug_mask & PPPOL2TP_MSG_CONTROL) {
222 dbglog("ppp%d: interface name %s",
229 if ((lcp_allowoptions[0].mru > 0) && (mtu > lcp_allowoptions[0].mru)) {
230 warn("Overriding mtu %d to %d", mtu, lcp_allowoptions[0].mru);
231 mtu = lcp_allowoptions[0].mru;
233 netif_set_mtu(ifunit, mtu);
236 if (pppol2tp_reorder_timeout > 0)
237 sprintf(&reorderto[0], "%d ", pppol2tp_reorder_timeout);
239 if (pppol2tp_tunnel_id > 0)
240 sprintf(&tid[0], "%hu ", pppol2tp_tunnel_id);
242 if (pppol2tp_session_id > 0)
243 sprintf(&sid[0], "%hu ", pppol2tp_session_id);
245 dbglog("PPPoL2TP options: %s%s%s%s%s%s%s%s%sdebugmask %d",
246 pppol2tp_recv_seq ? "recvseq " : "",
247 pppol2tp_send_seq ? "sendseq " : "",
248 pppol2tp_lns_mode ? "lnsmode " : "",
249 pppol2tp_reorder_timeout ? "reorderto " : "", reorderto,
250 pppol2tp_tunnel_id ? "tid " : "", tid,
251 pppol2tp_session_id ? "sid " : "", sid,
252 pppol2tp_debug_mask);
254 if (pppol2tp_recv_seq)
255 if (setsockopt(pppol2tp_fd, SOL_PPPOL2TP, PPPOL2TP_SO_RECVSEQ,
256 &on, sizeof(on)) < 0)
257 fatal("setsockopt(PPPOL2TP_RECVSEQ): %m");
258 if (pppol2tp_send_seq)
259 if (setsockopt(pppol2tp_fd, SOL_PPPOL2TP, PPPOL2TP_SO_SENDSEQ,
260 &on, sizeof(on)) < 0)
261 fatal("setsockopt(PPPOL2TP_SENDSEQ): %m");
262 if (pppol2tp_lns_mode)
263 if (setsockopt(pppol2tp_fd, SOL_PPPOL2TP, PPPOL2TP_SO_LNSMODE,
264 &on, sizeof(on)) < 0)
265 fatal("setsockopt(PPPOL2TP_LNSMODE): %m");
266 if (pppol2tp_reorder_timeout)
267 if (setsockopt(pppol2tp_fd, SOL_PPPOL2TP, PPPOL2TP_SO_REORDERTO,
268 &pppol2tp_reorder_timeout,
269 sizeof(pppol2tp_reorder_timeout)) < 0)
270 fatal("setsockopt(PPPOL2TP_REORDERTO): %m");
271 if (pppol2tp_debug_mask)
272 if (setsockopt(pppol2tp_fd, SOL_PPPOL2TP, PPPOL2TP_SO_DEBUG,
273 &pppol2tp_debug_mask, sizeof(pppol2tp_debug_mask)) < 0)
274 fatal("setsockopt(PPPOL2TP_DEBUG): %m");
277 static void recv_config_pppol2tp(int mru,
282 if ((lcp_allowoptions[0].mru > 0) && (mru > lcp_allowoptions[0].mru)) {
283 warn("Overriding mru %d to mtu value %d", mru,
284 lcp_allowoptions[0].mru);
285 mru = lcp_allowoptions[0].mru;
287 if ((ifunit >= 0) && ioctl(pppol2tp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
288 error("Couldn't set PPP MRU: %m");
291 /*****************************************************************************
292 * Snoop LCP message exchanges to capture negotiated ACCM values.
293 * When asyncmap values have been seen from both sides, give the values to
295 * This code is derived from Roaring Penguin L2TP.
296 *****************************************************************************/
298 static void pppol2tp_lcp_snoop(unsigned char *buf, int len, int incoming)
300 static bool got_send_accm = 0;
301 static bool got_recv_accm = 0;
302 static uint32_t recv_accm = 0xffffffff;
303 static uint32_t send_accm = 0xffffffff;
304 static bool snooping = 1;
307 uint16_t lcp_pkt_len;
310 unsigned char const *opt_data;
313 /* Skip HDLC header */
317 /* Unreasonably short frame?? */
318 if (len <= 0) return;
322 /* Compressed protcol field */
325 protocol = ((unsigned int) buf[0]) * 256 + buf[1];
328 /* If it's a network protocol, stop snooping */
329 if (protocol <= 0x3fff) {
330 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DEBUG) {
331 dbglog("Turning off snooping: "
332 "Network protocol %04x found.",
339 /* If it's not LCP, do not snoop */
340 if (protocol != 0xc021) {
344 /* Skip protocol; go to packet data */
348 /* Unreasonably short frame?? */
349 if (len <= 0) return;
351 /* Look for Configure-Ack or Configure-Reject code */
352 if (buf[0] != CONFACK && buf[0] != CONFREJ) return;
354 reject = (buf[0] == CONFREJ);
356 lcp_pkt_len = ((unsigned int) buf[2]) * 256 + buf[3];
358 /* Something fishy with length field? */
359 if (lcp_pkt_len > len) return;
361 /* Skip to options */
362 len = lcp_pkt_len - 4;
366 /* Pull off an option */
370 if (opt_len > len || opt_len < 2) break;
373 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DEBUG) {
374 dbglog("Found option type %02x; len %d", opt, opt_len);
377 /* We are specifically interested in ACCM */
378 if (opt == CI_ASYNCMAP && opt_len == 0x06) {
380 /* ACCM negotiation REJECTED; use default */
382 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DATA) {
383 dbglog("Rejected ACCM negotiation; "
385 incoming ? "incoming" : "outgoing");
392 memcpy(&accm, opt_data, sizeof(accm));
393 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DATA) {
394 dbglog("Found ACCM of %08x (%s)", accm,
395 incoming ? "incoming" : "outgoing");
406 if (got_recv_accm && got_send_accm) {
407 if (pppol2tp_debug_mask & PPPOL2TP_MSG_CONTROL) {
408 dbglog("Telling L2TP: Send ACCM = %08x; "
409 "Receive ACCM = %08x", send_accm, recv_accm);
411 if (pppol2tp_send_accm_hook != NULL) {
412 (*pppol2tp_send_accm_hook)(pppol2tp_tunnel_id,
414 send_accm, recv_accm);
423 static void pppol2tp_lcp_snoop_recv(unsigned char *p, int len)
425 if (old_snoop_recv_hook != NULL)
426 (*old_snoop_recv_hook)(p, len);
427 pppol2tp_lcp_snoop(p, len, 1);
430 static void pppol2tp_lcp_snoop_send(unsigned char *p, int len)
432 if (old_snoop_send_hook != NULL)
433 (*old_snoop_send_hook)(p, len);
434 pppol2tp_lcp_snoop(p, len, 0);
437 /*****************************************************************************
438 * Interface up/down events
439 *****************************************************************************/
441 static void pppol2tp_ip_up(void *opaque, int arg)
443 /* may get called twice (for IPv4 and IPv6) but the hook handles that well */
444 if (pppol2tp_ip_updown_hook != NULL) {
445 (*pppol2tp_ip_updown_hook)(pppol2tp_tunnel_id,
446 pppol2tp_session_id, 1);
450 static void pppol2tp_ip_down(void *opaque, int arg)
452 /* may get called twice (for IPv4 and IPv6) but the hook handles that well */
453 if (pppol2tp_ip_updown_hook != NULL) {
454 (*pppol2tp_ip_updown_hook)(pppol2tp_tunnel_id,
455 pppol2tp_session_id, 0);
459 /*****************************************************************************
461 *****************************************************************************/
463 static void pppol2tp_check_options(void)
465 /* Enable LCP snooping for ACCM options only for LNS */
466 if (pppol2tp_lns_mode) {
467 if ((pppol2tp_tunnel_id == 0) || (pppol2tp_session_id == 0)) {
468 fatal("tunnel_id/session_id values not specified");
470 if (pppol2tp_debug_mask & PPPOL2TP_MSG_CONTROL) {
471 dbglog("Enabling LCP snooping");
473 old_snoop_recv_hook = snoop_recv_hook;
474 old_snoop_send_hook = snoop_send_hook;
476 snoop_recv_hook = pppol2tp_lcp_snoop_recv;
477 snoop_send_hook = pppol2tp_lcp_snoop_send;
481 /* Called just before pppd exits.
483 static void pppol2tp_cleanup(void)
485 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DEBUG) {
486 dbglog("pppol2tp: exiting.");
488 disconnect_pppol2tp();
491 void plugin_init(void)
493 #if defined(__linux__)
494 extern int new_style_driver; /* From sys-linux.c */
495 if (!ppp_available() && !new_style_driver)
496 fatal("Kernel doesn't support ppp_generic - "
497 "needed for PPPoL2TP");
499 fatal("No PPPoL2TP support on this OS");
501 add_options(pppol2tp_options);
503 /* Hook up ip up/down notifiers to send indicator to openl2tpd
504 * that the link is up
506 add_notifier(&ip_up_notifier, pppol2tp_ip_up, NULL);
507 add_notifier(&ip_down_notifier, pppol2tp_ip_down, NULL);
508 add_notifier(&ipv6_up_notifier, pppol2tp_ip_up, NULL);
509 add_notifier(&ipv6_down_notifier, pppol2tp_ip_down, NULL);
512 struct channel pppol2tp_channel = {
513 options: pppol2tp_options,
514 process_extra_options: NULL,
515 check_options: &pppol2tp_check_options,
516 connect: &connect_pppol2tp,
517 disconnect: &disconnect_pppol2tp,
518 establish_ppp: &generic_establish_ppp,
519 disestablish_ppp: &generic_disestablish_ppp,
520 send_config: &send_config_pppol2tp,
521 recv_config: &recv_config_pppol2tp,