static char const RCSID[] =
"$Id: discovery.c,v 1.6 2008/06/15 04:35:50 paulus Exp $";
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#define _GNU_SOURCE 1
#include "pppoe.h"
-#include "pppd/pppd.h"
-#include "pppd/fsm.h"
-#include "pppd/lcp.h"
+#include <pppd/pppd.h>
+#include <pppd/fsm.h>
+#include <pppd/lcp.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
+#ifdef PLUGIN
+#define signaled(x) ppp_signaled(x)
+#define get_time(x) ppp_get_time(x)
+#else
+int signaled(int signal);
+int get_time(struct timeval *tv);
+
+#endif
+
/* Calculate time remaining until *exp, return 0 if now >= *exp */
static int time_left(struct timeval *diff, struct timeval *exp)
{
!strncmp((char *) data, conn->acName, len)) {
pc->acNameOK = 1;
}
+ /* save a copy of the AC name if we can */
+ conn->actualACname = realloc(conn->actualACname, len + 1);
+ if (conn->actualACname)
+ strlcpy(conn->actualACname, (char *) data, len + 1);
break;
case TAG_SERVICE_NAME:
pc->seenServiceName = 1;
+ if (pppoe_verbose >= 1 && len > 0) {
+ info("Service-Name: %.*s", (int) len, data);
+ }
if (conn->serviceName && len == strlen(conn->serviceName) &&
!strncmp((char *) data, conn->serviceName, len)) {
pc->serviceNameOK = 1;
}
break;
case TAG_AC_COOKIE:
- conn->cookie.type = htons(type);
- conn->cookie.length = htons(len);
- memcpy(conn->cookie.payload, data, len);
+ if (pppoe_verbose >= 1) {
+ char buffer[100];
+ char *ptr = buffer;
+ ptr += sprintf(ptr, "Cookie:");
+ /* Print first 20 bytes of cookie */
+ for (i=0; i<len && i < 20; i++) {
+ ptr += sprintf(ptr, " %02x", (unsigned) data[i]);
+ }
+ if (i < len) ptr += sprintf(ptr, "...");
+ info(buffer);
+ }
+ if (conn->discoveryState != STATE_RECEIVED_PADO) {
+ conn->cookie.type = htons(type);
+ conn->cookie.length = htons(len);
+ memcpy(conn->cookie.payload, data, len);
+ }
break;
case TAG_RELAY_SESSION_ID:
- conn->relayId.type = htons(type);
- conn->relayId.length = htons(len);
- memcpy(conn->relayId.payload, data, len);
+ if (pppoe_verbose >= 1) {
+ char buffer[100];
+ char *ptr = buffer;
+ ptr += sprintf(ptr, "Relay-ID:");
+ /* Print first 20 bytes of relay ID */
+ for (i=0; i<len && i < 20; i++) {
+ ptr += printf(ptr, " %02x", (unsigned) data[i]);
+ }
+ if (i < len) ptr += printf(ptr, "...");
+ info(buffer);
+ }
+ if (conn->discoveryState != STATE_RECEIVED_PADO) {
+ conn->relayId.type = htons(type);
+ conn->relayId.length = htons(len);
+ memcpy(conn->relayId.payload, data, len);
+ }
break;
case TAG_PPP_MAX_PAYLOAD:
if (len == sizeof(mru)) {
memcpy(&mru, data, sizeof(mru));
mru = ntohs(mru);
- if (mru >= ETH_PPPOE_MTU) {
+ info("Max-Payload: %u", (unsigned) mru);
+ if (mru >= ETH_PPPOE_MTU && conn->discoveryState != STATE_RECEIVED_PADO) {
if (conn->mtu > mru)
conn->mtu = mru;
if (conn->mru > mru)
UINT16_t mru;
switch(type) {
case TAG_SERVICE_NAME:
- dbglog("PADS: Service-Name: '%.*s'", (int) len, data);
+ if (pppoe_verbose >= 1 && len > 0) {
+ info("PADS: Service-Name: '%.*s'", (int) len, data);
+ }
break;
case TAG_PPP_MAX_PAYLOAD:
if (len == sizeof(mru)) {
* Waits for a PADO packet and copies useful information
***********************************************************************/
void
-waitForPADO(PPPoEConnection *conn, int timeout)
+waitForPADO(PPPoEConnection *conn, int timeout, int waitWholeTimeoutForPADO)
{
fd_set readable;
int r;
pc.seenACName = 0;
pc.seenServiceName = 0;
conn->seenMaxPayload = 0;
- conn->error = 0;
if (get_time(&expire_at) < 0) {
error("get_time (waitForPADO): %m");
while(1) {
r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);
- if (r >= 0 || errno != EINTR || got_sigterm) break;
+ if (r >= 0 || errno != EINTR || signaled(SIGTERM)) break;
}
if (r < 0) {
error("select (waitForPADO): %m");
return; /* Timed out */
}
+ conn->error = 0;
/* Get the packet */
receivePacket(conn->discoverySocket, &packet, &len);
continue;
}
if (parsePacket(&packet, parsePADOTags, &pc) < 0)
- return;
+ continue;
if (conn->error)
- return;
+ continue;
if (!pc.seenACName) {
error("Ignoring PADO packet with no AC-Name tag");
continue;
error("Ignoring PADO packet with no Service-Name tag");
continue;
}
+ if (pppoe_verbose >= 1) {
+ info("AC-Ethernet-Address: %02x:%02x:%02x:%02x:%02x:%02x",
+ (unsigned) packet.ethHdr.h_source[0],
+ (unsigned) packet.ethHdr.h_source[1],
+ (unsigned) packet.ethHdr.h_source[2],
+ (unsigned) packet.ethHdr.h_source[3],
+ (unsigned) packet.ethHdr.h_source[4],
+ (unsigned) packet.ethHdr.h_source[5]);
+ info("--------------------------------------------------");
+ }
conn->numPADOs++;
- if (pc.acNameOK && pc.serviceNameOK) {
+ if (pc.acNameOK && pc.serviceNameOK && conn->discoveryState != STATE_RECEIVED_PADO) {
memcpy(conn->peerEth, packet.ethHdr.h_source, ETH_ALEN);
conn->discoveryState = STATE_RECEIVED_PADO;
- break;
}
}
- } while (conn->discoveryState != STATE_RECEIVED_PADO);
+ } while (waitWholeTimeoutForPADO || conn->discoveryState != STATE_RECEIVED_PADO);
}
/***********************************************************************
while(1) {
r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);
- if (r >= 0 || errno != EINTR || got_sigterm) break;
+ if (r >= 0 || errno != EINTR || signaled(SIGTERM)) break;
}
if (r < 0) {
error("select (waitForPADS): %m");
* Performs the PPPoE discovery phase 1
***********************************************************************/
void
-discovery1(PPPoEConnection *conn)
+discovery1(PPPoEConnection *conn, int waitWholeTimeoutForPADO)
{
int padiAttempts = 0;
int timeout = conn->discoveryTimeout;
do {
padiAttempts++;
- if (got_sigterm || padiAttempts > conn->discoveryAttempts) {
+ if (signaled(SIGTERM) || padiAttempts > conn->discoveryAttempts) {
warn("Timeout waiting for PADO packets");
close(conn->discoverySocket);
conn->discoverySocket = -1;
}
sendPADI(conn);
conn->discoveryState = STATE_SENT_PADI;
- waitForPADO(conn, timeout);
+ waitForPADO(conn, timeout, waitWholeTimeoutForPADO);
timeout *= 2;
} while (conn->discoveryState == STATE_SENT_PADI);
do {
padrAttempts++;
- if (got_sigterm || padrAttempts > conn->discoveryAttempts) {
+ if (signaled(SIGTERM) || padrAttempts > conn->discoveryAttempts) {
warn("Timeout waiting for PADS packets");
close(conn->discoverySocket);
conn->discoverySocket = -1;