l2tp.c revision 79e6232ffa3765d3352e01e2b7887b6425c7c655
1/* 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 L2TP Access Concentrator (RFC 2661) which only 18 * creates a single session. The following code only handles control packets. 19 * Data packets are handled by PPPoLAC 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> 29#include <linux/if_pppolac.h> 30 31#include "mtpd.h" 32 33/* TODO: Support secrets. */ 34 35/* To avoid unnecessary endianness conversions, tunnels, sessions, attributes, 36 * and values are all accessed in network order. */ 37 38/* 0 is reserved. We put ACK here just for convenience. */ 39enum l2tp_message { 40 ACK = 0, 41 SCCRQ = 1, 42 SCCRP = 2, 43 SCCCN = 3, 44 STOPCCN = 4, 45 HELLO = 6, 46 OCRQ = 7, 47 OCRP = 8, 48 OCCN = 9, 49 ICRQ = 10, 50 ICRP = 11, 51 ICCN = 12, 52 CDN = 14, 53 WEN = 15, 54 SLI = 16, 55 MESSAGE_MAX = 16, 56}; 57 58static char *messages[] = { 59 "ACK", "SCCRQ", "SCCRP", "SCCCN", "STOPCCN", NULL, "HELLO", "OCRQ", 60 "OCRP", "OCCN", "ICRQ", "ICRP", "ICCN", NULL, "CDN", "WEN", "SLI", 61}; 62 63/* This is incomplete. Only those we used are listed here. */ 64#define RESULT_CODE htons(1) 65#define PROTOCOL_VERSION htons(2) 66#define FRAMING_CAPABILITIES htons(3) 67#define HOST_NAME htons(7) 68#define ASSIGNED_TUNNEL htons(9) 69#define WINDOW_SIZE htons(10) 70#define ASSIGNED_SESSION htons(14) 71#define CALL_SERIAL_NUMBER htons(15) 72#define FRAMING_TYPE htons(19) 73#define CONNECT_SPEED htons(24) 74 75#define MESSAGE_FLAG 0xC802 76#define MESSAGE_MASK 0xCB0F 77#define ATTRIBUTE_FLAG(length) (0x8006 + (length)) 78#define ATTRIBUTE_LENGTH(flag) (0x03FF & (flag)) 79#define ATTRIBUTE_HIDDEN(flag) (0x4000 & (flag)) 80 81#define ACK_SIZE 12 82#define MESSAGE_HEADER_SIZE 20 83#define ATTRIBUTE_HEADER_SIZE 6 84 85static uint16_t local_tunnel; 86static uint16_t local_session; 87static uint16_t local_sequence; 88static uint16_t remote_tunnel; 89static uint16_t remote_session; 90static uint16_t remote_sequence; 91 92static uint16_t state; 93static int acknowledged; 94 95/* According to RFC 2661 page 46, an exponential backoff strategy is required 96 * for retransmission. However, it might waste too much time waiting for IPsec 97 * negotiation. Here we use the same interval to keep things simple. */ 98#define TIMEOUT_INTERVAL 2000 99 100#define MAX_PACKET_LENGTH 2048 101 102static struct packet { 103 int message; 104 int length; 105 uint8_t buffer[MAX_PACKET_LENGTH] __attribute__((aligned)); 106} incoming, outgoing; 107 108struct attribute { 109 uint16_t flag; 110 uint16_t vendor; 111 uint16_t type; 112 uint8_t value[1]; 113} __attribute__((packed)); 114 115static void set_message(uint16_t session, uint16_t message) 116{ 117 uint16_t *p = (uint16_t *)outgoing.buffer; 118 p[0] = htons(MESSAGE_FLAG); 119 /* p[1] will be filled in send_packet(). */ 120 p[2] = remote_tunnel; 121 p[3] = session; 122 p[4] = htons(local_sequence); 123 p[5] = htons(remote_sequence); 124 p[6] = htons(ATTRIBUTE_FLAG(2)); 125 p[7] = 0; 126 p[8] = 0; 127 p[9] = htons(message); 128 outgoing.message = message; 129 outgoing.length = MESSAGE_HEADER_SIZE; 130 ++local_sequence; 131} 132 133static void add_attribute_raw(uint16_t type, void *value, int size) 134{ 135 struct attribute *p = (struct attribute *)&outgoing.buffer[outgoing.length]; 136 p->flag = htons(ATTRIBUTE_FLAG(size)); 137 p->vendor = 0; 138 p->type = type; 139 memcpy(&p->value, value, size); 140 outgoing.length += ATTRIBUTE_HEADER_SIZE + size; 141} 142 143static void add_attribute_u16(uint16_t attribute, uint16_t value) 144{ 145 add_attribute_raw(attribute, &value, sizeof(uint16_t)); 146} 147 148static void add_attribute_u32(uint16_t attribute, uint32_t value) 149{ 150 add_attribute_raw(attribute, &value, sizeof(uint32_t)); 151} 152 153static void send_packet() 154{ 155 uint16_t *p = (uint16_t *)outgoing.buffer; 156 p[1] = htons(outgoing.length); 157 send(the_socket, outgoing.buffer, outgoing.length, 0); 158 acknowledged = 0; 159} 160 161static void send_ack() 162{ 163 uint16_t buffer[6] = { 164 htons(MESSAGE_FLAG), htons(ACK_SIZE), remote_tunnel, 0, 165 htons(local_sequence), htons(remote_sequence), 166 }; 167 send(the_socket, buffer, ACK_SIZE, 0); 168} 169 170static int recv_packet(uint16_t *session) 171{ 172 uint16_t *p = (uint16_t *)incoming.buffer; 173 174 incoming.length = recv(the_socket, incoming.buffer, MAX_PACKET_LENGTH, 0); 175 if (incoming.length == -1 && errno != EINTR) { 176 log_print(FATAL, "Recv() %s", strerror(errno)); 177 exit(NETWORK_ERROR); 178 } 179 180 /* We only handle packets in our tunnel. */ 181 if ((incoming.length != ACK_SIZE && incoming.length < MESSAGE_HEADER_SIZE) 182 || (p[0] & htons(MESSAGE_MASK)) != htons(MESSAGE_FLAG) 183 || p[1] > htons(incoming.length) || p[2] != local_tunnel) { 184 return 0; 185 } 186 187 if (incoming.length == ACK_SIZE) { 188 incoming.message = ACK; 189 } else if (p[6] == htons(ATTRIBUTE_FLAG(2)) && !p[7] && !p[8]) { 190 incoming.message = ntohs(p[9]); 191 } else { 192 return 0; 193 } 194 195 /* Check if the packet is duplicated and send ACK if necessary. */ 196 if ((uint16_t)(ntohs(p[4]) - remote_sequence) > 32767) { 197 if (incoming.message != ACK) { 198 send_ack(); 199 } 200 return 0; 201 } 202 203 if (ntohs(p[5]) == local_sequence) { 204 acknowledged = 1; 205 } 206 207 /* Our sending and receiving window sizes are both 1. Thus we only handle 208 * this packet if it is their next one and they received our last one. */ 209 if (ntohs(p[4]) != remote_sequence || !acknowledged) { 210 return 0; 211 } 212 *session = p[3]; 213 if (incoming.message != ACK) { 214 ++remote_sequence; 215 } 216 return 1; 217} 218 219static int get_attribute_raw(uint16_t type, void *value, int size) 220{ 221 int offset = MESSAGE_HEADER_SIZE; 222 while (incoming.length >= offset + ATTRIBUTE_HEADER_SIZE) { 223 struct attribute *p = (struct attribute *)&incoming.buffer[offset]; 224 uint16_t flag = ntohs(p->flag); 225 int length = ATTRIBUTE_LENGTH(flag); 226 227 offset += length; 228 length -= ATTRIBUTE_HEADER_SIZE; 229 if (length < 0 || offset > incoming.length) { 230 break; 231 } 232 233 /* Currently we do not support hidden attributes. */ 234 if (!ATTRIBUTE_HIDDEN(flag) && !p->vendor && p->type == type) { 235 if (size > length) { 236 size = length; 237 } 238 memcpy(value, p->value, size); 239 return size; 240 } 241 } 242 return 0; 243} 244 245static int get_attribute_u16(uint16_t type, uint16_t *value) 246{ 247 return get_attribute_raw(type, value, sizeof(uint16_t)) == sizeof(uint16_t); 248} 249 250static int l2tp_connect(int argc, char **argv) 251{ 252 if (argc < 2) { 253 return -USAGE_ERROR; 254 } 255 create_socket(AF_INET, SOCK_DGRAM, argv[0], argv[1]); 256 257 while (!local_tunnel) { 258 local_tunnel = random(); 259 } 260 261 log_print(DEBUG, "Sending SCCRQ (local_tunnel = %d)", local_tunnel); 262 state = SCCRQ; 263 set_message(0, SCCRQ); 264 add_attribute_u16(PROTOCOL_VERSION, htons(0x0100)); 265 add_attribute_raw(HOST_NAME, "anonymous", 9); 266 add_attribute_u32(FRAMING_CAPABILITIES, htonl(3)); 267 add_attribute_u16(ASSIGNED_TUNNEL, local_tunnel); 268 add_attribute_u16(WINDOW_SIZE, htons(1)); 269 send_packet(); 270 return TIMEOUT_INTERVAL; 271} 272 273static int create_pppox() 274{ 275 int pppox; 276 log_print(INFO, "Creating PPPoX socket"); 277 pppox = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OLAC); 278 279 if (pppox == -1) { 280 log_print(FATAL, "Socket() %s", strerror(errno)); 281 exit(SYSTEM_ERROR); 282 } else { 283 struct sockaddr_pppolac address = { 284 .sa_family = AF_PPPOX, 285 .sa_protocol = PX_PROTO_OLAC, 286 .udp_socket = the_socket, 287 .local = {.tunnel = local_tunnel, .session = local_session}, 288 .remote = {.tunnel = remote_tunnel, .session = remote_session}, 289 }; 290 if (connect(pppox, (struct sockaddr *)&address, sizeof(address)) != 0) { 291 log_print(FATAL, "Connect() %s", strerror(errno)); 292 exit(SYSTEM_ERROR); 293 } 294 } 295 return pppox; 296} 297 298static int l2tp_process() 299{ 300 uint16_t sequence = local_sequence; 301 uint16_t tunnel; 302 uint16_t session; 303 304 if (!recv_packet(&session)) { 305 return acknowledged ? 0 : TIMEOUT_INTERVAL; 306 } 307 308 /* Here is the fun part. We always try to protect our tunnel and session 309 * from being closed even if we received unexpected messages. */ 310 switch(incoming.message) { 311 case SCCRP: 312 if (state == SCCRQ) { 313 if (get_attribute_u16(ASSIGNED_TUNNEL, &tunnel) && tunnel) { 314 remote_tunnel = tunnel; 315 log_print(DEBUG, "Received SCCRP (remote_tunnel = %d) -> " 316 "Sending SCCCN", remote_tunnel); 317 state = SCCCN; 318 set_message(0, SCCCN); 319 break; 320 } 321 log_print(DEBUG, "Received SCCRP without assigned tunnel"); 322 log_print(ERROR, "Protocol error"); 323 return -PROTOCOL_ERROR; 324 } 325 break; 326 327 case ICRP: 328 if (state == ICRQ && session == local_session) { 329 if (get_attribute_u16(ASSIGNED_SESSION, &session) && session) { 330 remote_session = session; 331 log_print(DEBUG, "Received ICRP (remote_session = %d) -> " 332 "Sending ICCN", remote_session); 333 state = ICCN; 334 set_message(remote_session, ICCN); 335 add_attribute_u32(CONNECT_SPEED, htonl(100000000)); 336 add_attribute_u32(FRAMING_TYPE, htonl(3)); 337 break; 338 } 339 log_print(DEBUG, "Received ICRP without assigned session"); 340 log_print(ERROR, "Protocol error"); 341 return -PROTOCOL_ERROR; 342 } 343 break; 344 345 case STOPCCN: 346 log_print(DEBUG, "Received STOPCCN"); 347 log_print(INFO, "Remote server hung up"); 348 state = STOPCCN; 349 return -REMOTE_REQUESTED; 350 351 case CDN: 352 if (session && session == local_session) { 353 log_print(DEBUG, "Received CDN (local_session = %d)", 354 local_session); 355 log_print(INFO, "Remote server hung up"); 356 return -REMOTE_REQUESTED; 357 } 358 break; 359 360 case ACK: 361 case HELLO: 362 case WEN: 363 case SLI: 364 /* These are harmless, so we just treat them the same way. */ 365 if (state == SCCCN) { 366 while (!local_session) { 367 local_session = random(); 368 } 369 log_print(DEBUG, "Received %s -> Sending ICRQ (local_session = " 370 "%d)", messages[incoming.message], local_session); 371 log_print(INFO, "Tunnel established"); 372 state = ICRQ; 373 set_message(0, ICRQ); 374 add_attribute_u16(ASSIGNED_SESSION, local_session); 375 add_attribute_u32(CALL_SERIAL_NUMBER, random()); 376 break; 377 } 378 379 if (incoming.message == ACK) { 380 log_print(DEBUG, "Received ACK"); 381 } else { 382 log_print(DEBUG, "Received %s -> Sending ACK", 383 messages[incoming.message]); 384 send_ack(); 385 } 386 387 if (state == ICCN) { 388 log_print(INFO, "Session established"); 389 state = ACK; 390 start_pppd(create_pppox()); 391 } 392 return 0; 393 394 case ICRQ: 395 case OCRQ: 396 /* Since we run pppd as a client, it does not makes sense to 397 * accept ICRQ or OCRQ. Always send CDN with a proper error. */ 398 if (get_attribute_u16(ASSIGNED_SESSION, &session) && session) { 399 log_print(DEBUG, "Received %s (remote_session = %d) -> " 400 "Sending CDN", messages[incoming.message], session); 401 set_message(session, CDN); 402 add_attribute_u32(RESULT_CODE, htonl(0x00020006)); 403 add_attribute_u16(ASSIGNED_SESSION, 0); 404 } 405 break; 406 } 407 408 if (sequence != local_sequence) { 409 send_packet(); 410 return TIMEOUT_INTERVAL; 411 } 412 413 /* We reach here if we got an unexpected message. Log it and send ACK. */ 414 if (incoming.message > MESSAGE_MAX || !messages[incoming.message]) { 415 log_print(DEBUG, "Received UNKNOWN %d -> Sending ACK anyway", 416 incoming.message); 417 } else { 418 log_print(DEBUG, "Received UNEXPECTED %s -> Sending ACK anyway", 419 messages[incoming.message]); 420 } 421 send_ack(); 422 return 0; 423} 424 425static int l2tp_timeout() 426{ 427 if (acknowledged) { 428 return 0; 429 } 430 log_print(DEBUG, "Timeout -> Sending %s", messages[outgoing.message]); 431 send(the_socket, outgoing.buffer, outgoing.length, 0); 432 return TIMEOUT_INTERVAL; 433} 434 435static void l2tp_shutdown() 436{ 437 if (state != STOPCCN) { 438 log_print(DEBUG, "Sending STOPCCN"); 439 set_message(0, STOPCCN); 440 add_attribute_u16(ASSIGNED_TUNNEL, local_tunnel); 441 add_attribute_u16(RESULT_CODE, htons(6)); 442 send_packet(); 443 } 444} 445 446struct protocol l2tp = { 447 .name = "l2tp", 448 .usage = "<server> <port>", 449 .connect = l2tp_connect, 450 .process = l2tp_process, 451 .timeout = l2tp_timeout, 452 .shutdown = l2tp_shutdown, 453}; 454