]> git.ozlabs.org Git - ppp.git/commitdiff
Merge branch 'pppoe-discovery' of https://github.com/pali/ppp
authorPaul Mackerras <paulus@ozlabs.org>
Fri, 26 Nov 2021 00:05:06 +0000 (11:05 +1100)
committerPaul Mackerras <paulus@ozlabs.org>
Fri, 26 Nov 2021 00:05:06 +0000 (11:05 +1100)
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pppd/plugins/pppoe/Makefile.am
pppd/plugins/pppoe/common.c
pppd/plugins/pppoe/debug.c [deleted file]
pppd/plugins/pppoe/discovery.c
pppd/plugins/pppoe/plugin.c
pppd/plugins/pppoe/pppoe-discovery.c
pppd/plugins/pppoe/pppoe.h
pppd/pppd.8

index e3c01cd054e9e03282ba2a9893b0bc9c9e4b3471..0d70380a13893385dafcacc9aa8cd4b70505f62e 100644 (file)
@@ -11,4 +11,4 @@ pppoe_la_LDFLAGS = -module -avoid-version
 pppoe_la_SOURCES = plugin.c discovery.c if.c common.c
 
 pppoe_discovery_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/include
-pppoe_discovery_SOURCES = pppoe-discovery.c debug.c
+pppoe_discovery_SOURCES = pppoe-discovery.c discovery.c if.c common.c
index 64bed1af6ca63df5de7344bbdc85c8ea262f22e8..8b0e636acb800ab923a6b6c6d2cb3053448189f2 100644 (file)
@@ -164,6 +164,42 @@ sendPADT(PPPoEConnection *conn, char const *msg)
     info("Sent PADT");
 }
 
+static void
+pppoe_printpkt_hex(void (*printer)(void *, char *, ...), void *arg, unsigned char const *buf, int len)
+{
+    int i;
+    int base;
+
+    /* do NOT dump PAP packets */
+    if (len >= 2 && buf[0] == 0xC0 && buf[1] == 0x23) {
+       printer(arg, "(PAP Authentication Frame -- Contents not dumped)\n");
+       return;
+    }
+
+    for (base=0; base<len; base += 16) {
+       for (i=base; i<base+16; i++) {
+           if (i < len) {
+               printer(arg, "%02x ", (unsigned) buf[i]);
+           } else {
+               printer(arg, "   ");
+           }
+       }
+       printer(arg, "  ");
+       for (i=base; i<base+16; i++) {
+           if (i < len) {
+               if (isprint(buf[i])) {
+                   printer(arg, "%c", buf[i]);
+               } else {
+                   printer(arg, ".");
+               }
+           } else {
+               break;
+           }
+       }
+       printer(arg, "\n");
+    }
+}
+
 #define EH(x)  (x)[0], (x)[1], (x)[2], (x)[3], (x)[4], (x)[5]
 
 /* Print out a PPPOE packet for debugging */
