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 union { 121 char buffer[128]; 122 struct sockaddr pppol2tp; 123 } s; 124 int len = sizeof(s); 125 char **a; 126 int tmp; 127 int tmp_len = sizeof(tmp); 128 129 if (device_got_set) 130 return 0; 131 132 if (!int_option(*argv, &pppol2tp_fd)) 133 return 0; 134 135 if(getsockname(pppol2tp_fd, (struct sockaddr *)&s, &len) < 0) { 136 fatal("Given FD for PPPoL2TP socket invalid (%s)", 137 strerror(errno)); 138 } 139 if(s.pppol2tp.sa_family != AF_PPPOX) { 140 fatal("Socket of not a PPPoX socket"); 141 } 142 143 /* Do a test getsockopt() to ensure that the kernel has the necessary 144 * feature available. 145 */ 146 if (getsockopt(pppol2tp_fd, SOL_PPPOL2TP, PPPOL2TP_SO_DEBUG, 147 &tmp, &tmp_len) < 0) { 148 fatal("PPPoL2TP kernel driver not installed"); 149 } 150 151 pppol2tp_fd_str = strdup(*argv); 152 if (pppol2tp_fd_str == NULL) 153 novm("PPPoL2TP FD"); 154 155 /* Setup option defaults. Compression options are disabled! */ 156 157 modem = 0; 158 159 lcp_allowoptions[0].neg_accompression = 1; 160 lcp_wantoptions[0].neg_accompression = 0; 161 162 lcp_allowoptions[0].neg_pcompression = 1; 163 lcp_wantoptions[0].neg_pcompression = 0; 164 165 ccp_allowoptions[0].deflate = 0; 166 ccp_wantoptions[0].deflate = 0; 167 168 ipcp_allowoptions[0].neg_vj = 0; 169 ipcp_wantoptions[0].neg_vj = 0; 170 171 ccp_allowoptions[0].bsd_compress = 0; 172 ccp_wantoptions[0].bsd_compress = 0; 173 174 the_channel = &pppol2tp_channel; 175 device_got_set = 1; 176 177 return 1; 178} 179 180static int connect_pppol2tp(void) 181{ 182 if(pppol2tp_fd == -1) { 183 fatal("No PPPoL2TP FD specified"); 184 } 185 186 return pppol2tp_fd; 187} 188 189static void disconnect_pppol2tp(void) 190{ 191 if (pppol2tp_fd >= 0) { 192 close(pppol2tp_fd); 193 pppol2tp_fd = -1; 194 } 195} 196 197static void send_config_pppol2tp(int mtu, 198 u_int32_t asyncmap, 199 int pcomp, 200 int accomp) 201{ 202 struct ifreq ifr; 203 int on = 1; 204 int fd; 205 char reorderto[16]; 206 char tid[8]; 207 char sid[8]; 208 209 if (pppol2tp_ifname[0]) { 210 struct ifreq ifr; 211 int fd; 212 213 fd = socket(AF_INET, SOCK_DGRAM, 0); 214 if (fd >= 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", 223 ifunit, ifname); 224 } 225 } 226 close(fd); 227 } 228 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; 232 } 233 netif_set_mtu(ifunit, mtu); 234 235 reorderto[0] = '\0'; 236 if (pppol2tp_reorder_timeout > 0) 237 sprintf(&reorderto[0], "%d ", pppol2tp_reorder_timeout); 238 tid[0] = '\0'; 239 if (pppol2tp_tunnel_id > 0) 240 sprintf(&tid[0], "%hu ", pppol2tp_tunnel_id); 241 sid[0] = '\0'; 242 if (pppol2tp_session_id > 0) 243 sprintf(&sid[0], "%hu ", pppol2tp_session_id); 244 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); 253 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"); 275} 276 277static void recv_config_pppol2tp(int mru, 278 u_int32_t asyncmap, 279 int pcomp, 280 int accomp) 281{ 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; 286 } 287 if ((ifunit >= 0) && ioctl(pppol2tp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) 288 error("Couldn't set PPP MRU: %m"); 289} 290 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 294 * L2TP. 295 * This code is derived from Roaring Penguin L2TP. 296 *****************************************************************************/ 297 298static void pppol2tp_lcp_snoop(unsigned char *buf, int len, int incoming) 299{ 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; 305 306 uint16_t protocol; 307 uint16_t lcp_pkt_len; 308 int opt, opt_len; 309 int reject; 310 unsigned char const *opt_data; 311 uint32_t accm; 312 313 /* Skip HDLC header */ 314 buf += 2; 315 len -= 2; 316 317 /* Unreasonably short frame?? */ 318 if (len <= 0) return; 319 320 /* Get protocol */ 321 if (buf[0] & 0x01) { 322 /* Compressed protcol field */ 323 protocol = buf[0]; 324 } else { 325 protocol = ((unsigned int) buf[0]) * 256 + buf[1]; 326 } 327 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.", 333 protocol); 334 } 335 snooping = 0; 336 return; 337 } 338 339 /* If it's not LCP, do not snoop */ 340 if (protocol != 0xc021) { 341 return; 342 } 343 344 /* Skip protocol; go to packet data */ 345 buf += 2; 346 len -= 2; 347 348 /* Unreasonably short frame?? */ 349 if (len <= 0) return; 350 351 /* Look for Configure-Ack or Configure-Reject code */ 352 if (buf[0] != CONFACK && buf[0] != CONFREJ) return; 353 354 reject = (buf[0] == CONFREJ); 355 356 lcp_pkt_len = ((unsigned int) buf[2]) * 256 + buf[3]; 357 358 /* Something fishy with length field? */ 359 if (lcp_pkt_len > len) return; 360 361 /* Skip to options */ 362 len = lcp_pkt_len - 4; 363 buf += 4; 364 365 while (len > 0) { 366 /* Pull off an option */ 367 opt = buf[0]; 368 opt_len = buf[1]; 369 opt_data = &buf[2]; 370 if (opt_len > len || opt_len < 2) break; 371 len -= opt_len; 372 buf += opt_len; 373 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DEBUG) { 374 dbglog("Found option type %02x; len %d", opt, opt_len); 375 } 376 377 /* We are specifically interested in ACCM */ 378 if (opt == CI_ASYNCMAP && opt_len == 0x06) { 379 if (reject) { 380 /* ACCM negotiation REJECTED; use default */ 381 accm = 0xffffffff; 382 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DATA) { 383 dbglog("Rejected ACCM negotiation; " 384 "defaulting (%s)", 385 incoming ? "incoming" : "outgoing"); 386 } 387 recv_accm = accm; 388 send_accm = accm; 389 got_recv_accm = 1; 390 got_send_accm = 1; 391 } else { 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"); 396 } 397 if (incoming) { 398 recv_accm = accm; 399 got_recv_accm = 1; 400 } else { 401 send_accm = accm; 402 got_send_accm = 1; 403 } 404 } 405 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); 410 } 411 if (pppol2tp_send_accm_hook != NULL) { 412 (*pppol2tp_send_accm_hook)(pppol2tp_tunnel_id, 413 pppol2tp_session_id, 414 send_accm, recv_accm); 415 } 416 got_recv_accm = 0; 417 got_send_accm = 0; 418 } 419 } 420 } 421} 422 423static void pppol2tp_lcp_snoop_recv(unsigned char *p, int len) 424{ 425 if (old_snoop_recv_hook != NULL) 426 (*old_snoop_recv_hook)(p, len); 427 pppol2tp_lcp_snoop(p, len, 1); 428} 429 430static void pppol2tp_lcp_snoop_send(unsigned char *p, int len) 431{ 432 if (old_snoop_send_hook != NULL) 433 (*old_snoop_send_hook)(p, len); 434 pppol2tp_lcp_snoop(p, len, 0); 435} 436 437/***************************************************************************** 438 * Interface up/down events 439 *****************************************************************************/ 440 441static void pppol2tp_ip_up(void *opaque, int arg) 442{ 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); 447 } 448} 449 450static void pppol2tp_ip_down(void *opaque, int arg) 451{ 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); 456 } 457} 458 459/***************************************************************************** 460 * Application init 461 *****************************************************************************/ 462 463static void pppol2tp_check_options(void) 464{ 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"); 469 } 470 if (pppol2tp_debug_mask & PPPOL2TP_MSG_CONTROL) { 471 dbglog("Enabling LCP snooping"); 472 } 473 old_snoop_recv_hook = snoop_recv_hook; 474 old_snoop_send_hook = snoop_send_hook; 475 476 snoop_recv_hook = pppol2tp_lcp_snoop_recv; 477 snoop_send_hook = pppol2tp_lcp_snoop_send; 478 } 479} 480 481/* Called just before pppd exits. 482 */ 483static void pppol2tp_cleanup(void) 484{ 485 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DEBUG) { 486 dbglog("pppol2tp: exiting."); 487 } 488 disconnect_pppol2tp(); 489} 490 491void plugin_init(void) 492{ 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"); 498#else 499 fatal("No PPPoL2TP support on this OS"); 500#endif 501 add_options(pppol2tp_options); 502 503 /* Hook up ip up/down notifiers to send indicator to openl2tpd 504 * that the link is up 505 */ 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); 510} 511 512struct 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, 522 close: NULL, 523 cleanup: NULL 524}; 525