1/* pppol2tp.c - pppd plugin to implement PPPoL2TP protocol 2 * for Linux using kernel pppol2tp support. 3 * 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/ 8 * 9 * Original by Martijn van Oosterhout <kleptog@svana.org> 10 * Modified by jchapman@katalix.com 11 * 12 * Heavily based upon pppoatm.c: original notice follows 13 * 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 17 * 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. 22 */ 23#include <unistd.h> 24#include <string.h> 25#include <stdlib.h> 26#include <errno.h> 27#include "pppd.h" 28#include "pathnames.h" 29#include "fsm.h" 30#include "lcp.h" 31#include "ccp.h" 32#include "ipcp.h" 33#include <sys/stat.h> 34#include <net/if.h> 35#include <sys/ioctl.h> 36#include <sys/socket.h> 37#include <netinet/in.h> 38#include <signal.h> 39#include <linux/version.h> 40#include <linux/sockios.h> 41#ifndef aligned_u64 42/* should be defined in sys/types.h */ 43#define aligned_u64 unsigned long long __attribute__((aligned(8))) 44#endif 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> 51 52/* should be added to system's socket.h... */ 53#ifndef SOL_PPPOL2TP 54#define SOL_PPPOL2TP 273 55#endif 56 57const char pppd_version[] = VERSION; 58 59static int setdevname_pppol2tp(char **argv); 60 61static int pppol2tp_fd = -1; 62static char *pppol2tp_fd_str; 63static bool pppol2tp_lns_mode = 0; 64static bool pppol2tp_recv_seq = 0; 65static bool pppol2tp_send_seq = 0; 66static int pppol2tp_debug_mask = 0; 67static int pppol2tp_reorder_timeout = 0; 68static char pppol2tp_ifname[32] = { 0, }; 69int pppol2tp_tunnel_id = 0; 70int pppol2tp_session_id = 0; 71 72static int device_got_set = 0; 73struct channel pppol2tp_channel; 74 75static void (*old_snoop_recv_hook)(unsigned char *p, int len) = NULL; 76static void (*old_snoop_send_hook)(unsigned char *p, int len) = NULL; 77 78/* Hook provided to allow other plugins to handle ACCM changes */ 79void (*pppol2tp_send_accm_hook)(int tunnel_id, int session_id, 80 uint32_t send_accm, uint32_t recv_accm) = NULL; 81 82/* Hook provided to allow other plugins to handle IP up/down */ 83void (*pppol2tp_ip_updown_hook)(int tunnel_id, int session_id, int up) = NULL; 84 85static option_t pppol2tp_options[] = { 86 { "pppol2tp", o_special, &setdevname_pppol2tp, 87 "FD for PPPoL2TP socket", OPT_DEVNAM | OPT_A2STRVAL, 88 &pppol2tp_fd_str }, 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. " 94 "Default off.", 95 OPT_PRIO | OPRIO_CFGFILE }, 96 { "pppol2tp_recv_seq", o_bool, &pppol2tp_recv_seq, 97 "PPPoL2TP enforce sequence numbers in received data packets. " 98 "Default off.", 99 OPT_PRIO | OPRIO_CFGFILE }, 100 { "pppol2tp_reorderto", o_int, &pppol2tp_reorder_timeout, 101 "PPPoL2TP data packet reorder timeout. Default 0 (no reordering).", 102 OPT_PRIO }, 103 { "pppol2tp_debug_mask", o_int, &pppol2tp_debug_mask, 104 "PPPoL2TP debug mask. Default: no debug.", 105 OPT_PRIO }, 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.", 111 OPT_PRIO }, 112 { "pppol2tp_session_id", o_int, &pppol2tp_session_id, 113 "PPPoL2TP session_id.", 114 OPT_PRIO }, 115 { NULL } 116}; 117 118static int setdevname_pppol2tp(char **argv) 119{ 120 struct sockaddr_pppol2tp sax; 121 int len = sizeof(sax); 122 123 if (device_got_set) 124 return 0; 125 126 if (!int_option(*argv, &pppol2tp_fd)) 127 return 0; 128 129 if(getsockname(pppol2tp_fd, (struct sockaddr *)&sax, &len) < 0) { 130 fatal("Given FD for PPPoL2TP socket invalid (%s)", 131 strerror(errno)); 132 } 133 if(sax.sa_family != AF_PPPOX || sax.sa_protocol != PX_PROTO_OL2TP) { 134 fatal("Socket is not a PPPoL2TP socket"); 135 } 136 137 /* Do a test getsockopt() to ensure that the kernel has the necessary 138 * feature available. 139 * driver returns -ENOTCONN until session established! 140 if (getsockopt(pppol2tp_fd, SOL_PPPOL2TP, PPPOL2TP_SO_DEBUG, 141 &tmp, &tmp_len) < 0) { 142 fatal("PPPoL2TP kernel driver not installed"); 143 } */ 144 145 /* Setup option defaults. Compression options are disabled! */ 146 147 modem = 0; 148 149 lcp_allowoptions[0].neg_accompression = 1; 150 lcp_wantoptions[0].neg_accompression = 0; 151 152 lcp_allowoptions[0].neg_pcompression = 1; 153 lcp_wantoptions[0].neg_pcompression = 0; 154 155 ccp_allowoptions[0].deflate = 0; 156 ccp_wantoptions[0].deflate = 0; 157 158 ipcp_allowoptions[0].neg_vj = 0; 159 ipcp_wantoptions[0].neg_vj = 0; 160 161 ccp_allowoptions[0].bsd_compress = 0; 162 ccp_wantoptions[0].bsd_compress = 0; 163 164 the_channel = &pppol2tp_channel; 165 device_got_set = 1; 166 167 return 1; 168} 169 170static int connect_pppol2tp(void) 171{ 172 struct sockaddr_pppol2tp sax; 173 int len = sizeof(sax); 174 175 if(pppol2tp_fd == -1) { 176 fatal("No PPPoL2TP FD specified"); 177 } 178 179 getsockname(pppol2tp_fd, (struct sockaddr *)&sax, &len); 180 sprintf(ppp_devnam, "l2tp (%s)", inet_ntoa(sax.pppol2tp.addr.sin_addr)); 181 182 return pppol2tp_fd; 183} 184 185static void disconnect_pppol2tp(void) 186{ 187 if (pppol2tp_fd >= 0) { 188 close(pppol2tp_fd); 189 pppol2tp_fd = -1; 190 } 191} 192 193static void send_config_pppol2tp(int mtu, 194 u_int32_t asyncmap, 195 int pcomp, 196 int accomp) 197{ 198 struct ifreq ifr; 199 int on = 1; 200 int fd; 201 char reorderto[16]; 202 char tid[8]; 203 char sid[8]; 204 205 if (pppol2tp_ifname[0]) { 206 struct ifreq ifr; 207 int fd; 208 209 fd = socket(AF_INET, SOCK_DGRAM, 0); 210 if (fd >= 0) { 211 memset (&ifr, '\0', sizeof (ifr)); 212 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 213 strlcpy(ifr.ifr_newname, pppol2tp_ifname, 214 sizeof(ifr.ifr_name)); 215 ioctl(fd, SIOCSIFNAME, (caddr_t) &ifr); 216 strlcpy(ifname, pppol2tp_ifname, 32); 217 if (pppol2tp_debug_mask & PPPOL2TP_MSG_CONTROL) { 218 dbglog("ppp%d: interface name %s", 219 ifunit, ifname); 220 } 221 } 222 close(fd); 223 } 224 225 if ((lcp_allowoptions[0].mru > 0) && (mtu > lcp_allowoptions[0].mru)) { 226 warn("Overriding mtu %d to %d", mtu, lcp_allowoptions[0].mru); 227 mtu = lcp_allowoptions[0].mru; 228 } 229 netif_set_mtu(ifunit, mtu); 230 231 reorderto[0] = '\0'; 232 if (pppol2tp_reorder_timeout > 0) 233 sprintf(&reorderto[0], "%d ", pppol2tp_reorder_timeout); 234 tid[0] = '\0'; 235 if (pppol2tp_tunnel_id > 0) 236 sprintf(&tid[0], "%hu ", pppol2tp_tunnel_id); 237 sid[0] = '\0'; 238 if (pppol2tp_session_id > 0) 239 sprintf(&sid[0], "%hu ", pppol2tp_session_id); 240 241 dbglog("PPPoL2TP options: %s%s%s%s%s%s%s%s%sdebugmask %d", 242 pppol2tp_recv_seq ? "recvseq " : "", 243 pppol2tp_send_seq ? "sendseq " : "", 244 pppol2tp_lns_mode ? "lnsmode " : "", 245 pppol2tp_reorder_timeout ? "reorderto " : "", reorderto, 246 pppol2tp_tunnel_id ? "tid " : "", tid, 247 pppol2tp_session_id ? "sid " : "", sid, 248 pppol2tp_debug_mask); 249 250 if (pppol2tp_recv_seq) 251 if (setsockopt(pppol2tp_fd, SOL_PPPOL2TP, PPPOL2TP_SO_RECVSEQ, 252 &on, sizeof(on)) < 0) 253 fatal("setsockopt(PPPOL2TP_RECVSEQ): %m"); 254 if (pppol2tp_send_seq) 255 if (setsockopt(pppol2tp_fd, SOL_PPPOL2TP, PPPOL2TP_SO_SENDSEQ, 256 &on, sizeof(on)) < 0) 257 fatal("setsockopt(PPPOL2TP_SENDSEQ): %m"); 258 if (pppol2tp_lns_mode) 259 if (setsockopt(pppol2tp_fd, SOL_PPPOL2TP, PPPOL2TP_SO_LNSMODE, 260 &on, sizeof(on)) < 0) 261 fatal("setsockopt(PPPOL2TP_LNSMODE): %m"); 262 if (pppol2tp_reorder_timeout) 263 if (setsockopt(pppol2tp_fd, SOL_PPPOL2TP, PPPOL2TP_SO_REORDERTO, 264 &pppol2tp_reorder_timeout, 265 sizeof(pppol2tp_reorder_timeout)) < 0) 266 fatal("setsockopt(PPPOL2TP_REORDERTO): %m"); 267 if (pppol2tp_debug_mask) 268 if (setsockopt(pppol2tp_fd, SOL_PPPOL2TP, PPPOL2TP_SO_DEBUG, 269 &pppol2tp_debug_mask, sizeof(pppol2tp_debug_mask)) < 0) 270 fatal("setsockopt(PPPOL2TP_DEBUG): %m"); 271} 272 273static void recv_config_pppol2tp(int mru, 274 u_int32_t asyncmap, 275 int pcomp, 276 int accomp) 277{ 278 if ((lcp_allowoptions[0].mru > 0) && (mru > lcp_allowoptions[0].mru)) { 279 warn("Overriding mru %d to mtu value %d", mru, 280 lcp_allowoptions[0].mru); 281 mru = lcp_allowoptions[0].mru; 282 } 283 if ((ifunit >= 0) && ioctl(pppol2tp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) 284 error("Couldn't set PPP MRU: %m"); 285} 286 287/***************************************************************************** 288 * Snoop LCP message exchanges to capture negotiated ACCM values. 289 * When asyncmap values have been seen from both sides, give the values to 290 * L2TP. 291 * This code is derived from Roaring Penguin L2TP. 292 *****************************************************************************/ 293 294static void pppol2tp_lcp_snoop(unsigned char *buf, int len, int incoming) 295{ 296 static bool got_send_accm = 0; 297 static bool got_recv_accm = 0; 298 static uint32_t recv_accm = 0xffffffff; 299 static uint32_t send_accm = 0xffffffff; 300 static bool snooping = 1; 301 302 uint16_t protocol; 303 uint16_t lcp_pkt_len; 304 int opt, opt_len; 305 int reject; 306 unsigned char const *opt_data; 307 uint32_t accm; 308 309 /* Skip HDLC header */ 310 buf += 2; 311 len -= 2; 312 313 /* Unreasonably short frame?? */ 314 if (len <= 0) return; 315 316 /* Get protocol */ 317 if (buf[0] & 0x01) { 318 /* Compressed protcol field */ 319 protocol = buf[0]; 320 } else { 321 protocol = ((unsigned int) buf[0]) * 256 + buf[1]; 322 } 323 324 /* If it's a network protocol, stop snooping */ 325 if (protocol <= 0x3fff) { 326 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DEBUG) { 327 dbglog("Turning off snooping: " 328 "Network protocol %04x found.", 329 protocol); 330 } 331 snooping = 0; 332 return; 333 } 334 335 /* If it's not LCP, do not snoop */ 336 if (protocol != 0xc021) { 337 return; 338 } 339 340 /* Skip protocol; go to packet data */ 341 buf += 2; 342 len -= 2; 343 344 /* Unreasonably short frame?? */ 345 if (len <= 0) return; 346 347 /* Look for Configure-Ack or Configure-Reject code */ 348 if (buf[0] != CONFACK && buf[0] != CONFREJ) return; 349 350 reject = (buf[0] == CONFREJ); 351 352 lcp_pkt_len = ((unsigned int) buf[2]) * 256 + buf[3]; 353 354 /* Something fishy with length field? */ 355 if (lcp_pkt_len > len) return; 356 357 /* Skip to options */ 358 len = lcp_pkt_len - 4; 359 buf += 4; 360 361 while (len > 0) { 362 /* Pull off an option */ 363 opt = buf[0]; 364 opt_len = buf[1]; 365 opt_data = &buf[2]; 366 if (opt_len > len || opt_len < 2) break; 367 len -= opt_len; 368 buf += opt_len; 369 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DEBUG) { 370 dbglog("Found option type %02x; len %d", opt, opt_len); 371 } 372 373 /* We are specifically interested in ACCM */ 374 if (opt == CI_ASYNCMAP && opt_len == 0x06) { 375 if (reject) { 376 /* ACCM negotiation REJECTED; use default */ 377 accm = 0xffffffff; 378 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DATA) { 379 dbglog("Rejected ACCM negotiation; " 380 "defaulting (%s)", 381 incoming ? "incoming" : "outgoing"); 382 } 383 recv_accm = accm; 384 send_accm = accm; 385 got_recv_accm = 1; 386 got_send_accm = 1; 387 } else { 388 memcpy(&accm, opt_data, sizeof(accm)); 389 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DATA) { 390 dbglog("Found ACCM of %08x (%s)", accm, 391 incoming ? "incoming" : "outgoing"); 392 } 393 if (incoming) { 394 recv_accm = accm; 395 got_recv_accm = 1; 396 } else { 397 send_accm = accm; 398 got_send_accm = 1; 399 } 400 } 401 402 if (got_recv_accm && got_send_accm) { 403 if (pppol2tp_debug_mask & PPPOL2TP_MSG_CONTROL) { 404 dbglog("Telling L2TP: Send ACCM = %08x; " 405 "Receive ACCM = %08x", send_accm, recv_accm); 406 } 407 if (pppol2tp_send_accm_hook != NULL) { 408 (*pppol2tp_send_accm_hook)(pppol2tp_tunnel_id, 409 pppol2tp_session_id, 410 send_accm, recv_accm); 411 } 412 got_recv_accm = 0; 413 got_send_accm = 0; 414 } 415 } 416 } 417} 418 419static void pppol2tp_lcp_snoop_recv(unsigned char *p, int len) 420{ 421 if (old_snoop_recv_hook != NULL) 422 (*old_snoop_recv_hook)(p, len); 423 pppol2tp_lcp_snoop(p, len, 1); 424} 425 426static void pppol2tp_lcp_snoop_send(unsigned char *p, int len) 427{ 428 if (old_snoop_send_hook != NULL) 429 (*old_snoop_send_hook)(p, len); 430 pppol2tp_lcp_snoop(p, len, 0); 431} 432 433/***************************************************************************** 434 * Interface up/down events 435 *****************************************************************************/ 436 437static void pppol2tp_ip_up(void *opaque, int arg) 438{ 439 /* may get called twice (for IPv4 and IPv6) but the hook handles that well */ 440 if (pppol2tp_ip_updown_hook != NULL) { 441 (*pppol2tp_ip_updown_hook)(pppol2tp_tunnel_id, 442 pppol2tp_session_id, 1); 443 } 444} 445 446static void pppol2tp_ip_down(void *opaque, int arg) 447{ 448 /* may get called twice (for IPv4 and IPv6) but the hook handles that well */ 449 if (pppol2tp_ip_updown_hook != NULL) { 450 (*pppol2tp_ip_updown_hook)(pppol2tp_tunnel_id, 451 pppol2tp_session_id, 0); 452 } 453} 454 455/***************************************************************************** 456 * Application init 457 *****************************************************************************/ 458 459static void pppol2tp_check_options(void) 460{ 461 /* Enable LCP snooping for ACCM options only for LNS */ 462 if (pppol2tp_lns_mode) { 463 if ((pppol2tp_tunnel_id == 0) || (pppol2tp_session_id == 0)) { 464 fatal("tunnel_id/session_id values not specified"); 465 } 466 if (pppol2tp_debug_mask & PPPOL2TP_MSG_CONTROL) { 467 dbglog("Enabling LCP snooping"); 468 } 469 old_snoop_recv_hook = snoop_recv_hook; 470 old_snoop_send_hook = snoop_send_hook; 471 472 snoop_recv_hook = pppol2tp_lcp_snoop_recv; 473 snoop_send_hook = pppol2tp_lcp_snoop_send; 474 } 475} 476 477/* Called just before pppd exits. 478 */ 479static void pppol2tp_cleanup(void) 480{ 481 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DEBUG) { 482 dbglog("pppol2tp: exiting."); 483 } 484 disconnect_pppol2tp(); 485} 486 487void plugin_init(void) 488{ 489#if defined(__linux__) 490 extern int new_style_driver; /* From sys-linux.c */ 491 if (!ppp_available() && !new_style_driver) 492 fatal("Kernel doesn't support ppp_generic - " 493 "needed for PPPoL2TP"); 494#else 495 fatal("No PPPoL2TP support on this OS"); 496#endif 497 add_options(pppol2tp_options); 498 499 /* Hook up ip up/down notifiers to send indicator to openl2tpd 500 * that the link is up 501 */ 502 add_notifier(&ip_up_notifier, pppol2tp_ip_up, NULL); 503 add_notifier(&ip_down_notifier, pppol2tp_ip_down, NULL); 504#ifdef INET6 505 add_notifier(&ipv6_up_notifier, pppol2tp_ip_up, NULL); 506 add_notifier(&ipv6_down_notifier, pppol2tp_ip_down, NULL); 507#endif 508} 509 510struct channel pppol2tp_channel = { 511 options: pppol2tp_options, 512 process_extra_options: NULL, 513 check_options: &pppol2tp_check_options, 514 connect: &connect_pppol2tp, 515 disconnect: &disconnect_pppol2tp, 516 establish_ppp: &generic_establish_ppp, 517 disestablish_ppp: &generic_disestablish_ppp, 518 send_config: &send_config_pppol2tp, 519 recv_config: &recv_config_pppol2tp, 520 close: NULL, 521 cleanup: NULL 522}; 523