diff options
author | Sam Protsenko <semen.protsenko@linaro.org> | 2018-07-26 22:18:15 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2018-07-26 22:18:15 -0700 |
commit | b06565468b3b5b4ef5cbb0a2a9cfb8a95458e692 (patch) | |
tree | 656403391258cb029f353eedb7e1aea28d189961 | |
parent | 77439edf07ff5a26d5880b4f2b177d0ffbb3906b (diff) | |
parent | 3df1710818f44d2a23bfd11ba02d0c1b169e7b70 (diff) | |
download | ppp-b06565468b3b5b4ef5cbb0a2a9cfb8a95458e692.tar.gz |
pppd: Add pppol2tp-android plugin am: 0c9566a278 am: b6a7858352 am: ad51db4000
am: 3df1710818
Change-Id: I6acdfbffb2446edfb73e0e63ab99dfff779383a1
-rw-r--r-- | pppd/README.pppol2tp | 33 | ||||
-rw-r--r-- | pppd/plugins/pppol2tp-android/pppol2tp-android.c | 129 |
2 files changed, 162 insertions, 0 deletions
diff --git a/pppd/README.pppol2tp b/pppd/README.pppol2tp new file mode 100644 index 0000000..e82548a --- /dev/null +++ b/pppd/README.pppol2tp @@ -0,0 +1,33 @@ +PPPoL2TP-Android plugin +======================= + +This PPPoL2TP-Android plugin was written for AOSP project from scratch. It has +nothing to do with pppol2tp plugin from upstream ppp project [1]. + +This plugin adds support for upstream kernel L2TP implementation in pppd +daemon. Only LAC part of L2TP is implemented, as we don't use Android devices +in LNS mode. + +In general case, the execution flow for VPN startup on Android devices is: + 1. Run IPSec client (racoon) + 2. Run L2TP client (mtpd) + 3. mtpd obtains "remote tunnel ID" and "remote session ID" from L2TP server + 4. mtpd creates L2TP sockets (see [2] for details): + - tunnel management PPPoX socket + - session PPPoX data socket + 5. mtpd runs pppd, passing arguments for pppol2tp-android plugin + 6. pppd dlopen() pppol2tp-android plugin (because it receives corresponding\ + arguments from mtpd) + +Main task of this plugin is to obtain session_fd socket from mtpd and pass it +back to pppd when .connect() callback is executed. In this respect it's similar +to old pppox.c implementation. The differences are next: + 1. pppol2tp-android also obtains the second socket (for tunnel management) + which allows us to handle it properly + 2. pppol2tp-android handles the setting of MTU/MRU size (which can be passed + to the plugin with pppd parameters) via kernel L2TP implementation + 3. pppol2tp-android plugin is actually loaded dynamically with dlopen(), + as opposed to pppox.c which is hard-coded into pppd code + +[1] https://github.com/paulusmack/ppp +[2] https://www.kernel.org/doc/Documentation/networking/l2tp.txt diff --git a/pppd/plugins/pppol2tp-android/pppol2tp-android.c b/pppd/plugins/pppol2tp-android/pppol2tp-android.c new file mode 100644 index 0000000..6a984de --- /dev/null +++ b/pppd/plugins/pppol2tp-android/pppol2tp-android.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pppd.h" +#include "fsm.h" +#include "lcp.h" +#include <unistd.h> +#include <sys/ioctl.h> +#include <linux/if_ppp.h> + +char pppd_version[] = VERSION; + +static struct channel pppol2tp_channel; + +/* Options variables */ +static int session_fd = -1; +static int tunnel_fd = -1; +static int session_id = 0; +static int tunnel_id = 0; + +static int pppol2tp_set_session_fd(char **argv); + +static option_t pppol2tp_options[] = { + { "session_fd", o_special, pppol2tp_set_session_fd, + "Session PPPoX data socket", OPT_DEVNAM }, + { "tunnel_fd", o_int, &tunnel_fd, + "Tunnel management PPPoX socket", OPT_PRIO }, + { "session_id", o_int, &session_id, "Session ID", OPT_PRIO }, + { "tunnel_id", o_int, &tunnel_id, "Tunnel ID", OPT_PRIO }, + { NULL } +}; + +static int pppol2tp_set_session_fd(char **argv) +{ + if (!int_option(*argv, &session_fd)) + return 0; + + info("Using PPPoL2TP (socket = %d)", session_fd); + the_channel = &pppol2tp_channel; + return 1; +} + +/** + * Set the MRU on the PPP network interface. + * + * @param mru New MRU value + * + * @note netif_set_mru() is missing in sys-linux.c, so implement it manually + * @note See net/l2tp/l2tp_ppp.c:pppol2tp_session_ioctl() in kernel for details + */ +static void pppol2tp_set_mru(int mru) +{ + int res; + + if (ifunit < 0) + return; + + res = ioctl(session_fd, PPPIOCSMRU, (caddr_t)&mru); + if (res < 0) + error("ioctl(PPPIOCSMRU): %m (line %d)", __LINE__); +} + +/* Set the transmit-side PPP parameters of the channel */ +static void pppol2tp_send_config(int mtu, u_int32_t accm, int pcomp, int accomp) +{ + int new_mtu = lcp_allowoptions[0].mru; /* "mtu" pppd option */ + + if (new_mtu <= PPP_MAXMTU && new_mtu >= PPP_MINMTU) + netif_set_mtu(ifunit, new_mtu); +} + +/* Set the receive-side PPP parameters of the channel */ +static void pppol2tp_recv_config(int mru, u_int32_t accm, int pcomp, int accomp) +{ + int new_mru = lcp_wantoptions[0].mru; /* "mru" pppd option */ + + if (new_mru <= PPP_MAXMRU && new_mru >= PPP_MINMRU) + pppol2tp_set_mru(new_mru); +} + +static int pppol2tp_connect(void) +{ + return session_fd; +} + +static void pppol2tp_disconnect(void) +{ + if (session_fd != -1) { + close(session_fd); + session_fd = -1; + } + + if (tunnel_fd != -1) { + close(tunnel_fd); + tunnel_fd = -1; + } +} + +void plugin_init(void) +{ + add_options(pppol2tp_options); +} + +static struct channel pppol2tp_channel = { + .options = pppol2tp_options, + .process_extra_options = NULL, + .check_options = NULL, + .connect = pppol2tp_connect, + .disconnect = pppol2tp_disconnect, + .establish_ppp = generic_establish_ppp, + .disestablish_ppp = generic_disestablish_ppp, + .send_config = pppol2tp_send_config, + .recv_config = pppol2tp_recv_config, + .cleanup = NULL, + .close = NULL, +}; |