1/*********************************************************************** 2* 3* discovery.c 4* 5* Perform PPPoE discovery 6* 7* Copyright (C) 1999-2012 by Roaring Penguin Software Inc. 8* 9* LIC: GPL 10* 11***********************************************************************/ 12 13static char const RCSID[] = 14"$Id$"; 15#define _GNU_SOURCE 1 16 17#include "pppoe.h" 18 19#ifdef HAVE_SYSLOG_H 20#include <syslog.h> 21#endif 22 23#include <string.h> 24#include <stdlib.h> 25#include <errno.h> 26 27#ifdef HAVE_SYS_TIME_H 28#include <sys/time.h> 29#endif 30#include <time.h> 31 32#ifdef HAVE_SYS_UIO_H 33#include <sys/uio.h> 34#endif 35 36#ifdef HAVE_UNISTD_H 37#include <unistd.h> 38#endif 39 40#ifdef USE_LINUX_PACKET 41#include <sys/ioctl.h> 42#include <fcntl.h> 43#endif 44 45#include <signal.h> 46 47#ifdef PLUGIN 48#include "pppd/pppd.h" 49#include "pppd/fsm.h" 50#include "pppd/lcp.h" 51extern int got_sigterm; 52extern int got_sighup; 53#else 54int persist = 0; 55#endif 56 57/********************************************************************** 58*%FUNCTION: parseForHostUniq 59*%ARGUMENTS: 60* type -- tag type 61* len -- tag length 62* data -- tag data. 63* extra -- user-supplied pointer. This is assumed to be a pointer to int. 64*%RETURNS: 65* Nothing 66*%DESCRIPTION: 67* If a HostUnique tag is found which matches our PID, sets *extra to 1. 68***********************************************************************/ 69static void 70parseForHostUniq(UINT16_t type, UINT16_t len, unsigned char *data, 71 void *extra) 72{ 73 int *val = (int *) extra; 74 if (type == TAG_HOST_UNIQ && len == sizeof(pid_t)) { 75 pid_t tmp; 76 memcpy(&tmp, data, len); 77 if (tmp == getpid()) { 78 *val = 1; 79 } 80 } 81} 82 83/********************************************************************** 84*%FUNCTION: packetIsForMe 85*%ARGUMENTS: 86* conn -- PPPoE connection info 87* packet -- a received PPPoE packet 88*%RETURNS: 89* 1 if packet is for this PPPoE daemon; 0 otherwise. 90*%DESCRIPTION: 91* If we are using the Host-Unique tag, verifies that packet contains 92* our unique identifier. 93***********************************************************************/ 94static int 95packetIsForMe(PPPoEConnection *conn, PPPoEPacket *packet) 96{ 97 int forMe = 0; 98 99 /* If packet is not directed to our MAC address, forget it */ 100 if (memcmp(packet->ethHdr.h_dest, conn->myEth, ETH_ALEN)) return 0; 101 102 /* If we're not using the Host-Unique tag, then accept the packet */ 103 if (!conn->useHostUniq) return 1; 104 105 parsePacket(packet, parseForHostUniq, &forMe); 106 return forMe; 107} 108 109/********************************************************************** 110*%FUNCTION: parsePADOTags 111*%ARGUMENTS: 112* type -- tag type 113* len -- tag length 114* data -- tag data 115* extra -- extra user data. Should point to a PacketCriteria structure 116* which gets filled in according to selected AC name and service 117* name. 118*%RETURNS: 119* Nothing 120*%DESCRIPTION: 121* Picks interesting tags out of a PADO packet 122***********************************************************************/ 123static void 124parsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data, 125 void *extra) 126{ 127 struct PacketCriteria *pc = (struct PacketCriteria *) extra; 128 PPPoEConnection *conn = pc->conn; 129 int i; 130#ifdef PLUGIN 131 UINT16_t mru; 132#endif 133 134 switch(type) { 135 case TAG_AC_NAME: 136 pc->seenACName = 1; 137 if (conn->printACNames) { 138 printf("Access-Concentrator: %.*s\n", (int) len, data); 139 } 140 if (conn->acName && len == strlen(conn->acName) && 141 !strncmp((char *) data, conn->acName, len)) { 142 pc->acNameOK = 1; 143 } 144 break; 145 case TAG_SERVICE_NAME: 146 pc->seenServiceName = 1; 147 if (conn->printACNames && len > 0) { 148 printf(" Service-Name: %.*s\n", (int) len, data); 149 } 150 if (conn->serviceName && len == strlen(conn->serviceName) && 151 !strncmp((char *) data, conn->serviceName, len)) { 152 pc->serviceNameOK = 1; 153 } 154 break; 155 case TAG_AC_COOKIE: 156 if (conn->printACNames) { 157 printf("Got a cookie:"); 158 /* Print first 20 bytes of cookie */ 159 for (i=0; i<len && i < 20; i++) { 160 printf(" %02x", (unsigned) data[i]); 161 } 162 if (i < len) printf("..."); 163 printf("\n"); 164 } 165 conn->cookie.type = htons(type); 166 conn->cookie.length = htons(len); 167 memcpy(conn->cookie.payload, data, len); 168 break; 169 case TAG_RELAY_SESSION_ID: 170 if (conn->printACNames) { 171 printf("Got a Relay-ID:"); 172 /* Print first 20 bytes of relay ID */ 173 for (i=0; i<len && i < 20; i++) { 174 printf(" %02x", (unsigned) data[i]); 175 } 176 if (i < len) printf("..."); 177 printf("\n"); 178 } 179 conn->relayId.type = htons(type); 180 conn->relayId.length = htons(len); 181 memcpy(conn->relayId.payload, data, len); 182 break; 183 case TAG_SERVICE_NAME_ERROR: 184 if (conn->printACNames) { 185 printf("Got a Service-Name-Error tag: %.*s\n", (int) len, data); 186 } else { 187 pktLogErrs("PADO", type, len, data, extra); 188 pc->gotError = 1; 189 if (!persist) { 190 exit(1); 191 } 192 } 193 break; 194 case TAG_AC_SYSTEM_ERROR: 195 if (conn->printACNames) { 196 printf("Got a System-Error tag: %.*s\n", (int) len, data); 197 } else { 198 pktLogErrs("PADO", type, len, data, extra); 199 pc->gotError = 1; 200 if (!persist) { 201 exit(1); 202 } 203 } 204 break; 205 case TAG_GENERIC_ERROR: 206 if (conn->printACNames) { 207 printf("Got a Generic-Error tag: %.*s\n", (int) len, data); 208 } else { 209 pktLogErrs("PADO", type, len, data, extra); 210 pc->gotError = 1; 211 if (!persist) { 212 exit(1); 213 } 214 } 215 break; 216#ifdef PLUGIN 217 case TAG_PPP_MAX_PAYLOAD: 218 if (len == sizeof(mru)) { 219 memcpy(&mru, data, sizeof(mru)); 220 mru = ntohs(mru); 221 if (mru >= ETH_PPPOE_MTU) { 222 if (lcp_allowoptions[0].mru > mru) lcp_allowoptions[0].mru = mru; 223 if (lcp_wantoptions[0].mru > mru) lcp_wantoptions[0].mru = mru; 224 conn->seenMaxPayload = 1; 225 } 226 } 227 break; 228#endif 229 } 230} 231 232/********************************************************************** 233*%FUNCTION: parsePADSTags 234*%ARGUMENTS: 235* type -- tag type 236* len -- tag length 237* data -- tag data 238* extra -- extra user data (pointer to PPPoEConnection structure) 239*%RETURNS: 240* Nothing 241*%DESCRIPTION: 242* Picks interesting tags out of a PADS packet 243***********************************************************************/ 244static void 245parsePADSTags(UINT16_t type, UINT16_t len, unsigned char *data, 246 void *extra) 247{ 248#ifdef PLUGIN 249 UINT16_t mru; 250#endif 251 PPPoEConnection *conn = (PPPoEConnection *) extra; 252 switch(type) { 253 case TAG_SERVICE_NAME: 254 syslog(LOG_DEBUG, "PADS: Service-Name: '%.*s'", (int) len, data); 255 break; 256 case TAG_GENERIC_ERROR: 257 case TAG_AC_SYSTEM_ERROR: 258 case TAG_SERVICE_NAME_ERROR: 259 pktLogErrs("PADS", type, len, data, extra); 260 conn->PADSHadError = 1; 261 break; 262 case TAG_RELAY_SESSION_ID: 263 conn->relayId.type = htons(type); 264 conn->relayId.length = htons(len); 265 memcpy(conn->relayId.payload, data, len); 266 break; 267#ifdef PLUGIN 268 case TAG_PPP_MAX_PAYLOAD: 269 if (len == sizeof(mru)) { 270 memcpy(&mru, data, sizeof(mru)); 271 mru = ntohs(mru); 272 if (mru >= ETH_PPPOE_MTU) { 273 if (lcp_allowoptions[0].mru > mru) lcp_allowoptions[0].mru = mru; 274 if (lcp_wantoptions[0].mru > mru) lcp_wantoptions[0].mru = mru; 275 conn->seenMaxPayload = 1; 276 } 277 } 278 break; 279#endif 280 } 281} 282 283/*********************************************************************** 284*%FUNCTION: sendPADI 285*%ARGUMENTS: 286* conn -- PPPoEConnection structure 287*%RETURNS: 288* Nothing 289*%DESCRIPTION: 290* Sends a PADI packet 291***********************************************************************/ 292static void 293sendPADI(PPPoEConnection *conn) 294{ 295 PPPoEPacket packet; 296 unsigned char *cursor = packet.payload; 297 PPPoETag *svc = (PPPoETag *) (&packet.payload); 298 UINT16_t namelen = 0; 299 UINT16_t plen; 300 int omit_service_name = 0; 301 302 if (conn->serviceName) { 303 namelen = (UINT16_t) strlen(conn->serviceName); 304 if (!strcmp(conn->serviceName, "NO-SERVICE-NAME-NON-RFC-COMPLIANT")) { 305 omit_service_name = 1; 306 } 307 } 308 309 /* Set destination to Ethernet broadcast address */ 310 memset(packet.ethHdr.h_dest, 0xFF, ETH_ALEN); 311 memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN); 312 313 packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery); 314 packet.ver = 1; 315 packet.type = 1; 316 packet.code = CODE_PADI; 317 packet.session = 0; 318 319 if (!omit_service_name) { 320 plen = TAG_HDR_SIZE + namelen; 321 CHECK_ROOM(cursor, packet.payload, plen); 322 323 svc->type = TAG_SERVICE_NAME; 324 svc->length = htons(namelen); 325 326 if (conn->serviceName) { 327 memcpy(svc->payload, conn->serviceName, strlen(conn->serviceName)); 328 } 329 cursor += namelen + TAG_HDR_SIZE; 330 } else { 331 plen = 0; 332 } 333 334 /* If we're using Host-Uniq, copy it over */ 335 if (conn->useHostUniq) { 336 PPPoETag hostUniq; 337 pid_t pid = getpid(); 338 hostUniq.type = htons(TAG_HOST_UNIQ); 339 hostUniq.length = htons(sizeof(pid)); 340 memcpy(hostUniq.payload, &pid, sizeof(pid)); 341 CHECK_ROOM(cursor, packet.payload, sizeof(pid) + TAG_HDR_SIZE); 342 memcpy(cursor, &hostUniq, sizeof(pid) + TAG_HDR_SIZE); 343 cursor += sizeof(pid) + TAG_HDR_SIZE; 344 plen += sizeof(pid) + TAG_HDR_SIZE; 345 } 346 347#ifdef PLUGIN 348 /* Add our maximum MTU/MRU */ 349 if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) { 350 PPPoETag maxPayload; 351 UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru)); 352 maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD); 353 maxPayload.length = htons(sizeof(mru)); 354 memcpy(maxPayload.payload, &mru, sizeof(mru)); 355 CHECK_ROOM(cursor, packet.payload, sizeof(mru) + TAG_HDR_SIZE); 356 memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE); 357 cursor += sizeof(mru) + TAG_HDR_SIZE; 358 plen += sizeof(mru) + TAG_HDR_SIZE; 359 } 360#endif 361 362 packet.length = htons(plen); 363 364 sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE)); 365#ifdef DEBUGGING_ENABLED 366 if (conn->debugFile) { 367 dumpPacket(conn->debugFile, &packet, "SENT"); 368 fprintf(conn->debugFile, "\n"); 369 fflush(conn->debugFile); 370 } 371#endif 372} 373 374/********************************************************************** 375*%FUNCTION: waitForPADO 376*%ARGUMENTS: 377* conn -- PPPoEConnection structure 378* timeout -- how long to wait (in seconds) 379*%RETURNS: 380* Nothing 381*%DESCRIPTION: 382* Waits for a PADO packet and copies useful information 383***********************************************************************/ 384static void 385waitForPADO(PPPoEConnection *conn, int timeout) 386{ 387 fd_set readable; 388 int r; 389 struct timeval tv; 390 struct timeval expire_at; 391 struct timeval now; 392 393 PPPoEPacket packet; 394 int len; 395 396 struct PacketCriteria pc; 397 pc.conn = conn; 398#ifdef PLUGIN 399 conn->seenMaxPayload = 0; 400#endif 401 402 if (gettimeofday(&expire_at, NULL) < 0) { 403 fatalSys("gettimeofday (waitForPADO)"); 404 } 405 expire_at.tv_sec += timeout; 406 407 do { 408#ifdef PLUGIN 409 if (got_sigterm || got_sighup) return; 410#endif 411 if (BPF_BUFFER_IS_EMPTY) { 412 if (gettimeofday(&now, NULL) < 0) { 413 fatalSys("gettimeofday (waitForPADO)"); 414 } 415 tv.tv_sec = expire_at.tv_sec - now.tv_sec; 416 tv.tv_usec = expire_at.tv_usec - now.tv_usec; 417 if (tv.tv_usec < 0) { 418 tv.tv_usec += 1000000; 419 if (tv.tv_sec) { 420 tv.tv_sec--; 421 } else { 422 /* Timed out */ 423 return; 424 } 425 } 426 if (tv.tv_sec <= 0 && tv.tv_usec <= 0) { 427 /* Timed out */ 428 return; 429 } 430 431 FD_ZERO(&readable); 432 FD_SET(conn->discoverySocket, &readable); 433 434 while(1) { 435 r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv); 436 if (r >= 0 || errno != EINTR) break; 437#ifdef PLUGIN 438 if (got_sigterm || got_sighup) return; 439#endif 440 } 441 if (r < 0) { 442 fatalSys("select (waitForPADO)"); 443 } 444 if (r == 0) { 445 /* Timed out */ 446 return; 447 } 448 } 449 450 /* Get the packet */ 451 receivePacket(conn->discoverySocket, &packet, &len); 452 453 /* Check length */ 454 if (ntohs(packet.length) + HDR_SIZE > len) { 455 syslog(LOG_ERR, "Bogus PPPoE length field (%u)", 456 (unsigned int) ntohs(packet.length)); 457 continue; 458 } 459 460#ifdef USE_BPF 461 /* If it's not a Discovery packet, loop again */ 462 if (etherType(&packet) != Eth_PPPOE_Discovery) continue; 463#endif 464 465#ifdef DEBUGGING_ENABLED 466 if (conn->debugFile) { 467 dumpPacket(conn->debugFile, &packet, "RCVD"); 468 fprintf(conn->debugFile, "\n"); 469 fflush(conn->debugFile); 470 } 471#endif 472 /* If it's not for us, loop again */ 473 if (!packetIsForMe(conn, &packet)) continue; 474 475 if (packet.code == CODE_PADO) { 476 if (BROADCAST(packet.ethHdr.h_source)) { 477 printErr("Ignoring PADO packet from broadcast MAC address"); 478 continue; 479 } 480#ifdef PLUGIN 481 if (conn->req_peer 482 && memcmp(packet.ethHdr.h_source, conn->req_peer_mac, ETH_ALEN) != 0) { 483 warn("Ignoring PADO packet from wrong MAC address"); 484 continue; 485 } 486#endif 487 pc.gotError = 0; 488 pc.seenACName = 0; 489 pc.seenServiceName = 0; 490 pc.acNameOK = (conn->acName) ? 0 : 1; 491 pc.serviceNameOK = (conn->serviceName) ? 0 : 1; 492 parsePacket(&packet, parsePADOTags, &pc); 493 if (pc.gotError) { 494 printErr("Error in PADO packet"); 495 continue; 496 } 497 498 if (!pc.seenACName) { 499 printErr("Ignoring PADO packet with no AC-Name tag"); 500 continue; 501 } 502 if (!pc.seenServiceName) { 503 printErr("Ignoring PADO packet with no Service-Name tag"); 504 continue; 505 } 506 conn->numPADOs++; 507 if (pc.acNameOK && pc.serviceNameOK) { 508 memcpy(conn->peerEth, packet.ethHdr.h_source, ETH_ALEN); 509 if (conn->printACNames) { 510 printf("AC-Ethernet-Address: %02x:%02x:%02x:%02x:%02x:%02x\n", 511 (unsigned) conn->peerEth[0], 512 (unsigned) conn->peerEth[1], 513 (unsigned) conn->peerEth[2], 514 (unsigned) conn->peerEth[3], 515 (unsigned) conn->peerEth[4], 516 (unsigned) conn->peerEth[5]); 517 printf("--------------------------------------------------\n"); 518 continue; 519 } 520 conn->discoveryState = STATE_RECEIVED_PADO; 521 break; 522 } 523 } 524 } while (conn->discoveryState != STATE_RECEIVED_PADO); 525} 526 527/*********************************************************************** 528*%FUNCTION: sendPADR 529*%ARGUMENTS: 530* conn -- PPPoE connection structur 531*%RETURNS: 532* Nothing 533*%DESCRIPTION: 534* Sends a PADR packet 535***********************************************************************/ 536static void 537sendPADR(PPPoEConnection *conn) 538{ 539 PPPoEPacket packet; 540 PPPoETag *svc = (PPPoETag *) packet.payload; 541 unsigned char *cursor = packet.payload; 542 543 UINT16_t namelen = 0; 544 UINT16_t plen; 545 546 if (conn->serviceName) { 547 namelen = (UINT16_t) strlen(conn->serviceName); 548 } 549 plen = TAG_HDR_SIZE + namelen; 550 CHECK_ROOM(cursor, packet.payload, plen); 551 552 memcpy(packet.ethHdr.h_dest, conn->peerEth, ETH_ALEN); 553 memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN); 554 555 packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery); 556 packet.ver = 1; 557 packet.type = 1; 558 packet.code = CODE_PADR; 559 packet.session = 0; 560 561 svc->type = TAG_SERVICE_NAME; 562 svc->length = htons(namelen); 563 if (conn->serviceName) { 564 memcpy(svc->payload, conn->serviceName, namelen); 565 } 566 cursor += namelen + TAG_HDR_SIZE; 567 568 /* If we're using Host-Uniq, copy it over */ 569 if (conn->useHostUniq) { 570 PPPoETag hostUniq; 571 pid_t pid = getpid(); 572 hostUniq.type = htons(TAG_HOST_UNIQ); 573 hostUniq.length = htons(sizeof(pid)); 574 memcpy(hostUniq.payload, &pid, sizeof(pid)); 575 CHECK_ROOM(cursor, packet.payload, sizeof(pid)+TAG_HDR_SIZE); 576 memcpy(cursor, &hostUniq, sizeof(pid) + TAG_HDR_SIZE); 577 cursor += sizeof(pid) + TAG_HDR_SIZE; 578 plen += sizeof(pid) + TAG_HDR_SIZE; 579 } 580 581 /* Copy cookie and relay-ID if needed */ 582 if (conn->cookie.type) { 583 CHECK_ROOM(cursor, packet.payload, 584 ntohs(conn->cookie.length) + TAG_HDR_SIZE); 585 memcpy(cursor, &conn->cookie, ntohs(conn->cookie.length) + TAG_HDR_SIZE); 586 cursor += ntohs(conn->cookie.length) + TAG_HDR_SIZE; 587 plen += ntohs(conn->cookie.length) + TAG_HDR_SIZE; 588 } 589 590 if (conn->relayId.type) { 591 CHECK_ROOM(cursor, packet.payload, 592 ntohs(conn->relayId.length) + TAG_HDR_SIZE); 593 memcpy(cursor, &conn->relayId, ntohs(conn->relayId.length) + TAG_HDR_SIZE); 594 cursor += ntohs(conn->relayId.length) + TAG_HDR_SIZE; 595 plen += ntohs(conn->relayId.length) + TAG_HDR_SIZE; 596 } 597 598#ifdef PLUGIN 599 /* Add our maximum MTU/MRU */ 600 if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) { 601 PPPoETag maxPayload; 602 UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru)); 603 maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD); 604 maxPayload.length = htons(sizeof(mru)); 605 memcpy(maxPayload.payload, &mru, sizeof(mru)); 606 CHECK_ROOM(cursor, packet.payload, sizeof(mru) + TAG_HDR_SIZE); 607 memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE); 608 cursor += sizeof(mru) + TAG_HDR_SIZE; 609 plen += sizeof(mru) + TAG_HDR_SIZE; 610 } 611#endif 612 613 packet.length = htons(plen); 614 sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE)); 615#ifdef DEBUGGING_ENABLED 616 if (conn->debugFile) { 617 dumpPacket(conn->debugFile, &packet, "SENT"); 618 fprintf(conn->debugFile, "\n"); 619 fflush(conn->debugFile); 620 } 621#endif 622} 623 624/********************************************************************** 625*%FUNCTION: waitForPADS 626*%ARGUMENTS: 627* conn -- PPPoE connection info 628* timeout -- how long to wait (in seconds) 629*%RETURNS: 630* Nothing 631*%DESCRIPTION: 632* Waits for a PADS packet and copies useful information 633***********************************************************************/ 634static void 635waitForPADS(PPPoEConnection *conn, int timeout) 636{ 637 fd_set readable; 638 int r; 639 struct timeval tv; 640 struct timeval expire_at; 641 struct timeval now; 642 643 PPPoEPacket packet; 644 int len; 645 646 if (gettimeofday(&expire_at, NULL) < 0) { 647 fatalSys("gettimeofday (waitForPADS)"); 648 } 649 expire_at.tv_sec += timeout; 650 651 do { 652#ifdef PLUGIN 653 if (got_sigterm || got_sighup) return; 654#endif 655 if (BPF_BUFFER_IS_EMPTY) { 656 if (gettimeofday(&now, NULL) < 0) { 657 fatalSys("gettimeofday (waitForPADS)"); 658 } 659 tv.tv_sec = expire_at.tv_sec - now.tv_sec; 660 tv.tv_usec = expire_at.tv_usec - now.tv_usec; 661 if (tv.tv_usec < 0) { 662 tv.tv_usec += 1000000; 663 if (tv.tv_sec) { 664 tv.tv_sec--; 665 } else { 666 /* Timed out */ 667 return; 668 } 669 } 670 if (tv.tv_sec <= 0 && tv.tv_usec <= 0) { 671 /* Timed out */ 672 return; 673 } 674 675 FD_ZERO(&readable); 676 FD_SET(conn->discoverySocket, &readable); 677 678 while(1) { 679 r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv); 680 if (r >= 0 || errno != EINTR) break; 681#ifdef PLUGIN 682 if (got_sigterm || got_sighup) return; 683#endif 684 } 685 if (r < 0) { 686 fatalSys("select (waitForPADS)"); 687 } 688 if (r == 0) { 689 /* Timed out */ 690 return; 691 } 692 } 693 694 /* Get the packet */ 695 receivePacket(conn->discoverySocket, &packet, &len); 696 697 /* Check length */ 698 if (ntohs(packet.length) + HDR_SIZE > len) { 699 syslog(LOG_ERR, "Bogus PPPoE length field (%u)", 700 (unsigned int) ntohs(packet.length)); 701 continue; 702 } 703 704#ifdef USE_BPF 705 /* If it's not a Discovery packet, loop again */ 706 if (etherType(&packet) != Eth_PPPOE_Discovery) continue; 707#endif 708#ifdef DEBUGGING_ENABLED 709 if (conn->debugFile) { 710 dumpPacket(conn->debugFile, &packet, "RCVD"); 711 fprintf(conn->debugFile, "\n"); 712 fflush(conn->debugFile); 713 } 714#endif 715 /* If it's not from the AC, it's not for me */ 716 if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) continue; 717 718 /* If it's not for us, loop again */ 719 if (!packetIsForMe(conn, &packet)) continue; 720 721 /* Is it PADS? */ 722 if (packet.code == CODE_PADS) { 723 /* Parse for goodies */ 724 conn->PADSHadError = 0; 725 parsePacket(&packet, parsePADSTags, conn); 726 if (!conn->PADSHadError) { 727 conn->discoveryState = STATE_SESSION; 728 break; 729 } 730 } 731 } while (conn->discoveryState != STATE_SESSION); 732 733 /* Don't bother with ntohs; we'll just end up converting it back... */ 734 conn->session = packet.session; 735 736 syslog(LOG_INFO, "PPP session is %d (0x%x)", (int) ntohs(conn->session), 737 (unsigned int) ntohs(conn->session)); 738 739 /* RFC 2516 says session id MUST NOT be zero or 0xFFFF */ 740 if (ntohs(conn->session) == 0 || ntohs(conn->session) == 0xFFFF) { 741 syslog(LOG_ERR, "Access concentrator used a session value of %x -- the AC is violating RFC 2516", (unsigned int) ntohs(conn->session)); 742 } 743} 744 745/********************************************************************** 746*%FUNCTION: discovery 747*%ARGUMENTS: 748* conn -- PPPoE connection info structure 749*%RETURNS: 750* Nothing 751*%DESCRIPTION: 752* Performs the PPPoE discovery phase 753***********************************************************************/ 754void 755discovery(PPPoEConnection *conn) 756{ 757 int padiAttempts; 758 int padrAttempts; 759 int timeout = conn->discoveryTimeout; 760 761 /* Skip discovery? */ 762 if (conn->skipDiscovery) { 763 conn->discoveryState = STATE_SESSION; 764 if (conn->killSession) { 765 sendPADT(conn, "RP-PPPoE: Session killed manually"); 766 exit(0); 767 } 768 return; 769 } 770 771 SEND_PADI: 772 padiAttempts = 0; 773 do { 774#ifdef PLUGIN 775 if (got_sigterm || got_sighup) return; 776#endif 777 padiAttempts++; 778 if (padiAttempts > MAX_PADI_ATTEMPTS) { 779 if (persist) { 780 padiAttempts = 0; 781 timeout = conn->discoveryTimeout; 782 printErr("Timeout waiting for PADO packets"); 783 } else { 784#ifdef PLUGIN 785 printErr("Timeout waiting for PADO packets"); 786 return; 787#else 788 rp_fatal("Timeout waiting for PADO packets"); 789#endif 790 } 791 } 792 sendPADI(conn); 793 conn->discoveryState = STATE_SENT_PADI; 794 waitForPADO(conn, timeout); 795 796 /* If we're just probing for access concentrators, don't do 797 exponential backoff. This reduces the time for an unsuccessful 798 probe to 15 seconds. */ 799 if (!conn->printACNames) { 800 timeout *= 2; 801 } 802 if (conn->printACNames && conn->numPADOs) { 803 break; 804 } 805 } while (conn->discoveryState == STATE_SENT_PADI); 806 807 /* If we're only printing access concentrator names, we're done */ 808 if (conn->printACNames) { 809 exit(0); 810 } 811 812 timeout = conn->discoveryTimeout; 813 padrAttempts = 0; 814 do { 815#ifdef PLUGIN 816 if (got_sigterm || got_sighup) return; 817#endif 818 padrAttempts++; 819 if (padrAttempts > MAX_PADI_ATTEMPTS) { 820 if (persist) { 821 padrAttempts = 0; 822 timeout = conn->discoveryTimeout; 823 printErr("Timeout waiting for PADS packets"); 824 /* Go back to sending PADI again */ 825 goto SEND_PADI; 826 } else { 827#ifdef PLUGIN 828 printErr("Timeout waiting for PADS packets"); 829 return; 830#else 831 rp_fatal("Timeout waiting for PADS packets"); 832#endif 833 } 834 } 835 sendPADR(conn); 836 conn->discoveryState = STATE_SENT_PADR; 837 waitForPADS(conn, timeout); 838 timeout *= 2; 839 } while (conn->discoveryState == STATE_SENT_PADR); 840 841#ifdef PLUGIN 842 if (!conn->seenMaxPayload) { 843 /* RFC 4638: MUST limit MTU/MRU to 1492 */ 844 if (lcp_allowoptions[0].mru > ETH_PPPOE_MTU) lcp_allowoptions[0].mru = ETH_PPPOE_MTU; 845 if (lcp_wantoptions[0].mru > ETH_PPPOE_MTU) lcp_wantoptions[0].mru = ETH_PPPOE_MTU; 846 } 847#endif 848 /* We're done. */ 849 conn->discoveryState = STATE_SESSION; 850 return; 851} 852