blob: 8825a9e62a75331177e1c343dcb7fac697fbaf8c [file] [log] [blame]
Chia-chi Yeh063bb922009-06-15 14:43:38 +08001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* A simple implementation of PPTP Network Server (RFC 2637) which only
18 * creates a single session. The following code only handles control packets.
19 * Data packets are handled by PPPoPNS driver which can be found in Android
20 * kernel tree. */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <errno.h>
26#include <sys/types.h>
27#include <sys/socket.h>
28#include <arpa/inet.h>
Chia-chi Yeh0f725852011-07-18 13:57:17 -070029#include <linux/netdevice.h>
30#include <linux/if_pppox.h>
Sam Protsenko537773c2018-06-25 21:20:39 +030031#include <linux/types.h>
Chia-chi Yeh063bb922009-06-15 14:43:38 +080032
33#include "mtpd.h"
34
35enum pptp_message {
36 SCCRQ = 1,
37 SCCRP = 2,
38 STOPCCRQ = 3,
39 STOPCCRP = 4,
40 ECHORQ = 5,
41 ECHORP = 6,
42 OCRQ = 7,
43 OCRP = 8,
44 ICRQ = 9,
45 ICRP = 10,
46 ICCN = 11,
47 CCRQ = 12,
48 CDN = 13,
49 WEN = 14,
50 SLI = 15,
51 MESSAGE_MAX = 15,
52};
53
54static char *messages[] = {
55 NULL, "SCCRQ", "SCCRP", "STOPCCRQ", "STOPCCRP", "ECHORQ", "ECHORP",
56 "OCRQ", "OCRP", "ICRQ", "ICRP", "ICCN", "CCRQ", "CDN", "WEN", "SLI",
57};
58
59static uint8_t lengths[] = {
60 0, 156, 156, 16, 16, 16, 20, 168, 32, 220, 24, 28, 16, 148, 40, 24,
61};
62
63#define CONTROL_MESSAGE htons(1)
64#define MAGIC_COOKIE htonl(0x1A2B3C4D)
65#define PROTOCOL_VERSION htons(0x0100)
66
67#define RESULT_OK 1
68#define RESULT_ERROR 2
69
70/* Some implementation uses 0 instead of 1, so we allow both of them. */
71#define ESTABLISHED(result) (result <= 1)
72
73#define HEADER_SIZE 8
74#define MIN_MESSAGE_SIZE 10
75
Sam Protsenko537773c2018-06-25 21:20:39 +030076static __be16 local;
77static __be16 remote;
Chia-chi Yeh063bb922009-06-15 14:43:38 +080078static uint16_t state;
79
80#define MAX_PACKET_LENGTH 220
81
82/* We define all the fields we used in this structure. Type conversion and byte
83 * alignment are solved in one place. Although it looks a little bit ugly, it
84 * really makes life easier. */
85static struct packet {
86 int length;
87 int expect;
88 union {
89 uint8_t buffer[MAX_PACKET_LENGTH];
90 struct {
91 struct __attribute__((packed)) {
92 uint16_t length;
93 uint16_t type;
94 uint32_t cookie;
95 } header;
96 uint16_t message;
97 uint16_t reserved;
98 union {
99 struct __attribute__((packed)) {
100 uint16_t protocol_version;
101 uint8_t result;
102 uint8_t error;
103 uint32_t framing;
104 uint32_t bearer;
105 uint16_t channels;
106 uint16_t firmware_revision;
107 char host[64];
108 } sccrp, sccrq;
109 struct __attribute__((packed)) {
110 uint16_t call;
111 uint16_t serial;
112 uint32_t minimum_speed;
113 uint32_t maximum_speed;
114 uint32_t bearer;
115 uint32_t framing;
116 uint16_t window_size;
117 } ocrq;
118 struct __attribute__((packed)) {
119 uint16_t call;
120 uint16_t peer;
121 uint8_t result;
122 } ocrp, icrp;
123 struct __attribute__((packed)) {
124 uint32_t identifier;
125 uint8_t result;
126 } echorq, echorp;
127 struct __attribute__((packed)) {
128 uint16_t call;
129 } icrq, ccrq, cdn;
130 };
131 } __attribute__((packed));
132 } __attribute__((aligned(4)));
133} incoming, outgoing;
134
135static void set_message(uint16_t message)
136{
137 uint16_t length = lengths[message];
138 memset(outgoing.buffer, 0, length);
139 outgoing.length = length;
140 outgoing.header.length = htons(length);
141 outgoing.header.type = CONTROL_MESSAGE;
142 outgoing.header.cookie = MAGIC_COOKIE;
143 outgoing.message = htons(message);
144}
145
146static void send_packet()
147{
148 send(the_socket, outgoing.buffer, outgoing.length, 0);
149}
150
151static int recv_packet()
152{
153 int length;
154
155 /* We are going to read a new message if incoming.expect is 0. */
156 if (!incoming.expect) {
157 incoming.length = 0;
158 incoming.expect = HEADER_SIZE;
159 }
160
161 /* The longest message defined in RFC 2637 is 220 bytes, but the protocol
162 * itself allows up to 65536 bytes. Therefore we always read a complete
163 * message but only keep the first 220 bytes before passing up. */
164 length = incoming.expect - incoming.length;
165 if (incoming.length >= MAX_PACKET_LENGTH) {
166 uint8_t buffer[length];
167 length = recv(the_socket, buffer, length, 0);
168 } else {
169 if (incoming.expect > MAX_PACKET_LENGTH) {
170 length = MAX_PACKET_LENGTH - incoming.length;
171 }
172 length = recv(the_socket, &incoming.buffer[incoming.length], length, 0);
173 }
174 if (length == -1) {
175 if (errno == EINTR) {
176 return 0;
177 }
178 log_print(FATAL, "Recv() %s", strerror(errno));
179 exit(NETWORK_ERROR);
180 }
181 if (length == 0) {
182 log_print(DEBUG, "Connection closed");
183 log_print(INFO, "Remote server hung up");
184 return -REMOTE_REQUESTED;
185 }
186 incoming.length += length;
187
188 /* If incoming.header is valid, check cookie and update incoming.expect. */
189 if (incoming.length == HEADER_SIZE && incoming.expect == HEADER_SIZE) {
190 if (incoming.header.cookie != MAGIC_COOKIE) {
191 log_print(DEBUG, "Loss of synchronization");
192 log_print(ERROR, "Protocol error");
193 return -PROTOCOL_ERROR;
194 }
195 incoming.expect = ntohs(incoming.header.length);
196 if (incoming.expect < HEADER_SIZE) {
197 log_print(DEBUG, "Invalid message length");
198 log_print(ERROR, "Protocol error");
199 return -PROTOCOL_ERROR;
200 }
201 }
202
203 /* Now we have a complete message. Reset incoming.expect. */
204 if (incoming.length == incoming.expect) {
205 incoming.expect = 0;
206
207 /* Return 1 if it is a control message. */
208 if (incoming.header.type == CONTROL_MESSAGE) {
209 return 1;
210 }
Sam Protsenko537773c2018-06-25 21:20:39 +0300211 log_print(DEBUG, "Ignored non-control message (type = %u)",
212 (unsigned)ntohs(incoming.header.type));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800213 }
214 return 0;
215}
216
Chia-chi Yeh7b66d202011-06-28 16:39:23 -0700217static int pptp_connect(char **arguments)
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800218{
Chia-chi Yeh7b66d202011-06-28 16:39:23 -0700219 create_socket(AF_UNSPEC, SOCK_STREAM, arguments[0], arguments[1]);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800220
221 log_print(DEBUG, "Sending SCCRQ");
222 state = SCCRQ;
223 set_message(SCCRQ);
224 outgoing.sccrq.protocol_version = PROTOCOL_VERSION;
225 outgoing.sccrq.framing = htonl(3);
226 outgoing.sccrq.bearer = htonl(3);
227 outgoing.sccrq.channels = htons(1);
228 strcpy(outgoing.sccrq.host, "anonymous");
229 send_packet();
230 return 0;
231}
232
Chia-chi Yeh0f725852011-07-18 13:57:17 -0700233static int create_pppox()
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800234{
Chia-chi Yeh0f725852011-07-18 13:57:17 -0700235 int pppox = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OPNS);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800236 log_print(INFO, "Creating PPPoX socket");
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800237
238 if (pppox == -1) {
239 log_print(FATAL, "Socket() %s", strerror(errno));
Chia-chi Yeh0f725852011-07-18 13:57:17 -0700240 exit(SYSTEM_ERROR);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800241 } else {
242 struct sockaddr_pppopns address = {
243 .sa_family = AF_PPPOX,
Chia-chi Yeh0f725852011-07-18 13:57:17 -0700244 .sa_protocol = PX_PROTO_OPNS,
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800245 .tcp_socket = the_socket,
246 .local = local,
247 .remote = remote,
248 };
Chia-chi Yehea299e62011-07-13 19:36:46 -0700249 if (connect(pppox, (struct sockaddr *)&address, sizeof(address))) {
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800250 log_print(FATAL, "Connect() %s", strerror(errno));
Chia-chi Yeh0f725852011-07-18 13:57:17 -0700251 exit(SYSTEM_ERROR);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800252 }
253 }
254 return pppox;
255}
256
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800257static int pptp_process()
258{
259 int result = recv_packet();
260 if (result <= 0) {
261 return result;
262 }
263
264 if (incoming.length < MIN_MESSAGE_SIZE) {
265 log_print(DEBUG, "Control message too short");
266 return 0;
267 }
268 incoming.message = ntohs(incoming.message);
269 if (incoming.message > MESSAGE_MAX || !messages[incoming.message]) {
270 log_print(DEBUG, "Received UNKNOWN %d", incoming.message);
271 return 0;
272 }
273 if (incoming.length < lengths[incoming.message]) {
274 log_print(DEBUG, "Received %s with invalid length (length = %d)",
Chia-chi Yehea299e62011-07-13 19:36:46 -0700275 messages[incoming.message], incoming.length);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800276 return 0;
277 }
278
279 switch(incoming.message) {
280 case SCCRP:
281 if (state == SCCRQ) {
Chia-chi Yehea299e62011-07-13 19:36:46 -0700282 if (incoming.sccrp.protocol_version == PROTOCOL_VERSION &&
283 ESTABLISHED(incoming.sccrp.result)) {
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800284 while (!local) {
285 local = random();
286 }
287 log_print(DEBUG, "Received SCCRP -> Sending OCRQ "
Sam Protsenko537773c2018-06-25 21:20:39 +0300288 "(local = %u)", (unsigned)ntohs(local));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800289 log_print(INFO, "Tunnel established");
290 state = OCRQ;
291 set_message(OCRQ);
292 outgoing.ocrq.call = local;
293 outgoing.ocrq.serial = random();
294 outgoing.ocrq.minimum_speed = htonl(1000);
295 outgoing.ocrq.maximum_speed = htonl(100000000);
296 outgoing.ocrq.bearer = htonl(3);
297 outgoing.ocrq.framing = htonl(3);
298 outgoing.ocrq.window_size = htons(8192);
299 send_packet();
300 return 0;
301 }
302 log_print(DEBUG, "Received SCCRP (result = %d)",
Chia-chi Yehea299e62011-07-13 19:36:46 -0700303 incoming.sccrq.result);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800304 log_print(INFO, "Remote server hung up");
305 return -REMOTE_REQUESTED;
306 }
307 break;
308
309 case OCRP:
310 if (state == OCRQ && incoming.ocrp.peer == local) {
311 if (ESTABLISHED(incoming.ocrp.result)) {
312 remote = incoming.ocrp.call;
Sam Protsenko537773c2018-06-25 21:20:39 +0300313 log_print(DEBUG, "Received OCRQ (remote = %u)",
314 (unsigned)ntohs(remote));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800315 log_print(INFO, "Session established");
316 state = OCRP;
317 start_pppd(create_pppox());
318 return 0;
319 }
320 log_print(DEBUG, "Received OCRP (result = %d)",
Chia-chi Yehea299e62011-07-13 19:36:46 -0700321 incoming.ocrp.result);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800322 log_print(INFO, "Remote server hung up");
323 return -REMOTE_REQUESTED;
324 }
325 break;
326
327 case STOPCCRQ:
328 log_print(DEBUG, "Received STOPCCRQ");
329 log_print(INFO, "Remote server hung up");
330 state = STOPCCRQ;
331 return -REMOTE_REQUESTED;
332
333 case CCRQ:
334 /* According to RFC 2637 page 45, we should never receive CCRQ for
335 * outgoing calls. However, some implementation only acts as PNS and
336 * always uses CCRQ to clear a call, so here we still handle it. */
337 if (state == OCRP && incoming.ccrq.call == remote) {
Sam Protsenko537773c2018-06-25 21:20:39 +0300338 log_print(DEBUG, "Received CCRQ (remote = %u)",
339 (unsigned)ntohs(remote));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800340 log_print(INFO, "Remote server hung up");
341 return -REMOTE_REQUESTED;
342 }
343 break;
344
345 case CDN:
346 if (state == OCRP && incoming.cdn.call == remote) {
Sam Protsenko537773c2018-06-25 21:20:39 +0300347 log_print(DEBUG, "Received CDN (remote = %u)",
348 (unsigned)ntohs(remote));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800349 log_print(INFO, "Remote server hung up");
350 return -REMOTE_REQUESTED;
351 }
352 break;
353
354 case ECHORQ:
355 log_print(DEBUG, "Received ECHORQ -> Sending ECHORP");
356 set_message(ECHORP);
357 outgoing.echorp.identifier = incoming.echorq.identifier;
358 outgoing.echorp.result = RESULT_OK;
359 send_packet();
360 return 0;
361
362 case WEN:
363 case SLI:
364 log_print(DEBUG, "Recevied %s", messages[incoming.message]);
365 return 0;
366
367 case ICRQ:
Sam Protsenko537773c2018-06-25 21:20:39 +0300368 log_print(DEBUG, "Received ICRQ (remote = %u, call = %u) -> "
369 "Sending ICRP with error", (unsigned)ntohs(remote),
370 (unsigned)ntohs(incoming.icrq.call));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800371 set_message(ICRP);
372 outgoing.icrp.peer = incoming.icrq.call;
373 outgoing.icrp.result = RESULT_ERROR;
374 send_packet();
375 return 0;
376
377 case OCRQ:
Sam Protsenko537773c2018-06-25 21:20:39 +0300378 log_print(DEBUG, "Received OCRQ (remote = %u, call = %u) -> "
379 "Sending OCRP with error", (unsigned)ntohs(remote),
380 (unsigned)ntohs(incoming.ocrq.call));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800381 set_message(OCRP);
382 outgoing.ocrp.peer = incoming.ocrq.call;
383 outgoing.ocrp.result = RESULT_ERROR;
384 send_packet();
385 return 0;
386 }
387
388 /* We reach here if we got an unexpected message. Just log it. */
389 log_print(DEBUG, "Received UNEXPECTED %s", messages[incoming.message]);
390 return 0;
391}
392
393static int pptp_timeout()
394{
395 return 0;
396}
397
398static void pptp_shutdown()
399{
400 /* Normally we should send STOPCCRQ and wait for STOPCCRP, but this might
401 * block for a long time. Here we simply take the shortcut: do nothing. */
402}
403
404struct protocol pptp = {
405 .name = "pptp",
Chia-chi Yeh7b66d202011-06-28 16:39:23 -0700406 .arguments = 2,
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800407 .usage = "<server> <port>",
408 .connect = pptp_connect,
409 .process = pptp_process,
410 .timeout = pptp_timeout,
411 .shutdown = pptp_shutdown,
412};