1 /* pppoe, a PPP-over-Ethernet redirector 2 * Copyright (C) 1999 Luke Stras <stras@ecf.toronto.edu> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 * 18 * Revision History 19 * 1999/09/22 stras Initial version 20 * 1999/09/24 stras Changed header files for greater portability 21 * 1999/10/02 stras Added more logging, bug fixes 22 * 1999/10/02 mr Port to bpf/OpenBSD; starvation fixed; efficiency fixes 23 * 1999/10/18 stras added BUGGY_AC code, partial forwarding 24 */ 25 26#include <sys/types.h> 27/* foxconn wklin added start, 07/26/2007 */ 28#include <sys/stat.h> 29/* foxconn wklin added end, 07/26/2007 */ 30#include <sys/socket.h> 31#include <netinet/in.h> 32#include <sys/time.h> /* wklin added, 01/10/2007 */ 33/* Foxconn modified start Winster Chan 11/25/2005 */ 34/* #include <net/if.h> */ 35#include "pppoe.h" 36/* Foxconn modified end Winster Chan 11/25/2005 */ 37#include <sys/sysinfo.h> /*added by EricHuang, 01/11/2007*/ 38 39#ifdef __linux__ 40#include <net/if_arp.h> 41#endif /* __linux__ */ 42#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ < 6 43#include <linux/if_ether> 44#else 45#include <netinet/if_ether.h> 46#endif 47 48#include <assert.h> 49#ifdef __linux__ 50#include <getopt.h> 51#endif 52#include <signal.h> 53#include <stdio.h> 54#include <stdlib.h> 55#include <string.h> 56#include <unistd.h> 57 58/* #include <sys/time.h> */ 59#include <time.h> 60#include <sys/ioctl.h> 61#include <sys/wait.h> 62 63 64#ifdef USE_BPF 65#ifndef ETH_ALEN 66#define ETH_ALEN 6 67#endif /* ETH_ALEN */ 68/* set this to desired size - you may not get this */ 69int bpf_buf_size = 65536; 70#include <net/bpf.h> 71#include <fcntl.h> 72#include <nlist.h> 73#include <kvm.h> 74unsigned char local_ether[ETH_ALEN]; /* need to this filter packets */ 75#endif /* USE_BPF */ 76 77#include <errno.h> 78#ifdef __linux__ 79extern int errno; 80#endif 81 82/* used as the size for a packet buffer */ 83/* should be > 2 * size of max packet size */ 84#define PACKETBUF (4096 + 30) 85/* Foxconn added start Winster Chan 11/25/2005 */ 86#define TAGBUF 128 87/* Foxconn added end Winster Chan 11/25/2005 */ 88 89/* Foxconn added start, Winster Chan, 06/26/2006 */ 90static int poxfd = -1; 91static int pppfd = -1; 92unsigned short sessId = 0; 93char dstMac[ETH_ALEN]; 94/* Foxconn added start, Winster Chan, 06/26/2006 */ 95 96char *service_name = NULL; /* foxconn wklin added, 03/27/2007 */ 97 98#define VERSION_MAJOR 0 99#define VERSION_MINOR 3 100 101/* references: RFC 2516 */ 102/* ETHER_TYPE fields for PPPoE */ 103 104#define ETH_P_PPPOE_DISC 0x8863 /* discovery stage */ 105#define ETH_P_PPPOE_SESS 0x8864 /* session stage */ 106 107/* ethernet broadcast address */ 108#define MAC_BCAST_ADDR "\xff\xff\xff\xff\xff\xff" 109 110/* PPPoE packet; includes Ethernet headers and such */ 111struct pppoe_packet { 112#ifdef __linux__ 113 struct ethhdr ethhdr; /* ethernet header */ 114#else 115 struct ether_header ethhdr; /* ethernet header */ 116#endif 117 unsigned int ver:4; /* pppoe version */ 118 unsigned int type:4; /* pppoe type */ 119 unsigned int code:8; /* pppoe code CODE_* */ 120 unsigned int session:16; /* session id */ 121 unsigned short length; /* payload length */ 122 /* payload follows */ 123}; 124 125/* maximum payload length */ 126#define MAX_PAYLOAD (1484 - sizeof(struct pppoe_packet)) 127 128/* PPPoE codes */ 129#define CODE_SESS 0x00 /* PPPoE session */ 130#define CODE_PADI 0x09 /* PPPoE Active Discovery Initiation */ 131#define CODE_PADO 0x07 /* PPPoE Active Discovery Offer */ 132#define CODE_PADR 0x19 /* PPPoE Active Discovery Request */ 133#define CODE_PADS 0x65 /* PPPoE Active Discovery Session-confirmation */ 134#define CODE_PADT 0xa7 /* PPPoE Active Discovery Terminate */ 135 136/* also need */ 137#define STATE_RUN (-1) 138 139/* PPPoE tag; the payload is a sequence of these */ 140struct pppoe_tag { 141 unsigned short type; /* tag type TAG_* */ 142 unsigned short length; /* tag length */ 143 /* payload follows */ 144} __attribute__ ((packed)); /*added by EricHuang, 07/23/2007*/ 145 146/* Foxconn added start Winster Chan 11/25/2005 */ 147#define TAG_STRUCT_SIZE sizeof(struct pppoe_tag) 148#define PPP_PPPOE_SESSION "/tmp/ppp/pppoe_session" 149/*#define PPP_PPPOE_IFNAME "/tmp/ppp/pppoe_ifname"*/ 150/* Foxconn added end Winster Chan 11/25/2005 */ 151 152/* PPPoE tag types */ 153#define TAG_END_OF_LIST 0x0000 154#define TAG_SERVICE_NAME 0x0101 155#define TAG_AC_NAME 0x0102 156#define TAG_HOST_UNIQ 0x0103 157#define TAG_AC_COOKIE 0x0104 158#define TAG_VENDOR_SPECIFIC 0x0105 159#define TAG_RELAY_SESSION_ID 0x0110 160#define TAG_SERVICE_NAME_ERROR 0x0201 161#define TAG_AC_SYSTEM_ERROR 0x0202 162#define TAG_GENERIC_ERROR 0x0203 163 164/* globals */ 165int opt_verbose = 0; /* logging */ 166int opt_fwd = 0; /* forward invalid packets */ 167int opt_fwd_search = 0; /* search for next packet when forwarding */ 168FILE *log_file = NULL; 169FILE *error_file = NULL; 170 171pid_t sess_listen = 0, pppd_listen = 0; /* child processes */ 172int disc_sock = 0, sess_sock = 0; /* PPPoE sockets */ 173char src_addr[ETH_ALEN]; /* source hardware address */ 174char dst_addr[ETH_ALEN]; /* destination hardware address */ 175char *if_name = NULL; /* interface to use */ 176int session = 0; /* identifier for our session */ 177int clean_child = 0; /* flag set when SIGCHLD received */ 178/* Foxconn added start Winster Chan 11/25/2005 */ 179char pado_tags[TAGBUF]; /* TAGs of PADO */ 180int pado_tag_size = 0; 181typedef struct { 182 unsigned short usPadLen; /* Tag length in type of unsigned short */ 183 int nPadLen; /* Tag length in type of integer */ 184 char *pPadStart; /* Start point of tag payload */ 185} sPadxTag, *pPadxTag; 186/* Foxconn added end Winster Chan 11/25/2005 */ 187 188/* Winster Chan debugtest */ 189#define DEBUG_PRINT_PACKET 0 190#define DEBUG_SEND_PACKET 0 191#define BUFRING 40 192#define DEBUG_PRINT 0 193#define PPPOE_DEBUG_FILE "/tmp/ppp/pppoeDbg" 194FILE *fp0; 195pid_t main_pid, sess_pid, pppd_pid; 196 197 198typedef struct { 199 /* unsigned char *pBufAddr; */ 200 unsigned char packetBuf[PACKETBUF]; 201} sPktBuf, *pPktBuf; 202 203void 204print_hex(unsigned char *buf, int len) 205{ 206 int i; 207 208 if (opt_verbose == 0) 209 return; 210 211 for (i = 0; i < len; i++) 212 fprintf(log_file, "%02x ", (unsigned char)*(buf+i)); 213 214 fprintf(log_file, "\n"); 215} 216 217void 218print_packet(struct pppoe_packet *p) 219{ 220 int i; 221 struct pppoe_tag *t = (struct pppoe_tag*)(p + 1); 222 struct pppoe_tag tag; /* needed to avoid alignment problems */ 223 char *buf; 224 time_t tm; 225 226 if (opt_verbose == 0) 227 return; 228 229 time(&tm); 230 231 fprintf(log_file, "Ethernet header:\n"); 232 fprintf(log_file, "h_dest: "); 233#ifdef __linux__ 234 for (i = 0; i < 6; i++) 235 fprintf(log_file, "%02x:", (unsigned)p->ethhdr.h_dest[i]); 236#else 237 for (i = 0; i < 6; i++) 238 fprintf(log_file, "%02x:", (unsigned)p->ethhdr.ether_dhost[i]); 239#endif 240 fprintf(log_file, "\nh_source: "); 241#ifdef __linux__ 242 for (i = 0; i < 6; i++) 243 fprintf(log_file, "%02x:", (unsigned)p->ethhdr.h_source[i]); 244#else 245 for (i = 0; i < 6; i++) 246 fprintf(log_file, "%02x:", (unsigned)p->ethhdr.ether_shost[i]); 247#endif 248 249#ifdef __linux__ 250 fprintf(log_file, "\nh_proto: 0x%04x ", 251 (unsigned)ntohs(p->ethhdr.h_proto)); 252#else 253 fprintf(log_file, "\nh_proto: 0x%04x ", 254 (unsigned)ntohs(p->ethhdr.ether_type)); 255#endif 256 257#ifdef __linux__ 258 switch((unsigned)ntohs(p->ethhdr.h_proto)) 259#else 260 switch((unsigned)ntohs(p->ethhdr.ether_type)) 261#endif 262 { 263 case ETH_P_PPPOE_DISC: 264 fprintf(log_file, "(PPPOE Discovery)\n"); 265 break; 266 case ETH_P_PPPOE_SESS: 267 fprintf(log_file, "(PPPOE Session)\n"); 268 break; 269 default: 270 fprintf(log_file, "(Unknown)\n"); 271 } 272 273 fprintf(log_file, "PPPoE header: \nver: 0x%01x type: 0x%01x code: 0x%02x " 274 "session: 0x%04x length: 0x%04x ", (unsigned)p->ver, 275 (unsigned)p->type, (unsigned)p->code, (unsigned)p->session, 276 (unsigned)ntohs(p->length)); 277 278 switch(p->code) 279 { 280 case CODE_PADI: 281 fprintf(log_file, "(PADI)\n"); 282 break; 283 case CODE_PADO: 284 fprintf(log_file, "(PADO)\n"); 285 break; 286 case CODE_PADR: 287 fprintf(log_file, "(PADR)\n"); 288 break; 289 case CODE_PADS: 290 fprintf(log_file, "(PADS)\n"); 291 break; 292 case CODE_PADT: 293 fprintf(log_file, "(PADT)\n"); 294 break; 295 default: 296 fprintf(log_file, "(Unknown)\n"); 297 } 298 299#ifdef __linux__ 300 if (ntohs(p->ethhdr.h_proto) != ETH_P_PPPOE_DISC) 301#else 302 if (ntohs(p->ethhdr.ether_type) != ETH_P_PPPOE_DISC) 303#endif 304 { 305 print_hex((unsigned char *)(p+1), ntohs(p->length)); 306 return; 307 } 308 309 310 while (t < (struct pppoe_tag *)((char *)(p+1) + ntohs(p->length))) 311 { 312 /* no guarantee in PPPoE spec that t is aligned at all... */ 313 memcpy(&tag,t,sizeof(tag)); 314 fprintf(log_file, "PPPoE tag:\ntype: %04x length: %04x ", 315 ntohs(tag.type), ntohs(tag.length)); 316 switch(ntohs(tag.type)) 317 { 318 case TAG_END_OF_LIST: 319 fprintf(log_file, "(End of list)\n"); 320 break; 321 case TAG_SERVICE_NAME: 322 fprintf(log_file, "(Service name)\n"); 323 break; 324 case TAG_AC_NAME: 325 fprintf(log_file, "(AC Name)\n"); 326 break; 327 case TAG_HOST_UNIQ: 328 fprintf(log_file, "(Host Uniq)\n"); 329 break; 330 case TAG_AC_COOKIE: 331 fprintf(log_file, "(AC Cookie)\n"); 332 break; 333 case TAG_VENDOR_SPECIFIC: 334 fprintf(log_file, "(Vendor Specific)\n"); 335 break; 336 case TAG_RELAY_SESSION_ID: 337 fprintf(log_file, "(Relay Session ID)\n"); 338 break; 339 case TAG_SERVICE_NAME_ERROR: 340 fprintf(log_file, "(Service Name Error)\n"); 341 break; 342 case TAG_AC_SYSTEM_ERROR: 343 fprintf(log_file, "(AC System Error)\n"); 344 break; 345 case TAG_GENERIC_ERROR: 346 fprintf(log_file, "(Generic Error)\n"); 347 break; 348 default: 349 fprintf(log_file, "(Unknown)\n"); 350 } 351 if (ntohs(tag.length) > 0) 352 switch (ntohs(tag.type)) 353 { 354 case TAG_SERVICE_NAME: 355 case TAG_AC_NAME: 356 case TAG_SERVICE_NAME_ERROR: 357 case TAG_AC_SYSTEM_ERROR: 358 case TAG_GENERIC_ERROR: /* ascii data */ 359 buf = malloc(ntohs(tag.length) + 1); 360 memset(buf, 0, ntohs(tag.length)+1); 361 strncpy(buf, (char *)(t+1), ntohs(tag.length)); 362 buf[ntohs(tag.length)] = '\0'; 363 fprintf(log_file, "data (UTF-8): %s\n", buf); 364 free(buf); 365 break; 366 367 case TAG_HOST_UNIQ: 368 case TAG_AC_COOKIE: 369 case TAG_RELAY_SESSION_ID: 370 fprintf(log_file, "data (bin): "); 371 for (i = 0; i < ntohs(tag.length); i++) 372 fprintf(log_file, "%02x", (unsigned)*((char *)(t+1) + i)); 373 fprintf(log_file, "\n"); 374 break; 375 376 default: 377 fprintf(log_file, "unrecognized data\n"); 378 } 379 t = (struct pppoe_tag *)((char *)(t+1)+ntohs(tag.length)); 380 } 381} 382 383/* Foxconn added start, Winster Chan, 06/26/2006 */ 384/************************************************************************** 385** Function: addr_itox() 386** Description: Convert the <int> address value getting from file to 387** <unsigned char> address type. 388** Parameters: (unsigned char *) daddr -- destination address value 389** (int *) saddr -- source address value 390** (int) convlen -- convert length 391** Return: none. 392**************************************************************************/ 393static void addr_itox(unsigned char *daddr, int *saddr, int convlen) 394{ 395 int i; 396 397 for (i = 0; i < convlen; i++) 398 daddr[i] = (unsigned char)saddr[i]; 399} 400 401/************************************************************************** 402** Function: pptp_pppox_open() 403** Description: Open socket to kernel pppox driver, and open ppp device 404** Parameters: (int *) poxfd -- pointer of file descriptor for pppox 405** (int *) pppfd -- pointer of file descriptor for ppp device 406** Return: none. 407**************************************************************************/ 408void pptp_pppox_open(int *poxfd, int *pppfd) 409{ 410 /* Open socket to pppox kernel module */ 411 *poxfd = socket(AF_PPPOX,SOCK_STREAM,PX_PROTO_OE); 412 if (*poxfd >= 0) { 413 /* Open ppp device */ 414 *pppfd = open("/dev/ppp", O_RDWR); 415 } 416 else { 417 *poxfd = -1; 418 *pppfd = -1; 419 } 420} 421 422/************************************************************************** 423** Function: pptp_pppox_get_info() 424** Description: Get the essential information for connecting pptp kernel 425** module. Such as Source IP, Destination IP, Remote MAC 426** address, Device name, call_id, and peer_call_id, etc. 427** Parameters: none. 428** Return: (struct sockaddr_pppox)sp_info -- structure of information. 429**************************************************************************/ 430struct sockaddr_pppox pptp_pppox_get_info(void) 431{ 432 struct sockaddr_pppox sp_info; 433 /* Foxconn modified start pling 01/17/2007 */ 434 /* char devName[] = "eth0"; */ 435 char devName[16]; 436 strcpy(devName, if_name); 437 /* Foxconn modified end pling 01/17/2007 */ 438 439 memset(&sp_info, 0, sizeof(struct sockaddr_pppox)); 440 441 sp_info.sa_family = AF_PPPOX; 442 sp_info.sa_protocol = PX_PROTO_OE; 443 sp_info.sa_addr.pppoe.sid = sessId; /* PPPoE session ID */ 444 memcpy(sp_info.sa_addr.pppoe.remote, dstMac, ETH_ALEN); /* Remote MAC address */ 445 memcpy(sp_info.sa_addr.pppoe.dev, devName, strlen(devName)); /* Remote MAC address */ 446 447 return (struct sockaddr_pppox)sp_info; 448} 449 450/************************************************************************** 451** Function: pptp_pppox_connect() 452** Description: Actually connect to pppox kernel module with the structure 453** got by pptp_pppox_get_info(). 454** Parameters: (int *) poxfd -- pointer of file descriptor for pppox 455** (int *) pppfd -- pointer of file descriptor for ppp device 456** Return: (int)err -- Fail = -1 457** Success = 0. 458**************************************************************************/ 459/* foxconn wklin modified start, 07/31/2007 */ 460int pptp_pppox_connect(int *poxfd, int *pppfd) 461{ 462 struct sockaddr_pppox lsp; 463 int err = -1; 464 int chindex; 465 int flags; 466 467 memset(&lsp, 0, sizeof(struct sockaddr_pppox)); 468 lsp = pptp_pppox_get_info(); 469 470 if (*poxfd >= 0) { 471 /* Connect pptp kernel connection */ 472 err = connect(*poxfd, (struct sockaddr*)&lsp, 473 sizeof(struct sockaddr_pppox)); 474 if (err == 0) { 475 /* Get PPP channel */ 476 if (ioctl(*poxfd, PPPIOCGCHAN, &chindex) == -1) { 477 fprintf(stderr, "Couldn't get channel number"); 478 return -1; 479 } 480 481 if (*pppfd >= 0) { 482 /* Attach to PPP channel */ 483 if ((err = ioctl(*pppfd, PPPIOCATTCHAN, &chindex)) < 0) { 484 fprintf(stderr, "Couldn't attach to channel"); 485 return -1; 486 } 487 flags = fcntl(*pppfd, F_GETFL); 488 if (flags == -1 || fcntl(*pppfd, F_SETFL, flags | O_NONBLOCK) == -1) { 489 fprintf(stderr, "Couldn't set /dev/ppp (channel) to nonblock"); 490 return -1; 491 } 492 } 493 else { 494 fprintf(stderr, "Couldn't reopen /dev/ppp"); 495 return -1; 496 } 497 } 498 else { 499 fprintf(stderr, "Couldn't connect pppox, err: %d, %s", err, strerror(errno)); 500 return -1; 501 } 502 } 503 return 0; 504} 505/* foxconn wklin modified end, 07/31/2007 */ 506 507/************************************************************************** 508** Function: pptp_pppox_release() 509** Description: Release the connection between user program and pppox kernel 510** driver with ioctl() and connect(), and clear the 511** essential information in kernel. 512** Parameters: (int *) poxfd -- pointer of file descriptor for pppox 513** (int *) pppfd -- pointer of file descriptor for ppp device 514** Return: (int)err -- Fail = -1 515** Success = 0. 516**************************************************************************/ 517void pptp_pppox_release(int *poxfd, int *pppfd) 518{ 519 struct sockaddr_pppox lsp; 520 int err = -1; 521 522 if (*poxfd >= 0) { 523 memset(&lsp, 0, sizeof(struct sockaddr_pppox)); 524 lsp = pptp_pppox_get_info(); 525 if (*pppfd >= 0) { 526 /* Detach from PPP */ 527 if (ioctl(*pppfd, PPPIOCDETACH) < 0) 528 ; /* fprintf(stderr, "pptp_pppox_release ioctl(PPPIOCDETACH) 529 failed\n"); */ /* foxconn wklin removed, 07/26/2007 */ 530 } 531 532 /* Release pptp kernel connection */ 533 lsp.sa_addr.pppoe.sid = 0; 534 err = connect(*poxfd, (struct sockaddr*)&lsp, 535 sizeof(struct sockaddr_pppox)); 536 if (err != 0) 537 fprintf(stderr, "Couldn't connect to pptp kernel module\n"); 538 } 539 else 540 fprintf(stderr, "Couldn't connect socket to pppox\n"); 541} 542/* Foxconn added end, Winster Chan, 06/26/2006 */ 543 544int 545open_interface(char *if_name, unsigned short type, char *hw_addr) 546{ 547/* BSD stuff by mr */ 548#ifdef USE_BPF 549 int fd; 550 struct ifreq ifr; 551 char bpf[16]; 552 int i, opt; 553#ifdef SIMPLE_BPF 554 /* a simple BPF program which just grabs the packets of the given type */ 555 /* by default use the clever BPF program - it works on my SPARC which 556 has the same endian as network order. If someone can confirm that 557 the ordering also works on the opposite ending (e.g. ix86) I'll 558 remove the simple filter BPF program for good */ 559 struct bpf_insn filt[] = { 560 BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12), 561 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0 /* fill-in */, 0, 1), /* check type */ 562 BPF_STMT(BPF_RET+BPF_K, (u_int)-1), 563 BPF_STMT(BPF_RET+BPF_K, 0) 564 }; 565#else 566 /* by default use the clever BPF program which filters out packets 567 originating from us in the kernel */ 568 /* note that we split the 6-byte ethernet address into a 4-byte word 569 and 2-byte half-word to minimize the number of comparisons */ 570 struct bpf_insn filt[] = { 571 BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12), 572 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0 /* fill-in */, 0, 5), /* check type */ 573 /* check src address != our hw address */ 574 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 6), 575 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0 /* fill-in */, 0, 2), /* 4 bytes */ 576 BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 10), 577 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0 /* fill-in */, 1, 0), /* 2 bytes */ 578 BPF_STMT(BPF_RET+BPF_K, (u_int)-1), 579 BPF_STMT(BPF_RET+BPF_K, 0) 580 }; 581#endif /* SIMPLE_BPF */ 582 struct bpf_program prog; 583 584 /* hunt for an open bpf */ 585 for(i = 0; i < 10; i++) { /* this max is arbitrary */ 586 sprintf(bpf,"/dev/bpf%d",i); 587 if ((fd = open(bpf, O_RDWR)) >= 0) 588 break; 589 } 590 if (fd < 0) { 591 perror("pppoe: open(bpf)"); 592 return -1; 593 } 594 595 /* try to increase BPF size if possible */ 596 (void) ioctl(fd, BIOCSBLEN, &bpf_buf_size); /* try to set buffer size */ 597 if (ioctl(fd, BIOCGBLEN, &bpf_buf_size) < 0) { /* but find out for sure */ 598 perror("pppoe: bpf(BIOCGBLEN)"); 599 return -1; 600 } 601 602 603 /* attach to given interface */ 604 strncpy(ifr.ifr_name,if_name,sizeof(ifr.ifr_name)); 605 if (ioctl(fd, BIOCSETIF, &ifr) < 0) { 606 perror("pppoe: bpf(BIOCSETIF)"); 607 return -1; 608 } 609 610 /* setup BPF */ 611 opt = 1; 612 if (ioctl(fd, BIOCIMMEDIATE, &opt) < 0) { 613 perror("pppoe: bpf(BIOCIMMEDIATE)"); 614 return -1; 615 } 616 if (ioctl(fd, BIOCGDLT, &opt) < 0) { 617 perror("pppoe: bpf(BIOCGDLT)"); 618 return -1; 619 } 620 if (opt != DLT_EN10MB) { 621 fprintf(stderr, "pppoe: interface %s is not Ethernet!\n", if_name); 622 return -1; 623 } 624 625 /************************************************************************* 626 * 627 * WARNING - Really non-portable stuff follows. This works on OpenBSD 2.5 628 * and may not work anywhere else. 629 * 630 * What's going on - there's no obvious user-level interface to determine 631 * the MAC address of a network interface in BSD that I know of. (If 632 * anyone has an idea, please let me know.) What happens here is that we 633 * dig around in the kernel symbol list to find its list of interfaces, 634 * walk through the list to find the interface we are interested in and 635 * then we can (inobviously) get the ethernet info from that. 636 * I don't like this solution, but it's the best I've got at this point. 637 * 638 *************************************************************************/ 639 640 { 641 kvm_t *k; 642 struct nlist n[2]; 643 struct ifnet_head ifhead; 644 struct ifnet intf; 645 unsigned long v; 646 char ifn[IFNAMSIZ+1]; 647 struct arpcom arp; 648 649 k = kvm_open(NULL,NULL,NULL,O_RDONLY,"pppoe"); 650 if (k == NULL) { 651 fprintf(stderr, "pppoe: failed to open kvm\n"); 652 return -1; 653 } 654 n[0].n_name = "_ifnet"; 655 n[1].n_name = NULL; 656 if (kvm_nlist(k,n) != 0) { 657 fprintf(stderr, "pppoe: could not find interface list\n"); 658 kvm_close(k); 659 return -1; 660 } 661 if (kvm_read(k,n[0].n_value,(void *)&ifhead,sizeof(ifhead)) != 662 sizeof(ifhead)) { 663 fprintf(stderr, "pppoe: could not read ifnet_head structure\n"); 664 kvm_close(k); 665 return -1; 666 } 667 v = (unsigned long)(ifhead.tqh_first); 668 while(v != 0) { 669 if (kvm_read(k,v,(void *)&intf,sizeof(intf)) != sizeof(intf)) { 670 fprintf(stderr, "pppoe: could not read ifnet structure\n"); 671 kvm_close(k); 672 return -1; 673 } 674 strncpy(ifn,intf.if_xname,IFNAMSIZ); 675 ifn[IFNAMSIZ] = '\0'; 676 if (strcmp(ifn,if_name) == 0) 677 /* found our interface */ 678 break; 679 else 680 /* walk the chain */ 681 v = (unsigned long)(intf.if_list.tqe_next); 682 } 683 if (v == 0) { 684 fprintf(stderr, "pppoe: cannot find interface %s in kernel\n",if_name); 685 kvm_close(k); 686 return -1; 687 } 688 /* since we have the right interface, and we determined previously 689 that it is an ethernet interface, reread from the same address into 690 a "struct arpcom" structure (which begins with a struct ifnet). 691 The ethernet address is located past the end of the ifnet structure */ 692 if (kvm_read(k,v,(void *)&arp,sizeof(arp)) != sizeof(arp)) { 693 fprintf(stderr, "could not read arpcom structure\n"); 694 kvm_close(k); 695 return -1; 696 } 697 /* whew! */ 698 /* save a copy of this for ourselves */ 699 memcpy(local_ether,arp.ac_enaddr,ETH_ALEN); 700 if (hw_addr) 701 memcpy(hw_addr,arp.ac_enaddr,ETH_ALEN); /* also copy if requested */ 702 kvm_close(k); 703 } 704 705 /* setup BPF filter */ 706 { 707 union { unsigned int i; unsigned char b[4]; } x; 708 union { unsigned short i; unsigned char b[2]; } y; 709 710 filt[1].k = type; /* set type of packet we are looking for */ 711#ifndef SIMPLE_BPF 712 /* now setup our source address so it gets filtered out */ 713 for(i = 0; i < 4; i++) 714 x.b[i] = local_ether[i]; 715 for(i = 0; i < 2; i++) 716 y.b[i] = local_ether[i+4]; 717 filt[3].k = x.i; 718 filt[5].k = y.i; 719#endif /* SIMPLE_BPF */ 720 } 721 prog.bf_insns = filt; 722 prog.bf_len = sizeof(filt)/sizeof(struct bpf_insn); 723 if (ioctl(fd, BIOCSETF, &prog) < 0) { 724 perror("pppoe: bpf(BIOCSETF)"); 725 return -1; 726 } 727 728 return fd; 729#else /* do regular linux stuff */ 730 int optval = 1, rv; 731 struct ifreq ifr; 732 733 if ((rv = socket(PF_INET, SOCK_PACKET, htons(type))) < 0) 734 { 735 perror("pppoe: socket"); 736 return -1; 737 } 738 739 if (setsockopt(rv, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) 740 { 741 perror("pppoe: setsockopt"); 742 return -1; 743 } 744 745 if (hw_addr != NULL) { 746 strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); 747 748 if (ioctl(rv, SIOCGIFHWADDR, &ifr) < 0) 749 { 750 perror("pppoe: ioctl(SIOCGIFHWADDR)"); 751 return -1; 752 } 753 754 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) 755 { 756 fprintf(error_file, "pppoe: interface %s is not Ethernet!\n", if_name); 757 return -1; 758 } 759 760 memcpy(hw_addr, ifr.ifr_hwaddr.sa_data, sizeof(ifr.ifr_hwaddr.sa_data)); 761 762 } 763 return rv; 764#endif /* USE_BPF / linux */ 765} 766 767/* Foxconn added start Winster Chan 12/02/2005 */ 768int 769get_padx_tag(struct pppoe_tag *pTag, int nLen, pPadxTag pTagStruc, const unsigned short tagType) 770{ 771 int bExitLoop = 0, nSearchLen = 0, bTagFound = 0; 772 struct pppoe_tag *pNextTag; 773 774 pTagStruc->usPadLen = 0; 775 pTagStruc->nPadLen = 0; 776 pTagStruc->pPadStart = NULL; 777 778 while (!bExitLoop && (nSearchLen < nLen)) { 779 if (htons(pTag->type) == tagType) { 780 pTagStruc->usPadLen = pTag->length; 781 pTagStruc->nPadLen = (int)(htons(pTag->length)); 782 pTagStruc->pPadStart = (char *)pTag + TAG_STRUCT_SIZE; 783 bExitLoop = 1; 784 bTagFound = 1; 785 } 786 else { 787 pNextTag = (struct pppoe_tag *)((char *)pTag + 788 (TAG_STRUCT_SIZE + (int)(htons(pTag->length)))); 789 nSearchLen += (int)((TAG_STRUCT_SIZE + (int)(htons(pTag->length)))); 790 pTag = pNextTag; 791 } 792 } 793 794 return bTagFound; 795} 796/* Foxconn added end Winster Chan 12/02/2005 */ 797 798int 799create_padi(struct pppoe_packet *packet, const char *src, const char *name) 800{ 801 int size; 802 803 if (packet == NULL) 804 return 0; 805 806 /* printf("Winster: create_padi\n"); */ 807 808 size = sizeof(struct pppoe_packet) + sizeof(struct pppoe_tag); 809 if (name != NULL) 810 size += strlen(name); 811 812#ifdef __linux__ 813 memcpy(packet->ethhdr.h_dest, MAC_BCAST_ADDR, 6); 814 memcpy(packet->ethhdr.h_source, src, 6); 815 packet->ethhdr.h_proto = htons(ETH_P_PPPOE_DISC); 816#else 817 memcpy(packet->ethhdr.ether_dhost, MAC_BCAST_ADDR, 6); 818 memcpy(packet->ethhdr.ether_shost, src, 6); 819 packet->ethhdr.ether_type = htons(ETH_P_PPPOE_DISC); 820#endif 821 packet->ver = 1; 822 packet->type = 1; 823 packet->code = CODE_PADI; 824 packet->session = 0; 825 packet->length = htons(size - sizeof(struct pppoe_packet)); 826 827 /* fill out a blank service-name tag */ 828 (*(struct pppoe_tag *)(packet+1)).type = htons(TAG_SERVICE_NAME); 829 (*(struct pppoe_tag *)(packet+1)).length = name ? htons(strlen(name)) : 0; 830 if (name != NULL) 831 memcpy((char *)(packet + 1) + sizeof(struct pppoe_tag), name, 832 strlen(name)); 833 834 return size; 835} 836 837int 838create_padr(struct pppoe_packet *packet, const char *src, const char *dst, 839 char *name) 840{ 841 int size; 842 /* Foxconn added start Winster Chan 11/25/2005 */ 843 char *pCookieStart = NULL; 844 int nCookieSize = 0; 845 int nNameSize = 0; 846 unsigned short usCookieSize = 0; 847 sPadxTag sTag; 848 /* Foxconn added end Winster Chan 11/25/2005 */ 849 /* Foxconn add start, Max Ding, 09/22/2008 for @add TAG_RELAY_SESSION_ID */ 850 char *pRelaySessionIdStart = NULL; 851 int nRelaySessionIdSize = 0; 852 unsigned short usRelaySessionIdSize = 0; 853 char *pPacketPoint = packet; 854 /* Foxconn add end, Max Ding, 09/22/2008 */ 855 856 if (packet == NULL) 857 return 0; 858 859 size = sizeof(struct pppoe_packet) + TAG_STRUCT_SIZE; 860 if (name != NULL) { 861 size += strlen(name); 862 /* Foxconn added start Winster Chan 11/25/2005 */ 863 nNameSize = strlen(name); 864 /* Foxconn added end Winster Chan 11/25/2005 */ 865 } 866 867 /* Foxconn added start Winster Chan 12/02/2005 */ 868 /* Add length of AC cookie to packet size */ 869 if (get_padx_tag((struct pppoe_tag *)pado_tags, pado_tag_size, &sTag, TAG_AC_COOKIE)) { 870 nCookieSize = sTag.nPadLen; 871 usCookieSize = sTag.usPadLen; 872 pCookieStart = sTag.pPadStart; 873 size += (int)(TAG_STRUCT_SIZE + sTag.nPadLen); 874 } 875 /* Foxconn added end Winster Chan 12/02/2005 */ 876 /* Foxconn add start, Max Ding, 09/22/2008 for @add TAG_RELAY_SESSION_ID */ 877 if (get_padx_tag((struct pppoe_tag *)pado_tags, pado_tag_size, &sTag, TAG_RELAY_SESSION_ID)) { 878 nRelaySessionIdSize = sTag.nPadLen; 879 usRelaySessionIdSize = sTag.usPadLen; 880 pRelaySessionIdStart = sTag.pPadStart; 881 size += (int)(TAG_STRUCT_SIZE + sTag.nPadLen); 882 } 883 /* Foxconn add end, Max Ding, 09/22/2008 */ 884 885#ifdef __linux__ 886 memcpy(packet->ethhdr.h_dest, dst, 6); 887 memcpy(packet->ethhdr.h_source, src, 6); 888 packet->ethhdr.h_proto = htons(ETH_P_PPPOE_DISC); 889#else 890 memcpy(packet->ethhdr.ether_dhost, dst, 6); 891 memcpy(packet->ethhdr.ether_shost, src, 6); 892 packet->ethhdr.ether_type = htons(ETH_P_PPPOE_DISC); 893#endif 894 packet->ver = 1; 895 packet->type = 1; 896 packet->code = CODE_PADR; 897 packet->session = 0; 898 packet->length = htons(size - sizeof(struct pppoe_packet)); 899 900 /* fill out a blank service-name tag */ 901 (*(struct pppoe_tag *)(packet+1)).type = htons(TAG_SERVICE_NAME); 902 (*(struct pppoe_tag *)(packet+1)).length = name ? htons(strlen(name)) : 0; 903 if (name != NULL) 904 memcpy((char *)(packet + 1) + TAG_STRUCT_SIZE, name, 905 strlen(name)); 906 907 pPacketPoint = (char *)(packet+1)+TAG_STRUCT_SIZE+nNameSize;/* Foxconn added by Max Ding, 09/23/2008 @add TAG_RELAY_SESSION_ID */ 908 /* foxconn modified start, wklin, 03/27/2007, winster doesn't count name len */ 909 /* Foxconn added start Winster Chan 11/25/2005 */ 910 /* fill out the AC cookie tag from PADO */ 911 if (nCookieSize > 0) { 912 (*(struct pppoe_tag *)((char *)(packet+1)+TAG_STRUCT_SIZE+ 913 nNameSize)).type = htons(TAG_AC_COOKIE); 914 (*(struct pppoe_tag *)((char *)(packet+1)+TAG_STRUCT_SIZE+ 915 nNameSize)).length = usCookieSize; 916 memcpy((char *)(packet+1)+(2*TAG_STRUCT_SIZE)+nNameSize, 917 (char *)pCookieStart, nCookieSize); 918 pPacketPoint = (char *)(packet+1)+(2*TAG_STRUCT_SIZE)+nNameSize+nCookieSize;/* Foxconn added by Max Ding, 09/23/2008 @add TAG_RELAY_SESSION_ID */ 919 } 920 /* Foxconn added end Winster Chan 11/25/2005 */ 921 /* foxconn modified end, wklin, 03/27/2007 */ 922 /* Foxconn add start, Max Ding, 09/22/2008 for @add TAG_RELAY_SESSION_ID */ 923 if (nRelaySessionIdSize > 0) { 924 (*(struct pppoe_tag *)(pPacketPoint)).type = htons(TAG_RELAY_SESSION_ID); 925 (*(struct pppoe_tag *)(pPacketPoint)).length = usRelaySessionIdSize; 926 memcpy((pPacketPoint+TAG_STRUCT_SIZE), 927 (char *)pRelaySessionIdStart, nRelaySessionIdSize); 928 pPacketPoint += TAG_STRUCT_SIZE + nRelaySessionIdSize; 929 } 930 /* Foxconn add end, Max Ding, 09/22/2008 */ 931 932 memset(((char *)packet) + size, 0, 14); 933 return size; 934} 935 936/* Foxconn added end Winster Chan 12/02/2005 */ 937int 938create_padt(struct pppoe_packet *packet, const char *src, const char *dst, unsigned short nSessId) 939{ 940 int size; 941 char *pCookieStart = NULL; 942 int nCookieSize = 0; 943 unsigned short usCookieSize = 0; 944 sPadxTag sTag; 945 946 if (packet == NULL) 947 return 0; 948 949 size = sizeof(struct pppoe_packet) + TAG_STRUCT_SIZE; 950 951 if (get_padx_tag((struct pppoe_tag *)pado_tags, pado_tag_size, &sTag, TAG_AC_COOKIE)) { 952 nCookieSize = sTag.nPadLen; 953 usCookieSize = sTag.usPadLen; 954 pCookieStart = sTag.pPadStart; 955 size += (int)(TAG_STRUCT_SIZE + sTag.nPadLen); 956 } 957 958#ifdef __linux__ 959 memcpy(packet->ethhdr.h_dest, dst, 6); 960 memcpy(packet->ethhdr.h_source, src, 6); 961 packet->ethhdr.h_proto = htons(ETH_P_PPPOE_DISC); 962#else 963 memcpy(packet->ethhdr.ether_dhost, dst, 6); 964 memcpy(packet->ethhdr.ether_shost, src, 6); 965 packet->ethhdr.ether_type = htons(ETH_P_PPPOE_DISC); 966#endif 967 packet->ver = 1; 968 packet->type = 1; 969 packet->code = CODE_PADT; 970 /*packet->session = session;*/ 971 packet->session = nSessId; 972 packet->length = htons(size - sizeof(struct pppoe_packet)); 973 974 /* fill out a blank generic-error tag */ 975 (*(struct pppoe_tag *)(packet+1)).type = htons(TAG_GENERIC_ERROR); 976 (*(struct pppoe_tag *)(packet+1)).length = 0; 977 978 /* fill out the AC cookie tag from PADO */ 979 if (nCookieSize > 0) { 980 (*(struct pppoe_tag *)((char *)(packet+1)+TAG_STRUCT_SIZE)).type 981 = htons(TAG_AC_COOKIE); 982 (*(struct pppoe_tag *)((char *)(packet+1)+TAG_STRUCT_SIZE)).length 983 = usCookieSize; 984 memcpy((char *)(packet+1)+(2*TAG_STRUCT_SIZE), 985 (char *)pCookieStart, nCookieSize); 986 } 987 988 memset(((char *)packet) + size, 0, 14); 989 return size; 990} 991/* Foxconn added end Winster Chan 12/02/2005 */ 992 993unsigned short fcstab[256] = { 994 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 995 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 996 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 997 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 998 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 999 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 1000 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 1001 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 1002 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 1003 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 1004 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 1005 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 1006 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 1007 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 1008 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 1009 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 1010 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 1011 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 1012 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 1013 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 1014 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 1015 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 1016 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 1017 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 1018 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 1019 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 1020 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 1021 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 1022 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 1023 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 1024 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 1025 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 1026}; 1027 1028#define PPPINITFCS16 0xffff /* Initial FCS value */ 1029#define PPPGOODFCS16 0xf0b8 /* Good final FCS value */ 1030/* 1031 * Calculate a new fcs given the current fcs and the new data. 1032 */ 1033unsigned short pppfcs16(register unsigned short fcs, 1034 register unsigned char * cp, 1035 register int len) 1036{ 1037/* assert(sizeof (unsigned short) == 2); 1038 assert(((unsigned short) -1) > 0); */ 1039 1040 while (len--) 1041 fcs = (fcs >> 8) ^ fcstab[(fcs ^ *cp++) & 0xff]; 1042 1043 return (fcs); 1044} 1045 1046#define FRAME_ESC 0x7d 1047#define FRAME_FLAG 0x7e 1048#define FRAME_ADDR 0xff 1049#define FRAME_CTL 0x03 1050#define FRAME_ENC 0x20 1051 1052#define ADD_OUT(c) { *out++ = (c); n++; if (opt_verbose) fprintf(log_file, "%x ", (c)); } 1053 1054void encode_ppp(int fd, unsigned char *buf, int len) 1055{ 1056 static int first = 0; 1057 unsigned char out_buf[PACKETBUF]; 1058 unsigned char *out = out_buf; 1059 unsigned char header[2], tail[2]; 1060 int i,n; 1061 unsigned short fcs; 1062 time_t tm; 1063 1064 header[0] = FRAME_ADDR; 1065 header[1] = FRAME_CTL; 1066 fcs = pppfcs16(PPPINITFCS16, header, 2); 1067 fcs = pppfcs16(fcs, buf, len) ^ 0xffff; 1068 tail[0] = fcs & 0x00ff; 1069 tail[1] = (fcs >> 8) & 0x00ff; 1070 1071 if (opt_verbose) 1072 { 1073 time(&tm); 1074 fprintf(log_file, "%sWriting to pppd: \n", ctime(&tm)); 1075 } 1076 1077 n = 0; 1078 if (!first) { 1079 ADD_OUT(FRAME_FLAG); 1080 first = 1; 1081 } 1082 ADD_OUT(FRAME_ADDR); /* the header - which is constant */ 1083 ADD_OUT(FRAME_ESC); 1084 ADD_OUT(FRAME_CTL ^ FRAME_ENC); 1085 1086 for (i = 0; i < len; i++) 1087 if (buf[i] == FRAME_FLAG || buf[i] == FRAME_ESC || buf[i] < 0x20) 1088 { 1089 ADD_OUT(FRAME_ESC); 1090 ADD_OUT(buf[i] ^ FRAME_ENC); 1091 } 1092 else 1093 ADD_OUT(buf[i]); 1094 1095 for (i = 0; i < 2; i++) { 1096 if (tail[i] == FRAME_FLAG || tail[i] == FRAME_ESC || tail[i] < 0x20) { 1097 ADD_OUT(FRAME_ESC); 1098 ADD_OUT(tail[i] ^ FRAME_ENC); 1099 } else 1100 ADD_OUT(tail[i]); 1101 } 1102 ADD_OUT(FRAME_FLAG); 1103 1104 write(fd, out_buf, n); 1105 1106 if (opt_verbose) 1107 fprintf(log_file, "\n"); 1108} 1109 1110int 1111create_sess(struct pppoe_packet *packet, const char *src, const char *dst, 1112 unsigned char *buf, int bufsize, int sess, int *bufRemain) 1113{ 1114 int size; 1115 int i, o = 0; 1116 int nBufLen = 0; 1117 int nTotalLen = 0, nAllLen = 0; 1118 int nTemp = 0; 1119 unsigned short usTotalLen = 0x0; 1120 unsigned char bufLen[2]; 1121 1122 /* Clear the length of remain buffer */ 1123 *bufRemain = 0; 1124 1125 if (opt_fwd || !((buf[0] == FRAME_FLAG) || (buf[0] == FRAME_ADDR))) 1126 { 1127 if (opt_fwd_search) /* search for a valid packet */ 1128 { 1129 while (*buf++ != FRAME_FLAG && bufsize != 0) 1130 bufsize--; 1131 if (bufsize == 0) { 1132 fprintf(error_file, "create_sess: bufsize == 0\n"); 1133 return 0; 1134 } 1135 } 1136 else 1137 { 1138 /* fprintf(error_file, "create_sess: invalid data\n"); */ /* foxconn wklin 1139 removed, 1140 07/26/2007 1141 */ 1142 return 0; 1143 } 1144 } 1145 1146 bufLen[0] = 0x0; 1147 bufLen[1] = 0x0; 1148 if (bufsize <= 4) { 1149 *bufRemain = bufsize; 1150 return 0; 1151 } 1152 else { 1153 nTemp = (buf[0] == FRAME_FLAG) ? 4 : 3; 1154 for (i = nTemp; i < bufsize; i++) { 1155 if (buf[i] == FRAME_ESC) { 1156 if ((o == 4) || (o == 5)) 1157 bufLen[o-4] = buf[++i] ^ FRAME_ENC; 1158 else 1159 ++i; 1160 } 1161 else { 1162 if ((o == 4) || (o == 5)) 1163 bufLen[o-4] = buf[i]; 1164 } 1165 o++; 1166 1167 /* Get the total length from IP packet header */ 1168 if (o == 6) { 1169 usTotalLen = ntohs(*(unsigned short *)bufLen); 1170 nTotalLen = (int)usTotalLen; 1171 nAllLen = nTotalLen + 5; 1172 } 1173 1174 /* Get the total buffer length of packet */ 1175 if ((o >= 6) && (o == nAllLen)) { 1176 nBufLen = i + 1; 1177 break; 1178 } 1179 } 1180 1181 if ((o < nAllLen) || (o < 6)) { 1182 *bufRemain = bufsize; 1183 return 0; 1184 } 1185 o = 0; 1186 } 1187 1188 /* for (i = (buf[0] == FRAME_FLAG ? 4 : 3); i < bufsize; i++) { */ 1189 for (i = nTemp; i < bufsize; i++) { 1190 if (buf[i] == FRAME_ESC) { 1191 buf[o++] = buf[++i] ^ FRAME_ENC; 1192 } 1193 else { 1194 buf[o++] = buf[i]; 1195 } 1196 1197 if (o == nAllLen) 1198 break; 1199 } /* End for() */ 1200 1201 /* Compute the length of remain buffer */ 1202 *bufRemain = bufsize - nBufLen; 1203 1204 bufsize = nTotalLen + 2; 1205 1206 if (packet == NULL) { 1207 return 0; 1208 } 1209 1210 size = sizeof(struct pppoe_packet) + bufsize; 1211 1212#ifdef __linux__ 1213 memcpy(packet->ethhdr.h_dest, dst, 6); 1214 memcpy(packet->ethhdr.h_source, src, 6); 1215 packet->ethhdr.h_proto = htons(ETH_P_PPPOE_SESS); 1216#else 1217 memcpy(packet->ethhdr.ether_dhost, dst, 6); 1218 memcpy(packet->ethhdr.ether_shost, src, 6); 1219 packet->ethhdr.ether_type = htons(ETH_P_PPPOE_SESS); 1220#endif 1221 packet->ver = 1; 1222 packet->type = 1; 1223 packet->code = CODE_SESS; 1224 packet->session = sess; 1225 packet->length = htons(size - sizeof(struct pppoe_packet)); 1226 1227 return size; 1228} 1229 1230int 1231send_packet(int sock, struct pppoe_packet *packet, int len, const char *ifn) 1232{ 1233#ifdef USE_BPF 1234 int c; 1235 if ((c = write(sock,packet,len)) != len) 1236 perror("pppoe: write (send_packet)"); 1237 return c; 1238#else /* regular linux stuff */ 1239 struct sockaddr addr; 1240 int c; 1241 time_t tm; 1242 1243 memset(&addr, 0, sizeof(addr)); 1244 strcpy(addr.sa_data, ifn); 1245 1246 if (opt_verbose == 1) 1247 { 1248 time(&tm); 1249 fprintf(log_file, "%sSending ", ctime(&tm)); 1250 print_packet(packet); 1251 fputc('\n', log_file); 1252 } 1253 1254 1255 if ((c = sendto(sock, packet, len, 0, &addr, sizeof(addr))) < 0) { 1256 /* fprintf(error_file, "send_packet c[%d] = sendto(len = %d)\n", c, len); */ 1257 perror("pppoe: sendto (send_packet)"); 1258 } 1259 1260 return c; 1261#endif /* USE_BPF */ 1262} 1263 1264#ifdef USE_BPF 1265/* return: -1 == error, 0 == okay, 1 == ignore this packet */ 1266int read_bpf_packet(int fd, struct pppoe_packet *packet) { 1267 /* Nastiness - BPF may return multiple packets in one fell swoop */ 1268 /* This makes select() difficult to use - you need to be ready to 1269 clear out packets as they arrive */ 1270 static char *buf = NULL; 1271 static int lastdrop = 0; 1272 static int n = 0, off = 0; 1273 struct bpf_hdr *h; 1274 1275 if (buf == NULL) { 1276 if ((buf = malloc(bpf_buf_size)) == NULL) { 1277 perror("pppoe:malloc"); 1278 return -1; 1279 } 1280 } 1281 1282 if (off < n) { 1283 /* read out of previously grabbed buffer */ 1284 if (n-off < sizeof(struct bpf_hdr)) { 1285 fprintf(stderr, "BPF: not enough left for header: %d\n", n-off); 1286 /* fprintf(error_file, "BPF: not enough left for header: %d\n", n-off); */ 1287 off = n = 0; /* force reread from BPF next time */ 1288 return 1; /* try again */ 1289 } 1290 h = (struct bpf_hdr *)&(buf[off]); 1291 memcpy(packet,&(buf[off + h->bh_hdrlen]),h->bh_caplen); 1292 off += BPF_WORDALIGN(h->bh_hdrlen + h->bh_caplen); 1293 if (h->bh_caplen != h->bh_datalen) { 1294 fprintf(stderr, "pppoe: truncated packet: %d -> %d\n", 1295 h->bh_datalen, h->bh_caplen); 1296 /* fprintf(error_file, "BPF: truncated packet: %d -> %d\n", 1297 h->bh_datalen, h->bh_caplen); */ 1298 return 1; /* try again */ 1299 } 1300 } else { 1301 struct bpf_stat s; 1302 if (ioctl(fd,BIOCGSTATS,&s)) { 1303 perror("pppoe: BIOCGSTATS"); 1304 } else { 1305 if (s.bs_drop > lastdrop) { 1306 fprintf(stderr, "BPF: dropped %d packets\n", s.bs_drop - lastdrop); 1307 /* fprintf(error_file, "BPF: dropped %d packets\n", s.bs_drop - lastdrop); */ 1308 lastdrop = s.bs_drop; 1309 } 1310 } 1311 if ((n = read(fd,buf,bpf_buf_size)) < 0) { 1312 perror("pppoe: read (read_bpf_packet)"); 1313 return -1; 1314 } 1315 if (n == 0) 1316 return 0; /* timeout on bpf - try again */ 1317 h = (struct bpf_hdr *)(buf); 1318 memcpy(packet,&(buf[h->bh_hdrlen]),h->bh_caplen); 1319 off = BPF_WORDALIGN(h->bh_hdrlen + h->bh_caplen); 1320 } 1321 /* need to filter packets here - interface could be in promiscuous 1322 mode - we shouldn't see packets that we sent out thanks to BPF, but 1323 a quick double-check here is unlikely to seriously impact performance 1324 Once you know BPF is working, you can pop this out */ 1325 if (memcmp(packet->ethhdr.ether_shost,local_ether,6) == 0) { 1326#ifdef SIMPLE_BPF 1327 return 1; /* ignore this packet */ 1328#else 1329 /* with the bigger BPF program, we should never get here */ 1330 fprintf(stderr, "BPF program is broken\n"); 1331 exit(1); 1332#endif /* SIMPLE_BPF */ 1333 } 1334 1335 if (memcmp(packet->ethhdr.ether_dhost,MAC_BCAST_ADDR,6) == 0 || 1336 memcmp(packet->ethhdr.ether_dhost,local_ether,6) == 0) 1337 return 0; /* I should look at this packet */ 1338 else { 1339 print_packet(packet); 1340 return 1; /* ignore this packet */ 1341 } 1342} 1343 1344int is_bpf(int fd) { 1345 /* is this socket tied to bpf? */ 1346 /* quick hack() - try a trivial bpf ioctl */ 1347 struct bpf_version v; 1348 return (ioctl(fd,BIOCVERSION,&v) == 0); 1349} 1350#endif /* USE_BPF */ 1351 1352int 1353read_packet(int sock, struct pppoe_packet *packet, int *len) 1354{ 1355/* struct sockaddr_in from; */ 1356#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ < 6 1357 int fromlen = PACKETBUF; 1358#else 1359 socklen_t fromlen = PACKETBUF; 1360#endif 1361 time_t tm; 1362 1363 time(&tm); 1364 1365 while(1) { 1366#ifdef USE_BPF 1367 { 1368 int j; 1369 if ((j = read_bpf_packet(sock, packet)) < 0) 1370 return -1; /* read_bpf_packet() will report error */ 1371 else if (j > 0) 1372 continue; /* read a packet, but not what we wanted */ 1373 } 1374#else 1375 /* wklin modified start, 01/10/2007 */ 1376 fd_set fdset; 1377 struct timeval tm; 1378 1379 FD_ZERO(&fdset); 1380 FD_SET(sock, &fdset); 1381 tm.tv_usec = 0; 1382 tm.tv_sec = 3; /* wait for 3 seconds */ 1383 if (select(sock + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) <= 0) { 1384 return -1; /* timeout or error */ 1385 } else if (FD_ISSET(sock, &fdset)) { 1386 if (recvfrom(sock, packet, PACKETBUF, 0, 1387 NULL /*(struct sockaddr *)&from*/, &fromlen) < 0) { 1388 perror("pppoe: recv (read_packet)"); 1389 return -1; 1390 } 1391 } 1392#if 0 1393 if (recvfrom(sock, packet, PACKETBUF, 0, 1394 NULL /*(struct sockaddr *)&from*/, &fromlen) < 0) { 1395 perror("pppoe: recv (read_packet)"); 1396 return -1; 1397 } 1398#endif /* 0 */ 1399 /* wklin modified end, 01/10/2007 */ 1400#endif /* USE_BPF */ 1401 if (opt_verbose) 1402 { 1403 fprintf(log_file, "Received packet at %s", ctime(&tm)); 1404 print_packet(packet); 1405 fputc('\n', log_file); 1406 } 1407 1408 return sock; 1409 } 1410} 1411 1412void sigchild(int src) { 1413 clean_child = 1; 1414} 1415 1416void cleanup_and_exit(int status) { 1417 /* Foxconn modified start, Winster Chan, 06/26/2006 */ 1418 pptp_pppox_release(&poxfd, &pppfd); 1419 close(pppfd); pppfd = -1; 1420 close(poxfd); poxfd = -1; 1421 /* Foxconn modified end, Winster Chan, 06/26/2006 */ 1422 1423 close(disc_sock); 1424 close(sess_sock); 1425 close(1); 1426 1427 if (pppd_listen > 0) 1428 /*if (pppd_pid > 0)*/ 1429 { 1430#ifdef __linux__ 1431 kill(pppd_listen, SIGTERM); 1432#else 1433 kill(SIGTERM, pppd_listen); 1434#endif 1435 } 1436 if (sess_listen > 0) 1437 /*if (sess_pid > 0)*/ 1438 { 1439#ifdef __linux__ 1440 kill(sess_listen, SIGTERM); 1441#else 1442 kill(SIGTERM, sess_listen); 1443#endif 1444 } 1445 /* system("killall pppoecd"); */ /* Foxconn added, Winster Chan, 06/26/2006 1446 */ /* foxconn wklin removed, 07/26/2007 */ 1447 exit(status); 1448} 1449 1450void sigint(int src) 1451{ 1452 /* Foxconn added start Winster Chan 12/02/2005 */ 1453 struct pppoe_packet *packet = NULL; 1454 int pkt_size; 1455 FILE *fp; 1456 1457 if (disc_sock && (pppd_listen > 0)) { 1458 /* allocate packet once */ 1459 packet = malloc(PACKETBUF); 1460 assert(packet != NULL); 1461 1462 /* send PADT */ 1463 if ((pkt_size = create_padt(packet, src_addr, dst_addr, session)) == 0) { 1464 fprintf(stderr, "pppoe: unable to create PADT packet\n"); 1465 /* exit(1); */ 1466 } 1467 if (send_packet(disc_sock, packet, pkt_size+14, if_name) < 0) { 1468 fprintf(stderr, "pppoe: unable to send PADT packet\n"); 1469 /* exit(1); */ 1470 } else { 1471 fprintf(stderr, "PPPOE: PADT sent*\n"); /* foxconn wklin added, 07/26/2007 */ 1472 } 1473 } 1474 /* Foxconn added end Winster Chan 12/02/2005 */ 1475 1476 /* Foxconn added start Winster Chan 12/05/2005 */ 1477 if (!(fp = fopen(PPP_PPPOE_SESSION, "w"))) { 1478 perror(PPP_PPPOE_SESSION); 1479 } 1480 else { 1481 /* Clear the PPPoE server MAC address and Session ID */ 1482 fprintf(fp, "%02x:%02x:%02x:%02x:%02x:%02x %d\n", 1483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0); 1484 fclose(fp); 1485 } 1486 /* Foxconn added end Winster Chan 12/05/2005 */ 1487 cleanup_and_exit(1); 1488} 1489 1490#ifdef NEW_WANDETECT 1491/*Foxconn added start James 11/12/2008 @new_internet_detection*/ 1492void sigint2(int src) 1493{ 1494 struct pppoe_packet *packet = NULL; 1495 int pkt_size; 1496 FILE *fp; 1497 time_t tm; 1498 1499 /* allocate packet once */ 1500 packet = malloc(PACKETBUF); 1501 assert(packet != NULL); 1502 /* send PADT */ 1503 if ((pkt_size = create_padt(packet, src_addr, dst_addr, session)) == 0) { 1504 fprintf(stderr, "pppoe: unable to create PADT packet\n"); 1505 /* exit(1); */ 1506 } 1507 if (send_packet(disc_sock, packet, pkt_size+14, if_name) < 0) { 1508 fprintf(stderr, "pppoe: unable to send PADT packet\n"); 1509 /* exit(1); */ 1510 } else { 1511 time(&tm); 1512 fprintf(stderr, "PPPOE: PADT sent* %s\n",ctime(&tm)); /* foxconn wklin added, 07/26/2007 */ 1513 } 1514 1515 /* Foxconn added end Winster Chan 12/02/2005 */ 1516 1517 /* Foxconn added start Winster Chan 12/05/2005 */ 1518 if (!(fp = fopen(PPP_PPPOE_SESSION, "w"))) { 1519 perror(PPP_PPPOE_SESSION); 1520 } 1521 else { 1522 /* Clear the PPPoE server MAC address and Session ID */ 1523 fprintf(fp, "%02x:%02x:%02x:%02x:%02x:%02x %d\n", 1524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0); 1525 fclose(fp); 1526 } 1527 /* Foxconn added end Winster Chan 12/05/2005 */ 1528 cleanup_and_exit(1); 1529 1530} 1531/* Foxconn added end James 11/12/2008 @new_internet_detection */ 1532#endif 1533 1534void sess_handler(void) { 1535 /* pull packets of sess_sock and feed to pppd */ 1536 struct pppoe_packet *packet = NULL; 1537 int pkt_size; 1538 1539#ifdef BUGGY_AC 1540/* the following code deals with buggy AC software which sometimes sends 1541 duplicate packets */ 1542#define DUP_COUNT 10 1543#define DUP_LENGTH 20 1544 unsigned char dup_check[DUP_COUNT][DUP_LENGTH]; 1545 int i, ptr = 0; 1546#endif /* BUGGY_AC */ 1547 1548#ifdef BUGGY_AC 1549 memset(dup_check, 0, sizeof(dup_check)); 1550#endif 1551 1552 /* allocate packet once */ 1553 packet = malloc(PACKETBUF); 1554 assert(packet != NULL); 1555 1556 /* fprintf(error_file, "sess_handler %d\n", getpid()); */ /* foxconn wklin 1557 removed, 1558 07/27/2007 */ 1559 while(1) 1560 { 1561 while(read_packet(sess_sock,packet,&pkt_size) != sess_sock) 1562 ; 1563#ifdef __linux__ 1564 if (memcmp(packet->ethhdr.h_source, dst_addr, sizeof(dst_addr)) != 0) 1565#else 1566 if (memcmp(packet->ethhdr.ether_shost, dst_addr, sizeof(dst_addr)) 1567 != 0) 1568#endif 1569 continue; /* packet not from AC */ 1570 if (packet->session != session) 1571 continue; /* discard other sessions */ 1572#ifdef __linux__ 1573 if (packet->ethhdr.h_proto != htons(ETH_P_PPPOE_SESS)) 1574 { 1575 fprintf(log_file, "pppoe: invalid session proto %x detected\n", 1576 ntohs(packet->ethhdr.h_proto)); 1577 continue; 1578 } 1579#else 1580 if (packet->ethhdr.ether_type != htons(ETH_P_PPPOE_SESS)) 1581 { 1582 fprintf(log_file, "pppoe: invalid session proto %x detected\n", 1583 ntohs(packet->ethhdr.ether_type)); 1584 continue; 1585 } 1586#endif 1587 if (packet->code != CODE_SESS) { 1588 fprintf(log_file, "pppoe: invalid session code %x\n", packet->code); 1589 continue; 1590 } 1591#if BUGGY_AC 1592 /* we need to go through a list of recently-received packets to 1593 make sure the AC hasn't sent us a duplicate */ 1594 for (i = 0; i < DUP_COUNT; i++) 1595 if (memcmp(packet, dup_check[i], sizeof(dup_check[0])) == 0) 1596 return; /* we've received a dup packet */ 1597#define min(a,b) ((a) < (b) ? (a) : (b)) 1598 memcpy(dup_check[ptr], packet, min(ntohs(packet->length), 1599 sizeof(dup_check[0]))); 1600 ptr = ++ptr % DUP_COUNT; 1601#endif /* BUGGY_AC */ 1602 1603 encode_ppp(1, (unsigned char *)(packet+1), ntohs(packet->length)); 1604 } 1605} 1606 1607void pppd_handler(void) { 1608 /* take packets from pppd and feed them to sess_sock */ 1609 struct pppoe_packet *packet = NULL; 1610 time_t tm; 1611 sPktBuf pktBuf[BUFRING]; 1612 int nPkt = 0; 1613 /* unsigned char buf[PACKETBUF]; */ 1614 int len, pkt_size; 1615 int i, bufRemain = 0, bufPos; 1616 unsigned char *currBufStart; 1617 1618 /* fprintf(error_file, "pppd_handler %d\n", getpid()); */ /* foxconn wklin 1619 removed, 1620 07/27/2007 */ 1621 1622 /* Clear data buffer */ 1623 for (i=0; i<BUFRING; i++) { 1624 memset(pktBuf[i].packetBuf, 0x0, sizeof(pktBuf[i].packetBuf)); 1625 } 1626 1627 while(1) { 1628 /* Read in data buffer, Maximum size is 4095 bytes for evey one read() */ 1629 if ((len = read(0, &(pktBuf[nPkt].packetBuf[(20+bufRemain)]), (4095-bufRemain))) < 0) { 1630 perror("pppoe"); 1631 fprintf(error_file, "pppd_handler: read packet error len < 0\n"); 1632 exit(1); 1633 } 1634 if (len == 0) { 1635 /* foxconn wklin modified start, 07/27/2007 */ 1636 /* fprintf(error_file, "pppd_handler: read packet len = 0 bytes\n"); */ 1637 usleep(10000); /* sleep 10ms */ 1638 /* foxconn wklin modified end, 07/27/2007 */ 1639 continue; 1640 } 1641 /* Append the length of previous remained data */ 1642 len += bufRemain; 1643 1644 if (opt_verbose == 1) { 1645 time(&tm); 1646 fprintf(log_file, "\n%sInput of %d bytes:\n", ctime(&tm), len); 1647 /*print_hex(buf, len);*/ 1648 print_hex(pktBuf[nPkt].packetBuf, len); 1649 fputc('\n', log_file); 1650 } 1651 1652 bufPos = 0; 1653 packet = &(pktBuf[nPkt].packetBuf[0]); 1654 currBufStart = &(pktBuf[nPkt].packetBuf[20]); 1655 do { 1656 /* Segment and compose packet from buffer */ 1657 if ((pkt_size = create_sess(packet, src_addr, dst_addr, currBufStart, len, 1658 session, &bufRemain)) == 0) { 1659 /* Copy incomplete content to next buffer */ 1660 if (bufRemain > 0) { 1661 if ((nPkt+1) < BUFRING) { 1662 memcpy(&(pktBuf[nPkt+1].packetBuf[20]), 1663 &(pktBuf[nPkt].packetBuf[(4115-bufRemain)]), /* 4115 = 4095 + 20 */ 1664 bufRemain); 1665 } 1666 else { 1667 memcpy(&(pktBuf[0].packetBuf[20]), 1668 &(pktBuf[(BUFRING-1)].packetBuf[(4115-bufRemain)]), /* 4115 = 4095 + 20 */ 1669 bufRemain); 1670 } 1671 } 1672 break; 1673 } 1674 1675 len -= bufRemain; 1676 1677 /* Send the completely composed packet */ 1678 if (send_packet(sess_sock, packet, pkt_size, if_name) < 0) { 1679 fprintf(error_file, "pppd_handler: unable to send PPPoE packet\n"); 1680 exit(1); 1681 } 1682 1683 /* Check if all the contents of buffer were processed */ 1684 if (bufRemain <= 0) { 1685 break; 1686 } 1687 else { 1688 /* Renew the positions of packet header and data buffer */ 1689 bufPos += len; 1690 currBufStart = &(pktBuf[nPkt].packetBuf[bufPos+20]); 1691 packet = &(pktBuf[nPkt].packetBuf[bufPos]); 1692 len = bufRemain; 1693 } 1694 } while (bufRemain > 0); 1695 1696 /* Process next read buffer */ 1697 nPkt++; 1698 if (nPkt >= BUFRING) 1699 nPkt = 0; 1700 1701 } 1702} 1703 1704 1705int main(int argc, char **argv) 1706{ 1707 struct pppoe_packet *packet = NULL; 1708 int pkt_size; 1709 /* Foxconn added start Winster Chan 12/05/2005 */ 1710 FILE *fp; 1711 char buf[64]; 1712 /* Foxconn added end Winster Chan 12/05/2005 */ 1713 int fd; /* wklin added, 07/26/2007 */ 1714 1715 int opt; 1716 int ret_sock; /* foxconn wklin added, 12/27/2007 */ 1717 time_t tm; /* foxconn wklin added, 12/27/2007 */ 1718 1719 /* initialize error_file here to avoid glibc2.1 issues */ 1720 error_file = stderr; 1721 1722 /* foxconn wklin added start, 07/26/2007 */ 1723 fd = open("/dev/console", O_WRONLY); 1724 if (fd != -1) 1725 dup2(fd, 2); 1726 /* foxconn wklin added end, 07/26/2007 */ 1727 1728 /* parse options */ 1729 /* foxconn wklin modified, 03/27/2007, add service name option S */ 1730 while ((opt = getopt(argc, argv, "I:L:VE:F:S:")) != -1) 1731 switch(opt) 1732 { 1733 case 'F': /* sets invalid forwarding */ 1734 if (*optarg == 'a') /* always forward */ 1735 opt_fwd = 1; 1736 else if (*optarg == 's') /* search for flag */ 1737 opt_fwd_search = 1; 1738 else 1739 fprintf(stderr, "Invalid forward option %c\n", *optarg); 1740 break; 1741 1742 case 'I': /* sets interface */ 1743 if (if_name != NULL) 1744 free(if_name); 1745 /* foxconn wklin modified, 03/27/2007 */ 1746 if ((if_name=malloc(strlen(optarg)+1)) == NULL) 1747 { 1748 fprintf(stderr, "malloc\n"); 1749 exit(1); 1750 } 1751 strcpy(if_name, optarg); 1752 /* wklin added start, 01/15/2007 */ 1753 if (log_file != NULL) 1754 fclose(log_file); 1755 if ((log_file=fopen("/dev/null", "w")) == NULL) { 1756 fprintf(stderr, "fopen\n"); 1757 exit(1); 1758 } 1759 /* wklin added end, 01/15/2007 */ 1760 break; 1761 1762 case 'L': /* log file */ 1763 opt_verbose = 1; 1764 if (log_file != NULL) 1765 fclose(log_file); 1766 if ((log_file=fopen(optarg, "w")) == NULL) 1767 { 1768 fprintf(stderr, "fopen\n"); 1769 exit(1); 1770 } 1771 if (setvbuf(log_file, NULL, _IONBF, 0) != 0) 1772 { 1773 fprintf(stderr, "setvbuf\n"); 1774 exit(1); 1775 } 1776 break; 1777 case 'V': /* version */ 1778 printf("pppoe version %d.%d\n", VERSION_MAJOR, VERSION_MINOR); 1779 exit(0); 1780 break; 1781 case 'E': /* error file */ 1782 if ((error_file = fopen(optarg, "w")) == NULL) 1783 { 1784 fprintf(stderr, "fopen\n"); 1785 exit(1); 1786 } 1787 if (setvbuf(error_file, NULL, _IONBF, 0) != 0) 1788 { 1789 fprintf(stderr, "setvbuf\n"); 1790 exit(1); 1791 } 1792 break; 1793 /* foxconn wklin added start, 03/27/2007, service name */ 1794 case 'S': /* set service name*/ 1795 if (service_name != NULL) 1796 free(service_name); 1797 if ((service_name=malloc(strlen(optarg)+1)) == NULL) { 1798 fprintf(stderr, "malloc\n"); 1799 exit(1); 1800 } 1801 strcpy(service_name, optarg); 1802 break; 1803 /* foxconn wklin added end, 03/27/2007 */ 1804 default: 1805 fprintf(stderr, "Unknown option %c\n", optopt); 1806 exit(1); 1807 } 1808 1809 /* Foxconn added start, Winster Chan, 06/26/2006 */ 1810 /* Foxconn removed start pling 01/17/2007, not necessary */ 1811#if 0 1812 char poeIfName[32]; 1813 if (!(fp = fopen(PPP_PPPOE_IFNAME, "r"))) { 1814 perror(PPP_PPPOE_IFNAME); 1815 } 1816 else { 1817 if(fgets(buf, sizeof(buf), fp)) { 1818 sscanf(buf, "%s", poeIfName); 1819 } 1820 } 1821 1822 if (if_name == 0) 1823 { 1824 /* if_name = "eth0"; */ 1825 if ((if_name=malloc(strlen(poeIfName+1))) == NULL) { 1826 fprintf(stderr, "malloc\n"); 1827 exit(1); 1828 } 1829 strcpy(if_name, poeIfName); 1830 } 1831#endif 1832 /* Foxconn removed end pling 01/17/2007, not necessary */ 1833 /* Foxconn added end, Winster Chan, 06/26/2006 */ 1834 /* allocate packet once */ 1835 packet = malloc(PACKETBUF); 1836 assert(packet != NULL); 1837 1838 /* create the raw socket we need */ 1839 1840 signal(SIGINT, sigint); 1841 signal(SIGTERM, sigint); 1842#ifdef NEW_WANDETECT 1843 signal(SIGUSR1, sigint2);/*Foxconn added James 11/11/2008 @new_internet_detection*/ 1844#endif 1845 1846 /* Foxconn added start, Winster Chan, 06/26/2006 */ 1847 pptp_pppox_open(&poxfd, &pppfd); 1848 /* Foxconn added end, Winster Chan, 06/26/2006 */ 1849 1850 if ((disc_sock = open_interface(if_name,ETH_P_PPPOE_DISC,src_addr)) < 0) 1851 { 1852 fprintf(error_file, "pppoe: unable to create raw socket\n"); 1853 return 1; 1854 } 1855 1856 /* initiate connection */ 1857 1858 /* Foxconn added start Winster Chan 12/05/2005 */ 1859 if (!(fp = fopen(PPP_PPPOE_SESSION, "r"))) { 1860 ; /* perror(PPP_PPPOE_SESSION);*/ /*foxconn wklin removed, 08/13/2007 */ 1861 } 1862 else { 1863 unsigned int nMacAddr[ETH_ALEN]; 1864 int nSessId, i; 1865 char cMacAddr[ETH_ALEN]; 1866 unsigned short usSessId; 1867 1868 /* Init variables */ 1869 for (i=0; i<ETH_ALEN; i++) { 1870 nMacAddr[i] = 0; 1871 cMacAddr[i] = 0x0; 1872 } 1873 nSessId = 0; 1874 1875 /* Get the PPPoE server MAC address and Session ID from file */ 1876 if(fgets(buf, sizeof(buf), fp)) { 1877 sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x %d", 1878 &nMacAddr[0], &nMacAddr[1], &nMacAddr[2], 1879 &nMacAddr[3], &nMacAddr[4], &nMacAddr[5], 1880 &nSessId); 1881 1882 /* Transfer types of data */ 1883 for (i=0; i<ETH_ALEN; i++) { 1884 cMacAddr[i] = (char)nMacAddr[i]; 1885 } 1886 usSessId = (unsigned short)nSessId; 1887 1888 /* Check if the previous MAC address and Session ID exist. */ 1889 if (!((cMacAddr[0]==0x0) && (cMacAddr[1]==0x0) && (cMacAddr[2]==0x0) && 1890 (cMacAddr[3]==0x0) && (cMacAddr[4]==0x0) && (cMacAddr[5]==0x0)) && 1891 (htons(usSessId) != 0x0)) { 1892 1893 /* send PADT to server to clear the previous connection */ 1894 if ((pkt_size = create_padt(packet, src_addr, cMacAddr, 1895 (unsigned short)htons(usSessId))) == 0) { 1896 fprintf(stderr, "pppoe: unable to create PADT packet\n"); 1897 fclose(fp); 1898 /*exit(1);*/ 1899 cleanup_and_exit(1); /* foxconn modified by EricHuang, 05/24/2007 */ 1900 } 1901 if (send_packet(disc_sock, packet, pkt_size+14, if_name) < 0) { 1902 fprintf(stderr, "pppoe: unable to send PADT packet\n"); 1903 fclose(fp); 1904 /*exit(1);*/ 1905 cleanup_and_exit(1); /* foxconn modified by EricHuang, 05/24/2007 */ 1906 } else { 1907 fprintf(stderr, "PPPOE: PADT sent\n"); /* foxconn wklin added, 07/26/2007 */ 1908 } 1909 1910 /* Foxconn modified start, Winster Chan, 06/26/2006 */ 1911 /*pptp_pppox_release(&poxfd, &pppfd);*/ /* foxconn removed by EricHuang, 05/24/2007 */ 1912 /* Foxconn modified end, Winster Chan, 06/26/2006 */ 1913 1914 /* Waiting 3 seconds for server finishing the termination */ 1915 sleep(3); 1916 } 1917 } 1918 fclose(fp); 1919 } 1920 /* Foxconn added end Winster Chan 12/05/2005 */ 1921 1922 /* start the PPPoE session */ 1923 /* foxconn wklin modified, 03/27/2007, add service name */ 1924 if ((pkt_size = create_padi(packet, src_addr, service_name)) == 0) { 1925 fprintf(stderr, "pppoe: unable to create PADI packet\n"); 1926 exit(1); 1927 } 1928 /* send the PADI packet */ 1929 if (send_packet(disc_sock, packet, pkt_size, if_name) < 0) { 1930 fprintf(stderr, "pppoe: unable to send PADI packet\n"); 1931 exit(1); 1932 } 1933 1934 time(&tm); /* foxconn wklin added, 12/27/2007, for storing PADI time */ 1935 /* wait for PADO */ 1936 while ((ret_sock = read_packet(disc_sock, packet, &pkt_size)) != disc_sock || 1937 (packet->code != CODE_PADO )) { /* foxconn wklin modified, 12/27/2007 */ 1938 fprintf(log_file, "pppoe: unexpected packet %x\n", 1939 packet->code); 1940 /* foxconn wklin added start, 12/27/2007 */ 1941 if (ret_sock == disc_sock && 1942 (packet->code == CODE_PADI || packet->code == CODE_PADR)) { 1943 if (time(NULL) - tm < 3) 1944 continue; 1945 } 1946 /* foxconn wklin added end, 12/27/2007 */ 1947 /* wklin added start, 01/10/2007 */ 1948 /* fprintf(stderr, "pppoe: resend PADI\n"); */ 1949 /* start the PPPoE session */ 1950 /* foxconn wklin modified, 03/27/2007, add service name */ 1951 if ((pkt_size = create_padi(packet, src_addr, service_name)) == 0) { 1952 fprintf(stderr, "pppoe: unable to create PADI packet\n"); 1953 exit(1); 1954 } 1955 /* send the PADI packet */ 1956 if (send_packet(disc_sock, packet, pkt_size, if_name) < 0) { 1957 fprintf(stderr, "pppoe: unable to send PADI packet\n"); 1958 exit(1); 1959 } 1960 time(&tm); /* foxconn added, 12/27/2007, for storing PADI time */ 1961 /* wklin added end, 01/10/2007 */ 1962 continue; 1963 } 1964 1965 /* Foxconn added start pling 12/20/2006 */ 1966 /* Touch a file on /tmp to indicate PADO is received */ 1967 if (1) 1968 { 1969 FILE *fp; 1970 struct sysinfo info; 1971 /* foxconn wklin modified start, 07/26/2007 */ 1972 /* system("echo \"DEBUG: PADO received\" > /dev/console"); */ 1973 fprintf(stderr, "PPPOE: PADO received\n"); 1974 /* foxconn wklin modified end, 07/26/2007 */ 1975 if ((fp = fopen("/tmp/PADO", "w")) != NULL) { 1976 sysinfo(&info); /* save current time in file */ 1977 fprintf(fp, "%ld", info.uptime); 1978 fclose(fp); 1979 } 1980 } 1981 /* Foxconn added end ling 12/20/2006 */ 1982 1983 1984#ifdef __linux__ 1985 memcpy(dst_addr, packet->ethhdr.h_source, sizeof(dst_addr)); 1986#else 1987 memcpy(dst_addr, packet->ethhdr.ether_shost, sizeof(dst_addr)); 1988#endif 1989 /* Foxconn added start Winster Chan 11/25/2005 */ 1990 /* Stored tags of PADO */ 1991 memset(pado_tags, 0x0, sizeof(pado_tags)); 1992 if ((htons(packet->length) < 0) || (htons(packet->length) > sizeof(pado_tags))) { 1993 pado_tag_size = sizeof(pado_tags); 1994 } 1995 else { 1996 pado_tag_size = (int)(htons(packet->length)); 1997 } 1998 memcpy((char *)pado_tags, (char *)(packet + 1), pado_tag_size); 1999 /* Foxconn added end Winster Chan 11/25/2005 */ 2000 2001 /* send PADR */ 2002 /* foxconn wklin modified, 03/27/2007, add service name */ 2003 if ((pkt_size = create_padr(packet, src_addr, dst_addr, service_name)) == 0) { 2004 fprintf(stderr, "pppoe: unable to create PADR packet\n"); 2005 exit(1); 2006 } 2007 if (send_packet(disc_sock, packet, pkt_size+14, if_name) < 0) { 2008 fprintf(stderr, "pppoe: unable to send PADR packet\n"); 2009 exit(1); 2010 } 2011 2012 /* wait for PADS */ 2013#ifdef __linux__ 2014 while (read_packet(disc_sock, packet, &pkt_size) != disc_sock || 2015 (memcmp(packet->ethhdr.h_source, dst_addr, sizeof(dst_addr)) != 0) || 2016 (packet->code != CODE_PADS && packet->code != CODE_PADT)) /* foxconn wklin modified, 08/09/2007 */ 2017#else 2018 while (read_packet(disc_sock, packet, &pkt_size) != disc_sock || 2019 (memcmp(packet->ethhdr.ether_shost, 2020 dst_addr, sizeof(dst_addr)) != 0)) 2021#endif 2022 { 2023 static int retried=0; /* wklin added, 01/26/2007 */ 2024 /* foxconn wklin removed start, 08/09/2007 */ 2025 /* if (packet->code != CODE_PADS && packet->code != CODE_PADT) 2026 fprintf(log_file, "pppoe: unexpected packet %x\n", packet->code); 2027 */ 2028 /* foxconn wklin removed end, 08/09/2007 */ 2029 2030 /* wklin modified start, 01/26/2007 */ 2031 /* send PADR */ 2032 /* foxconn wklin modified, 03/27/2007, add service name */ 2033 if ((pkt_size = create_padr(packet, src_addr, dst_addr, service_name)) == 0) { 2034 fprintf(stderr, "pppoe: unable to create PADR packet\n"); 2035 exit(1); 2036 } 2037 if (send_packet(disc_sock, packet, pkt_size+14, if_name) < 0) { 2038 fprintf(stderr, "pppoe: unable to send PADR packet\n"); 2039 exit(1); 2040 } 2041 if (retried++ == 5) { 2042 retried = 0; 2043 packet->code = CODE_PADT; 2044 break; 2045 } 2046 /* wklin modified end, 01/26/2007 */ 2047 continue; 2048 } 2049 2050 /* foxconn James added start, 11/12/2008 @new_internet_detection */ 2051#ifdef NEW_WANDETECT 2052 if (packet->code == CODE_PADS) 2053 { 2054 FILE *fp; 2055 struct sysinfo info; 2056 2057 time(&tm); 2058 fprintf(stderr, "PPPOE: PADS received %s\n", ctime(&tm)); 2059 if ((fp = fopen("/tmp/PADS", "w")) != NULL) { 2060 sysinfo(&info); /* save current time in file */ 2061 fprintf(fp, "%ld", info.uptime); 2062 fclose(fp); 2063 } 2064 } 2065#endif 2066 /* foxconn James added end, 11/12/2008 @new_internet_detection */ 2067 2068 2069 if (packet->code == CODE_PADT) /* early termination */ 2070 { 2071 cleanup_and_exit(0); 2072 } 2073 2074 session = packet->session; 2075 2076 /* foxconn wklin added start, 07/31/2007 */ 2077 if (session == 0) { /* PADS generic error */ 2078 sleep(3); /* wait for 3 seconds and exit, retry */ 2079 cleanup_and_exit(0); 2080 } 2081 2082 /* fprintf(stderr, "PPPOE: session id = 0x%08x\n", session); */ 2083 /* foxconn wklin added end, 07/31/2007 */ 2084 2085 if ((sess_sock = open_interface(if_name,ETH_P_PPPOE_SESS,NULL)) < 0) { 2086 fprintf(log_file, "pppoe: unable to create raw socket\n"); 2087 cleanup_and_exit(1); 2088 } 2089 2090 /* Foxconn added start, Winster Chan, 06/26/2006 */ 2091 memcpy(dstMac, dst_addr, ETH_ALEN); 2092 sessId = packet->session; 2093 2094 /* Connect pptp kernel module */ 2095 /* foxconn wklin modified start, 07/31/2007 */ 2096 if ( 0 > pptp_pppox_connect(&poxfd, &pppfd)) 2097 cleanup_and_exit(1); 2098 /* foxconn wklin modified end, 07/31/2007 */ 2099 /* Foxconn added end, Winster Chan, 06/26/2006 */ 2100 2101 /* Foxconn added start Winster Chan 12/05/2005 */ 2102 if (!(fp = fopen(PPP_PPPOE_SESSION, "w"))) { 2103 perror(PPP_PPPOE_SESSION); 2104 } 2105 else { 2106 /* Save the PPPoE server MAC address and Session ID */ 2107 fprintf(fp, "%02x:%02x:%02x:%02x:%02x:%02x %d\n", 2108 (unsigned char)(dst_addr[0]), (unsigned char)(dst_addr[1]), 2109 (unsigned char)(dst_addr[2]), (unsigned char)(dst_addr[3]), 2110 (unsigned char)(dst_addr[4]), (unsigned char)(dst_addr[5]), 2111 (int)htons(session)); 2112 fclose(fp); 2113 } 2114 /* Foxconn added end Winster Chan 12/05/2005 */ 2115 2116 clean_child = 0; 2117 signal(SIGCHLD, sigchild); 2118 2119 /* all sockets are open fork off handlers */ 2120 if ((sess_listen = fork()) == 0) 2121 { 2122 sess_handler(); /* child */ 2123 } 2124 if (sess_listen < 0) { 2125 perror("pppoe: fork"); 2126 cleanup_and_exit(1); 2127 } 2128 if ((pppd_listen = fork()) == 0) 2129 { 2130 pppd_handler(); /* child */ 2131 } 2132 if (pppd_listen < 0) { 2133 perror("pppoe: fork"); 2134 cleanup_and_exit(1); 2135 } 2136 2137 /* wait for all children to die */ 2138 /* this is not perfect - race conditions on dying children are still 2139 possible */ 2140 while(1) { 2141 if (waitpid((pid_t)-1,NULL,WNOHANG) < 0 && errno == ECHILD) 2142 break; /* all children dead */ 2143 if (read_packet(disc_sock, packet, &pkt_size) == disc_sock) { 2144 /* foxconn wklin modified, 03/23/2007, check PADT session ID */ 2145 /* foxconn wklin added start, 07/26/2007 */ 2146 if (packet->code == CODE_PADT) 2147 fprintf(stderr, "PPPOE: PADT received (%08x/%08x)\n", 2148 packet->session, session); 2149 /* foxconn wklin added end, 07/26/2007 */ 2150 if (packet->code == CODE_PADT && packet->session == session) 2151 { 2152 cleanup_and_exit(1); 2153 } 2154 } 2155 /* clean up any dead children */ 2156 while (waitpid((pid_t)-1,NULL,WNOHANG) > 0) 2157 ; 2158 2159 } 2160 /* Foxconn added start, Winster Chan, 06/26/2006 */ 2161 close(pppfd); pppfd = -1; 2162 close(poxfd); poxfd = -1; 2163 /* Foxconn added end, Winster Chan, 06/26/2006 */ 2164 2165 return 0; 2166} 2167