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 57 const char pppd_version[] = VERSION; 58 59 static int setdevname_pppol2tp(char **argv); 60 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; 71 72 static int device_got_set = 0; 73 struct channel pppol2tp_channel; 74 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; 77 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; 81 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; 84 85 static 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 118 static 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 180 static int connect_pppol2tp(void) 181 { 182 if(pppol2tp_fd == -1) { 183 fatal("No PPPoL2TP FD specified"); 184 } 185 186 return pppol2tp_fd; 187 } 188 189 static void disconnect_pppol2tp(void) 190 { 191 if (pppol2tp_fd >= 0) { 192 close(pppol2tp_fd); 193 pppol2tp_fd = -1; 194 } 195 } 196 197 static 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 277 static 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 298 static 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 423 static 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 430 static 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 441 static 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 450 static 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 463 static 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 */ 483 static void pppol2tp_cleanup(void) 484 { 485 if (pppol2tp_debug_mask & PPPOL2TP_MSG_DEBUG) { 486 dbglog("pppol2tp: exiting."); 487 } 488 disconnect_pppol2tp(); 489 } 490 491 void 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 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, 522 close: NULL, 523 cleanup: NULL 524 }; 525