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