blob: ee5d1651765e3a1fc850a67e886b3bea8635bf83 [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>
Chia-chi Yeh04d2aa72011-06-28 14:31:15 -070026#include <unistd.h>
Chia-chi Yeh063bb922009-06-15 14:43:38 +080027#include <sys/types.h>
28#include <sys/socket.h>
29#include <arpa/inet.h>
30#include <linux/if_pppopns.h>
31
32#include "mtpd.h"
33
34enum pptp_message {
35 SCCRQ = 1,
36 SCCRP = 2,
37 STOPCCRQ = 3,
38 STOPCCRP = 4,
39 ECHORQ = 5,
40 ECHORP = 6,
41 OCRQ = 7,
42 OCRP = 8,
43 ICRQ = 9,
44 ICRP = 10,
45 ICCN = 11,
46 CCRQ = 12,
47 CDN = 13,
48 WEN = 14,
49 SLI = 15,
50 MESSAGE_MAX = 15,
51};
52
53static char *messages[] = {
54 NULL, "SCCRQ", "SCCRP", "STOPCCRQ", "STOPCCRP", "ECHORQ", "ECHORP",
55 "OCRQ", "OCRP", "ICRQ", "ICRP", "ICCN", "CCRQ", "CDN", "WEN", "SLI",
56};
57
58static uint8_t lengths[] = {
59 0, 156, 156, 16, 16, 16, 20, 168, 32, 220, 24, 28, 16, 148, 40, 24,
60};
61
62#define CONTROL_MESSAGE htons(1)
63#define MAGIC_COOKIE htonl(0x1A2B3C4D)
64#define PROTOCOL_VERSION htons(0x0100)
65
66#define RESULT_OK 1
67#define RESULT_ERROR 2
68
69/* Some implementation uses 0 instead of 1, so we allow both of them. */
70#define ESTABLISHED(result) (result <= 1)
71
72#define HEADER_SIZE 8
73#define MIN_MESSAGE_SIZE 10
74
75static uint16_t local;
76static uint16_t remote;
77static uint16_t state;
78
79#define MAX_PACKET_LENGTH 220
80
81/* We define all the fields we used in this structure. Type conversion and byte
82 * alignment are solved in one place. Although it looks a little bit ugly, it
83 * really makes life easier. */
84static struct packet {
85 int length;
86 int expect;
87 union {
88 uint8_t buffer[MAX_PACKET_LENGTH];
89 struct {
90 struct __attribute__((packed)) {
91 uint16_t length;
92 uint16_t type;
93 uint32_t cookie;
94 } header;
95 uint16_t message;
96 uint16_t reserved;
97 union {
98 struct __attribute__((packed)) {
99 uint16_t protocol_version;
100 uint8_t result;
101 uint8_t error;
102 uint32_t framing;
103 uint32_t bearer;
104 uint16_t channels;
105 uint16_t firmware_revision;
106 char host[64];
107 } sccrp, sccrq;
108 struct __attribute__((packed)) {
109 uint16_t call;
110 uint16_t serial;
111 uint32_t minimum_speed;
112 uint32_t maximum_speed;
113 uint32_t bearer;
114 uint32_t framing;
115 uint16_t window_size;
116 } ocrq;
117 struct __attribute__((packed)) {
118 uint16_t call;
119 uint16_t peer;
120 uint8_t result;
121 } ocrp, icrp;
122 struct __attribute__((packed)) {
123 uint32_t identifier;
124 uint8_t result;
125 } echorq, echorp;
126 struct __attribute__((packed)) {
127 uint16_t call;
128 } icrq, ccrq, cdn;
129 };
130 } __attribute__((packed));
131 } __attribute__((aligned(4)));
132} incoming, outgoing;
133
134static void set_message(uint16_t message)
135{
136 uint16_t length = lengths[message];
137 memset(outgoing.buffer, 0, length);
138 outgoing.length = length;
139 outgoing.header.length = htons(length);
140 outgoing.header.type = CONTROL_MESSAGE;
141 outgoing.header.cookie = MAGIC_COOKIE;
142 outgoing.message = htons(message);
143}
144
145static void send_packet()
146{
147 send(the_socket, outgoing.buffer, outgoing.length, 0);
148}
149
150static int recv_packet()
151{
152 int length;
153
154 /* We are going to read a new message if incoming.expect is 0. */
155 if (!incoming.expect) {
156 incoming.length = 0;
157 incoming.expect = HEADER_SIZE;
158 }
159
160 /* The longest message defined in RFC 2637 is 220 bytes, but the protocol
161 * itself allows up to 65536 bytes. Therefore we always read a complete
162 * message but only keep the first 220 bytes before passing up. */
163 length = incoming.expect - incoming.length;
164 if (incoming.length >= MAX_PACKET_LENGTH) {
165 uint8_t buffer[length];
166 length = recv(the_socket, buffer, length, 0);
167 } else {
168 if (incoming.expect > MAX_PACKET_LENGTH) {
169 length = MAX_PACKET_LENGTH - incoming.length;
170 }
171 length = recv(the_socket, &incoming.buffer[incoming.length], length, 0);
172 }
173 if (length == -1) {
174 if (errno == EINTR) {
175 return 0;
176 }
177 log_print(FATAL, "Recv() %s", strerror(errno));
178 exit(NETWORK_ERROR);
179 }
180 if (length == 0) {
181 log_print(DEBUG, "Connection closed");
182 log_print(INFO, "Remote server hung up");
183 return -REMOTE_REQUESTED;
184 }
185 incoming.length += length;
186
187 /* If incoming.header is valid, check cookie and update incoming.expect. */
188 if (incoming.length == HEADER_SIZE && incoming.expect == HEADER_SIZE) {
189 if (incoming.header.cookie != MAGIC_COOKIE) {
190 log_print(DEBUG, "Loss of synchronization");
191 log_print(ERROR, "Protocol error");
192 return -PROTOCOL_ERROR;
193 }
194 incoming.expect = ntohs(incoming.header.length);
195 if (incoming.expect < HEADER_SIZE) {
196 log_print(DEBUG, "Invalid message length");
197 log_print(ERROR, "Protocol error");
198 return -PROTOCOL_ERROR;
199 }
200 }
201
202 /* Now we have a complete message. Reset incoming.expect. */
203 if (incoming.length == incoming.expect) {
204 incoming.expect = 0;
205
206 /* Return 1 if it is a control message. */
207 if (incoming.header.type == CONTROL_MESSAGE) {
208 return 1;
209 }
210 log_print(DEBUG, "Ignored non-control message (type = %d)",
Chia-chi Yehea299e62011-07-13 19:36:46 -0700211 ntohs(incoming.header.type));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800212 }
213 return 0;
214}
215
Chia-chi Yeh7b66d202011-06-28 16:39:23 -0700216static int pptp_connect(char **arguments)
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800217{
Chia-chi Yeh7b66d202011-06-28 16:39:23 -0700218 create_socket(AF_UNSPEC, SOCK_STREAM, arguments[0], arguments[1]);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800219
220 log_print(DEBUG, "Sending SCCRQ");
221 state = SCCRQ;
222 set_message(SCCRQ);
223 outgoing.sccrq.protocol_version = PROTOCOL_VERSION;
224 outgoing.sccrq.framing = htonl(3);
225 outgoing.sccrq.bearer = htonl(3);
226 outgoing.sccrq.channels = htons(1);
227 strcpy(outgoing.sccrq.host, "anonymous");
228 send_packet();
229 return 0;
230}
231
Chia-chi Yeh04d2aa72011-06-28 14:31:15 -0700232static int create_pppox_hack(unsigned int protocol)
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800233{
234 int pppox;
235 log_print(INFO, "Creating PPPoX socket");
Chia-chi Yeh04d2aa72011-06-28 14:31:15 -0700236 pppox = socket(AF_PPPOX, SOCK_DGRAM, protocol);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800237
238 if (pppox == -1) {
239 log_print(FATAL, "Socket() %s", strerror(errno));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800240 } else {
241 struct sockaddr_pppopns address = {
242 .sa_family = AF_PPPOX,
Chia-chi Yeh04d2aa72011-06-28 14:31:15 -0700243 .sa_protocol = protocol,
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800244 .tcp_socket = the_socket,
245 .local = local,
246 .remote = remote,
247 };
Chia-chi Yehea299e62011-07-13 19:36:46 -0700248 if (connect(pppox, (struct sockaddr *)&address, sizeof(address))) {
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800249 log_print(FATAL, "Connect() %s", strerror(errno));
Chia-chi Yeh04d2aa72011-06-28 14:31:15 -0700250 close(pppox);
251 return -1;
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800252 }
253 }
254 return pppox;
255}
256
Chia-chi Yeh04d2aa72011-06-28 14:31:15 -0700257static int create_pppox() {
258 /* PX_PROTO_OPNS is bumped from 3 to 4 after 2.6.38. :( */
259 int pppox = create_pppox_hack(4);
260 if (pppox == -1) {
261 pppox = create_pppox_hack(3);
262 }
263 if (pppox == -1) {
264 exit(SYSTEM_ERROR);
265 }
266 return pppox;
267}
268
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800269static int pptp_process()
270{
271 int result = recv_packet();
272 if (result <= 0) {
273 return result;
274 }
275
276 if (incoming.length < MIN_MESSAGE_SIZE) {
277 log_print(DEBUG, "Control message too short");
278 return 0;
279 }
280 incoming.message = ntohs(incoming.message);
281 if (incoming.message > MESSAGE_MAX || !messages[incoming.message]) {
282 log_print(DEBUG, "Received UNKNOWN %d", incoming.message);
283 return 0;
284 }
285 if (incoming.length < lengths[incoming.message]) {
286 log_print(DEBUG, "Received %s with invalid length (length = %d)",
Chia-chi Yehea299e62011-07-13 19:36:46 -0700287 messages[incoming.message], incoming.length);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800288 return 0;
289 }
290
291 switch(incoming.message) {
292 case SCCRP:
293 if (state == SCCRQ) {
Chia-chi Yehea299e62011-07-13 19:36:46 -0700294 if (incoming.sccrp.protocol_version == PROTOCOL_VERSION &&
295 ESTABLISHED(incoming.sccrp.result)) {
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800296 while (!local) {
297 local = random();
298 }
299 log_print(DEBUG, "Received SCCRP -> Sending OCRQ "
Chia-chi Yehea299e62011-07-13 19:36:46 -0700300 "(local = %d)", local);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800301 log_print(INFO, "Tunnel established");
302 state = OCRQ;
303 set_message(OCRQ);
304 outgoing.ocrq.call = local;
305 outgoing.ocrq.serial = random();
306 outgoing.ocrq.minimum_speed = htonl(1000);
307 outgoing.ocrq.maximum_speed = htonl(100000000);
308 outgoing.ocrq.bearer = htonl(3);
309 outgoing.ocrq.framing = htonl(3);
310 outgoing.ocrq.window_size = htons(8192);
311 send_packet();
312 return 0;
313 }
314 log_print(DEBUG, "Received SCCRP (result = %d)",
Chia-chi Yehea299e62011-07-13 19:36:46 -0700315 incoming.sccrq.result);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800316 log_print(INFO, "Remote server hung up");
317 return -REMOTE_REQUESTED;
318 }
319 break;
320
321 case OCRP:
322 if (state == OCRQ && incoming.ocrp.peer == local) {
323 if (ESTABLISHED(incoming.ocrp.result)) {
324 remote = incoming.ocrp.call;
325 log_print(DEBUG, "Received OCRQ (remote = %d)", remote);
326 log_print(INFO, "Session established");
327 state = OCRP;
328 start_pppd(create_pppox());
329 return 0;
330 }
331 log_print(DEBUG, "Received OCRP (result = %d)",
Chia-chi Yehea299e62011-07-13 19:36:46 -0700332 incoming.ocrp.result);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800333 log_print(INFO, "Remote server hung up");
334 return -REMOTE_REQUESTED;
335 }
336 break;
337
338 case STOPCCRQ:
339 log_print(DEBUG, "Received STOPCCRQ");
340 log_print(INFO, "Remote server hung up");
341 state = STOPCCRQ;
342 return -REMOTE_REQUESTED;
343
344 case CCRQ:
345 /* According to RFC 2637 page 45, we should never receive CCRQ for
346 * outgoing calls. However, some implementation only acts as PNS and
347 * always uses CCRQ to clear a call, so here we still handle it. */
348 if (state == OCRP && incoming.ccrq.call == remote) {
349 log_print(DEBUG, "Received CCRQ (remote = %d)", remote);
350 log_print(INFO, "Remote server hung up");
351 return -REMOTE_REQUESTED;
352 }
353 break;
354
355 case CDN:
356 if (state == OCRP && incoming.cdn.call == remote) {
357 log_print(DEBUG, "Received CDN (remote = %d)", remote);
358 log_print(INFO, "Remote server hung up");
359 return -REMOTE_REQUESTED;
360 }
361 break;
362
363 case ECHORQ:
364 log_print(DEBUG, "Received ECHORQ -> Sending ECHORP");
365 set_message(ECHORP);
366 outgoing.echorp.identifier = incoming.echorq.identifier;
367 outgoing.echorp.result = RESULT_OK;
368 send_packet();
369 return 0;
370
371 case WEN:
372 case SLI:
373 log_print(DEBUG, "Recevied %s", messages[incoming.message]);
374 return 0;
375
376 case ICRQ:
377 log_print(DEBUG, "Received ICRQ (remote = %d) -> Sending ICRP "
Chia-chi Yehea299e62011-07-13 19:36:46 -0700378 "with error", incoming.icrq.call);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800379 set_message(ICRP);
380 outgoing.icrp.peer = incoming.icrq.call;
381 outgoing.icrp.result = RESULT_ERROR;
382 send_packet();
383 return 0;
384
385 case OCRQ:
386 log_print(DEBUG, "Received OCRQ (remote = %d) -> Sending OCRP "
Chia-chi Yehea299e62011-07-13 19:36:46 -0700387 "with error", incoming.ocrq.call);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800388 set_message(OCRP);
389 outgoing.ocrp.peer = incoming.ocrq.call;
390 outgoing.ocrp.result = RESULT_ERROR;
391 send_packet();
392 return 0;
393 }
394
395 /* We reach here if we got an unexpected message. Just log it. */
396 log_print(DEBUG, "Received UNEXPECTED %s", messages[incoming.message]);
397 return 0;
398}
399
400static int pptp_timeout()
401{
402 return 0;
403}
404
405static void pptp_shutdown()
406{
407 /* Normally we should send STOPCCRQ and wait for STOPCCRP, but this might
408 * block for a long time. Here we simply take the shortcut: do nothing. */
409}
410
411struct protocol pptp = {
412 .name = "pptp",
Chia-chi Yeh7b66d202011-06-28 16:39:23 -0700413 .arguments = 2,
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800414 .usage = "<server> <port>",
415 .connect = pptp_connect,
416 .process = pptp_process,
417 .timeout = pptp_timeout,
418 .shutdown = pptp_shutdown,
419};