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