1/* pptp_gre.c -- encapsulate PPP in PPTP-GRE. 2 * Handle the IP Protocol 47 portion of PPTP. 3 * C. Scott Ananian <cananian@alumni.princeton.edu> 4 * 5 * $Id: pptp_gre.c,v 1.39 2005/07/11 03:23:48 quozl Exp $ 6 */ 7 8#include <sys/types.h> 9#include <netinet/in.h> 10#include <arpa/inet.h> 11#include <sys/socket.h> 12#include <sys/stat.h> 13#include <sys/time.h> 14#include <unistd.h> 15#include <string.h> 16#include <errno.h> 17#include <fcntl.h> 18#include "ppp_fcs.h" 19#include "pptp_msg.h" 20#include "pptp_gre.h" 21#include "util.h" 22#include "pqueue.h" 23/* Foxconn added start, Winster Chan, 06/26/2006 */ 24#include "pptpox.h" 25#include <stdio.h> 26#include <linux/types.h> 27#include <linux/ppp_defs.h> 28#include <linux/if_ppp.h> 29#include <fcntl.h> 30#include <sys/file.h> 31#include <sys/ioctl.h> 32/* Foxconn added end, Winster Chan, 06/26/2006 */ 33 34#define PACKET_MAX 8196 35/* test for a 32 bit counter overflow */ 36#define WRAPPED( curseq, lastseq) \ 37 ((((curseq) & 0xffffff00) == 0) && \ 38 (((lastseq) & 0xffffff00 ) == 0xffffff00)) 39 40static u_int32_t ack_sent, ack_recv; 41static u_int32_t seq_sent, seq_recv; 42static u_int16_t pptp_gre_call_id, pptp_gre_peer_call_id; 43gre_stats_t stats; 44 45/* Foxconn added start, Winster Chan, 06/26/2006 */ 46static int pox_fd = -1; 47/* Foxconn added start, Winster Chan, 06/26/2006 */ 48 49typedef int (*callback_t)(int cl, void *pack, unsigned int len); 50 51/* decaps_hdlc gets all the packets possible with ONE blocking read */ 52/* returns <0 if read() call fails */ 53int decaps_hdlc(int fd, callback_t callback, int cl); 54int encaps_hdlc(int fd, void *pack, unsigned int len); 55int decaps_gre (int fd, callback_t callback, int cl); 56int encaps_gre (int fd, void *pack, unsigned int len); 57int dequeue_gre(callback_t callback, int cl); 58 59#ifdef CODE_IN_USE //Winster Chan added 05/16/2006 60#include <stdio.h> 61void print_packet(int fd, void *pack, unsigned int len) 62{ 63 unsigned char *b = (unsigned char *)pack; 64 unsigned int i,j; 65 FILE *out = fdopen(fd, "w"); 66 fprintf(out,"-- begin packet (%u) --\n", len); 67 for (i = 0; i < len; i += 16) { 68 for (j = 0; j < 8; j++) 69 if (i + 2 * j + 1 < len) 70 fprintf(out, "%02x%02x ", 71 (unsigned int) b[i + 2 * j], 72 (unsigned int) b[i + 2 * j + 1]); 73 else if (i + 2 * j < len) 74 fprintf(out, "%02x ", (unsigned int) b[i + 2 * j]); 75 fprintf(out, "\n"); 76 } 77 fprintf(out, "-- end packet --\n"); 78 fflush(out); 79} 80#endif //CODE_IN_USE Winster Chan added 05/16/2006 81 82/*** time_now_usecs ***********************************************************/ 83uint64_t time_now_usecs() 84{ 85 struct timeval tv; 86 gettimeofday(&tv, NULL); 87 return (tv.tv_sec * 1000000) + tv.tv_usec; 88} 89 90/* Foxconn added start, Winster Chan, 06/26/2006 */ 91/************************************************************************** 92** Function: addr_itox() 93** Description: Convert the <int> address value getting from file to 94** <unsigned char> address type. 95** Parameters: (unsigned char *) daddr -- destination address value 96** (int *) saddr -- source address value 97** (int) convlen -- convert length 98** Return: none. 99**************************************************************************/ 100static void addr_itox(unsigned char *daddr, int *saddr, int convlen) 101{ 102 int i; 103 104 for (i = 0; i < convlen; i++) 105 daddr[i] = (unsigned char)saddr[i]; 106} 107 108/************************************************************************** 109** Function: pptp_pppox_open() 110** Description: Open socket to kernel pppox driver, and open ppp device 111** Parameters: (int *) poxfd -- pointer of file descriptor for pppox 112** (int *) pppfd -- pointer of file descriptor for ppp device 113** Return: none. 114**************************************************************************/ 115void pptp_pppox_open(int *poxfd, int *pppfd) 116{ 117 /* Open socket to pppox kernel module */ 118 *poxfd = socket(AF_PPPOX,SOCK_STREAM,PX_PROTO_TP); 119 if (*poxfd >= 0) { 120 /* 121 * Save the file descriptor for getting the GRE sequence number 122 * from kernel side. 123 */ 124 pox_fd = *poxfd; 125 /* Open ppp device */ 126 *pppfd = open("/dev/ppp", O_RDWR); 127 } 128 else { 129 *poxfd = -1; 130 *pppfd = -1; 131 } 132} 133 134/************************************************************************** 135** Function: pptp_pppox_get_info() 136** Description: Get the essential information for connecting pptp kernel 137** module. Such as Source IP, Destination IP, Remote MAC 138** address, Device name, call_id, and peer_call_id, etc. 139** Parameters: none. 140** Return: (struct sockaddr_pptpox)sp_info -- structure of information. 141**************************************************************************/ 142struct sockaddr_pptpox pptp_pppox_get_info(void) 143{ 144 struct sockaddr_pptpox sp_info; 145 FILE *fp = NULL; 146 int nulluserip = 0; 147 unsigned char buf[128]; 148 unsigned char userIp[IPV4_LEN], servIp[IPV4_LEN], arpIp[IPV4_LEN]; 149 unsigned char userNetMask[IPV4_LEN]; /* pling added 03/22/2012 */ 150 unsigned char dhcpIp[IPV4_LEN], gateWay[IPV4_LEN], netMask[IPV4_LEN]; 151 //unsigned char addrname[12]; 152 unsigned char addrname[32]; 153 unsigned int getIp[IPV4_LEN]; 154 int call_id = 0, peer_call_id = 0; 155 unsigned char wan_ifname[IFNAMSIZ]; /* Foxconn, added by EricHuang, 03/20/2007 */ 156 unsigned char pptp_gw[IPV4_LEN]; /* for static IP case, Foxconn added by EricHuang, 04/03/2007 */ 157 158 memset(&sp_info, 0, sizeof(struct sockaddr_pptpox)); 159 160 sp_info.sa_family = AF_PPPOX; 161 sp_info.sa_protocol = PX_PROTO_TP; 162 163 memset(userIp, 0, IPV4_LEN); 164 memset(servIp, 0, IPV4_LEN); 165 memset(arpIp, 0, IPV4_LEN); 166 memset(dhcpIp, 0, IPV4_LEN); 167 memset(gateWay, 0, IPV4_LEN); 168 memset(netMask, 0, IPV4_LEN); 169 170 /* Get user IP and server IP from /tmp/ppp/pptpIp file */ 171 if ((fp = fopen("/tmp/ppp/pptpIp", "r")) != NULL) { 172 char user_nvram[] = "pptp_user_ip"; 173 char gw_nvram[] = "pptp_gateway_ip"; /* Foxconn added by EricHuang, 04/03/2007 */ 174 char user_netmask[] = "pptp_user_netmask"; /* Foxconn added by EricHuang, 04/03/2007 */ 175 176 /* Get WAN interface name */ 177 fgets(buf, sizeof(buf), fp); 178 sscanf(buf, "%s", &wan_ifname[0]); 179 memcpy(sp_info.sa_addr.pptp.dev, wan_ifname, IFNAMSIZ); 180 181 while (fgets(buf, sizeof(buf), fp)) { 182 sscanf(buf, "%s %d.%d.%d.%d", 183 &addrname[0], &getIp[0], &getIp[1], &getIp[2], &getIp[3]); 184 /* Get user IP */ 185 if (memcmp(addrname, user_nvram, sizeof(user_nvram)) == 0) { 186 /* User IP is not NULL. It's tatic IP */ 187 addr_itox(userIp, getIp, IPV4_LEN); 188 if ((userIp[0] == 0x0) && (userIp[1] == 0x0) && 189 (userIp[2] == 0x0) && (userIp[3] == 0x0)) { 190 nulluserip = 1; 191 } 192 else { 193 memcpy(&sp_info.sa_addr.pptp.srcaddr, userIp, IPV4_LEN); 194 nulluserip = 0; 195 } 196 } 197 /* Foxconn added start by EricHuang, 04/03/2007 */ 198 else if (memcmp(addrname, gw_nvram, sizeof(gw_nvram)) == 0) { 199 addr_itox(pptp_gw, getIp, IPV4_LEN); 200 //memcpy(&sp_info.sa_addr.pptp.srcaddr, pptp_gw, IPV4_LEN); 201 } 202 /* Foxconn added end by EricHuang, 04/03/2007 */ 203 /* Foxconn added start pling 03/22/2012 */ 204 /* Read the user's static netmask settings */ 205 else if (memcmp(addrname, user_netmask, sizeof(user_netmask)) == 0) { 206 addr_itox(userNetMask, getIp, IPV4_LEN); 207 } 208 /* Foxconn added end pling 03/22/2012 */ 209 210 } /* End while() */ 211 fclose(fp); 212 //unlink("/tmp/ppp/pptpIp"); 213 } /* End if(fp) */ 214 215 /* Foxconn added start by EricHuang, 03/20/2007 */ 216 /* get pptp server ip after gethostbyname, it called in pptp.c */ 217 if ((fp = fopen("/tmp/ppp/pptpSrvIp", "r")) != NULL) { 218 memcpy(sp_info.sa_addr.pptp.dev, wan_ifname, IFNAMSIZ); 219 220 while (fgets(buf, sizeof(buf), fp)) { 221 sscanf(buf, "%d.%d.%d.%d", 222 &getIp[0], &getIp[1], &getIp[2], &getIp[3]); 223 224 addr_itox(servIp, getIp, IPV4_LEN); 225 memcpy(&sp_info.sa_addr.pptp.dstaddr, servIp, IPV4_LEN); 226 } 227 fclose(fp); 228 } 229 /* Foxconn added end by EricHuang, 03/20/2007 */ 230 231 232 if (nulluserip) { 233 /* NULL user IP, get user IP by dhcp client */ 234 char dhcp_ip[] = "user_ip_addr"; 235 char gate_way[] = "gateway_addr"; 236 char net_mask[] = "netmask_addr"; 237 238 if ((fp = fopen("/tmp/ppp/dhcpIp", "r")) != NULL) { 239 /* Get IP by dhcp client */ 240 while (fgets(buf, sizeof(buf), fp)) { 241 sscanf(buf, "%s %d.%d.%d.%d", &addrname[0], 242 &getIp[0], &getIp[1], &getIp[2], &getIp[3]); 243 if (memcmp(addrname, dhcp_ip, sizeof(dhcp_ip)) == 0) { 244 /* Save dhcp user IP address */ 245 addr_itox(dhcpIp, getIp, IPV4_LEN); 246 memcpy(&sp_info.sa_addr.pptp.srcaddr, dhcpIp, IPV4_LEN); 247 } 248 else if (memcmp(addrname, gate_way, sizeof(gate_way)) == 0) { 249 /* Save gateway address */ 250 addr_itox(gateWay, getIp, IPV4_LEN); 251 } 252 else if (memcmp(addrname, net_mask, sizeof(net_mask)) == 0) { 253 /* Save net mask address */ 254 addr_itox(netMask, getIp, IPV4_LEN); 255 } 256 } /* End while() */ 257 fclose(fp); 258 //unlink("/tmp/ppp/dhcpIp"); 259 } /* End if(fp) */ 260 } 261 262 /* Get MAC address and interface name from /proc/net/arp file */ 263 if ((fp = fopen("/proc/net/arp", "r")) != NULL) { 264 int nMac[ETH_ALEN]; 265 unsigned char cMac[ETH_ALEN], ifname[IFNAMSIZ]; 266 unsigned char tmpChr[16]; 267 unsigned char cmpIp[IPV4_LEN]; 268 269 memset(nMac, 0, ETH_ALEN); 270 memset(cMac, 0, ETH_ALEN); 271 272 if (nulluserip) { 273 /* Case: get IP by dhcp client */ 274 if (((dhcpIp[0] & netMask[0]) == (servIp[0] & netMask[0])) && 275 ((dhcpIp[1] & netMask[1]) == (servIp[1] & netMask[1])) && 276 ((dhcpIp[2] & netMask[2]) == (servIp[2] & netMask[2])) && 277 ((dhcpIp[3] & netMask[3]) == (servIp[3] & netMask[3]))) { 278 /* 279 * dhcp IP & server IP are in same subnet, 280 * match the arp table with server IP. 281 */ 282 memcpy(cmpIp, servIp, IPV4_LEN); 283 } 284 else { 285 /* 286 * dhcp IP & server IP are in different subnet, 287 * match the arp table with gateway IP. 288 */ 289 memcpy(cmpIp, gateWay, IPV4_LEN); 290 } 291 } 292 else { 293 /* Case: static IP */ 294 /* TODO: not consider gateway case currently! */ 295 296 /* foxconn modified start by EricHuang, 04/03/2007 */ 297 /* pptp_gw will be solved in /rc/pptp.c, and if user don't enter the 298 gateway address in the gui, we use pptp server ip as gateway ip. 299 */ 300 //memcpy(cmpIp, servIp, IPV4_LEN); 301 //memcpy(cmpIp, pptp_gw, IPV4_LEN); /* pling removed 03/22/2012 */ 302 /* foxconn modified end by EricHuang, 04/03/2007 */ 303 304 /* Foxconn added start pling 03/22/2012 */ 305 /* Set the gateway properly according to subnet */ 306 if (((userIp[0] & userNetMask[0]) == (servIp[0] & userNetMask[0])) && 307 ((userIp[1] & userNetMask[1]) == (servIp[1] & userNetMask[1])) && 308 ((userIp[2] & userNetMask[2]) == (servIp[2] & userNetMask[2])) && 309 ((userIp[3] & userNetMask[3]) == (servIp[3] & userNetMask[3]))) { 310 /* 311 * dhcp IP & server IP are in same subnet, 312 * match the arp table with server IP. 313 */ 314 memcpy(cmpIp, servIp, IPV4_LEN); 315 } 316 else { 317 /* 318 * dhcp IP & server IP are in different subnet, 319 * match the arp table with gateway IP. 320 */ 321 memcpy(cmpIp, pptp_gw, IPV4_LEN); 322 } 323 /* Foxconn added end pling 03/22/2012 */ 324 } 325 326 /* Skip the title name line */ 327 fgets(buf, sizeof(buf), fp); 328 while (fgets(buf, sizeof(buf), fp)) { 329 sscanf(buf, "%d.%d.%d.%d %s %s %02x:%02x:%02x:%02x:%02x:%02x %s %s", 330 &getIp[0], &getIp[1], &getIp[2], &getIp[3], 331 &tmpChr[0], &tmpChr[0], 332 &nMac[0], &nMac[1], &nMac[2], &nMac[3], &nMac[4], &nMac[5], 333 &tmpChr[0], &ifname[0]); 334 addr_itox(arpIp, getIp, IPV4_LEN); 335 /* Destination entry was found in the arp table */ 336 if (memcmp(cmpIp, arpIp, IPV4_LEN) == 0) { 337 addr_itox(sp_info.sa_addr.pptp.remote, nMac, ETH_ALEN); 338 break; /* Break off the while loop */ 339 } 340 } /* End while() */ 341 fclose(fp); 342 } /* End if(fp) */ 343 344 /* Get PPTP call_id & peer_call_id */ 345 if ((fp = fopen("/tmp/ppp/callIds", "r")) != NULL) { 346 while (fgets(buf, sizeof(buf), fp)) { 347 sscanf(buf, "%d %d", &call_id, &peer_call_id); 348 349 sp_info.sa_addr.pptp.cid = call_id; 350 sp_info.sa_addr.pptp.pcid = peer_call_id; 351 } 352 fclose(fp); 353 } /* End if(fp) */ 354 355 return (struct sockaddr_pptpox)sp_info; 356} 357 358/************************************************************************** 359** Function: pptp_pppox_connect() 360** Description: Actually connect to pppox kernel module with the structure 361** got by pptp_pppox_get_info(). 362** Parameters: (int *) poxfd -- pointer of file descriptor for pppox 363** (int *) pppfd -- pointer of file descriptor for ppp device 364** (u_int16_t) call_id -- local host call id 365** (u_int16_t) peer_call_id -- peer server call id 366** Return: (int)err -- Fail = -1 367** Success = 0. 368**************************************************************************/ 369void pptp_pppox_connect(int *poxfd, int *pppfd, 370 u_int16_t call_id, u_int16_t peer_call_id) 371{ 372 struct sockaddr_pptpox lsp; 373 int err = -1; 374 int chindex; 375 int flags; 376 377 memset(&lsp, 0, sizeof(struct sockaddr_pptpox)); 378 lsp = pptp_pppox_get_info(); 379 380 if (*poxfd >= 0) { 381 /* Connect pptp kernel connection */ 382 err = connect(*poxfd, (struct sockaddr*)&lsp, 383 sizeof(struct sockaddr_pptpox)); 384 if (err == 0) { 385 /* Get PPP channel */ 386 if (ioctl(*poxfd, PPPIOCGCHAN, &chindex) == -1) 387 warn("Couldn't get channel number"); 388 389 if (*pppfd >= 0) { 390 /* Attach to PPP channel */ 391 if ((err = ioctl(*pppfd, PPPIOCATTCHAN, &chindex)) < 0) 392 warn("Couldn't attach to channel"); 393 flags = fcntl(*pppfd, F_GETFL); 394 if (flags == -1 || fcntl(*pppfd, F_SETFL, flags | O_NONBLOCK) == -1) 395 warn("Couldn't set /dev/ppp (channel) to nonblock"); 396 } 397 else 398 warn("Couldn't reopen /dev/ppp"); 399 } 400 else 401 warn("Couldn't connect pppox, err: %d, %s", err, strerror(errno)); 402 } 403} 404 405/************************************************************************** 406** Function: pptp_pppox_release() 407** Description: Release the connection between user program and pppox kernel 408** driver with ioctl() and connect(), and clear the 409** essential information in kernel. 410** Parameters: (int *) poxfd -- pointer of file descriptor for pppox 411** (int *) pppfd -- pointer of file descriptor for ppp device 412** Return: (int)err -- Fail = -1 413** Success = 0. 414**************************************************************************/ 415void pptp_pppox_release(int *poxfd, int *pppfd) 416{ 417 struct sockaddr_pptpox lsp; 418 int err = -1; 419 420 if (*poxfd >= 0) { 421 memset(&lsp, 0, sizeof(struct sockaddr_pptpox)); 422 lsp = pptp_pppox_get_info(); 423 if (*pppfd >= 0) { 424 /* Detach from PPP */ 425 if (ioctl(*pppfd, PPPIOCDETACH) < 0) 426 warn("pptp_pppox_release ioctl(PPPIOCDETACH) failed"); 427 } 428 429 /* Release pptp kernel connection */ 430 lsp.sa_addr.pptp.srcaddr = 0; 431 err = connect(*poxfd, (struct sockaddr*)&lsp, 432 sizeof(struct sockaddr_pptpox)); 433 if (err != 0) 434 warn("Couldn't connect to pptp kernel module"); 435 } 436 else 437 warn("Couldn't connect socket to pppox"); 438} 439/* Foxconn added end, Winster Chan, 06/26/2006 */ 440 441/*** Open IP protocol socket **************************************************/ 442int pptp_gre_bind(struct in_addr inetaddr) 443{ 444 struct sockaddr_in src_addr, loc_addr; 445 extern struct in_addr localbind; 446 int s = socket(AF_INET, SOCK_RAW, PPTP_PROTO); 447 if (s < 0) { warn("socket: %s", strerror(errno)); return -1; } 448 if (localbind.s_addr != INADDR_NONE) { 449 bzero(&loc_addr, sizeof(loc_addr)); 450 loc_addr.sin_family = AF_INET; 451 loc_addr.sin_addr = localbind; 452 if (bind(s, (struct sockaddr *) &loc_addr, sizeof(loc_addr)) != 0) { 453 warn("bind: %s", strerror(errno)); close(s); return -1; 454 } 455 } 456 src_addr.sin_family = AF_INET; 457 src_addr.sin_addr = inetaddr; 458 src_addr.sin_port = 0; 459 if (connect(s, (struct sockaddr *) &src_addr, sizeof(src_addr)) < 0) { 460 warn("connect: %s", strerror(errno)); close(s); return -1; 461 } 462 return s; 463} 464 465/*** pptp_gre_copy ************************************************************/ 466void pptp_gre_copy(u_int16_t call_id, u_int16_t peer_call_id, 467 int pty_fd, int gre_fd) 468{ 469 int max_fd; 470 pptp_gre_call_id = call_id; 471 pptp_gre_peer_call_id = peer_call_id; 472 /* Pseudo-terminal already open. */ 473 ack_sent = ack_recv = seq_sent = seq_recv = 0; 474 /* weird select semantics */ 475 max_fd = gre_fd; 476 if (pty_fd > max_fd) max_fd = pty_fd; 477 /* Dispatch loop */ 478 for (;;) { /* until error happens on gre_fd or pty_fd */ 479 struct timeval tv = {0, 0}; 480 struct timeval *tvp; 481 fd_set rfds; 482 int retval; 483 pqueue_t *head; 484 int block_usecs = -1; /* wait forever */ 485 extern void connect_pppunit(void); /* foxconn wklin added, 04/08/2011 */ 486 connect_pppunit(); /* foxconn wklin added, 04/08/2011 */ 487 /* watch terminal and socket for input */ 488 FD_ZERO(&rfds); 489 FD_SET(gre_fd, &rfds); 490 FD_SET(pty_fd, &rfds); 491 /* 492 * if there are multiple pending ACKs, then do a minimal timeout; 493 * else if there is a single pending ACK then timeout after 0,5 seconds; 494 * else block until data is available. 495 */ 496 if (ack_sent != seq_recv) { 497 if (ack_sent + 1 == seq_recv) /* u_int wrap-around safe */ 498 block_usecs = 500000; 499 else 500 /* don't use zero, this will force a resceduling */ 501 /* when calling select(), giving pppd a chance to */ 502 /* run. */ 503 block_usecs = 1; 504 } 505 /* otherwise block_usecs == -1, which means wait forever */ 506 /* 507 * If there is a packet in the queue, then don't wait longer than 508 * the time remaining until it expires. 509 */ 510 head = pqueue_head(); 511 if (head != NULL) { 512 int expiry_time = pqueue_expiry_time(head); 513 if (block_usecs == -1 || expiry_time < block_usecs) 514 block_usecs = expiry_time; 515 } 516 if (block_usecs == -1) { 517 tvp = NULL; 518 } else { 519 tvp = &tv; 520 tv.tv_usec = block_usecs; 521 tv.tv_sec = tv.tv_usec / 1000000; 522 tv.tv_usec %= 1000000; 523 } 524 retval = select(max_fd + 1, &rfds, NULL, NULL, tvp); 525 if (FD_ISSET(pty_fd, &rfds)) { 526 if (decaps_hdlc(pty_fd, encaps_gre, gre_fd) < 0) 527 break; 528 } else if (retval == 0 && ack_sent != seq_recv) { 529 /* if outstanding ack */ 530 /* send ack with no payload */ 531 encaps_gre(gre_fd, NULL, 0); 532 } 533 if (FD_ISSET(gre_fd, &rfds)) { 534 if (decaps_gre (gre_fd, encaps_hdlc, pty_fd) < 0) 535 break; 536 } 537 if (dequeue_gre (encaps_hdlc, pty_fd) < 0) 538 break; 539 } 540 /* Close up when done. */ 541 close(gre_fd); 542 close(pty_fd); 543} 544 545#define HDLC_FLAG 0x7E 546#define HDLC_ESCAPE 0x7D 547#define HDLC_TRANSPARENCY 0x20 548 549/* ONE blocking read per call; dispatches all packets possible */ 550/* returns 0 on success, or <0 on read failure */ 551int decaps_hdlc(int fd, int (*cb)(int cl, void *pack, unsigned int len), int cl) 552{ 553 unsigned char buffer[PACKET_MAX]; 554 unsigned int start = 0; 555 int end; 556 int status; 557 static unsigned int len = 0, escape = 0; 558 static unsigned char copy[PACKET_MAX]; 559 static int checkedsync = 0; 560 /* start is start of packet. end is end of buffer data */ 561 /* this is the only blocking read we will allow */ 562 if ((end = read (fd, buffer, sizeof(buffer))) <= 0) { 563 int saved_errno = errno; 564 warn("short read (%d): %s", end, strerror(saved_errno)); 565 switch (saved_errno) { 566 case EMSGSIZE: { 567 int optval, optlen = sizeof(optval); 568 warn("transmitted GRE packet triggered an ICMP destination unreachable, fragmentation needed, or exceeds the MTU of the network interface"); 569#define IP_MTU 14 570 if(getsockopt(fd, IPPROTO_IP, IP_MTU, &optval, &optlen) < 0) 571 warn("getsockopt: %s", strerror(errno)); 572 warn("getsockopt: IP_MTU: %d\n", optval); 573 return 0; 574 } 575 case EIO: 576 warn("pppd may have shutdown, see pppd log"); 577 break; 578 } 579 return -1; 580 } 581 /* warn if the sync options of ppp and pptp don't match */ 582 if( !checkedsync) { 583 checkedsync = 1; 584 if( buffer[0] == HDLC_FLAG){ 585 if( syncppp ) 586 warn( "pptp --sync option is active, " 587 "yet the ppp mode is asynchronous!\n"); 588 } 589 else if( !syncppp ) 590 warn( "The ppp mode is synchronous, " 591 "yet no pptp --sync option is specified!\n"); 592 } 593 /* in synchronous mode there are no hdlc control characters nor checksum 594 * bytes. Find end of packet with the length information in the PPP packet 595 */ 596 if ( syncppp ){ 597 while ( start + 8 < end) { 598 len = ntoh16(*(short int *)(buffer + start + 6)) + 4; 599 /* note: the buffer may contain an incomplete packet at the end 600 * this packet will be read again at the next read() */ 601 if ( start + len <= end) 602 if ((status = cb (cl, buffer + start, len)) < 0) 603 return status; /* error-check */ 604 start += len; 605 } 606 return 0; 607 } 608 /* asynchronous mode */ 609 while (start < end) { 610 /* Copy to 'copy' and un-escape as we go. */ 611 while (buffer[start] != HDLC_FLAG) { 612 if ((escape == 0) && buffer[start] == HDLC_ESCAPE) { 613 escape = HDLC_TRANSPARENCY; 614 } else { 615 if (len < PACKET_MAX) 616 copy [len++] = buffer[start] ^ escape; 617 escape = 0; 618 } 619 start++; 620 if (start >= end) 621 return 0; /* No more data, but the frame is not complete yet. */ 622 } 623 /* found flag. skip past it */ 624 start++; 625 /* check for over-short packets and silently discard, as per RFC1662 */ 626 if ((len < 4) || (escape != 0)) { 627 len = 0; escape = 0; 628 continue; 629 } 630 /* check, then remove the 16-bit FCS checksum field */ 631 if (pppfcs16 (PPPINITFCS16, copy, len) != PPPGOODFCS16) 632 warn("Bad Frame Check Sequence during PPP to GRE decapsulation"); 633 len -= sizeof(u_int16_t); 634 /* so now we have a packet of length 'len' in 'copy' */ 635 if ((status = cb (cl, copy, len)) < 0) 636 return status; /* error-check */ 637 /* Great! Let's do more! */ 638 len = 0; escape = 0; 639 } 640 return 0; 641 /* No more data to process. */ 642} 643 644/*** Make stripped packet into HDLC packet ************************************/ 645int encaps_hdlc(int fd, void *pack, unsigned int len) 646{ 647 unsigned char *source = (unsigned char *)pack; 648 unsigned char dest[2 * PACKET_MAX + 2]; /* largest expansion possible */ 649 unsigned int pos = 0, i; 650 u_int16_t fcs; 651 /* in synchronous mode there is little to do */ 652 if ( syncppp ) 653 return write(fd, source, len); 654 /* asynchronous mode */ 655 /* Compute the FCS */ 656 fcs = pppfcs16(PPPINITFCS16, source, len) ^ 0xFFFF; 657 /* start character */ 658 dest[pos++] = HDLC_FLAG; 659 /* escape the payload */ 660 for (i = 0; i < len + 2; i++) { 661 /* wacked out assignment to add FCS to end of source buffer */ 662 unsigned char c = 663 (i < len)?source[i]:(i == len)?(fcs & 0xFF):((fcs >> 8) & 0xFF); 664 if (pos >= sizeof(dest)) break; /* truncate on overflow */ 665 if ( (c < 0x20) || (c == HDLC_FLAG) || (c == HDLC_ESCAPE) ) { 666 dest[pos++] = HDLC_ESCAPE; 667 if (pos < sizeof(dest)) 668 dest[pos++] = c ^ 0x20; 669 } else 670 dest[pos++] = c; 671 } 672 /* tack on the end-flag */ 673 if (pos < sizeof(dest)) 674 dest[pos++] = HDLC_FLAG; 675 /* now write this packet */ 676 return write(fd, dest, pos); 677} 678 679/*** decaps_gre ***************************************************************/ 680int decaps_gre (int fd, callback_t callback, int cl) 681{ 682 unsigned char buffer[PACKET_MAX + 64 /*ip header*/]; 683 struct pptp_gre_header *header; 684 int status, ip_len = 0; 685 static int first = 1; 686 unsigned int headersize; 687 unsigned int payload_len; 688 u_int32_t seq; 689 690 if ((status = read (fd, buffer, sizeof(buffer))) <= 0) { 691 warn("short read (%d): %s", status, strerror(errno)); 692 stats.rx_errors++; 693 return -1; 694 } 695 /* strip off IP header, if present */ 696 if ((buffer[0] & 0xF0) == 0x40) 697 ip_len = (buffer[0] & 0xF) * 4; 698 header = (struct pptp_gre_header *)(buffer + ip_len); 699 /* verify packet (else discard) */ 700 if ( /* version should be 1 */ 701 ((ntoh8(header->ver) & 0x7F) != PPTP_GRE_VER) || 702 /* PPTP-GRE protocol for PPTP */ 703 (ntoh16(header->protocol) != PPTP_GRE_PROTO)|| 704 /* flag C should be clear */ 705 PPTP_GRE_IS_C(ntoh8(header->flags)) || 706 /* flag R should be clear */ 707 PPTP_GRE_IS_R(ntoh8(header->flags)) || 708 /* flag K should be set */ 709 (!PPTP_GRE_IS_K(ntoh8(header->flags))) || 710 /* routing and recursion ctrl = 0 */ 711 ((ntoh8(header->flags)&0xF) != 0)) { 712 /* if invalid, discard this packet */ 713 warn("Discarding GRE: %X %X %X %X %X %X", 714 ntoh8(header->ver)&0x7F, ntoh16(header->protocol), 715 PPTP_GRE_IS_C(ntoh8(header->flags)), 716 PPTP_GRE_IS_R(ntoh8(header->flags)), 717 PPTP_GRE_IS_K(ntoh8(header->flags)), 718 ntoh8(header->flags) & 0xF); 719 stats.rx_invalid++; 720 return 0; 721 } 722 /* silently discard packets not for this call */ 723 if (ntoh16(header->call_id) != pptp_gre_call_id) return 0; 724 /* test if acknowledgement present */ 725 if (PPTP_GRE_IS_A(ntoh8(header->ver))) { 726 u_int32_t ack = (PPTP_GRE_IS_S(ntoh8(header->flags)))? 727 header->ack:header->seq; /* ack in different place if S = 0 */ 728 ack = ntoh32( ack); 729 if (ack > ack_recv) ack_recv = ack; 730 /* also handle sequence number wrap-around */ 731 if (WRAPPED(ack,ack_recv)) ack_recv = ack; 732 if (ack_recv == stats.pt.seq) { 733 int rtt = time_now_usecs() - stats.pt.time; 734 stats.rtt = (stats.rtt + rtt) / 2; 735 } 736 } 737 /* test if payload present */ 738 if (!PPTP_GRE_IS_S(ntoh8(header->flags))) 739 return 0; /* ack, but no payload */ 740 headersize = sizeof(*header); 741 payload_len = ntoh16(header->payload_len); 742 seq = ntoh32(header->seq); 743 /* no ack present? */ 744 if (!PPTP_GRE_IS_A(ntoh8(header->ver))) headersize -= sizeof(header->ack); 745 /* check for incomplete packet (length smaller than expected) */ 746 if (status - headersize < payload_len) { 747 warn("discarding truncated packet (expected %d, got %d bytes)", 748 payload_len, status - headersize); 749 stats.rx_truncated++; 750 return 0; 751 } 752 /* wklin modified start, 01/25/2007 */ 753 /* The seq# is maintained in the kernel, cannot use the seq# to determine if 754 * the packet can be accepted or not. Just forward all the ppp control 755 * packets to pppd, those packets should be justified there. 756 */ 757 stats.rx_accepted++; 758 first = 0; 759 seq_recv = seq; 760 return callback(cl, buffer + ip_len + headersize, payload_len); 761#if 0 762 /* check for expected sequence number */ 763 if ( first || (seq == seq_recv + 1)) { /* wrap-around safe */ 764 if ( log_level >= 2 ) 765 log("accepting packet %d", seq); 766 stats.rx_accepted++; 767 first = 0; 768 seq_recv = seq; 769 return callback(cl, buffer + ip_len + headersize, payload_len); 770 /* out of order, check if the number is too low and discard the packet. 771 * (handle sequence number wrap-around, and try to do it right) */ 772 } else if ( seq < seq_recv + 1 || WRAPPED(seq_recv, seq) ) { 773 if ( log_level >= 1 ) 774 log("discarding duplicate or old packet %d (expecting %d)", 775 seq, seq_recv + 1); 776 stats.rx_underwin++; 777 /* sequence number too high, is it reasonably close? */ 778 } else if ( seq < seq_recv + MISSING_WINDOW || 779 WRAPPED(seq, seq_recv + MISSING_WINDOW) ) { 780 stats.rx_buffered++; 781 if ( log_level >= 1 ) 782 log("%s packet %d (expecting %d, lost or reordered)", 783 disable_buffer ? "accepting" : "buffering", 784 seq, seq_recv+1); 785 if ( disable_buffer ) { 786 seq_recv = seq; 787 stats.rx_lost += seq - seq_recv - 1; 788 return callback(cl, buffer + ip_len + headersize, payload_len); 789 } else { 790 pqueue_add(seq, buffer + ip_len + headersize, payload_len); 791 } 792 /* no, packet must be discarded */ 793 } else { 794 if ( log_level >= 1 ) 795 warn("discarding bogus packet %d (expecting %d)", 796 seq, seq_recv + 1); 797 stats.rx_overwin++; 798 } 799#endif /* wklin modified end, 01/25/2007 */ 800 return 0; 801} 802 803/*** dequeue_gre **************************************************************/ 804int dequeue_gre (callback_t callback, int cl) 805{ 806 pqueue_t *head; 807 int status; 808 /* process packets in the queue that either are expected or have 809 * timed out. */ 810 head = pqueue_head(); 811 while ( head != NULL && 812 ( (head->seq == seq_recv + 1) || /* wrap-around safe */ 813 (pqueue_expiry_time(head) <= 0) 814 ) 815 ) { 816 /* if it is timed out... */ 817 if (head->seq != seq_recv + 1 ) { /* wrap-around safe */ 818 stats.rx_lost += head->seq - seq_recv - 1; 819 if (log_level >= 2) 820 log("timeout waiting for %d packets", head->seq - seq_recv - 1); 821 } 822 if (log_level >= 2) 823 log("accepting %d from queue", head->seq); 824 seq_recv = head->seq; 825 status = callback(cl, head->packet, head->packlen); 826 pqueue_del(head); 827 if (status < 0) 828 return status; 829 head = pqueue_head(); 830 } 831 return 0; 832} 833 834/*** encaps_gre ***************************************************************/ 835int encaps_gre (int fd, void *pack, unsigned int len) 836{ 837 union { 838 struct pptp_gre_header header; 839 unsigned char buffer[PACKET_MAX + sizeof(struct pptp_gre_header)]; 840 } u; 841 //static u_int32_t seq = 1; /* first sequence number sent must be 1 */ 842 unsigned int header_len; 843 int rc; 844 /* Foxconn added start, Winster Chan, 06/26/2006 */ 845 static u_int32_t kerseq; /* Sequence number got from kernel by ioctl() */ 846 /* Foxconn added end, Winster Chan, 06/26/2006 */ 847 848 /* package this up in a GRE shell. */ 849 u.header.flags = hton8 (PPTP_GRE_FLAG_K); 850 u.header.ver = hton8 (PPTP_GRE_VER); 851 u.header.protocol = hton16(PPTP_GRE_PROTO); 852 u.header.payload_len = hton16(len); 853 u.header.call_id = hton16(pptp_gre_peer_call_id); 854 /* special case ACK with no payload */ 855 if (pack == NULL) { 856 if (ack_sent != seq_recv) { 857 u.header.ver |= hton8(PPTP_GRE_FLAG_A); 858 u.header.payload_len = hton16(0); 859 /* ack is in odd place because S == 0 */ 860 u.header.seq = hton32(seq_recv); 861 ack_sent = seq_recv; 862 rc = write(fd, &u.header, sizeof(u.header) - sizeof(u.header.seq)); 863 if (rc < 0) { 864 stats.tx_failed++; 865 } else if (rc < sizeof(u.header) - sizeof(u.header.seq)) { 866 stats.tx_short++; 867 } else { 868 stats.tx_acks++; 869 } 870 return rc; 871 } else return 0; /* we don't need to send ACK */ 872 } /* explicit brace to avoid ambiguous `else' warning */ 873 /* send packet with payload */ 874 u.header.flags |= hton8(PPTP_GRE_FLAG_S); 875 /* Foxconn modified start, Winster Chan, 06/26/2006 */ 876 //u.header.seq = hton32(seq); 877 if (pox_fd >= 0) { 878 if (ioctl(pox_fd, PPTPIOCGGRESEQ, &kerseq) == -1) { 879 warn("Couldn't get GRE sequence number"); 880 } 881 } 882 else 883 warn("Socket not opened"); 884 u.header.seq = hton32(kerseq); 885 /* Foxconn modified end, Winster Chan, 06/26/2006 */ 886 if (ack_sent != seq_recv) { /* send ack with this message */ 887 u.header.ver |= hton8(PPTP_GRE_FLAG_A); 888 u.header.ack = hton32(seq_recv); 889 ack_sent = seq_recv; 890 header_len = sizeof(u.header); 891 } else { /* don't send ack */ 892 header_len = sizeof(u.header) - sizeof(u.header.ack); 893 } 894 if (header_len + len >= sizeof(u.buffer)) { 895 stats.tx_oversize++; 896 return 0; /* drop this, it's too big */ 897 } 898 /* copy payload into buffer */ 899 memcpy(u.buffer + header_len, pack, len); 900 /* record and increment sequence numbers */ 901 /* Foxconn modified start, Winster Chan, 06/26/2006 */ 902 //seq_sent = seq; seq++; 903 /* 904 * Note: the kerseq(kernel sequence number) is maintained by 905 * pptp kernel driver 906 */ 907 seq_sent = kerseq; 908 /* Foxconn modified end, Winster Chan, 06/26/2006 */ 909 /* write this baby out to the net */ 910 /* print_packet(2, u.buffer, header_len + len); */ 911 rc = write(fd, u.buffer, header_len + len); 912 if (rc < 0) { 913 stats.tx_failed++; 914 } else if (rc < header_len + len) { 915 stats.tx_short++; 916 } else { 917 stats.tx_sent++; 918 stats.pt.seq = seq_sent; 919 stats.pt.time = time_now_usecs(); 920 } 921 return rc; 922} 923