- fd_set readable;
- int r;
- struct timeval tv;
- PPPoEPacket packet;
- int len;
-
- struct PacketCriteria pc;
- pc.conn = conn;
- pc.acNameOK = (conn->acName) ? 0 : 1;
- pc.serviceNameOK = (conn->serviceName) ? 0 : 1;
- pc.seenACName = 0;
- pc.seenServiceName = 0;
- conn->error = 0;
-
- do {
- if (BPF_BUFFER_IS_EMPTY) {
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
-
- FD_ZERO(&readable);
- FD_SET(conn->discoverySocket, &readable);
-
- while(1) {
- r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);
- if (r >= 0 || errno != EINTR) break;
- }
- if (r < 0) {
- perror("select (waitForPADO)");
- return;
- }
- if (r == 0) return; /* Timed out */
- }
-
- /* Get the packet */
- receivePacket(conn->discoverySocket, &packet, &len);
-
- /* Check length */
- if (ntohs(packet.length) + HDR_SIZE > len) {
- fprintf(stderr, "Bogus PPPoE length field (%u)\n",
- (unsigned int) ntohs(packet.length));
- continue;
- }
-
-#ifdef USE_BPF
- /* If it's not a Discovery packet, loop again */
- if (etherType(&packet) != Eth_PPPOE_Discovery) continue;
-#endif
-
- if (conn->debugFile) {
- dumpPacket(conn->debugFile, &packet, "RCVD");
- fprintf(conn->debugFile, "\n");
- fflush(conn->debugFile);
- }
- /* If it's not for us, loop again */
- if (!packetIsForMe(conn, &packet)) continue;
-
- if (packet.code == CODE_PADO) {
- if (BROADCAST(packet.ethHdr.h_source)) {
- fprintf(stderr, "Ignoring PADO packet from broadcast MAC address\n");
- continue;
- }
- parsePacket(&packet, parsePADOTags, &pc);
- if (conn->error)
- return;
- if (!pc.seenACName) {
- fprintf(stderr, "Ignoring PADO packet with no AC-Name tag\n");
- continue;
- }
- if (!pc.seenServiceName) {
- fprintf(stderr, "Ignoring PADO packet with no Service-Name tag\n");
- continue;
- }
- conn->numPADOs++;
- if (pc.acNameOK && pc.serviceNameOK) {
- memcpy(conn->peerEth, packet.ethHdr.h_source, ETH_ALEN);
- if (pppoe_verbose >= 1) {
- printf("AC-Ethernet-Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
- (unsigned) conn->peerEth[0],
- (unsigned) conn->peerEth[1],
- (unsigned) conn->peerEth[2],
- (unsigned) conn->peerEth[3],
- (unsigned) conn->peerEth[4],
- (unsigned) conn->peerEth[5]);
- printf("--------------------------------------------------\n");
- continue;
- }
- conn->discoveryState = STATE_RECEIVED_PADO;
- break;
- }
- }
- } while (conn->discoveryState != STATE_RECEIVED_PADO);