summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHansen Kurli <hkurli@google.com>2023-11-14 09:46:00 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-11-14 09:46:00 +0000
commit05b547a953d4db4524d9abca73eb716aa2bc4f2a (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904
parent311c07353ce1899fadf73a50dabd65ea84e34e85 (diff)
parent98c77a5a5806feb322c4d7e7fe6a4cd1a65181e4 (diff)
downloadmtpd-05b547a953d4db4524d9abca73eb716aa2bc4f2a.tar.gz
Merge "Remove mtpd" into main am: 98c77a5a58
Original change: https://android-review.googlesource.com/c/platform/external/mtpd/+/2825795 Change-Id: I840f95ac3cea49095dfb6cf251b90729fe40c1b9 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--Android.bp51
-rw-r--r--METADATA3
-rw-r--r--MODULE_LICENSE_APACHE20
-rw-r--r--NOTICE190
-rw-r--r--OWNERS2
-rw-r--r--l2tp.c683
-rw-r--r--mtpd.c473
-rw-r--r--mtpd.h97
-rw-r--r--mtpd.rc8
-rw-r--r--pptp.c583
10 files changed, 0 insertions, 2090 deletions
diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index 9efa325..0000000
--- a/Android.bp
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2016 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.
-
-package {
- default_applicable_licenses: ["external_mtpd_license"],
-}
-
-// Added automatically by a large-scale-change
-// See: http://go/android-license-faq
-license {
- name: "external_mtpd_license",
- visibility: [":__subpackages__"],
- license_kinds: [
- "SPDX-license-identifier-Apache-2.0",
- ],
- license_text: [
- "NOTICE",
- ],
-}
-
-cc_binary {
- name: "mtpd",
- srcs: [
- "mtpd.c",
- "l2tp.c",
- "pptp.c"
- ],
- shared_libs: [
- "libcrypto",
- "libcutils",
- "liblog",
- "libnetd_client",
- ],
- cflags: [
- "-DANDROID_CHANGES",
- "-Wall",
- "-Werror",
- ],
- init_rc: ["mtpd.rc"],
-}
diff --git a/METADATA b/METADATA
deleted file mode 100644
index d97975c..0000000
--- a/METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-third_party {
- license_type: NOTICE
-}
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index 64aaa8d..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
- Copyright (c) 2009, 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.
-
- 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.
-
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
diff --git a/OWNERS b/OWNERS
deleted file mode 100644
index c24680e..0000000
--- a/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-set noparent
-file:platform/packages/modules/Connectivity:main:/OWNERS_core_networking
diff --git a/l2tp.c b/l2tp.c
deleted file mode 100644
index ae6088d..0000000
--- a/l2tp.c
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-/*
- * Implementation of L2TP Access Concentrator (RFC 2661). The following code
- * only handles control packets. Data packets are handled by kernel driver:
- * - PX_PROTO_OL2TP (upstream impl.), if it's enabled in kernel
- * - or PX_PROTO_OLAC (Android impl.), if upstream implementation is not
- * available / not enabled. It will be removed in new Android kernels.
- */
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <linux/netdevice.h>
-#include <linux/if_pppox.h>
-#include <linux/types.h>
-#include <openssl/md5.h>
-
-#include "mtpd.h"
-
-/* To avoid unnecessary endianness conversions, tunnels, sessions, attributes,
- * and values are all accessed in network order. */
-
-/* 0 is reserved. We put ACK here just for convenience. */
-enum l2tp_message {
- ACK = 0,
- SCCRQ = 1,
- SCCRP = 2,
- SCCCN = 3,
- STOPCCN = 4,
- HELLO = 6,
- OCRQ = 7,
- OCRP = 8,
- OCCN = 9,
- ICRQ = 10,
- ICRP = 11,
- ICCN = 12,
- CDN = 14,
- WEN = 15,
- SLI = 16,
- MESSAGE_MAX = 16,
-};
-
-static char *messages[] = {
- "ACK", "SCCRQ", "SCCRP", "SCCCN", "STOPCCN", NULL, "HELLO", "OCRQ",
- "OCRP", "OCCN", "ICRQ", "ICRP", "ICCN", NULL, "CDN", "WEN", "SLI",
-};
-
-/* This is incomplete. Only those we used are listed here. */
-#define RESULT_CODE htons(1)
-#define PROTOCOL_VERSION htons(2)
-#define FRAMING_CAPABILITIES htons(3)
-#define HOST_NAME htons(7)
-#define ASSIGNED_TUNNEL htons(9)
-#define WINDOW_SIZE htons(10)
-#define CHALLENGE htons(11)
-#define CHALLENGE_RESPONSE htons(13)
-#define ASSIGNED_SESSION htons(14)
-#define CALL_SERIAL_NUMBER htons(15)
-#define FRAMING_TYPE htons(19)
-#define CONNECT_SPEED htons(24)
-#define RANDOM_VECTOR htons(36)
-
-#define MESSAGE_FLAG 0xC802
-#define MESSAGE_MASK 0xCB0F
-#define ATTRIBUTE_FLAG(length) (0x8006 + (length))
-#define ATTRIBUTE_LENGTH(flag) (0x03FF & (flag))
-#define ATTRIBUTE_HIDDEN(flag) (0x4000 & (flag))
-
-#define ACK_SIZE 12
-#define MESSAGE_HEADER_SIZE 20
-#define ATTRIBUTE_HEADER_SIZE 6
-#define MAX_ATTRIBUTE_SIZE 1024
-
-static __be16 local_tunnel;
-static __be16 local_session;
-static uint16_t local_sequence;
-static __be16 remote_tunnel;
-static __be16 remote_session;
-static uint16_t remote_sequence;
-
-static uint16_t state;
-static int acknowledged;
-
-#define RANDOM_DEVICE "/dev/urandom"
-#define CHALLENGE_SIZE 32
-
-static char *secret;
-static int secret_length;
-static uint8_t challenge[CHALLENGE_SIZE];
-
-/* According to RFC 2661 page 46, an exponential backoff strategy is required
- * for retransmission. However, it might waste too much time waiting for IPsec
- * negotiation. Here we use the same interval to keep things simple. */
-#define TIMEOUT_INTERVAL 2000
-
-#define MAX_PACKET_LENGTH 2048
-
-static struct packet {
- int message;
- int length;
- uint8_t buffer[MAX_PACKET_LENGTH] __attribute__((aligned(4)));
-} incoming, outgoing;
-
-struct attribute {
- uint16_t flag;
- uint16_t vendor;
- uint16_t type;
- uint8_t value[1];
-} __attribute__((packed));
-
-static void set_message(uint16_t session, uint16_t message)
-{
- uint16_t *p = (uint16_t *)outgoing.buffer;
- p[0] = htons(MESSAGE_FLAG);
- /* p[1] will be filled in send_packet(). */
- p[2] = remote_tunnel;
- p[3] = session;
- p[4] = htons(local_sequence);
- p[5] = htons(remote_sequence);
- p[6] = htons(ATTRIBUTE_FLAG(2));
- p[7] = 0;
- p[8] = 0;
- p[9] = htons(message);
- outgoing.message = message;
- outgoing.length = MESSAGE_HEADER_SIZE;
- ++local_sequence;
-}
-
-static void add_attribute_raw(uint16_t type, void *value, int size)
-{
- struct attribute *p = (struct attribute *)&outgoing.buffer[outgoing.length];
- p->flag = htons(ATTRIBUTE_FLAG(size));
- p->vendor = 0;
- p->type = type;
- memcpy(&p->value, value, size);
- outgoing.length += ATTRIBUTE_HEADER_SIZE + size;
-}
-
-static void add_attribute_u16(uint16_t attribute, uint16_t value)
-{
- add_attribute_raw(attribute, &value, sizeof(uint16_t));
-}
-
-static void add_attribute_u32(uint16_t attribute, uint32_t value)
-{
- add_attribute_raw(attribute, &value, sizeof(uint32_t));
-}
-
-static void send_packet()
-{
- uint16_t *p = (uint16_t *)outgoing.buffer;
- p[1] = htons(outgoing.length);
- send(the_socket, outgoing.buffer, outgoing.length, 0);
- acknowledged = 0;
-}
-
-static void send_ack()
-{
- uint16_t buffer[6] = {
- htons(MESSAGE_FLAG), htons(ACK_SIZE), remote_tunnel, 0,
- htons(local_sequence), htons(remote_sequence),
- };
- send(the_socket, buffer, ACK_SIZE, 0);
-}
-
-static int recv_packet(uint16_t *session)
-{
- uint16_t *p = (uint16_t *)incoming.buffer;
-
- incoming.length = recv(the_socket, incoming.buffer, MAX_PACKET_LENGTH, 0);
- if (incoming.length == -1) {
- if (errno == EINTR) {
- return 0;
- }
- log_print(FATAL, "Recv() %s", strerror(errno));
- exit(NETWORK_ERROR);
- }
-
- /* We only handle packets in our tunnel. */
- if ((incoming.length != ACK_SIZE && incoming.length < MESSAGE_HEADER_SIZE)
- || (p[0] & htons(MESSAGE_MASK)) != htons(MESSAGE_FLAG) ||
- ntohs(p[1]) != incoming.length || p[2] != local_tunnel) {
- return 0;
- }
-
- if (incoming.length == ACK_SIZE) {
- incoming.message = ACK;
- } else if (p[6] == htons(ATTRIBUTE_FLAG(2)) && !p[7] && !p[8]) {
- incoming.message = ntohs(p[9]);
- } else {
- return 0;
- }
-
- /* Check if the packet is duplicated and send ACK if necessary. */
- if ((uint16_t)(ntohs(p[4]) - remote_sequence) > 32767) {
- if (incoming.message != ACK) {
- send_ack();
- }
- return 0;
- }
-
- if (ntohs(p[5]) == local_sequence) {
- acknowledged = 1;
- }
-
- /* Our sending and receiving window sizes are both 1. Thus we only handle
- * this packet if it is their next one and they received our last one. */
- if (ntohs(p[4]) != remote_sequence || !acknowledged) {
- return 0;
- }
- *session = p[3];
- if (incoming.message != ACK) {
- ++remote_sequence;
- }
- return 1;
-}
-
-static int get_attribute_raw(uint16_t type, void *value, int size)
-{
- int offset = MESSAGE_HEADER_SIZE;
- uint8_t *vector = NULL;
- int vector_length = 0;
-
- while (incoming.length >= offset + ATTRIBUTE_HEADER_SIZE) {
- struct attribute *p = (struct attribute *)&incoming.buffer[offset];
- uint16_t flag = ntohs(p->flag);
- int length = ATTRIBUTE_LENGTH(flag);
-
- offset += length;
- length -= ATTRIBUTE_HEADER_SIZE;
- if (length < 0 || offset > incoming.length) {
- break;
- }
- if (p->vendor) {
- continue;
- }
- if (p->type != type) {
- if (p->type == RANDOM_VECTOR && !ATTRIBUTE_HIDDEN(flag)) {
- vector = p->value;
- vector_length = length;
- }
- continue;
- }
-
- if (!ATTRIBUTE_HIDDEN(flag)) {
- if (size > length) {
- size = length;
- }
- memcpy(value, p->value, size);
- return size;
- }
-
- if (!secret || !vector || length < 2) {
- return 0;
- } else {
- uint8_t buffer[MAX_ATTRIBUTE_SIZE];
- uint8_t hash[MD5_DIGEST_LENGTH];
- MD5_CTX ctx;
- int i;
-
- MD5_Init(&ctx);
- MD5_Update(&ctx, &type, sizeof(uint16_t));
- MD5_Update(&ctx, secret, secret_length);
- MD5_Update(&ctx, vector, vector_length);
- MD5_Final(hash, &ctx);
-
- for (i = 0; i < length; ++i) {
- int j = i % MD5_DIGEST_LENGTH;
- if (i && !j) {
- MD5_Init(&ctx);
- MD5_Update(&ctx, secret, secret_length);
- MD5_Update(&ctx, &p->value[i - MD5_DIGEST_LENGTH],
- MD5_DIGEST_LENGTH);
- MD5_Final(hash, &ctx);
- }
- buffer[i] = p->value[i] ^ hash[j];
- }
-
- length = buffer[0] << 8 | buffer[1];
- if (length > i - 2) {
- return 0;
- }
- if (size > length) {
- size = length;
- }
- memcpy(value, &buffer[2], size);
- return size;
- }
- }
- return 0;
-}
-
-static int get_attribute_u16(uint16_t type, uint16_t *value)
-{
- return get_attribute_raw(type, value, sizeof(uint16_t)) == sizeof(uint16_t);
-}
-
-static int l2tp_connect(char **arguments)
-{
- create_socket(AF_INET, SOCK_DGRAM, arguments[0], arguments[1]);
-
- while (!local_tunnel) {
- local_tunnel = random();
- }
-
- log_print(DEBUG, "Sending SCCRQ (local_tunnel = %u)",
- (unsigned)ntohs(local_tunnel));
- state = SCCRQ;
- set_message(0, SCCRQ);
- add_attribute_u16(PROTOCOL_VERSION, htons(0x0100));
- add_attribute_raw(HOST_NAME, "anonymous", 9);
- add_attribute_u32(FRAMING_CAPABILITIES, htonl(3));
- add_attribute_u16(ASSIGNED_TUNNEL, local_tunnel);
- add_attribute_u16(WINDOW_SIZE, htons(1));
-
- if (arguments[2][0]) {
- int fd = open(RANDOM_DEVICE, O_RDONLY);
- if (fd == -1 || read(fd, challenge, CHALLENGE_SIZE) != CHALLENGE_SIZE) {
- log_print(FATAL, "Cannot read %s", RANDOM_DEVICE);
- exit(SYSTEM_ERROR);
- }
- close(fd);
-
- add_attribute_raw(CHALLENGE, challenge, CHALLENGE_SIZE);
- secret = arguments[2];
- secret_length = strlen(arguments[2]);
- }
-
- send_packet();
- return TIMEOUT_INTERVAL;
-}
-
-/**
- * Check if upstream kernel implementation of L2TP should be used.
- *
- * @return true If upstream L2TP should be used, which is the case if
- * the obsolete OLAC feature is not available.
- */
-static bool check_ol2tp(void)
-{
- int fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OLAC);
-
- if (fd < 0) {
- return true;
- } else {
- close(fd);
- return false;
- }
-}
-
-/**
- * Create OLAC session.
- *
- * @deprecated It will be removed soon in favor of upstream OL2TP.
- *
- * @return PPPoX socket file descriptor
- */
-static int create_pppox_olac(void)
-{
- int pppox;
-
- log_print(WARNING, "Using deprecated OLAC protocol. "
- "Its support will be removed soon. "
- "Please enable OL2TP support in your kernel");
-
- log_print(INFO, "Creating PPPoX socket");
- pppox = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OLAC);
-
- if (pppox == -1) {
- log_print(FATAL, "Socket() %s", strerror(errno));
- exit(SYSTEM_ERROR);
- } else {
- struct sockaddr_pppolac address = {
- .sa_family = AF_PPPOX,
- .sa_protocol = PX_PROTO_OLAC,
- .udp_socket = the_socket,
- .local = {.tunnel = local_tunnel, .session = local_session},
- .remote = {.tunnel = remote_tunnel, .session = remote_session},
- };
- if (connect(pppox, (struct sockaddr *)&address, sizeof(address))) {
- log_print(FATAL, "Connect() %s", strerror(errno));
- exit(SYSTEM_ERROR);
- }
- }
- return pppox;
-}
-
-/**
- * Create OL2TP tunnel and session.
- *
- * @param[out] tfd Will contain tunnel socket file descriptor
- * @param[out] sfd Will contain session socket file descriptor
- */
-static void create_pppox_ol2tp(int *tfd, int *sfd)
-{
- int tunnel_fd;
- int session_fd;
- struct sockaddr_pppol2tp tunnel_sa;
- struct sockaddr_pppol2tp session_sa;
-
- log_print(INFO, "Creating PPPoX tunnel socket...");
- tunnel_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
- if (tunnel_fd < 0) {
- log_print(FATAL, "Tunnel socket(): %s", strerror(errno));
- exit(SYSTEM_ERROR);
- }
-
- memset(&tunnel_sa, 0, sizeof(tunnel_sa));
- tunnel_sa.sa_family = AF_PPPOX;
- tunnel_sa.sa_protocol = PX_PROTO_OL2TP;
- tunnel_sa.pppol2tp.fd = the_socket; /* UDP socket */
- tunnel_sa.pppol2tp.s_tunnel = ntohs(local_tunnel);
- tunnel_sa.pppol2tp.s_session = 0; /* special case: mgmt socket */
- tunnel_sa.pppol2tp.d_tunnel = ntohs(remote_tunnel);
- tunnel_sa.pppol2tp.d_session = 0; /* special case: mgmt socket */
-
- log_print(INFO, "Connecting to tunnel socket...");
- if (connect(tunnel_fd, (struct sockaddr *)&tunnel_sa,
- sizeof(tunnel_sa))) {
- log_print(FATAL, "Tunnel connect(): %s", strerror(errno));
- exit(SYSTEM_ERROR);
- }
-
- log_print(INFO, "Creating PPPoX session socket...");
- session_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
- if (session_fd < 0) {
- log_print(FATAL, "Session socket(): %s", strerror(errno));
- exit(SYSTEM_ERROR);
- }
-
- memset(&session_sa, 0, sizeof(session_sa));
- session_sa.sa_family = AF_PPPOX;
- session_sa.sa_protocol = PX_PROTO_OL2TP;
- session_sa.pppol2tp.fd = the_socket;
- session_sa.pppol2tp.s_tunnel = ntohs(local_tunnel);
- session_sa.pppol2tp.s_session = ntohs(local_session);
- session_sa.pppol2tp.d_tunnel = ntohs(remote_tunnel);
- session_sa.pppol2tp.d_session = ntohs(remote_session);
-
- log_print(INFO, "Connecting to session socket...");
- if (connect(session_fd, (struct sockaddr *)&session_sa,
- sizeof(session_sa))) {
- log_print(FATAL, "Session connect(): %s", strerror(errno));
- exit(SYSTEM_ERROR);
- }
-
- *tfd = tunnel_fd;
- *sfd = session_fd;
-}
-
-static uint8_t *compute_response(uint8_t type, void *challenge, int size)
-{
- static uint8_t response[MD5_DIGEST_LENGTH];
- MD5_CTX ctx;
- MD5_Init(&ctx);
- MD5_Update(&ctx, &type, sizeof(uint8_t));
- MD5_Update(&ctx, secret, secret_length);
- MD5_Update(&ctx, challenge, size);
- MD5_Final(response, &ctx);
- return response;
-}
-
-static bool verify_challenge()
-{
- if (secret) {
- uint8_t response[MD5_DIGEST_LENGTH];
- if (get_attribute_raw(CHALLENGE_RESPONSE, response, MD5_DIGEST_LENGTH)
- != MD5_DIGEST_LENGTH) {
- return false;
- }
- return !memcmp(compute_response(SCCRP, challenge, CHALLENGE_SIZE),
- response, MD5_DIGEST_LENGTH);
- }
- return true;
-}
-
-static void answer_challenge()
-{
- if (secret) {
- uint8_t challenge[MAX_ATTRIBUTE_SIZE];
- int size = get_attribute_raw(CHALLENGE, challenge, MAX_ATTRIBUTE_SIZE);
- if (size > 0) {
- uint8_t *response = compute_response(SCCCN, challenge, size);
- add_attribute_raw(CHALLENGE_RESPONSE, response, MD5_DIGEST_LENGTH);
- }
- }
-}
-
-static int l2tp_process()
-{
- uint16_t sequence = local_sequence;
- __be16 tunnel = 0;
- __be16 session = 0;
-
- if (!recv_packet(&session)) {
- return acknowledged ? 0 : TIMEOUT_INTERVAL;
- }
-
- /* Here is the fun part. We always try to protect our tunnel and session
- * from being closed even if we received unexpected messages. */
- switch(incoming.message) {
- case SCCRP:
- if (state == SCCRQ) {
- if (get_attribute_u16(ASSIGNED_TUNNEL, &tunnel) && tunnel &&
- verify_challenge()) {
- remote_tunnel = tunnel;
- log_print(DEBUG, "Received SCCRP (remote_tunnel = %u) -> "
- "Sending SCCCN", (unsigned)ntohs(remote_tunnel));
- state = SCCCN;
- set_message(0, SCCCN);
- answer_challenge();
- break;
- }
- log_print(DEBUG, "Received SCCRP without %s", tunnel ?
- "valid challenge response" : "assigned tunnel");
- log_print(ERROR, "Protocol error");
- return tunnel ? -CHALLENGE_FAILED : -PROTOCOL_ERROR;
- }
- break;
-
- case ICRP:
- if (state == ICRQ && session == local_session) {
- if (get_attribute_u16(ASSIGNED_SESSION, &session) && session) {
- remote_session = session;
- log_print(DEBUG, "Received ICRP (remote_session = %u) -> "
- "Sending ICCN", (unsigned)ntohs(remote_session));
- state = ICCN;
- set_message(remote_session, ICCN);
- add_attribute_u32(CONNECT_SPEED, htonl(100000000));
- add_attribute_u32(FRAMING_TYPE, htonl(3));
- break;
- }
- log_print(DEBUG, "Received ICRP without assigned session");
- log_print(ERROR, "Protocol error");
- return -PROTOCOL_ERROR;
- }
- break;
-
- case STOPCCN:
- log_print(DEBUG, "Received STOPCCN");
- log_print(INFO, "Remote server hung up");
- state = STOPCCN;
- return -REMOTE_REQUESTED;
-
- case CDN:
- if (session && session == local_session) {
- log_print(DEBUG, "Received CDN (local_session = %u)",
- (unsigned)ntohs(local_session));
- log_print(INFO, "Remote server hung up");
- return -REMOTE_REQUESTED;
- }
- break;
-
- case ACK:
- case HELLO:
- case WEN:
- case SLI:
- /* These are harmless, so we just treat them in the same way. */
- if (state == SCCCN) {
- while (!local_session) {
- local_session = random();
- }
- log_print(DEBUG, "Received %s -> Sending ICRQ (local_session = "
- "%u)", messages[incoming.message],
- (unsigned)ntohs(local_session));
- log_print(INFO, "Tunnel established");
- state = ICRQ;
- set_message(0, ICRQ);
- add_attribute_u16(ASSIGNED_SESSION, local_session);
- add_attribute_u32(CALL_SERIAL_NUMBER, random());
- break;
- }
-
- if (incoming.message == ACK) {
- log_print(DEBUG, "Received ACK");
- } else {
- log_print(DEBUG, "Received %s -> Sending ACK",
- messages[incoming.message]);
- send_ack();
- }
-
- if (state == ICCN) {
- log_print(INFO, "Session established");
- state = ACK;
-
- if (check_ol2tp()) {
- int tunnel_fd, session_fd;
-
- create_pppox_ol2tp(&tunnel_fd, &session_fd);
- start_pppd_ol2tp(tunnel_fd, session_fd,
- ntohs(remote_tunnel),
- ntohs(remote_session));
- } else {
- start_pppd(create_pppox_olac());
- }
- }
- return 0;
-
- case ICRQ:
- case OCRQ:
- /* Since we run pppd as a client, it does not makes sense to
- * accept ICRQ or OCRQ. Always send CDN with a proper error. */
- if (get_attribute_u16(ASSIGNED_SESSION, &session) && session) {
- log_print(DEBUG, "Received %s (remote_session = %u) -> "
- "Sending CDN", messages[incoming.message],
- (unsigned)ntohs(session));
- set_message(session, CDN);
- add_attribute_u32(RESULT_CODE, htonl(0x00020006));
- add_attribute_u16(ASSIGNED_SESSION, 0);
- }
- break;
- }
-
- if (sequence != local_sequence) {
- send_packet();
- return TIMEOUT_INTERVAL;
- }
-
- /* We reach here if we got an unexpected message. Log it and send ACK. */
- if (incoming.message > MESSAGE_MAX || !messages[incoming.message]) {
- log_print(DEBUG, "Received UNKNOWN %d -> Sending ACK anyway",
- incoming.message);
- } else {
- log_print(DEBUG, "Received UNEXPECTED %s -> Sending ACK anyway",
- messages[incoming.message]);
- }
- send_ack();
- return 0;
-}
-
-static int l2tp_timeout()
-{
- if (acknowledged) {
- return 0;
- }
- log_print(DEBUG, "Timeout -> Sending %s", messages[outgoing.message]);
- send(the_socket, outgoing.buffer, outgoing.length, 0);
- return TIMEOUT_INTERVAL;
-}
-
-static void l2tp_shutdown()
-{
- if (state != STOPCCN) {
- log_print(DEBUG, "Sending STOPCCN");
- set_message(0, STOPCCN);
- add_attribute_u16(ASSIGNED_TUNNEL, local_tunnel);
- add_attribute_u16(RESULT_CODE, htons(6));
- send_packet();
- }
-}
-
-struct protocol l2tp = {
- .name = "l2tp",
- .arguments = 3,
- .usage = "<server> <port> <secret>",
- .connect = l2tp_connect,
- .process = l2tp_process,
- .timeout = l2tp_timeout,
- .shutdown = l2tp_shutdown,
-};
diff --git a/mtpd.c b/mtpd.c
deleted file mode 100644
index ac724ac..0000000
--- a/mtpd.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * Copyright (C) 2009 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 <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/poll.h>
-#include <sys/wait.h>
-#include <netdb.h>
-#include <signal.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-#include <limits.h>
-
-#ifdef ANDROID_CHANGES
-#include <android/log.h>
-#include <cutils/sockets.h>
-#endif
-
-#include "mtpd.h"
-#include "NetdClient.h"
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
-/* Characters count in string with max value of unsigned type t */
-#define TYPE_STRLEN_U(t) ((((sizeof(t) * CHAR_BIT) * 1233) >> 12) + 1)
-/* Length of string with max file descriptor value */
-#define FD_MAX_LEN TYPE_STRLEN_U(int)
-
-int the_socket = -1;
-
-extern struct protocol l2tp;
-extern struct protocol pptp;
-static struct protocol *protocols[] = {&l2tp, &pptp, NULL};
-static struct protocol *the_protocol;
-
-static char *interface;
-static int pppd_argc;
-static char **pppd_argv;
-static pid_t pppd_pid;
-
-/* We redirect signals to a pipe in order to prevent race conditions. */
-static int signals[2];
-
-static void interrupt(int signal)
-{
- write(signals[1], &signal, sizeof(int));
-}
-
-static int initialize(int argc, char **argv)
-{
- int i;
-
- for (i = 0; protocols[i]; ++i) {
- struct protocol *p = protocols[i];
- if (argc - 3 >= p->arguments && !strcmp(argv[2], p->name)) {
- log_print(INFO, "Using protocol %s", p->name);
- the_protocol = p;
- break;
- }
- }
-
- if (!the_protocol) {
- printf("Usages:\n");
- for (i = 0; protocols[i]; ++i) {
- struct protocol *p = protocols[i];
- printf(" %s interface %s %s pppd-arguments\n",
- argv[0], p->name, p->usage);
- }
- exit(0);
- }
-
- interface = argv[1];
- pppd_argc = argc - 3 - the_protocol->arguments;
- pppd_argv = &argv[3 + the_protocol->arguments];
- return the_protocol->connect(&argv[3]);
-}
-
-static void stop_pppd()
-{
- if (pppd_pid) {
- int status;
- log_print(INFO, "Sending signal to pppd (pid = %d)", pppd_pid);
- kill(pppd_pid, SIGTERM);
- waitpid(pppd_pid, &status, 0);
- pppd_pid = 0;
- }
-}
-
-#ifdef ANDROID_CHANGES
-
-static int android_get_control_and_arguments(int *argc, char ***argv)
-{
- static char *args[32];
- int control;
- int i;
-
- if ((i = android_get_control_socket("mtpd")) == -1) {
- return -1;
- }
- log_print(DEBUG, "Waiting for control socket");
- if (listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) {
- log_print(FATAL, "Cannot get control socket");
- exit(SYSTEM_ERROR);
- }
- close(i);
- fcntl(control, F_SETFD, FD_CLOEXEC);
-
- args[0] = (*argv)[0];
- for (i = 1; i < 32; ++i) {
- unsigned char bytes[2];
- if (recv(control, &bytes[0], 1, 0) != 1 ||
- recv(control, &bytes[1], 1, 0) != 1) {
- log_print(FATAL, "Cannot get argument length");
- exit(SYSTEM_ERROR);
- } else {
- int length = bytes[0] << 8 | bytes[1];
- int offset = 0;
-
- if (length == 0xFFFF) {
- break;
- }
- args[i] = malloc(length + 1);
- while (offset < length) {
- int n = recv(control, &args[i][offset], length - offset, 0);
- if (n > 0) {
- offset += n;
- } else {
- log_print(FATAL, "Cannot get argument value");
- exit(SYSTEM_ERROR);
- }
- }
- args[i][length] = 0;
- }
- }
- log_print(DEBUG, "Received %d arguments", i - 1);
-
- *argc = i;
- *argv = args;
- return control;
-}
-
-#endif
-
-int main(int argc, char **argv)
-{
- struct pollfd pollfds[3];
- int control = -1;
- int timeout;
- int status;
-
-#ifdef ANDROID_CHANGES
- control = android_get_control_and_arguments(&argc, &argv);
- shutdown(control, SHUT_WR);
-#endif
-
- srandom(time(NULL));
-
- if (pipe(signals) == -1) {
- log_print(FATAL, "Pipe() %s", strerror(errno));
- exit(SYSTEM_ERROR);
- }
- fcntl(signals[0], F_SETFD, FD_CLOEXEC);
- fcntl(signals[1], F_SETFD, FD_CLOEXEC);
-
- timeout = initialize(argc, argv);
-
- signal(SIGHUP, interrupt);
- signal(SIGINT, interrupt);
- signal(SIGTERM, interrupt);
- signal(SIGCHLD, interrupt);
- signal(SIGPIPE, SIG_IGN);
- atexit(stop_pppd);
-
- pollfds[0].fd = the_socket;
- pollfds[0].events = POLLIN;
- pollfds[1].fd = signals[0];
- pollfds[1].events = POLLIN;
- pollfds[2].fd = control;
- pollfds[2].events = 0;
-
- while (timeout >= 0) {
- if (poll(pollfds, 3, timeout ? timeout : -1) == -1 && errno != EINTR) {
- log_print(FATAL, "Poll() %s", strerror(errno));
- exit(SYSTEM_ERROR);
- }
- if (pollfds[1].revents) {
- break;
- }
- if (pollfds[2].revents) {
- interrupt(SIGTERM);
- }
- timeout = pollfds[0].revents ?
- the_protocol->process() : the_protocol->timeout();
-#ifdef ANDROID_CHANGES
- if (!access("/data/misc/vpn/abort", F_OK)) {
- interrupt(SIGTERM);
- }
- if (!timeout) {
- timeout = 5000;
- }
-#endif
- }
-
- if (timeout < 0) {
- status = -timeout;
- } else {
- int signal;
- read(signals[0], &signal, sizeof(int));
- log_print(INFO, "Received signal %d", signal);
- if (signal == SIGCHLD && waitpid(pppd_pid, &status, WNOHANG) == pppd_pid
- && WIFEXITED(status)) {
- status = WEXITSTATUS(status);
- log_print(INFO, "Pppd is terminated (status = %d)", status);
- status += PPPD_EXITED;
- pppd_pid = 0;
- } else {
- status = USER_REQUESTED;
- }
- }
-
- stop_pppd();
- the_protocol->shutdown();
- log_print(INFO, "Mtpd is terminated (status = %d)", status);
- return status;
-}
-
-void log_print(int level, char *format, ...)
-{
- if (level >= 0 && level <= LOG_MAX) {
-#ifdef ANDROID_CHANGES
- static int levels[5] = {
- ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
- ANDROID_LOG_ERROR, ANDROID_LOG_FATAL
- };
- va_list ap;
- va_start(ap, format);
- __android_log_vprint(levels[level], "mtpd", format, ap);
- va_end(ap);
-#else
- static char *levels = "DIWEF";
- va_list ap;
- fprintf(stderr, "%c: ", levels[level]);
- va_start(ap, format);
- vfprintf(stderr, format, ap);
- va_end(ap);
- fputc('\n', stderr);
-#endif
- }
-}
-
-void create_socket(int family, int type, char *server, char *port)
-{
- struct addrinfo hints = {
- .ai_flags = AI_NUMERICSERV,
- .ai_family = family,
- .ai_socktype = type,
- };
- struct addrinfo *records;
- struct addrinfo *r;
- int error;
-
- log_print(INFO, "Connecting to %s port %s via %s", server, port, interface);
-
- error = getaddrinfo(server, port, &hints, &records);
- if (error) {
- log_print(FATAL, "Getaddrinfo() %s", (error == EAI_SYSTEM) ?
- strerror(errno) : gai_strerror(error));
- exit(NETWORK_ERROR);
- }
-
- for (r = records; r; r = r->ai_next) {
- int s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
- if (!setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, interface,
- strlen(interface)) && !connect(s, r->ai_addr, r->ai_addrlen)) {
- the_socket = s;
- break;
- }
- close(s);
- }
-
- freeaddrinfo(records);
-
- if (the_socket == -1) {
- log_print(FATAL, "Connect() %s", strerror(errno));
- exit(NETWORK_ERROR);
- }
-
-#ifdef ANDROID_CHANGES
- protectFromVpn(the_socket);
-#endif
-
- fcntl(the_socket, F_SETFD, FD_CLOEXEC);
- log_print(INFO, "Connection established (socket = %d)", the_socket);
-}
-
-void start_pppd(int pppox)
-{
- if (pppd_pid) {
- log_print(WARNING, "Pppd is already started (pid = %d)", pppd_pid);
- close(pppox);
- return;
- }
-
- log_print(INFO, "Starting pppd (pppox = %d)", pppox);
-
- pppd_pid = fork();
- if (pppd_pid < 0) {
- log_print(FATAL, "Fork() %s", strerror(errno));
- exit(SYSTEM_ERROR);
- }
-
- if (!pppd_pid) {
- char *args[pppd_argc + 5];
- char number[FD_MAX_LEN + 1];
-
- snprintf(number, FD_MAX_LEN + 1, "%d", pppox);
- args[0] = "pppd";
- args[1] = "nodetach";
- args[2] = "pppox";
- args[3] = number;
- memcpy(&args[4], pppd_argv, sizeof(char *) * pppd_argc);
- args[4 + pppd_argc] = NULL;
-
- execvp("pppd", args);
- log_print(FATAL, "Exec() %s", strerror(errno));
- exit(SYSTEM_ERROR); /* Pretending a fatal error in pppd. */
- }
-
- log_print(INFO, "Pppd started (pid = %d)", pppd_pid);
- close(pppox);
-}
-
-/**
- * Start pppd daemon with pppol2tp-android plugin.
- *
- * @param tunnel_fd Tunnel socket file descriptor
- * @param session_fd Session socket file descriptor
- * @param tunnel_id Tunnel ID; must be in host byte order
- * @param session_id Session ID; must be in host byte order
- */
-void start_pppd_ol2tp(int tunnel_fd, int session_fd, int tunnel_id,
- int session_id)
-{
- if (pppd_pid) {
- log_print(WARNING, "Pppd is already started (pid = %d)", pppd_pid);
- goto ret;
- }
-
- log_print(INFO, "Starting pppd (tunnel_fd = %d, session_fd = %d)",
- tunnel_fd, session_fd);
-
- pppd_pid = fork();
- if (pppd_pid < 0) {
- log_print(FATAL, "Fork() %s", strerror(errno));
- exit(SYSTEM_ERROR);
- }
-
- if (!pppd_pid) {
- char tunnel_fd_str[FD_MAX_LEN + 1];
- char session_fd_str[FD_MAX_LEN + 1];
- char tunnel_id_str[FD_MAX_LEN + 1];
- char session_id_str[FD_MAX_LEN + 1];
-
- snprintf(tunnel_fd_str, FD_MAX_LEN + 1, "%d", tunnel_fd);
- snprintf(session_fd_str, FD_MAX_LEN + 1, "%d", session_fd);
- snprintf(tunnel_id_str, FD_MAX_LEN + 1, "%d", tunnel_id);
- snprintf(session_id_str, FD_MAX_LEN + 1, "%d", session_id);
-
- const char *l2tp_args[] = {
- "pppd",
- "nodetach",
- "plugin",
- "pppol2tp-android.so",
- "session_fd",
- session_fd_str,
- "tunnel_fd",
- tunnel_fd_str,
- "session_id",
- session_id_str,
- "tunnel_id",
- tunnel_id_str,
- };
- const size_t args_len = ARRAY_SIZE(l2tp_args) + pppd_argc + 1;
- char *args[args_len];
-
- /* Populate args[] from l2tp_args[] and pppd_argv[] */
- memcpy(args, l2tp_args, sizeof(l2tp_args));
- memcpy(args + ARRAY_SIZE(l2tp_args), pppd_argv,
- sizeof(char *) * pppd_argc);
- args[args_len - 1] = NULL;
-
- execvp("pppd", args);
- log_print(FATAL, "Exec() %s", strerror(errno));
- exit(SYSTEM_ERROR); /* Pretending a fatal error in pppd. */
- }
-
- log_print(INFO, "Pppd started (pid = %d)", pppd_pid);
-
-ret:
- close(session_fd);
- close(tunnel_fd);
-}
-
-/**
- * Start pppd daemon with pppopptp-android plugin.
- *
- * @param pptp_fd PPTP socket file descriptor
- */
-void start_pppd_pptp(int pptp_fd)
-{
- if (pppd_pid) {
- log_print(WARNING, "Pppd is already started (pid = %d)", pppd_pid);
- goto ret;
- }
-
- log_print(INFO, "Starting pppd (pptp_fd = %d)", pptp_fd);
-
- pppd_pid = fork();
- if (pppd_pid < 0) {
- log_print(FATAL, "Fork() %s", strerror(errno));
- exit(SYSTEM_ERROR);
- }
-
- if (!pppd_pid) {
- char pptp_fd_str[FD_MAX_LEN + 1];
-
- snprintf(pptp_fd_str, FD_MAX_LEN + 1, "%d", pptp_fd);
-
- const char *pptp_args[] = {
- "pppd",
- "nodetach",
- "plugin",
- "pppopptp-android.so",
- "pptp_socket",
- pptp_fd_str,
- };
- const size_t args_len = ARRAY_SIZE(pptp_args) + pppd_argc + 1;
- char *args[args_len];
-
- /* Populate args[] from pptp_args[] and pppd_argv[] */
- memcpy(args, pptp_args, sizeof(pptp_args));
- memcpy(args + ARRAY_SIZE(pptp_args), pppd_argv,
- sizeof(char *) * pppd_argc);
- args[args_len - 1] = NULL;
-
- execvp("pppd", args);
- log_print(FATAL, "Exec() %s", strerror(errno));
- exit(SYSTEM_ERROR); /* Pretending a fatal error in pppd. */
- }
-
- log_print(INFO, "Pppd started (pid = %d)", pppd_pid);
-
-ret:
- close(pptp_fd);
-}
diff --git a/mtpd.h b/mtpd.h
deleted file mode 100644
index 290a583..0000000
--- a/mtpd.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef __MTPD_H__
-#define __MTPD_H__
-
-#if !defined(PX_PROTO_OLAC)
-#define USING_UAPI
-#endif
-
-#if defined(USING_UAPI)
-/* This stuff isn't in uapi. */
-#define PX_PROTO_OLAC 3
-#define PX_PROTO_OPNS 4
-
-struct sockaddr_pppopns {
- sa_family_t sa_family;
- unsigned int sa_protocol;
- int tcp_socket;
- uint16_t local;
- uint16_t remote;
-} __attribute__((packed));
-
-struct sockaddr_pppolac {
- sa_family_t sa_family;
- unsigned int sa_protocol;
- int udp_socket;
- struct __attribute__((packed)) {
- uint16_t tunnel;
- uint16_t session;
- } local, remote;
-} __attribute__((packed));
-#endif
-
-/* The socket to the server. */
-extern int the_socket;
-
-enum exit_code {
- SYSTEM_ERROR = 1,
- NETWORK_ERROR = 2,
- PROTOCOL_ERROR = 3,
- CHALLENGE_FAILED = 4,
- USER_REQUESTED = 5,
- REMOTE_REQUESTED = 6,
- PPPD_EXITED = 32,
-};
-
-enum log_level {
- DEBUG = 0,
- INFO = 1,
- WARNING = 2,
- ERROR = 3,
- FATAL = 4,
- LOG_MAX = 4,
-};
-
-void log_print(int level, char *format, ...);
-void create_socket(int family, int type, char *server, char *port);
-void start_pppd(int pppox);
-void start_pppd_ol2tp(int tunnel_fd, int session_fd, int tunnel_id,
- int session_id);
-void start_pppd_pptp(int pptp_fd);
-
-/* Each protocol must implement everything defined in this structure. Note that
- * timeout intervals are in milliseconds, where zero means forever. To indicate
- * an error, one should use a negative exit code such as -REMOTE_REQUESTED. */
-struct protocol {
- /* The name of this protocol. */
- char *name;
- /* The number of arguments. */
- int arguments;
- /* The usage of the arguments. */
- char *usage;
- /* Connect to the server and return the next timeout interval. */
- int (*connect)(char **arguments);
- /* Process the incoming packet and return the next timeout interval. */
- int (*process)();
- /* Handle the timeout event and return the next timeout interval. */
- int (*timeout)();
- /* Handle the shutdown event. */
- void (*shutdown)();
-};
-
-#endif /* __MTPD_H__ */
diff --git a/mtpd.rc b/mtpd.rc
deleted file mode 100644
index af701d5..0000000
--- a/mtpd.rc
+++ /dev/null
@@ -1,8 +0,0 @@
-service mtpd /system/bin/mtpd
- class main
- socket mtpd stream 600 system system
- user vpn
- group vpn inet
- capabilities NET_ADMIN NET_RAW
- disabled
- oneshot
diff --git a/pptp.c b/pptp.c
deleted file mode 100644
index 7a58a27..0000000
--- a/pptp.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-/* A simple implementation of PPTP Network Server (RFC 2637) which only
- * creates a single session. The following code only handles control packets.
- * Data packets are handled by PPPoPNS driver which can be found in Android
- * kernel tree. */
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <linux/netdevice.h>
-#include <linux/if_pppox.h>
-#include <linux/types.h>
-
-#include "mtpd.h"
-
-enum pptp_message {
- SCCRQ = 1,
- SCCRP = 2,
- STOPCCRQ = 3,
- STOPCCRP = 4,
- ECHORQ = 5,
- ECHORP = 6,
- OCRQ = 7,
- OCRP = 8,
- ICRQ = 9,
- ICRP = 10,
- ICCN = 11,
- CCRQ = 12,
- CDN = 13,
- WEN = 14,
- SLI = 15,
- MESSAGE_MAX = 15,
-};
-
-static char *messages[] = {
- NULL, "SCCRQ", "SCCRP", "STOPCCRQ", "STOPCCRP", "ECHORQ", "ECHORP",
- "OCRQ", "OCRP", "ICRQ", "ICRP", "ICCN", "CCRQ", "CDN", "WEN", "SLI",
-};
-
-static uint8_t lengths[] = {
- 0, 156, 156, 16, 16, 16, 20, 168, 32, 220, 24, 28, 16, 148, 40, 24,
-};
-
-#define CONTROL_MESSAGE htons(1)
-#define MAGIC_COOKIE htonl(0x1A2B3C4D)
-#define PROTOCOL_VERSION htons(0x0100)
-
-#define RESULT_OK 1
-#define RESULT_ERROR 2
-
-/* Some implementation uses 0 instead of 1, so we allow both of them. */
-#define ESTABLISHED(result) (result <= 1)
-
-#define HEADER_SIZE 8
-#define MIN_MESSAGE_SIZE 10
-
-static __be16 local;
-static __be16 remote;
-static uint16_t state;
-static const char *remote_name; /* server host name or IP address */
-
-#define MAX_PACKET_LENGTH 220
-
-/* We define all the fields we used in this structure. Type conversion and byte
- * alignment are solved in one place. Although it looks a little bit ugly, it
- * really makes life easier. */
-static struct packet {
- int length;
- int expect;
- union {
- uint8_t buffer[MAX_PACKET_LENGTH];
- struct {
- struct __attribute__((packed)) {
- uint16_t length;
- uint16_t type;
- uint32_t cookie;
- } header;
- uint16_t message;
- uint16_t reserved;
- union {
- struct __attribute__((packed)) {
- uint16_t protocol_version;
- uint8_t result;
- uint8_t error;
- uint32_t framing;
- uint32_t bearer;
- uint16_t channels;
- uint16_t firmware_revision;
- char host[64];
- } sccrp, sccrq;
- struct __attribute__((packed)) {
- uint16_t call;
- uint16_t serial;
- uint32_t minimum_speed;
- uint32_t maximum_speed;
- uint32_t bearer;
- uint32_t framing;
- uint16_t window_size;
- } ocrq;
- struct __attribute__((packed)) {
- uint16_t call;
- uint16_t peer;
- uint8_t result;
- } ocrp, icrp;
- struct __attribute__((packed)) {
- uint32_t identifier;
- uint8_t result;
- } echorq, echorp;
- struct __attribute__((packed)) {
- uint16_t call;
- } icrq, ccrq, cdn;
- };
- } __attribute__((packed));
- } __attribute__((aligned(4)));
-} incoming, outgoing;
-
-static void set_message(uint16_t message)
-{
- uint16_t length = lengths[message];
- memset(outgoing.buffer, 0, length);
- outgoing.length = length;
- outgoing.header.length = htons(length);
- outgoing.header.type = CONTROL_MESSAGE;
- outgoing.header.cookie = MAGIC_COOKIE;
- outgoing.message = htons(message);
-}
-
-static void send_packet()
-{
- send(the_socket, outgoing.buffer, outgoing.length, 0);
-}
-
-static int recv_packet()
-{
- int length;
-
- /* We are going to read a new message if incoming.expect is 0. */
- if (!incoming.expect) {
- incoming.length = 0;
- incoming.expect = HEADER_SIZE;
- }
-
- /* The longest message defined in RFC 2637 is 220 bytes, but the protocol
- * itself allows up to 65536 bytes. Therefore we always read a complete
- * message but only keep the first 220 bytes before passing up. */
- length = incoming.expect - incoming.length;
- if (incoming.length >= MAX_PACKET_LENGTH) {
- uint8_t buffer[length];
- length = recv(the_socket, buffer, length, 0);
- } else {
- if (incoming.expect > MAX_PACKET_LENGTH) {
- length = MAX_PACKET_LENGTH - incoming.length;
- }
- length = recv(the_socket, &incoming.buffer[incoming.length], length, 0);
- }
- if (length == -1) {
- if (errno == EINTR) {
- return 0;
- }
- log_print(FATAL, "Recv() %s", strerror(errno));
- exit(NETWORK_ERROR);
- }
- if (length == 0) {
- log_print(DEBUG, "Connection closed");
- log_print(INFO, "Remote server hung up");
- return -REMOTE_REQUESTED;
- }
- incoming.length += length;
-
- /* If incoming.header is valid, check cookie and update incoming.expect. */
- if (incoming.length == HEADER_SIZE && incoming.expect == HEADER_SIZE) {
- if (incoming.header.cookie != MAGIC_COOKIE) {
- log_print(DEBUG, "Loss of synchronization");
- log_print(ERROR, "Protocol error");
- return -PROTOCOL_ERROR;
- }
- incoming.expect = ntohs(incoming.header.length);
- if (incoming.expect < HEADER_SIZE) {
- log_print(DEBUG, "Invalid message length");
- log_print(ERROR, "Protocol error");
- return -PROTOCOL_ERROR;
- }
- }
-
- /* Now we have a complete message. Reset incoming.expect. */
- if (incoming.length == incoming.expect) {
- incoming.expect = 0;
-
- /* Return 1 if it is a control message. */
- if (incoming.header.type == CONTROL_MESSAGE) {
- return 1;
- }
- log_print(DEBUG, "Ignored non-control message (type = %u)",
- (unsigned)ntohs(incoming.header.type));
- }
- return 0;
-}
-
-static int pptp_connect(char **arguments)
-{
- remote_name = arguments[0];
-
- create_socket(AF_UNSPEC, SOCK_STREAM, arguments[0], arguments[1]);
-
- log_print(DEBUG, "Sending SCCRQ");
- state = SCCRQ;
- set_message(SCCRQ);
- outgoing.sccrq.protocol_version = PROTOCOL_VERSION;
- outgoing.sccrq.framing = htonl(3);
- outgoing.sccrq.bearer = htonl(3);
- outgoing.sccrq.channels = htons(1);
- strcpy(outgoing.sccrq.host, "anonymous");
- send_packet();
- return 0;
-}
-
-/**
- * Check if upstream kernel implementation of PPTP should be used.
- *
- * @return true If upstream PPTP should be used, which is the case if
- * the obsolete OPNS feature is not available.
- */
-static bool check_pptp(void)
-{
- int fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OPNS);
-
- if (fd < 0) {
- return true;
- } else {
- close(fd);
- return false;
- }
-}
-
-/**
- * Create OPNS session.
- *
- * @deprecated It will be removed soon in favor of upstream PPTP.
- *
- * @return PPPoX socket file descriptor
- */
-static int create_pppox_opns(void)
-{
- int pppox;
-
- log_print(WARNING, "Using deprecated OPNS protocol. "
- "Its support will be removed soon. "
- "Please enable PPTP support in your kernel");
-
- log_print(INFO, "Creating PPPoX socket");
- pppox = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OPNS);
-
- if (pppox == -1) {
- log_print(FATAL, "Socket() %s", strerror(errno));
- exit(SYSTEM_ERROR);
- } else {
- struct sockaddr_pppopns address = {
- .sa_family = AF_PPPOX,
- .sa_protocol = PX_PROTO_OPNS,
- .tcp_socket = the_socket,
- .local = local,
- .remote = remote,
- };
- if (connect(pppox, (struct sockaddr *)&address, sizeof(address))) {
- log_print(FATAL, "Connect() %s", strerror(errno));
- exit(SYSTEM_ERROR);
- }
- }
- return pppox;
-}
-
-/**
- * Get IP address by host name.
- *
- * @param name Host name to get IP address for
- *
- * @return IP address for given host name
- */
-static struct in_addr get_addr_by_name(const char *name)
-{
- struct addrinfo hints;
- struct addrinfo *res, *rp;
- struct in_addr addr;
- int err;
-
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_INET; /* allow only IPv4 */
- hints.ai_socktype = SOCK_DGRAM; /* UDP */
- hints.ai_protocol = 0; /* any protocol */
-
- err = getaddrinfo(name, NULL, &hints, &res);
- if (err) {
- log_print(FATAL, "%s: getaddrinfo: %s", __func__, gai_strerror(err));
- exit(SYSTEM_ERROR);
- }
-
- for (rp = res; rp != NULL; rp = rp->ai_next) {
- /* For now we only support IPv4 */
- if (rp->ai_family == AF_INET) {
- addr = ((struct sockaddr_in *)rp->ai_addr)->sin_addr;
- break;
- }
- }
-
- if (rp == NULL) {
- log_print(FATAL, "%s: No IPv4 addresses found", __func__);
- freeaddrinfo(res);
- exit(SYSTEM_ERROR);
- }
-
- freeaddrinfo(res);
-
- return addr;
-}
-
-/**
- * Get local IP address.
- *
- * Make a socket connection with remote server and then call getsockname() on
- * the connected socket. This will return the local IP address.
- *
- * @param remote_addr Server IP address
- *
- * @return Local IP address
- */
-static struct in_addr get_local_addr(struct in_addr remote_addr)
-{
- int sock;
- struct sockaddr_in addr;
- socklen_t addr_len;
-
- addr_len = sizeof(struct sockaddr_in);
- addr.sin_addr = remote_addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(0);
-
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0) {
- log_print(FATAL, "%s: Socket() %s", __func__, strerror(errno));
- exit(SYSTEM_ERROR);
- }
-
- if (connect(sock, (struct sockaddr*)&addr, sizeof(addr))) {
- close(sock);
- log_print(FATAL, "%s: Connect() %s", __func__, strerror(errno));
- exit(SYSTEM_ERROR);
- }
-
- getsockname(sock, (struct sockaddr*)&addr, &addr_len);
- close(sock);
-
- return addr.sin_addr;
-}
-
-/**
- * Create PPTP session.
- *
- * @return PPTP socket file descriptor
- */
-static int create_pppox_pptp(void)
-{
- int pptp_fd;
- struct sockaddr_pppox src, dst;
- struct in_addr remote_addr; /* server IP address */
- struct in_addr local_addr; /* client IP address */
-
- remote_addr = get_addr_by_name(remote_name);
- local_addr = get_local_addr(remote_addr);
-
- src.sa_family = AF_PPPOX;
- src.sa_protocol = PX_PROTO_PPTP;
- src.sa_addr.pptp.call_id = ntohs(local);
- src.sa_addr.pptp.sin_addr = local_addr;
-
- dst.sa_family = AF_PPPOX;
- dst.sa_protocol = PX_PROTO_PPTP;
- dst.sa_addr.pptp.call_id = ntohs(remote);
- dst.sa_addr.pptp.sin_addr = remote_addr;
-
- pptp_fd = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_PPTP);
- if (pptp_fd < 0) {
- log_print(FATAL, "Failed to create PPTP socket (%s)", strerror(errno));
- exit(SYSTEM_ERROR);
- }
-
- if (bind(pptp_fd, (struct sockaddr*)&src, sizeof(src))) {
- log_print(FATAL, "Failed to bind PPTP socket (%s)", strerror(errno));
- close(pptp_fd);
- exit(SYSTEM_ERROR);
- }
-
- if (connect(pptp_fd, (struct sockaddr*)&dst, sizeof(dst))) {
- log_print(FATAL, "Failed to connect PPTP socket (%s)", strerror(errno));
- close(pptp_fd);
- exit(SYSTEM_ERROR);
- }
-
- return pptp_fd;
-}
-
-static int pptp_process()
-{
- int result = recv_packet();
- if (result <= 0) {
- return result;
- }
-
- if (incoming.length < MIN_MESSAGE_SIZE) {
- log_print(DEBUG, "Control message too short");
- return 0;
- }
- incoming.message = ntohs(incoming.message);
- if (incoming.message > MESSAGE_MAX || !messages[incoming.message]) {
- log_print(DEBUG, "Received UNKNOWN %d", incoming.message);
- return 0;
- }
- if (incoming.length < lengths[incoming.message]) {
- log_print(DEBUG, "Received %s with invalid length (length = %d)",
- messages[incoming.message], incoming.length);
- return 0;
- }
-
- switch(incoming.message) {
- case SCCRP:
- if (state == SCCRQ) {
- if (incoming.sccrp.protocol_version == PROTOCOL_VERSION &&
- ESTABLISHED(incoming.sccrp.result)) {
- while (!local) {
- local = random();
- }
- log_print(DEBUG, "Received SCCRP -> Sending OCRQ "
- "(local = %u)", (unsigned)ntohs(local));
- log_print(INFO, "Tunnel established");
- state = OCRQ;
- set_message(OCRQ);
- outgoing.ocrq.call = local;
- outgoing.ocrq.serial = random();
- outgoing.ocrq.minimum_speed = htonl(1000);
- outgoing.ocrq.maximum_speed = htonl(100000000);
- outgoing.ocrq.bearer = htonl(3);
- outgoing.ocrq.framing = htonl(3);
- outgoing.ocrq.window_size = htons(8192);
- send_packet();
- return 0;
- }
- log_print(DEBUG, "Received SCCRP (result = %d)",
- incoming.sccrq.result);
- log_print(INFO, "Remote server hung up");
- return -REMOTE_REQUESTED;
- }
- break;
-
- case OCRP:
- if (state == OCRQ && incoming.ocrp.peer == local) {
- if (ESTABLISHED(incoming.ocrp.result)) {
- remote = incoming.ocrp.call;
- log_print(DEBUG, "Received OCRQ (remote = %u)",
- (unsigned)ntohs(remote));
- log_print(INFO, "Session established");
- state = OCRP;
-
- if (check_pptp())
- start_pppd_pptp(create_pppox_pptp());
- else
- start_pppd(create_pppox_opns());
-
- return 0;
- }
- log_print(DEBUG, "Received OCRP (result = %d)",
- incoming.ocrp.result);
- log_print(INFO, "Remote server hung up");
- return -REMOTE_REQUESTED;
- }
- break;
-
- case STOPCCRQ:
- log_print(DEBUG, "Received STOPCCRQ");
- log_print(INFO, "Remote server hung up");
- state = STOPCCRQ;
- return -REMOTE_REQUESTED;
-
- case CCRQ:
- /* According to RFC 2637 page 45, we should never receive CCRQ for
- * outgoing calls. However, some implementation only acts as PNS and
- * always uses CCRQ to clear a call, so here we still handle it. */
- if (state == OCRP && incoming.ccrq.call == remote) {
- log_print(DEBUG, "Received CCRQ (remote = %u)",
- (unsigned)ntohs(remote));
- log_print(INFO, "Remote server hung up");
- return -REMOTE_REQUESTED;
- }
- break;
-
- case CDN:
- if (state == OCRP && incoming.cdn.call == remote) {
- log_print(DEBUG, "Received CDN (remote = %u)",
- (unsigned)ntohs(remote));
- log_print(INFO, "Remote server hung up");
- return -REMOTE_REQUESTED;
- }
- break;
-
- case ECHORQ:
- log_print(DEBUG, "Received ECHORQ -> Sending ECHORP");
- set_message(ECHORP);
- outgoing.echorp.identifier = incoming.echorq.identifier;
- outgoing.echorp.result = RESULT_OK;
- send_packet();
- return 0;
-
- case WEN:
- case SLI:
- log_print(DEBUG, "Recevied %s", messages[incoming.message]);
- return 0;
-
- case ICRQ:
- log_print(DEBUG, "Received ICRQ (remote = %u, call = %u) -> "
- "Sending ICRP with error", (unsigned)ntohs(remote),
- (unsigned)ntohs(incoming.icrq.call));
- set_message(ICRP);
- outgoing.icrp.peer = incoming.icrq.call;
- outgoing.icrp.result = RESULT_ERROR;
- send_packet();
- return 0;
-
- case OCRQ:
- log_print(DEBUG, "Received OCRQ (remote = %u, call = %u) -> "
- "Sending OCRP with error", (unsigned)ntohs(remote),
- (unsigned)ntohs(incoming.ocrq.call));
- set_message(OCRP);
- outgoing.ocrp.peer = incoming.ocrq.call;
- outgoing.ocrp.result = RESULT_ERROR;
- send_packet();
- return 0;
- }
-
- /* We reach here if we got an unexpected message. Just log it. */
- log_print(DEBUG, "Received UNEXPECTED %s", messages[incoming.message]);
- return 0;
-}
-
-static int pptp_timeout()
-{
- return 0;
-}
-
-static void pptp_shutdown()
-{
- /* Normally we should send STOPCCRQ and wait for STOPCCRP, but this might
- * block for a long time. Here we simply take the shortcut: do nothing. */
-}
-
-struct protocol pptp = {
- .name = "pptp",
- .arguments = 2,
- .usage = "<server> <port>",
- .connect = pptp_connect,
- .process = pptp_process,
- .timeout = pptp_timeout,
- .shutdown = pptp_shutdown,
-};