1/* 2 * pptpgre.c 3 * 4 * originally by C. S. Ananian 5 * Modified for PoPToP 6 * 7 * $Id: pptpgre.c,v 1.9 2007/04/16 00:21:02 quozl Exp $ 8 */ 9 10#ifdef HAVE_CONFIG_H 11#include "config.h" 12#endif 13 14#ifdef __linux__ 15#define _GNU_SOURCE 1 /* broken arpa/inet.h */ 16#endif 17 18#include "our_syslog.h" 19 20#include <stdio.h> 21#include <stdlib.h> 22#include <sys/types.h> 23#include <sys/socket.h> 24#include <netinet/in.h> 25#include <arpa/inet.h> 26#include <sys/stat.h> 27#include <time.h> 28#include <sys/time.h> 29#include <unistd.h> 30#include <string.h> 31#include <errno.h> 32#include <fcntl.h> 33#ifdef HAVE_SYS_UIO_H 34#include <sys/uio.h> 35#endif 36 37#include "ppphdlc.h" 38#include "pptpgre.h" 39#include "pptpdefs.h" 40#include "pptpctrl.h" 41#include "defaults.h" 42#include "pqueue.h" 43 44#ifndef HAVE_STRERROR 45#include "compat.h" 46#endif 47 48#define PACKET_MAX 8196 49 50typedef int (*callback_t)(int cl, void *pack, unsigned int len); 51 52/* test for a 32 bit counter overflow */ 53#define WRAPPED( curseq, lastseq) \ 54 ((((curseq) & 0xffffff00) == 0) && \ 55 (((lastseq) & 0xffffff00 ) == 0xffffff00)) 56 57static struct gre_state gre; 58gre_stats_t stats; 59 60static uint64_t time_now_usecs() 61{ 62 struct timeval tv; 63 gettimeofday(&tv, NULL); 64 return (tv.tv_sec * 1000000) + tv.tv_usec; 65} 66 67int pptp_gre_init(u_int32_t call_id_pair, int pty_fd, struct in_addr *inetaddrs) 68{ 69 struct sockaddr_in addr; 70 int gre_fd; 71 72 /* Open IP protocol socket */ 73 gre_fd = socket(AF_INET, SOCK_RAW, PPTP_PROTO); 74 if (gre_fd < 0) { 75 syslog(LOG_ERR, "GRE: socket() failed"); 76 return -1; 77 } 78 79 memset(&addr, 0, sizeof(addr)); 80 81 addr.sin_family = AF_INET; 82 addr.sin_addr = inetaddrs[0]; 83 addr.sin_port = 0; 84 if (bind(gre_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 85 syslog(LOG_ERR, "GRE: bind() failed: %s", strerror(errno)); 86 syslog(LOG_ERR, "GRE: continuing, but may not work if multi-homed"); 87 } 88 89 addr.sin_family = AF_INET; 90 addr.sin_addr = inetaddrs[1]; 91 addr.sin_port = 0; 92 if (connect(gre_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 93 syslog(LOG_ERR, "GRE: connect() failed: %s", strerror(errno)); 94 return -1; 95 } 96 97 gre.seq_sent = 0; 98 gre.ack_sent = gre.ack_recv = gre.seq_recv = 0xFFFFFFFF; 99 /* seq_recv is -1, therefore next packet expected is seq 0, 100 to comply with RFC 2637: 'The sequence number for each 101 user session is set to zero at session startup.' */ 102 103 gre.call_id_pair = call_id_pair; /* network byte order */ 104 return gre_fd; 105} 106 107/* ONE blocking read per call; dispatches all packets possible */ 108/* returns 0 on success, or <0 on read failure */ 109int decaps_hdlc(int fd, int (*cb) (int cl, void *pack, unsigned len), int cl) 110{ 111 static unsigned char buffer[PACKET_MAX], copy[PACKET_MAX]; 112 static unsigned start = 0, end = 0; 113 static unsigned len = 0, escape = 0; 114 static u_int16_t fcs = PPPINITFCS16; 115 static unsigned char err = 0; 116 unsigned char c; 117 int status; 118 119 /* we do one read only, since it may block. and only if the 120 * buffer is empty (start == end) 121 */ 122 123 if (fd == -1) { 124 if(cb == NULL) { 125 /* peek mode */ 126 return err ? -1 : 0; 127 } else if (!err) { 128 /* re-xmit and nothing queued */ 129 syslog(LOG_ERR, "GRE: Re-xmit called with nothing queued"); 130 return -1; 131 } 132 } 133 134 if (!err) { 135 /* All known data is processed. This true unless the last 136 * network write failed. 137 */ 138 if ((status = read(fd, buffer, sizeof(buffer))) <= 0) { 139 syslog(LOG_ERR, "GRE: read(fd=%d,buffer=%lx,len=%d) from PTY failed: status = %d error = %s%s", 140 fd, (unsigned long) buffer, sizeof(buffer), 141 status, status ? strerror(errno) : "No error", 142 errno != EIO ? "" : ", usually caused by unexpected termination of pppd, check option syntax and pppd logs"); 143 /* FAQ: mistakes in pppd option spelling in 144 * /etc/ppp/options.pptpd often cause EIO, 145 * with pppd not reporting the problem to any 146 * logs. Termination of pppd by signal can 147 * *also* cause this situation. -- James Cameron 148 */ 149 return -1; 150 } 151 end = status; 152 start = 0; 153 } else { 154 /* We're here because of a network write failure. Try again. 155 * Then do what we would do normally and enter the loop as if 156 * just continuing the while(1). Not sure that this ever 157 * really happens, but since we error-check status then we 158 * should have the code to handle an error :-) 159 */ 160 err = 0; 161 if ((status = cb(cl, copy, len)) < 0) { 162 syslog(LOG_ERR, "GRE: re-xmit failed from decaps_hdlc: %s", strerror(errno)); 163 err = 1; 164 return status; /* return error */ 165 } 166 /* Great! Let's do more! */ 167 fcs = PPPINITFCS16; 168 len = 0; 169 escape = 0; 170 } 171 172 while (1) { 173 /* Infinite loop, we return when we're out of data */ 174 175 /* Check if out of data */ 176 if (start == end) 177 return 0; 178 179 /* Add to the packet up till the next HDLC_FLAG (start/end of 180 * packet marker). Copy to 'copy', un-escape and checksum as we go. 181 */ 182 while (buffer[start] != HDLC_FLAG) { 183 184 /* Dispose of 'too long' packets */ 185 if (len >= PACKET_MAX) { 186 syslog(LOG_ERR, "GRE: Received too long packet from pppd."); 187 while (buffer[start] != HDLC_FLAG && start < end) 188 start++; 189 if (start < end) { 190 goto newpacket; 191 } else 192 return 0; 193 } 194 /* Read a character, un-escaping if needed */ 195 if (buffer[start] == HDLC_ESCAPE && !escape) 196 escape = 1; 197 else { 198 if (escape) { 199 copy[len] = c = buffer[start] ^ 0x20; 200 escape = 0; 201 } else 202 copy[len] = c = buffer[start]; 203 fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff]; 204 len++; 205 } 206 start++; 207 208 /* Check if out of data */ 209 if (start == end) 210 return 0; 211 } 212 213 /* Found flag. Skip past it */ 214 start++; 215 216 /* Check for over-short packets and silently discard, as per RFC1662 */ 217 if ((len < 4) || (escape == 1)) { 218 /* len == 0 is possible, we generate it :-) [using HDLC_ESCAPE at 219 * start and end of packet]. Others are worth recording. 220 */ 221 if (len && len < 4) 222 syslog(LOG_ERR, "GRE: Received too short packet from pppd."); 223 if (escape) 224 syslog(LOG_ERR, "GRE: Received bad packet from pppd."); 225 goto newpacket; 226 } 227 /* Check, then remove the 16-bit FCS checksum field */ 228 if (fcs != PPPGOODFCS16) { 229 syslog(LOG_ERR, "GRE: Bad checksum from pppd."); 230 goto newpacket; 231 } 232 len -= sizeof(u_int16_t); 233 234 /* So now we have a packet of length 'len' in 'copy' */ 235 if ((status = cb(cl, copy, len)) < 0) { 236 syslog(LOG_ERR, "GRE: xmit failed from decaps_hdlc: %s", strerror(errno)); 237 err = 1; 238 return status; /* return error */ 239 } 240 newpacket: 241 /* Great! Let's do more! */ 242 fcs = PPPINITFCS16; 243 len = 0; 244 escape = 0; 245 } 246} 247 248#define seq_greater(A,B) ((A)>(B) || \ 249 (((u_int32_t)(A)<0xff) && ((~((u_int32_t)(B)))<0xff))) 250 251/* Macro used in encaps_hdlc(). add "val" to "dest" at position "pos", 252 * incrementing "pos" to point after the added value. set "tmp" to "val" 253 * as a side-effect. 254 */ 255#define ADD_CHAR(dest, pos, val, tmp) \ 256 tmp = (val); \ 257 if ((tmp<0x20) || (tmp==HDLC_FLAG) || (tmp==HDLC_ESCAPE)) { \ 258 dest[pos++]=HDLC_ESCAPE; \ 259 dest[pos++]=tmp^0x20; \ 260 } else \ 261 dest[pos++]=tmp 262 263/* Make stripped packet into HDLC packet */ 264int encaps_hdlc(int fd, void *pack, unsigned len) 265{ 266 unsigned char *source = (unsigned char *) pack; 267 /* largest expansion possible - double all + double fcs + 2 flags */ 268 static unsigned char dest[2 * PACKET_MAX + 6]; 269 unsigned pos = 1, i; 270 u_int16_t fcs; 271 unsigned char c; 272 273 fcs = PPPINITFCS16; 274 275 /* make sure overflow is impossible so we don't have to bounds check 276 * in loop. drop large packets. 277 */ 278 if (len > PACKET_MAX) { 279 syslog(LOG_ERR, "GRE: Asked to encapsulate too large packet (len = %d)", len); 280 return -1; 281 } 282 /* start character */ 283 dest[0] = HDLC_FLAG; 284 285 /* escape the payload */ 286 for (i = 0; i < len; i++) { 287 ADD_CHAR(dest, pos, source[i], c); 288 fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff]; 289 } 290 291 fcs ^= 0xFFFF; 292 293 ADD_CHAR(dest, pos, fcs & 0xFF, c); 294 ADD_CHAR(dest, pos, fcs >> 8, c); 295 296 /* tack on the end-flag */ 297 dest[pos++] = HDLC_FLAG; 298 299 /* now write this packet */ 300 return write(fd, dest, pos); 301} 302 303#undef ADD_CHAR 304 305 306static int dequeue_gre (callback_t callback, int cl) 307{ 308 pqueue_t *head; 309 int status; 310 /* process packets in the queue that either are expected or 311 have timed out. */ 312 head = pqueue_head(); 313 while ( head != NULL && 314 ( (head->seq == gre.seq_recv + 1) || /* wrap-around safe */ 315 (pqueue_expiry_time(head) <= 0) 316 ) 317 ) { 318 /* if it is timed out... */ 319 if (head->seq != gre.seq_recv + 1 ) { /* wrap-around safe */ 320 stats.rx_lost += head->seq - gre.seq_recv - 1; 321 if (pptpctrl_debug) 322 syslog(LOG_DEBUG, 323 "GRE: timeout waiting for %d packets", 324 head->seq - gre.seq_recv - 1); 325 } 326 if (pptpctrl_debug) 327 syslog(LOG_DEBUG, "GRE: accepting #%d from queue", 328 head->seq); 329 gre.seq_recv = head->seq; 330 status = callback(cl, head->packet, head->packlen); 331 pqueue_del(head); 332 if (status < 0) return status; 333 head = pqueue_head(); 334 } 335 return 0; 336} 337 338 339int decaps_gre(int fd, int (*cb) (int cl, void *pack, unsigned len), int cl) 340{ 341 static unsigned char buffer[PACKET_MAX + 64 /*ip header */ ]; 342 struct pptp_gre_header *header; 343 int status, ip_len = 0; 344 345 dequeue_gre(cb, cl); 346 if ((status = read(fd, buffer, sizeof(buffer))) <= 0) { 347 syslog(LOG_ERR, "GRE: read(fd=%d,buffer=%lx,len=%d) from network failed: status = %d error = %s", 348 fd, (unsigned long) buffer, sizeof(buffer), status, status ? strerror(errno) : "No error"); 349 stats.rx_errors++; 350 return -1; 351 } 352 /* strip off IP header, if present */ 353 if ((buffer[0] & 0xF0) == 0x40) 354 ip_len = (buffer[0] & 0xF) * 4; 355 header = (struct pptp_gre_header *) (buffer + ip_len); 356 357 /* verify packet (else discard) */ 358 if (((ntoh8(header->ver) & 0x7F) != PPTP_GRE_VER) || /* version should be 1 */ 359 (ntoh16(header->protocol) != PPTP_GRE_PROTO) || /* GRE protocol for PPTP */ 360 PPTP_GRE_IS_C(ntoh8(header->flags)) || /* flag C should be clear */ 361 PPTP_GRE_IS_R(ntoh8(header->flags)) || /* flag R should be clear */ 362 (!PPTP_GRE_IS_K(ntoh8(header->flags))) || /* flag K should be set */ 363 ((ntoh8(header->flags) & 0xF) != 0)) { /* routing and recursion ctrl = 0 */ 364 /* if invalid, discard this packet */ 365 syslog(LOG_ERR, "GRE: Discarding packet by header check"); 366 stats.rx_invalid++; 367 return 0; 368 } 369 if (header->call_id != GET_VALUE(PAC, gre.call_id_pair)) { 370 /* 371 * Discard silently to allow more than one GRE tunnel from 372 * the same IP address in case clients are behind the 373 * firewall. 374 * 375 * syslog(LOG_ERR, "GRE: Discarding for incorrect call"); 376 */ 377 return 0; 378 } 379 if (PPTP_GRE_IS_A(ntoh8(header->ver))) { /* acknowledgement present */ 380 u_int32_t ack = (PPTP_GRE_IS_S(ntoh8(header->flags))) ? 381 ntoh32(header->ack) : ntoh32(header->seq); 382 /* ack in different place if S=0 */ 383 384 if (seq_greater(ack, gre.ack_recv)) 385 gre.ack_recv = ack; 386 387 /* also handle sequence number wrap-around */ 388 if (WRAPPED(ack,gre.ack_recv)) gre.ack_recv = ack; 389 if (gre.ack_recv == stats.pt.seq) { 390 int rtt = time_now_usecs() - stats.pt.time; 391 stats.rtt = (stats.rtt + rtt) / 2; 392 } 393 } 394 if (PPTP_GRE_IS_S(ntoh8(header->flags))) { /* payload present */ 395 unsigned headersize = sizeof(*header); 396 unsigned payload_len = ntoh16(header->payload_len); 397 u_int32_t seq = ntoh32(header->seq); 398 399 if (!PPTP_GRE_IS_A(ntoh8(header->ver))) 400 headersize -= sizeof(header->ack); 401 /* check for incomplete packet (length smaller than expected) */ 402 if (status - headersize < payload_len) { 403 stats.rx_truncated++; 404 return 0; 405 } 406 /* check for out-of-order sequence number */ 407 if (seq == gre.seq_recv + 1) { 408 if (pptpctrl_debug) 409 syslog(LOG_DEBUG, "GRE: accepting packet #%d", 410 seq); 411 stats.rx_accepted++; 412 gre.seq_recv = seq; 413 return cb(cl, buffer + ip_len + headersize, payload_len); 414 } else if (seq == gre.seq_recv) { 415 if (pptpctrl_debug) 416 syslog(LOG_DEBUG, 417 "GRE: discarding duplicate or old packet #%d (expecting #%d)", 418 seq, gre.seq_recv + 1); 419 return 0; /* discard duplicate packets */ 420 } else { 421 stats.rx_buffered++; 422 if (pptpctrl_debug) 423 syslog(LOG_DEBUG, 424 "GRE: buffering packet #%d (expecting #%d, lost or reordered)", 425 seq, gre.seq_recv + 1); 426 pqueue_add(seq, buffer + ip_len + headersize, payload_len); 427 return 0; /* discard out-of-order packets */ 428 } 429 } 430 return 0; /* ack, but no payload */ 431} 432 433 434int encaps_gre(int fd, void *pack, unsigned len) 435{ 436 static union { 437 struct pptp_gre_header header; 438 unsigned char buffer[PACKET_MAX + sizeof(struct pptp_gre_header)]; 439 } u; 440 unsigned header_len; 441#ifdef HAVE_WRITEV 442 struct iovec iovec[2]; 443#endif 444 445 if(fd == -1) 446 /* peek mode */ 447 return (gre.ack_sent == gre.seq_recv) ? 0 : -1; 448 449 /* package this up in a GRE shell. */ 450 u.header.flags = hton8(PPTP_GRE_FLAG_K); 451 u.header.ver = hton8(PPTP_GRE_VER); 452 u.header.protocol = hton16(PPTP_GRE_PROTO); 453 u.header.payload_len = hton16(len); 454 u.header.call_id = GET_VALUE(PNS, gre.call_id_pair); 455 456 /* special case ACK with no payload */ 457 if (pack == NULL) { 458 if (gre.ack_sent != gre.seq_recv) { 459 u.header.ver |= hton8(PPTP_GRE_FLAG_A); 460 u.header.payload_len = hton16(0); 461 u.header.seq = hton32(gre.seq_recv); /* ack is in odd place because S=0 */ 462 gre.ack_sent = gre.seq_recv; 463 /* don't sent ACK field, ACK is in SYN field */ 464 return write(fd, u.buffer, sizeof(u.header) - sizeof(u.header.ack)); 465 } else 466 return 0; /* we don't need to send ACK */ 467 } 468 /* send packet with payload */ 469 u.header.flags |= hton8(PPTP_GRE_FLAG_S); 470 u.header.seq = hton32(gre.seq_sent); 471 gre.seq_sent++; 472 if (gre.ack_sent != gre.seq_recv) { /* send ack with this message */ 473 u.header.ver |= hton8(PPTP_GRE_FLAG_A); 474 u.header.ack = hton32(gre.seq_recv); 475 gre.ack_sent = gre.seq_recv; 476 header_len = sizeof(u.header); 477 } else { /* don't send ack */ 478 header_len = sizeof(u.header) - sizeof(u.header.ack); 479 } 480 if (len > PACKET_MAX) { 481 syslog(LOG_ERR, "GRE: packet is too large %d", len); 482 stats.tx_oversize++; 483 return 0; /* drop this, it's too big */ 484 } 485#ifdef HAVE_WRITEV 486 /* write header and buffer without copying. */ 487 iovec[0].iov_base = u.buffer; 488 iovec[0].iov_len = header_len; 489 iovec[1].iov_base = pack; 490 iovec[1].iov_len = len; 491 return writev(fd, iovec, 2); 492#else 493 /* copy payload into buffer */ 494 memcpy(u.buffer + header_len, pack, len); 495 /* record and increment sequence numbers */ 496 /* write this baby out to the net */ 497 return write(fd, u.buffer, header_len + len); 498#endif 499} 500