@@ -171,7 +207,7 @@ void pppoe_printpkt(PPPoEPacket *packet,
                    void (*printer)(void *, char *, ...), void *arg)
 {
     int len = ntohs(packet->length);
-    int i, tag, tlen, text;
+    int i, j, tag, tlen, text;
 
     switch (ntohs(packet->ethHdr.h_proto)) {
     case ETH_PPPOE_DISCOVERY:
@@ -211,6 +247,8 @@ void pppoe_printpkt(PPPoEPacket *packet,
 
     printer(arg, " dst %02x:%02x:%02x:%02x:%02x:%02x ", EH(packet->ethHdr.h_dest));
     printer(arg, " src %02x:%02x:%02x:%02x:%02x:%02x\n", EH(packet->ethHdr.h_source));
+    if (pppoe_verbose >= 2)
+       pppoe_printpkt_hex(printer, arg, packet->payload, ntohs(packet->length));
     if (ntohs(packet->ethHdr.h_proto) != ETH_PPPOE_DISCOVERY)
        return;
 
@@ -266,12 +304,13 @@ void pppoe_printpkt(PPPoEPacket *packet,
        }
        if (tlen) {
            if (text)
-               printer(arg, " %.*v", tlen, &packet->payload[i]);
-           else if (tlen <= 32)
-               printer(arg, " %.*B", tlen, &packet->payload[i]);
-           else
-               printer(arg, " %.32B... (length %d)",
-                       &packet->payload[i], tlen);
+               printer(arg, " %.*s", tlen, &packet->payload[i]);
+           else {
+               for (j = 0; j < tlen && j < 32; j++)
+                   printer(arg, " %02x", (unsigned) *(&packet->payload[i]+j));
+               if (j < tlen)
+                   printer(arg, "... (length %d)", tlen);
+           }
        }
        printer(arg, "]");
     }
diff --git a/pppd/plugins/pppoe/debug.c b/pppd/plugins/pppoe/debug.c
deleted file mode 100644 (file)
index 3478b5f..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/***********************************************************************
-*
-* debug.c
-*
-* Implementation of user-space PPPoE redirector for Linux.
-*
-* Functions for printing debugging information
-*
-* Copyright (C) 2000 by Roaring Penguin Software Inc.
-*
-* This program may be distributed according to the terms of the GNU
-* General Public License, version 2 or (at your option) any later version.
-*
-***********************************************************************/
-
-static char const RCSID[] =
-"$Id: debug.c,v 1.2 2008/06/09 08:34:23 paulus Exp $";
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "pppoe.h"
-#include <sys/time.h>
-#include <time.h>
-#include <unistd.h>
-#include <ctype.h>
-
-/**********************************************************************
-*%FUNCTION: dumpHex
-*%ARGUMENTS:
-* fp -- file to dump to
-* buf -- buffer to dump
-* len -- length of data
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Dumps buffer to fp in an easy-to-read format
-***********************************************************************/
-void
-dumpHex(FILE *fp, unsigned char const *buf, int len)
-{
-    int i;
-    int base;
-
-    if (!fp) return;
-
-    /* do NOT dump PAP packets */
-    if (len >= 2 && buf[0] == 0xC0 && buf[1] == 0x23) {
-       fprintf(fp, "(PAP Authentication Frame -- Contents not dumped)\n");
-       return;
-    }
-
-    for (base=0; base<len; base += 16) {
-       for (i=base; i<base+16; i++) {
-           if (i < len) {
-               fprintf(fp, "%02x ", (unsigned) buf[i]);
-           } else {
-               fprintf(fp, "   ");
-           }
-       }
-       fprintf(fp, "  ");
-       for (i=base; i<base+16; i++) {
-           if (i < len) {
-               if (isprint(buf[i])) {
-                   fprintf(fp, "%c", buf[i]);
-               } else {
-                   fprintf(fp, ".");
-               }
-           } else {
-               break;
-           }
-       }
-       fprintf(fp, "\n");
-    }
-}
-
-/**********************************************************************
-*%FUNCTION: dumpPacket
-*%ARGUMENTS:
-* fp -- file to dump to
-* packet -- a PPPoE packet
-* dir -- either SENT or RCVD
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Dumps the PPPoE packet to fp in an easy-to-read format
-***********************************************************************/
-void
-dumpPacket(FILE *fp, PPPoEPacket *packet, char const *dir)
-{
-    int len = ntohs(packet->length);
-
-    /* Sheesh... printing times is a pain... */
-    struct timeval tv;
-    time_t now;
-    int millisec;
-    struct tm *lt;
-    char timebuf[256];
-
-    UINT16_t type = etherType(packet);
-    if (!fp) return;
-    gettimeofday(&tv, NULL);
-    now = (time_t) tv.tv_sec;
-    millisec = tv.tv_usec / 1000;
-    lt = localtime(&now);
-    strftime(timebuf, 256, "%H:%M:%S", lt);
-    fprintf(fp, "%s.%03d %s PPPoE ", timebuf, millisec, dir);
-    if (type == Eth_PPPOE_Discovery) {
-       fprintf(fp, "Discovery (%x) ", (unsigned) type);
-    } else if (type == Eth_PPPOE_Session) {
-       fprintf(fp, "Session (%x) ", (unsigned) type);
-    } else {
-       fprintf(fp, "Unknown (%x) ", (unsigned) type);
-    }
-
-    switch(packet->code) {
-    case CODE_PADI: fprintf(fp, "PADI "); break;
-    case CODE_PADO: fprintf(fp, "PADO "); break;
-    case CODE_PADR: fprintf(fp, "PADR "); break;
-    case CODE_PADS: fprintf(fp, "PADS "); break;
-    case CODE_PADT: fprintf(fp, "PADT "); break;
-    case CODE_PADM: fprintf(fp, "PADM "); break;
-    case CODE_PADN: fprintf(fp, "PADN "); break;
-    case CODE_SESS: fprintf(fp, "SESS "); break;
-    }
-
-    fprintf(fp, "sess-id %d length %d\n",
-           (int) ntohs(packet->session),
-           len);
-
-    /* Ugly... I apologize... */
-    fprintf(fp,
-           "SourceAddr %02x:%02x:%02x:%02x:%02x:%02x "
-           "DestAddr %02x:%02x:%02x:%02x:%02x:%02x\n",
-           (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],
-           (unsigned) packet->ethHdr.h_dest[0],
-           (unsigned) packet->ethHdr.h_dest[1],
-           (unsigned) packet->ethHdr.h_dest[2],
-           (unsigned) packet->ethHdr.h_dest[3],
-           (unsigned) packet->ethHdr.h_dest[4],
-           (unsigned) packet->ethHdr.h_dest[5]);
-    dumpHex(fp, packet->payload, ntohs(packet->length));
-}
index bd281bdb863b1a6be44e6c9530f99e7b6f05997e..b32b0c891dcd89c5fb46ebe402adc698f9a0611f 100644 (file)
@@ -142,7 +142,7 @@ parsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data,
     switch(type) {
     case TAG_AC_NAME:
        pc->seenACName = 1;
-       if (conn->printACNames) {
+       if (pppoe_verbose >= 1) {
            info("Access-Concentrator: %.*s", (int) len, data);
        }
        if (conn->acName && len == strlen(conn->acName) &&
@@ -152,30 +152,60 @@ parsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data,
        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) {
-               if (lcp_allowoptions[0].mru > mru)
-                   lcp_allowoptions[0].mru = mru;
-               if (lcp_wantoptions[0].mru > mru)
-                   lcp_wantoptions[0].mru = mru;
+           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)
+                   conn->mru = mru;
                conn->seenMaxPayload = 1;
            }
        }
@@ -215,17 +245,19 @@ parsePADSTags(UINT16_t type, UINT16_t len, unsigned char *data,
     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)) {
            memcpy(&mru, data, sizeof(mru));
            mru = ntohs(mru);
            if (mru >= ETH_PPPOE_MTU) {
-               if (lcp_allowoptions[0].mru > mru)
-                   lcp_allowoptions[0].mru = mru;
-               if (lcp_wantoptions[0].mru > mru)
-                   lcp_wantoptions[0].mru = mru;
+               if (conn->mtu > mru)
+                   conn->mtu = mru;
+               if (conn->mru > mru)
+                   conn->mru = mru;
                conn->seenMaxPayload = 1;
            }
        }
@@ -310,9 +342,9 @@ sendPADI(PPPoEConnection *conn)
     }
 
     /* Add our maximum MTU/MRU */
