Home | History | Annotate | Line # | Download | only in pppoe
      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