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