-    if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) {
+    if (MIN(conn->mtu, conn->mru) > ETH_PPPOE_MTU) {
        PPPoETag maxPayload;
-       UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru));
+       UINT16_t mru = htons(MIN(conn->mtu, conn->mru));
        maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD);
        maxPayload.length = htons(sizeof(mru));
        memcpy(maxPayload.payload, &mru, sizeof(mru));
@@ -355,7 +387,6 @@ waitForPADO(PPPoEConnection *conn, int timeout)
     pc.seenACName    = 0;
     pc.seenServiceName = 0;
     conn->seenMaxPayload = 0;
-    conn->error = 0;
 
     if (get_time(&expire_at) < 0) {
        error("get_time (waitForPADO): %m");
@@ -383,6 +414,7 @@ waitForPADO(PPPoEConnection *conn, int timeout)
                return;         /* Timed out */
        }
 
+       conn->error = 0;
        /* Get the packet */
        receivePacket(conn->discoverySocket, &packet, &len);
 
@@ -412,9 +444,9 @@ waitForPADO(PPPoEConnection *conn, int timeout)
                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;
@@ -423,14 +455,23 @@ waitForPADO(PPPoEConnection *conn, int timeout)
                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 (pppoe_verbose >= 1 || conn->discoveryState != STATE_RECEIVED_PADO);
 }
 
 /***********************************************************************
@@ -483,9 +524,9 @@ sendPADR(PPPoEConnection *conn)
     }
 
     /* Add our maximum MTU/MRU */
-    if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) {
+    if (MIN(conn->mtu, conn->mru) > ETH_PPPOE_MTU) {
        PPPoETag maxPayload;
-       UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru));
+       UINT16_t mru = htons(MIN(conn->mtu, conn->mru));
        maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD);
        maxPayload.length = htons(sizeof(mru));
        memcpy(maxPayload.payload, &mru, sizeof(mru));
@@ -609,19 +650,18 @@ waitForPADS(PPPoEConnection *conn, int timeout)
 }
 
 /**********************************************************************
-*%FUNCTION: discovery
+*%FUNCTION: discovery1
 *%ARGUMENTS:
 * conn -- PPPoE connection info structure
 *%RETURNS:
 * Nothing
 *%DESCRIPTION:
-* Performs the PPPoE discovery phase
+* Performs the PPPoE discovery phase 1
 ***********************************************************************/
 void
