]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/plugins/rp-pppoe/pppoe-discovery.c
pppd: Use a compile test to detect crypt.h (#198)
[ppp.git] / pppd / plugins / rp-pppoe / pppoe-discovery.c
index 7f3659ef7ea1cb4df882a91ad45536c5f16488e6..c97033739e0f0504a03dadc7ac4632973e08321a 100644 (file)
@@ -15,6 +15,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <string.h>
+#include <time.h>
 
 #include "pppoe.h"
 
 #include <linux/if_packet.h>
 #endif
 
-#ifdef HAVE_NET_ETHERNET_H
-#include <net/ethernet.h>
-#endif
-
 #ifdef HAVE_ASM_TYPES_H
 #include <asm/types.h>
 #endif
@@ -181,7 +178,8 @@ openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr)
     sa.sll_family = AF_PACKET;
     sa.sll_protocol = htons(type);
 
-    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+    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");
     }
@@ -326,14 +324,10 @@ void
 parseForHostUniq(UINT16_t type, UINT16_t len, unsigned char *data,
                 void *extra)
 {
-    int *val = (int *) extra;
-    if (type == TAG_HOST_UNIQ && len == sizeof(pid_t)) {
-       pid_t tmp;
-       memcpy(&tmp, data, len);
-       if (tmp == getpid()) {
-           *val = 1;
-       }
-    }
+    PPPoETag *tag = extra;
+
+    if (type == TAG_HOST_UNIQ && len == ntohs(tag->length))
+       tag->length = memcmp(data, tag->payload, len);
 }
 
 /**********************************************************************
@@ -350,16 +344,16 @@ parseForHostUniq(UINT16_t type, UINT16_t len, unsigned char *data,
 int
 packetIsForMe(PPPoEConnection *conn, PPPoEPacket *packet)
 {
-    int forMe = 0;
+    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->useHostUniq) return 1;
+    if (!conn->hostUniq.length) return 1;
 
-    parsePacket(packet, parseForHostUniq, &forMe);
-    return forMe;
+    parsePacket(packet, parseForHostUniq, &hostUniq);
+    return !hostUniq.length;
 }
 
 /**********************************************************************
@@ -494,16 +488,12 @@ sendPADI(PPPoEConnection *conn)
     cursor += namelen + TAG_HDR_SIZE;
 
     /* If we're using Host-Uniq, copy it over */
-    if (conn->useHostUniq) {
-       PPPoETag hostUniq;
-       pid_t pid = getpid();
-       hostUniq.type = htons(TAG_HOST_UNIQ);
-       hostUniq.length = htons(sizeof(pid));
-       memcpy(hostUniq.payload, &pid, sizeof(pid));
-       CHECK_ROOM(cursor, packet.payload, sizeof(pid) + TAG_HDR_SIZE);
-       memcpy(cursor, &hostUniq, sizeof(pid) + TAG_HDR_SIZE);
-       cursor += sizeof(pid) + TAG_HDR_SIZE;
-       plen += sizeof(pid) + TAG_HDR_SIZE;
+    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);
@@ -635,14 +625,14 @@ void
 discovery(PPPoEConnection *conn)
 {
     int padiAttempts = 0;
-    int timeout = PADI_TIMEOUT;
+    int timeout = conn->discoveryTimeout;
 
     conn->discoverySocket =
        openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth);
 
     do {
        padiAttempts++;
-       if (padiAttempts > MAX_PADI_ATTEMPTS) {
+       if (padiAttempts > conn->discoveryAttempts) {
            fprintf(stderr, "Timeout waiting for PADO packets\n");
            close(conn->discoverySocket);
            conn->discoverySocket = -1;
@@ -666,8 +656,10 @@ int main(int argc, char *argv[])
     memset(conn, 0, sizeof(PPPoEConnection));
 
     conn->printACNames = 1;
+    conn->discoveryTimeout = PADI_TIMEOUT;
+    conn->discoveryAttempts = MAX_PADI_ATTEMPTS;
 
-    while ((opt = getopt(argc, argv, "I:D:VUQS:C:h")) > 0) {
+    while ((opt = getopt(argc, argv, "I:D:VUQS:C:W:t:a:h")) > 0) {
        switch(opt) {
        case 'S':
            conn->serviceName = xstrdup(optarg);
@@ -675,8 +667,44 @@ int main(int argc, char *argv[])
        case 'C':
            conn->acName = xstrdup(optarg);
            break;
+       case 't':
+           if (sscanf(optarg, "%d", &conn->discoveryTimeout) != 1) {
+               fprintf(stderr, "Illegal argument to -t: Should be -t timeout\n");
+               exit(EXIT_FAILURE);
+           }
+           if (conn->discoveryTimeout < 1) {
+               conn->discoveryTimeout = 1;
+           }
+           break;
+       case 'a':
+           if (sscanf(optarg, "%d", &conn->discoveryAttempts) != 1) {
+               fprintf(stderr, "Illegal argument to -a: Should be -a attempts\n");
+               exit(EXIT_FAILURE);
+           }
+           if (conn->discoveryAttempts < 1) {
+               conn->discoveryAttempts = 1;
+           }
+           break;
        case 'U':
-           conn->useHostUniq = 1;
+           if(conn->hostUniq.length) {
+               fprintf(stderr, "-U and -W are mutually exclusive\n");
+               exit(EXIT_FAILURE);
+           } else {
+               pid_t pid = getpid();
+               conn->hostUniq.type = htons(TAG_HOST_UNIQ);
+               conn->hostUniq.length = htons(sizeof(pid));
+               memcpy(conn->hostUniq.payload, &pid, sizeof(pid));
+           }
+           break;
+       case 'W':
+           if(conn->hostUniq.length) {
+               fprintf(stderr, "-U and -W are mutually exclusive\n");
+               exit(EXIT_FAILURE);
+           }
+           if (!parseHostUniq(optarg, &conn->hostUniq)) {
+               fprintf(stderr, "Invalid host-uniq argument: %s\n", optarg);
+               exit(EXIT_FAILURE);
+            }
            break;
        case 'D':
            conn->debugFile = fopen(optarg, "w");
@@ -750,11 +778,14 @@ void usage(void)
     fprintf(stderr, "   -I if_name     -- Specify interface (default eth0)\n");
     fprintf(stderr, "   -D filename    -- Log debugging information in filename.\n");
     fprintf(stderr,
+           "   -t timeout     -- Initial timeout for discovery packets in seconds\n"
+           "   -a attempts    -- Number of discovery attempts\n"
            "   -V             -- Print version and exit.\n"
            "   -Q             -- Quit Mode: Do not print access concentrator names\n"
            "   -S name        -- Set desired service name.\n"
            "   -C name        -- Set desired access concentrator name.\n"
            "   -U             -- Use Host-Unique to allow multiple PPPoE sessions.\n"
+           "   -W hexvalue    -- Set the Host-Unique to the supplied hex string.\n"
            "   -h             -- Print usage information.\n");
     fprintf(stderr, "\nVersion " RP_VERSION "\n");
 }