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 <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 
setdevname_pppol2tp(char ** argv)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 
connect_pppol2tp(void)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 
disconnect_pppol2tp(void)199 static void disconnect_pppol2tp(void)
200 {
201           if (pppol2tp_fd >= 0) {
202                     close(pppol2tp_fd);
203                     pppol2tp_fd = -1;
204           }
205 }
206 
send_config_pppol2tp(int mtu,uint32_t asyncmap,int pcomp,int accomp)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 
recv_config_pppol2tp(int mru,uint32_t asyncmap,int pcomp,int accomp)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 
pppol2tp_lcp_snoop(unsigned char * buf,int len,int incoming)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 
pppol2tp_lcp_snoop_recv(unsigned char * p,int len)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 
pppol2tp_lcp_snoop_send(unsigned char * p,int len)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 
pppol2tp_ip_up(void * opaque,int arg)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 
pppol2tp_ip_down(void * opaque,int arg)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 
pppol2tp_check_options(void)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  */
pppol2tp_cleanup(void)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 
plugin_init(void)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