-discovery(PPPoEConnection *conn)
+discovery1(PPPoEConnection *conn)
 {
     int padiAttempts = 0;
-    int padrAttempts = 0;
     int timeout = conn->discoveryTimeout;
 
     do {
@@ -638,8 +678,23 @@ discovery(PPPoEConnection *conn)
 
        timeout *= 2;
     } while (conn->discoveryState == STATE_SENT_PADI);
+}
+
+/**********************************************************************
+*%FUNCTION: discovery2
+*%ARGUMENTS:
+* conn -- PPPoE connection info structure
+*%RETURNS:
+* Nothing
+*%DESCRIPTION:
+* Performs the PPPoE discovery phase 2
+***********************************************************************/
+void
+discovery2(PPPoEConnection *conn)
+{
+    int padrAttempts = 0;
+    int timeout = conn->discoveryTimeout;
 
-    timeout = conn->discoveryTimeout;
     do {
        padrAttempts++;
        if (got_sigterm || padrAttempts > conn->discoveryAttempts) {
@@ -656,10 +711,10 @@ discovery(PPPoEConnection *conn)
 
     if (!conn->seenMaxPayload) {
        /* RFC 4638: MUST limit MTU/MRU to 1492 */
-       if (lcp_allowoptions[0].mru > ETH_PPPOE_MTU)
-           lcp_allowoptions[0].mru = ETH_PPPOE_MTU;
-       if (lcp_wantoptions[0].mru > ETH_PPPOE_MTU)
-           lcp_wantoptions[0].mru = ETH_PPPOE_MTU;
+       if (conn->mtu > ETH_PPPOE_MTU)
+           conn->mtu = ETH_PPPOE_MTU;
+       if (conn->mru > ETH_PPPOE_MTU)
+           conn->mru = ETH_PPPOE_MTU;
     }
 
     /* We're done. */
index 8bcd1f8d0306d372997647d0e5c9221836057919..c53450752b7c481fda436891622ebdac2cdc9c6b 100644 (file)
@@ -68,7 +68,7 @@ extern int new_style_driver;
 char *pppd_pppoe_service = NULL;
 static char *acName = NULL;
 static char *existingSession = NULL;
-static int printACNames = 0;
+int pppoe_verbose = 0;
 static char *pppoe_reqd_mac = NULL;
 unsigned char pppoe_reqd_mac_addr[6];
 static char *pppoe_host_uniq;
@@ -93,9 +93,9 @@ static option_t Options[] = {
       "Attach to existing session (sessid:macaddr)" },
     { "rp_pppoe_sess",    o_string, &existingSession,
       "Legacy alias for pppoe-sess", OPT_ALIAS },
-    { "pppoe-verbose", o_int, &printACNames,
+    { "pppoe-verbose", o_int, &pppoe_verbose,
       "Be verbose about discovered access concentrators" },
-    { "rp_pppoe_verbose", o_int, &printACNames,
+    { "rp_pppoe_verbose", o_int, &pppoe_verbose,
       "Legacy alias for pppoe-verbose", OPT_ALIAS },
     { "pppoe-mac", o_string, &pppoe_reqd_mac,
       "Only connect to specified MAC address" },
@@ -132,7 +132,6 @@ PPPOEInitDevice(void)
     conn->ifName = devnam;
     conn->discoverySocket = -1;
     conn->sessionSocket = -1;
-    conn->printACNames = printACNames;
     conn->discoveryTimeout = pppoe_padi_timeout;
     conn->discoveryAttempts = pppoe_padi_attempts;
     return 1;
@@ -166,8 +165,8 @@ PPPOEConnectDevice(void)
     }
 
     /* Restore configuration */
-    lcp_allowoptions[0].mru = conn->mtu;
-    lcp_wantoptions[0].mru = conn->mru;
+    lcp_allowoptions[0].mru = conn->mtu = conn->storedmtu;
+    lcp_wantoptions[0].mru = conn->mru = conn->storedmru;
 
     /* Update maximum MRU */
     s = socket(AF_INET, SOCK_DGRAM, 0);
@@ -184,9 +183,9 @@ PPPOEConnectDevice(void)
     close(s);
 
     if (lcp_allowoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD)
-       lcp_allowoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD;
+       lcp_allowoptions[0].mru = conn->mtu = ifr.ifr_mtu - TOTAL_OVERHEAD;
     if (lcp_wantoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD)
-       lcp_wantoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD;
+       lcp_wantoptions[0].mru = conn->mru = ifr.ifr_mtu - TOTAL_OVERHEAD;
 
     if (pppoe_host_uniq) {
        if (!parseHostUniq(pppoe_host_uniq, &conn->hostUniq))
@@ -221,9 +220,20 @@ PPPOEConnectDevice(void)
            error("Failed to create PPPoE discovery socket: %m");
            goto errout;
        }
-       discovery(conn);
+       discovery1(conn);
+       /* discovery1() may update conn->mtu and conn->mru */
+       lcp_allowoptions[0].mru = conn->mtu;
+       lcp_wantoptions[0].mru = conn->mru;
+       if (conn->discoveryState != STATE_RECEIVED_PADO) {
+           error("Unable to complete PPPoE Discovery phase 1");
+           goto errout;
+       }
+       discovery2(conn);
+       /* discovery2() may update conn->mtu and conn->mru */
+       lcp_allowoptions[0].mru = conn->mtu;
+       lcp_wantoptions[0].mru = conn->mru;
        if (conn->discoveryState != STATE_SESSION) {
-           error("Unable to complete PPPoE Discovery");
+           error("Unable to complete PPPoE Discovery phase 2");
            goto errout;
        }
     }
@@ -452,8 +462,8 @@ void pppoe_check_options(void)
        lcp_wantoptions[0].mru = MAX_PPPOE_MTU;
 
     /* Save configuration */
-    conn->mtu = lcp_allowoptions[0].mru;
-    conn->mru = lcp_wantoptions[0].mru;
+    conn->storedmtu = lcp_allowoptions[0].mru;
+    conn->storedmru = lcp_wantoptions[0].mru;
 
     ccp_allowoptions[0].deflate = 0;
     ccp_wantoptions[0].deflate = 0;
index 96d6333edddfd451d710dcbf78d42ecc2ee5a7e8..1fe999dbdf55b16fa7bbefe5ce6557b1f848fa26 100644 (file)
@@ -20,6 +20,7 @@
 #include <errno.h>
 #include <string.h>
 #include <time.h>
+#include <signal.h>
 
 #include "pppoe.h"
 
 #include <net/if_arp.h>
 #endif
 
-char *xstrdup(const char *s);
-void usage(void);
+int debug;
+int got_sigterm;
+int pppoe_verbose;
+static FILE *debugFile;
 
-void die(int status)
-{
-       exit(status);
-}
-
-void error(char *fmt, ...)
+void
+fatal(char *fmt, ...)
 {
     va_list pvar;
     va_start(pvar, fmt);
     vfprintf(stderr, fmt, pvar);
     va_end(pvar);
+    fputc('\n', stderr);
+    exit(1);
 }
 
-/* Initialize frame types to RFC 2516 values.  Some broken peers apparently
-   use different frame types... sigh... */
-
-UINT16_t Eth_PPPOE_Discovery = ETH_PPPOE_DISCOVERY;
-UINT16_t Eth_PPPOE_Session   = ETH_PPPOE_SESSION;
-
-/**********************************************************************
-*%FUNCTION: etherType
-*%ARGUMENTS:
-* packet -- a received PPPoE packet
-*%RETURNS:
-* ethernet packet type (see /usr/include/net/ethertypes.h)
-*%DESCRIPTION:
-* Checks the ethernet packet header to determine its type.
-* We should only be receveing DISCOVERY and SESSION types if the BPF
-* is set up correctly.  Logs an error if an unexpected type is received.
-* Note that the ethernet type names come from "pppoe.h" and the packet
-* packet structure names use the LINUX dialect to maintain consistency
-* with the rest of this file.  See the BSD section of "pppoe.h" for
-* translations of the data structure names.
-***********************************************************************/
-UINT16_t
-etherType(PPPoEPacket *packet)
-{
-    UINT16_t type = (UINT16_t) ntohs(packet->ethHdr.h_proto);
-    if (type != Eth_PPPOE_Discovery && type != Eth_PPPOE_Session) {
-       fprintf(stderr, "Invalid ether type 0x%x\n", type);
-    }
-    return type;
-}
-
-/**********************************************************************
-*%FUNCTION: openInterface
-*%ARGUMENTS:
-* ifname -- name of interface
-* type -- Ethernet frame type
-* hwaddr -- if non-NULL, set to the hardware address
-*%RETURNS:
-* A raw socket for talking to the Ethernet card.  Exits on error.
-*%DESCRIPTION:
-* Opens a raw Ethernet socket
-***********************************************************************/
-int
-openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr)
+void
+error(char *fmt, ...)
 {
-    int optval=1;
-    int fd;
-    struct ifreq ifr;
-    int domain, stype;
-
-#ifdef HAVE_STRUCT_SOCKADDR_LL
-    struct sockaddr_ll sa;
-#else
-    struct sockaddr sa;
-#endif
-
-    memset(&sa, 0, sizeof(sa));
-
-#ifdef HAVE_STRUCT_SOCKADDR_LL
-    domain = PF_PACKET;
-    stype = SOCK_RAW;
-#else
-    domain = PF_INET;
-    stype = SOCK_PACKET;
-#endif
-
-    if ((fd = socket(domain, stype, htons(type))) < 0) {
-       /* Give a more helpful message for the common error case */
-       if (errno == EPERM) {
-           fatal("Cannot create raw socket -- pppoe must be run as root.");
-       }
-       fatalSys("socket");
-    }
-
-    if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) {
-       fatalSys("setsockopt");
-    }
-
-    /* Fill in hardware address */
-    if (hwaddr) {
-       strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-       if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
-           fatalSys("ioctl(SIOCGIFHWADDR)");
-       }
-       memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
-#ifdef ARPHRD_ETHER
-       if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
-           fatal("Interface %.16s is not Ethernet", ifname);
-       }
-#endif
-       if (NOT_UNICAST(hwaddr)) {
-           fatal("Interface %.16s has broadcast/multicast MAC address??", ifname);
-       }
-    }
-
-    /* Sanity check on MTU */
-    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-    if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) {
-       fatalSys("ioctl(SIOCGIFMTU)");
-    }
-    if (ifr.ifr_mtu < ETH_DATA_LEN) {
-       fprintf(stderr, "Interface %.16s has MTU of %d -- should be %d.\n",
-             ifname, ifr.ifr_mtu, ETH_DATA_LEN);
-       fprintf(stderr, "You may have serious connection problems.\n");
-    }
-
-#ifdef HAVE_STRUCT_SOCKADDR_LL
-    /* Get interface index */
-    sa.sll_family = AF_PACKET;
-    sa.sll_protocol = htons(type);
-
-    strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
-    ifr.ifr_name[IFNAMSIZ - 1] = 0;
-    if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
-       fatalSys("ioctl(SIOCFIGINDEX): Could not get interface index");
-    }
-    sa.sll_ifindex = ifr.ifr_ifindex;
-
-#else
-    strcpy(sa.sa_data, ifname);
-#endif
-
-    /* We're only interested in packets on specified interface */
-    if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
-       fatalSys("bind");
-    }
-
-    return fd;
+    va_list pvar;
+    va_start(pvar, fmt);
+    vfprintf(stderr, fmt, pvar);
+    fputc('\n', stderr);
+    va_end(pvar);
 }
 
