diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2018-07-27 05:00:48 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2018-07-27 05:00:48 +0000 |
commit | 813c1e1d6d2ba87a6428100e735ba1d041e7aac2 (patch) | |
tree | 0b26260efce8da808ad742b0545f41adae2fcb73 | |
parent | 90da8c8f15db2c82aece6e4085aaf9c116d481f2 (diff) | |
parent | ea3c64e6fe432a91938e52fe9529d4fea0961b66 (diff) | |
download | ppp-813c1e1d6d2ba87a6428100e735ba1d041e7aac2.tar.gz |
Merge changes from topic "pppolac"
* changes:
pppd: Convert Android.mk to Android.bp
pppd: Add rules for building the pppol2tp-android plugin
pppd: Fix pppol2tp-android.so build
pppd: Enable plugin support in pppd
pppd: Add pppol2tp-android plugin
pppd: Remove obsolete way of receiving args from mtpd
-rw-r--r-- | Android.bp | 15 | ||||
-rw-r--r-- | pppd/Android.bp | 88 | ||||
-rw-r--r-- | pppd/Android.mk | 46 | ||||
-rw-r--r-- | pppd/README.pppol2tp | 33 | ||||
-rw-r--r-- | pppd/include/net/ppp_defs.h | 8 | ||||
-rw-r--r-- | pppd/main.c | 27 | ||||
-rw-r--r-- | pppd/pathnames.h | 16 | ||||
-rw-r--r-- | pppd/plugins/pppol2tp-android/pppol2tp-android.c | 129 |
8 files changed, 291 insertions, 71 deletions
diff --git a/Android.bp b/Android.bp new file mode 100644 index 0000000..3704241 --- /dev/null +++ b/Android.bp @@ -0,0 +1,15 @@ +// 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. + +subdirs = ["pppd"] diff --git a/pppd/Android.bp b/pppd/Android.bp new file mode 100644 index 0000000..d995a0d --- /dev/null +++ b/pppd/Android.bp @@ -0,0 +1,88 @@ +// 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. + +cc_defaults { + name: "ppp_defaults", + cflags: [ + "-DCHAPMS=1", + "-DMPPE=1", + "-DINET6=1", + "-DUSE_OPENSSL=1", + "-Wno-missing-field-initializers", + "-Wno-unused-parameter", + "-Werror", + "-Wno-pointer-sign", + ], + local_include_dirs: ["include"], +} + +cc_binary { + name: "pppd", + defaults: ["ppp_defaults"], + + srcs: [ + "auth.c", + "ccp.c", + "chap-md5.c", + "chap-new.c", + "chap_ms.c", + "demand.c", + "eap.c", + "ecp.c", + "eui64.c", + "fsm.c", + "ipcp.c", + "ipv6cp.c", + "lcp.c", + "magic.c", + "main.c", + "options.c", + "pppcrypt.c", + "pppox.c", + "session.c", + "sys-linux.c", + "tty.c", + "upap.c", + "utils.c", + ], + + // options.c:623:21: error: passing 'const char *' to parameter of + // type 'char *' discards qualifiers. + // [-Werror,-Wincompatible-pointer-types-discards-qualifiers] + clang_cflags: ["-Wno-incompatible-pointer-types-discards-qualifiers"], + + shared_libs: [ + "libdl", + "liblog", + "libcutils", + "libcrypto", + ], + + cflags: [ + "-Wno-empty-body", + "-Wno-attributes", + "-Wno-sign-compare", + "-DPLUGIN", + ], + + ldflags: ["-rdynamic"], + required: ["pppol2tp-android"], +} + +cc_library_shared { + name: "pppol2tp-android", + defaults: ["ppp_defaults"], + srcs: ["plugins/pppol2tp-android/pppol2tp-android.c"], + allow_undefined_symbols: true, +} diff --git a/pppd/Android.mk b/pppd/Android.mk deleted file mode 100644 index 88cfe35..0000000 --- a/pppd/Android.mk +++ /dev/null @@ -1,46 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - auth.c \ - ccp.c \ - chap-md5.c \ - chap-new.c \ - chap_ms.c \ - demand.c \ - eap.c \ - ecp.c \ - eui64.c \ - fsm.c \ - ipcp.c \ - ipv6cp.c \ - lcp.c \ - magic.c \ - main.c \ - options.c \ - pppcrypt.c \ - pppox.c \ - session.c \ - sys-linux.c \ - tty.c \ - upap.c \ - utils.c - -# options.c:623:21: error: passing 'const char *' to parameter of type 'char *' discards qualifiers. -# [-Werror,-Wincompatible-pointer-types-discards-qualifiers] -LOCAL_CLANG_CFLAGS += -Wno-incompatible-pointer-types-discards-qualifiers - -LOCAL_SHARED_LIBRARIES := \ - libcutils liblog libcrypto - -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/include - -LOCAL_CFLAGS := -DCHAPMS=1 -DMPPE=1 -DINET6=1 -DUSE_OPENSSL=1 -Wno-unused-parameter -Wno-empty-body -Wno-missing-field-initializers -Wno-attributes -Wno-sign-compare -Wno-pointer-sign -Werror - -# Turn off warnings for now until this is fixed upstream. b/18632512 -LOCAL_CFLAGS += -Wno-unused-variable - -LOCAL_MODULE:= pppd - -include $(BUILD_EXECUTABLE) 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/include/net/ppp_defs.h b/pppd/include/net/ppp_defs.h index a21afdb..9522290 100644 --- a/pppd/include/net/ppp_defs.h +++ b/pppd/include/net/ppp_defs.h @@ -38,6 +38,10 @@ #ifndef _PPP_DEFS_H_ #define _PPP_DEFS_H_ +#if defined(__linux__) +#include <linux/ppp_defs.h> +#endif + #if defined(PPP_ADDRESS) #define USING_UAPI #endif @@ -131,6 +135,10 @@ typedef u_int32_t ext_accm[8]; * What to do with network protocol (NP) packets. */ #if defined(USING_UAPI) + +/* For struct ifreq */ +#include <net/if.h> + /* This stuff isn't in uapi. TODO: is there a newer pppd that doesn't use this? */ #define ifr__name b.ifr_ifrn.ifrn_name #define stats_ptr b.ifr_ifru.ifru_data diff --git a/pppd/main.c b/pppd/main.c index 5424e42..09f5a53 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -357,39 +357,16 @@ main(argc, argv) */ tty_init(); - progname = *argv; - #if defined(__ANDROID__) { extern void pppox_init(); pppox_init(); privileged = 1; } - { - char *envargs = getenv("envargs"); - if (envargs) { - int i; - /* Decode the arguments in-place and count the number of them. - * They were hex encoded using [A-P] instead of [0-9A-F]. */ - for (argc = 0, i = 0; envargs[i] && envargs[i + 1]; i += 2) { - char c = ((envargs[i] - 'A') << 4) + (envargs[i + 1] - 'A'); - if (c == 0) { - ++argc; - } - envargs[i / 2 + 1] = c; - } - if (argc == 0 || (argv = malloc(sizeof(char *) * argc)) == NULL) { - fatal("Failed to parse envargs!"); - } - for (envargs[0] = 0, i = 0; i < argc; ++envargs) { - if (envargs[0] == 0) { - argv[i++] = &envargs[1]; - } - } - } - } #endif + progname = *argv; + /* * Parse, in order, the system options file, the user's options file, * and the command line arguments. diff --git a/pppd/pathnames.h b/pppd/pathnames.h index a33f046..ea74736 100644 --- a/pppd/pathnames.h +++ b/pppd/pathnames.h @@ -56,10 +56,26 @@ #endif /* __STDC__ */ #ifdef PLUGIN +#ifdef __ANDROID__ + +/* + * In Android we can't load plugins from /system/lib{64}/pppd/, because + * Bionic loader only allows us to dlopen() libraries from /system/lib{64} root + * directory (as specified in ld.config.txt, see "default" linker namespace). + */ +#ifdef __LP64__ +#define _PATH_PLUGIN "/system/lib64" +#else /* __LP64__ */ +#define _PATH_PLUGIN "/system/lib" +#endif /* __LP64__ */ + +#else /* __ANDROID__ */ + #ifdef __STDC__ #define _PATH_PLUGIN DESTDIR "/lib/pppd/" VERSION #else /* __STDC__ */ #define _PATH_PLUGIN "/usr/lib/pppd" #endif /* __STDC__ */ +#endif /* __ANDROID__ */ #endif /* PLUGIN */ 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, +}; |