-
-/***********************************************************************
-*%FUNCTION: sendPacket
-*%ARGUMENTS:
-* sock -- socket to send to
-* pkt -- the packet to transmit
-* size -- size of packet (in bytes)
-*%RETURNS:
-* 0 on success; -1 on failure
-*%DESCRIPTION:
-* Transmits a packet
-***********************************************************************/
-int
-sendPacket(PPPoEConnection *conn, int sock, PPPoEPacket *pkt, int size)
+void
+warn(char *fmt, ...)
 {
-#if defined(HAVE_STRUCT_SOCKADDR_LL)
-    if (send(sock, pkt, size, 0) < 0) {
-       fatalSys("send (sendPacket)");
-       return -1;
-    }
-#else
-    struct sockaddr sa;
-
-    if (!conn) {
-       fatal("relay and server not supported on Linux 2.0 kernels");
-    }
-    strcpy(sa.sa_data, conn->ifName);
-    if (sendto(sock, pkt, size, 0, &sa, sizeof(sa)) < 0) {
-       fatalSys("sendto (sendPacket)");
-       return -1;
-    }
-#endif
-    return 0;
+    va_list pvar;
+    va_start(pvar, fmt);
+    vfprintf(stderr, fmt, pvar);
+    fputc('\n', stderr);
+    va_end(pvar);
 }
 
-/***********************************************************************
-*%FUNCTION: receivePacket
-*%ARGUMENTS:
-* sock -- socket to read from
-* pkt -- place to store the received packet
-* size -- set to size of packet in bytes
-*%RETURNS:
-* >= 0 if all OK; < 0 if error
-*%DESCRIPTION:
-* Receives a packet
-***********************************************************************/
-int
-receivePacket(int sock, PPPoEPacket *pkt, int *size)
+void
+info(char *fmt, ...)
 {
-    if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) {
-       fatalSys("recv (receivePacket)");
-       return -1;
-    }
-    return 0;
+    va_list pvar;
+    va_start(pvar, fmt);
+    vprintf(fmt, pvar);
+    putchar('\n');
+    va_end(pvar);
 }
 
-/**********************************************************************
-*%FUNCTION: parsePacket
-*%ARGUMENTS:
-* packet -- the PPPoE discovery packet to parse
-* func -- function called for each tag in the packet
-* extra -- an opaque data pointer supplied to parsing function
-*%RETURNS:
-* 0 if everything went well; -1 if there was an error
-*%DESCRIPTION:
-* Parses a PPPoE discovery packet, calling "func" for each tag in the packet.
-* "func" is passed the additional argument "extra".
-***********************************************************************/
-int
-parsePacket(PPPoEPacket *packet, ParseFunc *func, void *extra)
+void
+init_pr_log(const char *prefix, int level)
 {
-    UINT16_t len = ntohs(packet->length);
-    unsigned char *curTag;
-    UINT16_t tagType, tagLen;
-
-    if (PPPOE_VER(packet->vertype) != 1) {
-       fprintf(stderr, "Invalid PPPoE version (%d)\n",
-               PPPOE_VER(packet->vertype));
-       return -1;
-    }
-    if (PPPOE_TYPE(packet->vertype) != 1) {
-       fprintf(stderr, "Invalid PPPoE type (%d)\n",
-               PPPOE_TYPE(packet->vertype));
-       return -1;
-    }
-
-    /* Do some sanity checks on packet */
-    if (len > ETH_JUMBO_LEN - PPPOE_OVERHEAD) { /* 6-byte overhead for PPPoE header */
-       fprintf(stderr, "Invalid PPPoE packet length (%u)\n", len);
-       return -1;
-    }
-
-    /* Step through the tags */
-    curTag = packet->payload;
-    while(curTag - packet->payload < len) {
-       /* Alignment is not guaranteed, so do this by hand... */
-       tagType = (curTag[0] << 8) + curTag[1];
-       tagLen = (curTag[2] << 8) + curTag[3];
-       if (tagType == TAG_END_OF_LIST) {
-           return 0;
-       }
-       if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) {
-           fprintf(stderr, "Invalid PPPoE tag length (%u)\n", tagLen);
-           return -1;
-       }
-       func(tagType, tagLen, curTag+TAG_HDR_SIZE, extra);
-       curTag = curTag + TAG_HDR_SIZE + tagLen;
-    }
-    return 0;
 }
 
-/**********************************************************************
-*%FUNCTION: parseForHostUniq
-*%ARGUMENTS:
-* type -- tag type
-* len -- tag length
-* data -- tag data.
-* extra -- user-supplied pointer.  This is assumed to be a pointer to int.
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* If a HostUnique tag is found which matches our PID, sets *extra to 1.
-***********************************************************************/
 void
-parseForHostUniq(UINT16_t type, UINT16_t len, unsigned char *data,
-                void *extra)
+end_pr_log(void)
 {
-    PPPoETag *tag = extra;
-
-    if (type == TAG_HOST_UNIQ && len == ntohs(tag->length))
-       tag->length = memcmp(data, tag->payload, len);
+    fflush(debugFile);
 }
 
-/**********************************************************************
-*%FUNCTION: packetIsForMe
-*%ARGUMENTS:
-* conn -- PPPoE connection info
-* packet -- a received PPPoE packet
-*%RETURNS:
-* 1 if packet is for this PPPoE daemon; 0 otherwise.
-*%DESCRIPTION:
-* If we are using the Host-Unique tag, verifies that packet contains
-* our unique identifier.
-***********************************************************************/
-int
-packetIsForMe(PPPoEConnection *conn, PPPoEPacket *packet)
+void
+pr_log(void *arg, char *fmt, ...)
 {
-    PPPoETag hostUniq = conn->hostUniq;
-
-    /* If packet is not directed to our MAC address, forget it */
-    if (memcmp(packet->ethHdr.h_dest, conn->myEth, ETH_ALEN)) return 0;
-
-    /* If we're not using the Host-Unique tag, then accept the packet */
-    if (!conn->hostUniq.length) return 1;
-
-    parsePacket(packet, parseForHostUniq, &hostUniq);
-    return !hostUniq.length;
+    va_list ap;
+    va_start(ap, fmt);
+    vfprintf(debugFile, fmt, ap);
+    va_end(ap);
 }
 
-/**********************************************************************
-*%FUNCTION: parsePADOTags
-*%ARGUMENTS:
-* type -- tag type
-* len -- tag length
-* data -- tag data
-* extra -- extra user data.  Should point to a PacketCriteria structure
-*          which gets filled in according to selected AC name and service
-*          name.
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Picks interesting tags out of a PADO packet
-***********************************************************************/
-void
-parsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data,
-             void *extra)
+size_t
+strlcpy(char *dest, const char *src, size_t len)
 {
-    struct PacketCriteria *pc = (struct PacketCriteria *) extra;
-    PPPoEConnection *conn = pc->conn;
-    int i;
-
-    switch(type) {
-    case TAG_AC_NAME:
-       pc->seenACName = 1;
-       if (conn->printACNames) {
-           printf("Access-Concentrator: %.*s\n", (int) len, data);
-       }
-       if (conn->acName && len == strlen(conn->acName) &&
-           !strncmp((char *) data, conn->acName, len)) {
-           pc->acNameOK = 1;
-       }
-       break;
-    case TAG_SERVICE_NAME:
-       pc->seenServiceName = 1;
-       if (conn->printACNames && len > 0) {
-           printf("       Service-Name: %.*s\n", (int) len, data);
-       }
-       if (conn->serviceName && len == strlen(conn->serviceName) &&
-           !strncmp((char *) data, conn->serviceName, len)) {
-           pc->serviceNameOK = 1;
-       }
-       break;
-    case TAG_AC_COOKIE:
-       if (conn->printACNames) {
-           printf("Got a cookie:");
-           /* Print first 20 bytes of cookie */
-           for (i=0; i<len && i < 20; i++) {
-               printf(" %02x", (unsigned) data[i]);
-           }
-           if (i < len) printf("...");
-           printf("\n");
-       }
-       conn->cookie.type = htons(type);
-       conn->cookie.length = htons(len);
-       memcpy(conn->cookie.payload, data, len);
-       break;
-    case TAG_RELAY_SESSION_ID:
-       if (conn->printACNames) {
-           printf("Got a Relay-ID:");
-           /* Print first 20 bytes of relay ID */
-           for (i=0; i<len && i < 20; i++) {
-               printf(" %02x", (unsigned) data[i]);
-           }
-           if (i < len) printf("...");
-           printf("\n");
-       }
-       conn->relayId.type = htons(type);
-       conn->relayId.length = htons(len);
-       memcpy(conn->relayId.payload, data, len);
-       break;
-    case TAG_SERVICE_NAME_ERROR:
-       if (conn->printACNames) {
-           printf("Got a Service-Name-Error tag: %.*s\n", (int) len, data);
-       }
-       break;
-    case TAG_AC_SYSTEM_ERROR:
-       if (conn->printACNames) {
-           printf("Got a System-Error tag: %.*s\n", (int) len, data);
+    size_t ret = strlen(src);
+
+    if (len != 0) {
+       if (ret < len)
+           strcpy(dest, src);
+       else {
+           strncpy(dest, src, len - 1);
+           dest[len-1] = 0;
        }
-       break;
-    case TAG_GENERIC_ERROR:
-       if (conn->printACNames) {
-           printf("Got a Generic-Error tag: %.*s\n", (int) len, data);
-       }
-       break;
     }
+    return ret;
 }
 
-/***********************************************************************
-*%FUNCTION: sendPADI
-*%ARGUMENTS:
-* conn -- PPPoEConnection structure
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Sends a PADI packet
-***********************************************************************/
-void
-sendPADI(PPPoEConnection *conn)
+static char *
+xstrdup(const char *s)
 {
-    PPPoEPacket packet;
-    unsigned char *cursor = packet.payload;
-    PPPoETag *svc = (PPPoETag *) (&packet.payload);
-    UINT16_t namelen = 0;
-    UINT16_t plen;
-
-    if (conn->serviceName) {
-       namelen = (UINT16_t) strlen(conn->serviceName);
-    }
-    plen = TAG_HDR_SIZE + namelen;
-    CHECK_ROOM(cursor, packet.payload, plen);
-
-    /* Set destination to Ethernet broadcast address */
-    memset(packet.ethHdr.h_dest, 0xFF, ETH_ALEN);
-    memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN);
-
-    packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery);
-    packet.vertype = PPPOE_VER_TYPE(1, 1);
-    packet.code = CODE_PADI;
-    packet.session = 0;
-
-    svc->type = TAG_SERVICE_NAME;
-    svc->length = htons(namelen);
-    CHECK_ROOM(cursor, packet.payload, namelen+TAG_HDR_SIZE);
-
-    if (conn->serviceName) {
-       memcpy(svc->payload, conn->serviceName, strlen(conn->serviceName));
-    }
-    cursor += namelen + TAG_HDR_SIZE;
-
-    /* If we're using Host-Uniq, copy it over */
-    if (conn->hostUniq.length) {
-       int len = ntohs(conn->hostUniq.length);
-       CHECK_ROOM(cursor, packet.payload, len + TAG_HDR_SIZE);
-       memcpy(cursor, &conn->hostUniq, len + TAG_HDR_SIZE);
-       cursor += len + TAG_HDR_SIZE;
-       plen += len + TAG_HDR_SIZE;
-    }
-
-    packet.length = htons(plen);
-
-    sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE));
-    if (conn->debugFile) {
-       dumpPacket(conn->debugFile, &packet, "SENT");
-       fprintf(conn->debugFile, "\n");
-       fflush(conn->debugFile);
+    char *ret = strdup(s);
+    if (!ret) {
+        perror("strdup");
+        exit(1);
     }
+    return ret;
 }
 
-/**********************************************************************
-*%FUNCTION: waitForPADO
-*%ARGUMENTS:
-* conn -- PPPoEConnection structure
-* timeout -- how long to wait (in seconds)
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Waits for a PADO packet and copies useful information
-***********************************************************************/
-void
-waitForPADO(PPPoEConnection *conn, int timeout)
+int
+get_time(struct timeval *tv)
 {
-    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 (conn->printACNames) {
-                   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);
+    return gettimeofday(tv, NULL);
 }
 
-/**********************************************************************
-*%FUNCTION: discovery
-*%ARGUMENTS:
-* conn -- PPPoE connection info structure
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Performs the PPPoE discovery phase
-***********************************************************************/
-void
-discovery(PPPoEConnection *conn)
+static void
+term_handler(int signum)
 {
-    int padiAttempts = 0;
-    int timeout = conn->discoveryTimeout;
-
-    conn->discoverySocket =
-       openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth);
-
-    do {
-       padiAttempts++;
-       if (padiAttempts > conn->discoveryAttempts) {
-           fprintf(stderr, "Timeout waiting for PADO packets\n");
-           close(conn->discoverySocket);
-           conn->discoverySocket = -1;
-           return;
-       }
-       sendPADI(conn);
-       conn->discoveryState = STATE_SENT_PADI;
-       waitForPADO(conn, timeout);
-    } while (!conn->numPADOs);
+    got_sigterm = 1;
 }
 
+static void usage(void);
+
 int main(int argc, char *argv[])
 {
     int opt;
     PPPoEConnection *conn;
 
+    signal(SIGINT, term_handler);
+    signal(SIGTERM, term_handler);
+
     conn = malloc(sizeof(PPPoEConnection));
-    if (!conn)
-       fatalSys("malloc");
+    if (!conn) {
+        perror("malloc");
+        exit(1);
+    }
 
     memset(conn, 0, sizeof(PPPoEConnection));
 
-    conn->printACNames = 1;
+    pppoe_verbose = 1;
     conn->discoveryTimeout = PADI_TIMEOUT;
     conn->discoveryAttempts = MAX_PADI_ATTEMPTS;
 
@@ -705,19 +225,21 @@ int main(int argc, char *argv[])
             }
            break;
        case 'D':
-           conn->debugFile = fopen(optarg, "w");
-           if (!conn->debugFile) {
+           pppoe_verbose = 2;
+           debug = 1;
+           debugFile = fopen(optarg, "w");
+           if (!debugFile) {
                fprintf(stderr, "Could not open %s: %s\n",
                        optarg, strerror(errno));
                exit(1);
            }
-           fprintf(conn->debugFile, "pppoe-discovery from pppd %s\n", VERSION);
+           fprintf(debugFile, "pppoe-discovery from pppd %s\n", VERSION);
            break;
        case 'I':
            conn->ifName = xstrdup(optarg);
            break;
        case 'Q':
-           conn->printACNames = 0;
+           pppoe_verbose = 0;
            break;
        case 'V':
        case 'h':
@@ -731,12 +253,17 @@ int main(int argc, char *argv[])
 
     /* default interface name */
     if (!conn->ifName)
-       conn->ifName = strdup("eth0");
+       conn->ifName = xstrdup("eth0");
 
-    conn->discoverySocket = -1;
     conn->sessionSocket = -1;
 
-    discovery(conn);
+    conn->discoverySocket = openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth);
+    if (conn->discoverySocket < 0) {
+       perror("Cannot create PPPoE discovery socket");
+       exit(1);
+    }
+
+    discovery1(conn);
 
     if (!conn->numPADOs)
        exit(1);
@@ -744,31 +271,8 @@ int main(int argc, char *argv[])
        exit(0);
 }
 
-void fatal(char * fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    vfprintf(stderr, fmt, ap);
-    va_end(ap);
-    fputc('\n', stderr);
-    exit(1);
-}
-
-void fatalSys(char const *str)
-{
-    perror(str);
-    exit(1);
-}
-
-char *xstrdup(const char *s)
-{
-    register char *ret = strdup(s);
-    if (!ret)
-       fatalSys("strdup");
-    return ret;
-}
-
-void usage(void)
+static void
+usage(void)
 {
     fprintf(stderr, "Usage: pppoe-discovery [options]\n");
     fprintf(stderr, "Options:\n");
index 5d96f0cf0c88ee197cc8732d90dce4186cf87b52..26e14f5d9f4fade2857887b4ee600e39abce00fa 100644 (file)
@@ -231,18 +231,17 @@ typedef struct PPPoEConnectionStruct {
     char *acName;              /* Desired AC name, if any */
     int synchronous;           /* Use synchronous PPP */
     PPPoETag hostUniq;         /* Use Host-Uniq tag */
-    int printACNames;          /* Just print AC names */
-    FILE *debugFile;           /* Debug file for dumping packets */
     int numPADOs;              /* Number of PADO packets received */
     PPPoETag cookie;           /* We have to send this if we get it */
     PPPoETag relayId;          /* Ditto */
     int error;                 /* Error packet received */
-    int debug;                 /* Set to log packets sent and received */
     int discoveryTimeout;       /* Timeout for discovery packets */
     int discoveryAttempts;      /* Number of discovery attempts */
     int seenMaxPayload;
-    int mtu;                   /* Stored MTU */
-    int mru;                   /* Stored MRU */
+    int storedmtu;             /* Stored MTU */
+    int storedmru;             /* Stored MRU */
+    int mtu;
+    int mru;
 } PPPoEConnection;
 
 /* Structure used to determine acceptable PADO or PADS packet */
@@ -259,9 +258,6 @@ UINT16_t etherType(PPPoEPacket *packet);
 int openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr);
 int sendPacket(PPPoEConnection *conn, int sock, PPPoEPacket *pkt, int size);
 int receivePacket(int sock, PPPoEPacket *pkt, int *size);
-void fatalSys(char const *str);
-void dumpPacket(FILE *fp, PPPoEPacket *packet, char const *dir);
-void dumpHex(FILE *fp, unsigned char const *buf, int len);
 int parsePacket(PPPoEPacket *packet, ParseFunc *func, void *extra);
 void parseLogErrs(UINT16_t typ, UINT16_t len, unsigned char *data, void *xtra);
 void syncReadFromPPP(PPPoEConnection *conn, PPPoEPacket *packet);
@@ -276,10 +272,12 @@ void initPPP(void);
 void clampMSS(PPPoEPacket *packet, char const *dir, int clampMss);
 UINT16_t computeTCPChecksum(unsigned char *ipHdr, unsigned char *tcpHdr);
 UINT16_t pppFCS16(UINT16_t fcs, unsigned char *cp, int len);
-void discovery(PPPoEConnection *conn);
+void discovery1(PPPoEConnection *conn);
+void discovery2(PPPoEConnection *conn);
 unsigned char *findTag(PPPoEPacket *packet, UINT16_t tagType,
                       PPPoETag *tag);
 
+extern int pppoe_verbose;
 void pppoe_printpkt(PPPoEPacket *packet,
                    void (*printer)(void *, char *, ...), void *arg);
 void pppoe_log_packet(const char *prefix, PPPoEPacket *packet);
index 7417a36ed2632ae4172a2776b1c4d574c62f8d2e..b31594ac3be8b97b5b67cacd02ae55328a37ccbf 100644 (file)
@@ -1294,8 +1294,9 @@ Attach to existing PPPoE session. For backward compatibility also
 \fBrp_pppoe_sess\fP option name is supported.
 .TP
 .B pppoe-verbose \fIn
-Be verbose about discovered access concentrators. For backward
-compatibility also \fBrp_pppoe_verbose\fP option name is supported.
+Be verbose about discovered access concentrators. When set to 2 or bigger
+value then dump also discovery packets. For backward compatibility also
+\fBrp_pppoe_verbose\fP option name is supported.
 .TP
 .B pppoe-mac \fImacaddr
 Connect to specified MAC address.