]> git.ozlabs.org Git - ppp.git/commitdiff
Rename rp-pppoe.so plugin to pppoe.so
authorPali Rohár <pali@kernel.org>
Thu, 31 Dec 2020 17:46:01 +0000 (18:46 +0100)
committerPali Rohár <pali@kernel.org>
Thu, 31 Dec 2020 17:46:01 +0000 (18:46 +0100)
Original out-of-tree rp-pppoe plugin for pppd software is still available
at website https://dianne.skoll.ca/projects/rp-pppoe/ and receives new
releases. The last update is from the June 2020.

Currently it is ambiguous if user is using original out-of-tree rp-pppoe
plugin or in-tree pppd's rp-pppoe plugin. These two plugins are different,
come from different sources but share same name.

Some users want to use original rp-pppoe plugin and not pppd's in-tree
rp-pppoe plugin. Also some distribution want to package both plugins,
pppd's in-tree and original rp-pppoe.

So for this reason and also because all other PPP over <something> plugins
have just pppo prefix, rename in-tree rp-pppoe.so plugin to just pppoe.so.

This will allow to distinguish and make it clear what is the original
rp-pppoe plugin and what is pppd's in-tree pppoe plugin.

When installing pppd create a compatibility symlink from pppoe.so to
rp-pppoe.so so nothing would be broken. This compatibility symlink may be
removed by Linux distribution which do not want to have compatibility with
the old name as before and rather use rp-pppoe.so name for original
rp-pppoe software.

Signed-off-by: Pali Rohár <pali@kernel.org>
24 files changed:
README.pppoe
configure
pppd/plugins/Makefile.linux
pppd/plugins/pppoe/.gitignore [new file with mode: 0644]
pppd/plugins/pppoe/Makefile.linux [new file with mode: 0644]
pppd/plugins/pppoe/common.c [new file with mode: 0644]
pppd/plugins/pppoe/config.h [new file with mode: 0644]
pppd/plugins/pppoe/debug.c [new file with mode: 0644]
pppd/plugins/pppoe/discovery.c [new file with mode: 0644]
pppd/plugins/pppoe/if.c [new file with mode: 0644]
pppd/plugins/pppoe/plugin.c [new file with mode: 0644]
pppd/plugins/pppoe/pppoe-discovery.c [new file with mode: 0644]
pppd/plugins/pppoe/pppoe.h [new file with mode: 0644]
pppd/plugins/rp-pppoe/.gitignore [deleted file]
pppd/plugins/rp-pppoe/Makefile.linux [deleted file]
pppd/plugins/rp-pppoe/common.c [deleted file]
pppd/plugins/rp-pppoe/config.h [deleted file]
pppd/plugins/rp-pppoe/debug.c [deleted file]
pppd/plugins/rp-pppoe/discovery.c [deleted file]
pppd/plugins/rp-pppoe/if.c [deleted file]
pppd/plugins/rp-pppoe/plugin.c [deleted file]
pppd/plugins/rp-pppoe/pppoe-discovery.c [deleted file]
pppd/plugins/rp-pppoe/pppoe.h [deleted file]
pppd/pppd.8

index 9f4e5cdf36171019ad0765bbe5cff92be0d31e2f..2909e1310a31f23f62719bc97cd0538084240704 100644 (file)
@@ -52,7 +52,7 @@ to connect to their ISP who is providing PPPoE based services.
 
 4.  Add the following line to /etc/ppp/options:
 
 
 4.  Add the following line to /etc/ppp/options:
 
-    plugin rp-pppoe.so
+    plugin pppoe.so
 
     The effect of this line is simply to make "eth0", "eth1",
     ....,"ethx" all valid device names for pppd (just like ttyS0,
 
     The effect of this line is simply to make "eth0", "eth1",
     ....,"ethx" all valid device names for pppd (just like ttyS0,
index 6a55e0f08be42a139ced1b61a25170381db5067c..ecd1b0d8ebf3a5fc40f80229e51b648d939545cf 100755 (executable)
--- a/configure
+++ b/configure
@@ -193,7 +193,7 @@ if [ -d "$ksrc" ]; then
     echo "Creating Makefiles."
     mkmkf $ksrc/Makefile.top Makefile
     mkmkf $ksrc/Makedefs$compiletype Makedefs.com
     echo "Creating Makefiles."
     mkmkf $ksrc/Makefile.top Makefile
     mkmkf $ksrc/Makedefs$compiletype Makedefs.com
-    for dir in pppd pppstats chat pppdump pppd/plugins pppd/plugins/rp-pppoe \
+    for dir in pppd pppstats chat pppdump pppd/plugins pppd/plugins/pppoe \
               pppd/plugins/radius pppd/plugins/pppoatm \
               pppd/plugins/pppol2tp; do
        mkmkf $dir/Makefile.$makext $dir/Makefile
               pppd/plugins/radius pppd/plugins/pppoatm \
               pppd/plugins/pppol2tp; do
        mkmkf $dir/Makefile.$makext $dir/Makefile
index 5a7bd7966215e97f89b774d95645fb37477a7240..e2a680e85f955140432ef832a5a22ab9b0ccfce4 100644 (file)
@@ -12,7 +12,7 @@ BINDIR = $(DESTDIR)/sbin
 MANDIR = $(DESTDIR)/share/man/man8
 LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION)
 
 MANDIR = $(DESTDIR)/share/man/man8
 LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION)
 
-SUBDIRS := rp-pppoe pppoatm pppol2tp
+SUBDIRS := pppoe pppoatm pppol2tp
 # Uncomment the next line to include the radius authentication plugin
 SUBDIRS += radius
 PLUGINS := minconn.so passprompt.so passwordfd.so winbind.so
 # Uncomment the next line to include the radius authentication plugin
 SUBDIRS += radius
 PLUGINS := minconn.so passprompt.so passwordfd.so winbind.so
diff --git a/pppd/plugins/pppoe/.gitignore b/pppd/plugins/pppoe/.gitignore
new file mode 100644 (file)
index 0000000..00c7f9c
--- /dev/null
@@ -0,0 +1 @@
+pppoe-discovery
diff --git a/pppd/plugins/pppoe/Makefile.linux b/pppd/plugins/pppoe/Makefile.linux
new file mode 100644 (file)
index 0000000..473f269
--- /dev/null
@@ -0,0 +1,64 @@
+# Generated automatically from Makefile.in by configure.
+#***********************************************************************
+#
+# Makefile
+#
+# Makefile for Roaring Penguin's Linux PPPoE plugin.
+# Modified for integration with pppd sources by Paul Mackerras.
+#
+# Copyright (C) 2001 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.
+#
+# $Id: Makefile.linux,v 1.8 2008/06/09 08:34:23 paulus Exp $
+#***********************************************************************
+
+DESTDIR = $(INSTROOT)@DESTDIR@
+BINDIR = $(DESTDIR)/sbin
+LIBDIR = $(DESTDIR)/lib/pppd/$(PPPDVERSION)
+
+PPPDVERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h)
+
+INSTALL        = install
+LN_S   = ln -sf
+
+COPTS=-O2 -g
+CFLAGS=$(COPTS) -I../../../include
+all: pppoe.so pppoe-discovery
+
+pppoe-discovery: pppoe-discovery.o debug.o
+       $(CC) $(LDFLAGS) -o pppoe-discovery pppoe-discovery.o debug.o
+
+pppoe-discovery.o: pppoe-discovery.c
+       $(CC) $(CFLAGS) -I../../.. -c -o pppoe-discovery.o pppoe-discovery.c
+
+debug.o: debug.c
+       $(CC) $(CFLAGS) -I../../.. -c -o debug.o debug.c
+
+pppoe.so: plugin.o discovery.o if.o common.o
+       $(CC) $(LDFLAGS) -o pppoe.so -shared plugin.o discovery.o if.o common.o
+
+install: all
+       $(INSTALL) -d -m 755 $(LIBDIR)
+       $(INSTALL) -c -m 4550 pppoe.so $(LIBDIR)
+       # Symlink for backward compatibility
+       $(LN_S) pppoe.so $(LIBDIR)/rp-pppoe.so
+       $(INSTALL) -d -m 755 $(BINDIR)
+       $(INSTALL) -c -m 555 pppoe-discovery $(BINDIR)
+
+clean:
+       rm -f *.o *.so pppoe-discovery
+
+plugin.o: plugin.c
+       $(CC) $(CFLAGS) -I../../.. -c -o plugin.o -fPIC plugin.c
+
+discovery.o: discovery.c
+       $(CC) $(CFLAGS) -I../../.. -c -o discovery.o -fPIC discovery.c
+
+if.o: if.c
+       $(CC) $(CFLAGS) -I../../.. -c -o if.o -fPIC if.c
+
+common.o: common.c
+       $(CC) $(CFLAGS) -I../../.. -c -o common.o -fPIC common.c
+
diff --git a/pppd/plugins/pppoe/common.c b/pppd/plugins/pppoe/common.c
new file mode 100644 (file)
index 0000000..9ea7fd6
--- /dev/null
@@ -0,0 +1,282 @@
+/***********************************************************************
+*
+* common.c
+*
+* Implementation of user-space PPPoE redirector for Linux.
+*
+* Common functions used by PPPoE client and server
+*
+* 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: common.c,v 1.3 2008/06/09 08:34:23 paulus Exp $";
+
+#define _GNU_SOURCE 1
+#include "pppoe.h"
+#include "pppd/pppd.h"
+
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <syslog.h>    /* for LOG_DEBUG */
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/**********************************************************************
+*%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)
+{
+    UINT16_t len = ntohs(packet->length);
+    unsigned char *curTag;
+    UINT16_t tagType, tagLen;
+
+    if (PPPOE_VER(packet->vertype) != 1) {
+       error("Invalid PPPoE version (%d)", PPPOE_VER(packet->vertype));
+       return -1;
+    }
+    if (PPPOE_TYPE(packet->vertype) != 1) {
+       error("Invalid PPPoE type (%d)", 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 */
+       error("Invalid PPPoE packet length (%u)", len);
+       return -1;
+    }
+
+    /* Step through the tags */
+    curTag = packet->payload;
+    while (curTag - packet->payload + TAG_HDR_SIZE <= 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) {
+           error("Invalid PPPoE tag length (%u)", tagLen);
+           return -1;
+       }
+       func(tagType, tagLen, curTag+TAG_HDR_SIZE, extra);
+       curTag = curTag + TAG_HDR_SIZE + tagLen;
+    }
+    return 0;
+}
+
+/***********************************************************************
+*%FUNCTION: sendPADT
+*%ARGUMENTS:
+* conn -- PPPoE connection
+* msg -- if non-NULL, extra error message to include in PADT packet.
+*%RETURNS:
+* Nothing
+*%DESCRIPTION:
+* Sends a PADT packet
+***********************************************************************/
+void
+sendPADT(PPPoEConnection *conn, char const *msg)
+{
+    PPPoEPacket packet;
+    unsigned char *cursor = packet.payload;
+
+    UINT16_t plen = 0;
+
+    /* Do nothing if no session established yet */
+    if (!conn->session) return;
+
+    /* Do nothing if no discovery socket */
+    if (conn->discoverySocket < 0) return;
+
+    memcpy(packet.ethHdr.h_dest, conn->peerEth, 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_PADT;
+    packet.session = conn->session;
+
+    /* Reset Session to zero so there is no possibility of
+       recursive calls to this function by any signal handler */
+    conn->session = 0;
+
+    /* If we're using Host-Uniq, copy it over */
+    if (conn->hostUniq.length) {
+       int len = ntohs(conn->hostUniq.length);
+       memcpy(cursor, &conn->hostUniq, len + TAG_HDR_SIZE);
+       cursor += len + TAG_HDR_SIZE;
+       plen += len + TAG_HDR_SIZE;
+    }
+
+    /* Copy error message */
+    if (msg) {
+       PPPoETag err;
+       size_t elen = strlen(msg);
+       err.type = htons(TAG_GENERIC_ERROR);
+       err.length = htons(elen);
+       strcpy(err.payload, msg);
+       memcpy(cursor, &err, elen + TAG_HDR_SIZE);
+       cursor += elen + TAG_HDR_SIZE;
+       plen += elen + TAG_HDR_SIZE;
+    }
+
+    /* Copy cookie and relay-ID if needed */
+    if (conn->cookie.type) {
+       CHECK_ROOM(cursor, packet.payload,
+                  ntohs(conn->cookie.length) + TAG_HDR_SIZE);
+       memcpy(cursor, &conn->cookie, ntohs(conn->cookie.length) + TAG_HDR_SIZE);
+       cursor += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
+       plen += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
+    }
+
+    if (conn->relayId.type) {
+       CHECK_ROOM(cursor, packet.payload,
+                  ntohs(conn->relayId.length) + TAG_HDR_SIZE);
+       memcpy(cursor, &conn->relayId, ntohs(conn->relayId.length) + TAG_HDR_SIZE);
+       cursor += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
+       plen += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
+    }
+
+    packet.length = htons(plen);
+    sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE));
+    info("Sent PADT");
+}
+
+#define EH(x)  (x)[0], (x)[1], (x)[2], (x)[3], (x)[4], (x)[5]
+
+/* Print out a PPPOE packet for debugging */
+void pppoe_printpkt(PPPoEPacket *packet,
+                   void (*printer)(void *, char *, ...), void *arg)
+{
+    int len = ntohs(packet->length);
+    int i, tag, tlen, text;
+
+    switch (ntohs(packet->ethHdr.h_proto)) {
+    case ETH_PPPOE_DISCOVERY:
+       printer(arg, "PPPOE Discovery V%dT%d ", PPPOE_VER(packet->vertype),
+               PPPOE_TYPE(packet->vertype));
+       switch (packet->code) {
+       case CODE_PADI:
+           printer(arg, "PADI");
+           break;
+       case CODE_PADO:
+           printer(arg, "PADO");
+           break;
+       case CODE_PADR:
+           printer(arg, "PADR");
+           break;
+       case CODE_PADS:
+           printer(arg, "PADS");
+           break;
+       case CODE_PADT:
+           printer(arg, "PADT");
+           break;
+       default:
+           printer(arg, "unknown code %x", packet->code);
+       }
+       printer(arg, " session 0x%x length %d\n", ntohs(packet->session), len);
+       break;
+    case ETH_PPPOE_SESSION:
+       printer(arg, "PPPOE Session V%dT%d", PPPOE_VER(packet->vertype),
+               PPPOE_TYPE(packet->vertype));
+       printer(arg, " code 0x%x session 0x%x length %d\n", packet->code,
+               ntohs(packet->session), len);
+       break;
+    default:
+       printer(arg, "Unknown ethernet frame with proto = 0x%x\n",
+               ntohs(packet->ethHdr.h_proto));
+    }
+
+    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 (ntohs(packet->ethHdr.h_proto) != ETH_PPPOE_DISCOVERY)
+       return;
+
+    for (i = 0; i + TAG_HDR_SIZE <= len; i += tlen) {
+       tag = (packet->payload[i] << 8) + packet->payload[i+1];
+       tlen = (packet->payload[i+2] << 8) + packet->payload[i+3];
+       if (i + tlen + TAG_HDR_SIZE > len)
+           break;
+       text = 0;
+       i += TAG_HDR_SIZE;
+       printer(arg, " [");
+       switch (tag) {
+       case TAG_END_OF_LIST:
+           printer(arg, "end-of-list");
+           break;
+       case TAG_SERVICE_NAME:
+           printer(arg, "service-name");
+           text = 1;
+           break;
+       case TAG_AC_NAME:
+           printer(arg, "AC-name");
+           text = 1;
+           break;
+       case TAG_HOST_UNIQ:
+           printer(arg, "host-uniq");
+           break;
+       case TAG_AC_COOKIE:
+           printer(arg, "AC-cookie");
+           break;
+       case TAG_VENDOR_SPECIFIC:
+           printer(arg, "vendor-specific");
+           break;
+       case TAG_RELAY_SESSION_ID:
+           printer(arg, "relay-session-id");
+           break;
+       case TAG_PPP_MAX_PAYLOAD:
+           printer(arg, "PPP-max-payload");
+           break;
+       case TAG_SERVICE_NAME_ERROR:
+           printer(arg, "service-name-error");
+           text = 1;
+           break;
+       case TAG_AC_SYSTEM_ERROR:
+           printer(arg, "AC-system-error");
+           text = 1;
+           break;
+       case TAG_GENERIC_ERROR:
+           printer(arg, "generic-error");
+           text = 1;
+           break;
+       default:
+           printer(arg, "unknown tag 0x%x", tag);
+       }
+       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, "]");
+    }
+    printer(arg, "\n");
+}
+
+void pppoe_log_packet(const char *prefix, PPPoEPacket *packet)
+{
+    init_pr_log(prefix, LOG_DEBUG);
+    pppoe_printpkt(packet, pr_log, NULL);
+    end_pr_log();
+}
diff --git a/pppd/plugins/pppoe/config.h b/pppd/plugins/pppoe/config.h
new file mode 100644 (file)
index 0000000..a708859
--- /dev/null
@@ -0,0 +1,129 @@
+/* config.h.  Generated automatically by configure.  */
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define to empty if the keyword does not work.  */
+/* #undef const */
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+/* #undef pid_t */
+
+/* Define as the return type of signal handlers (int or void).  */
+#define RETSIGTYPE void
+
+/* Define if the setvbuf function takes the buffering type as its second
+   argument and the buffer pointer as the third, as on System V
+   before release 3.  */
+/* #undef SETVBUF_REVERSED */
+
+/* Define if you have the ANSI C header files.  */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>.  */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define if your <sys/time.h> declares struct tm.  */
+/* #undef TM_IN_SYS_TIME */
+
+#define HAVE_STRUCT_SOCKADDR_LL 1
+
+/* The number of bytes in a unsigned int.  */
+#define SIZEOF_UNSIGNED_INT 4
+
+/* The number of bytes in a unsigned long.  */
+#define SIZEOF_UNSIGNED_LONG 4
+
+/* The number of bytes in a unsigned short.  */
+#define SIZEOF_UNSIGNED_SHORT 2
+
+/* Define if you have the select function.  */
+#define HAVE_SELECT 1
+
+/* Define if you have the socket function.  */
+#define HAVE_SOCKET 1
+
+/* Define if you have the strerror function.  */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strtol function.  */
+#define HAVE_STRTOL 1
+
+/* Define if you have the <asm/types.h> header file.  */
+#define HAVE_ASM_TYPES_H 1
+
+/* Define if you have the <fcntl.h> header file.  */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <getopt.h> header file.  */
+#define HAVE_GETOPT_H 1
+
+/* Define if you have the <linux/if_ether.h> header file.  */
+#define HAVE_LINUX_IF_ETHER_H 1
+
+/* Define if you have kernel-mode PPPoE in Linux file.  */
+#define HAVE_LINUX_KERNEL_PPPOE 1
+
+/* Define if you have the <linux/if_packet.h> header file.  */
+#define HAVE_LINUX_IF_PACKET_H 1
+
+/* Define if you have the <linux/if_pppox.h> header file.  */
+#define HAVE_LINUX_IF_PPPOX_H 1
+
+/* Define if you have the <net/bpf.h> header file.  */
+#define HAVE_NET_BPF_H 1
+
+/* Define if you have the <net/if_arp.h> header file.  */
+#define HAVE_NET_IF_ARP_H 1
+
+/* Define if you have the <net/ethernet.h> header file.  */
+#define HAVE_NET_ETHERNET_H 1
+
+/* Define if you have the <net/if.h> header file.  */
+#define HAVE_NET_IF_H 1
+
+/* Define if you have the <linux/if.h> header file.  */
+#define HAVE_LINUX_IF_H 1
+
+/* Define if you have the <net/if_dl.h> header file.  */
+/* #undef HAVE_NET_IF_DL_H */
+
+/* Define if you have the <net/if_ether.h> header file.  */
+/* #undef HAVE_NET_IF_ETHER_H */
+
+/* Define if you have the <net/if_types.h> header file.  */
+/* #undef HAVE_NET_IF_TYPES_H */
+
+/* Define if you have the <netinet/if_ether.h> header file.  */
+#define HAVE_NETINET_IF_ETHER_H 1
+
+/* Define if you have the <netpacket/packet.h> header file.  */
+#define HAVE_NETPACKET_PACKET_H 1
+
+/* Define if you have the <sys/dlpi.h> header file.  */
+/* #undef HAVE_SYS_DLPI_H */
+
+/* Define if you have the <sys/ioctl.h> header file.  */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/param.h> header file.  */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/socket.h> header file.  */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define if you have the <sys/time.h> header file.  */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <sys/uio.h> header file.  */
+#define HAVE_SYS_UIO_H 1
+
+/* Define if you have the <syslog.h> header file.  */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <unistd.h> header file.  */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the N_HDLC line discipline in linux/termios.h */
+#define HAVE_N_HDLC 1
diff --git a/pppd/plugins/pppoe/debug.c b/pppd/plugins/pppoe/debug.c
new file mode 100644 (file)
index 0000000..a6e6981
--- /dev/null
@@ -0,0 +1,145 @@
+/***********************************************************************
+*
+* 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 $";
+
+#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));
+}
diff --git a/pppd/plugins/pppoe/discovery.c b/pppd/plugins/pppoe/discovery.c
new file mode 100644 (file)
index 0000000..23089df
--- /dev/null
@@ -0,0 +1,666 @@
+/***********************************************************************
+*
+* discovery.c
+*
+* Perform PPPoE discovery
+*
+* Copyright (C) 1999 by Roaring Penguin Software Inc.
+*
+***********************************************************************/
+
+static char const RCSID[] =
+"$Id: discovery.c,v 1.6 2008/06/15 04:35:50 paulus Exp $";
+
+#define _GNU_SOURCE 1
+#include "pppoe.h"
+#include "pppd/pppd.h"
+#include "pppd/fsm.h"
+#include "pppd/lcp.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef USE_LINUX_PACKET
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#endif
+
+#include <signal.h>
+
+/* Calculate time remaining until *exp, return 0 if now >= *exp */
+static int time_left(struct timeval *diff, struct timeval *exp)
+{
+    struct timeval now;
+
+    if (get_time(&now) < 0) {
+       error("get_time: %m");
+       return 0;
+    }
+
+    if (now.tv_sec > exp->tv_sec
+       || (now.tv_sec == exp->tv_sec && now.tv_usec >= exp->tv_usec))
+       return 0;
+
+    diff->tv_sec = exp->tv_sec - now.tv_sec;
+    diff->tv_usec = exp->tv_usec - now.tv_usec;
+    if (diff->tv_usec < 0) {
+       diff->tv_usec += 1000000;
+       --diff->tv_sec;
+    }
+
+    return 1;
+}
+
+/**********************************************************************
+*%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.
+***********************************************************************/
+static void
+parseForHostUniq(UINT16_t type, UINT16_t len, unsigned char *data,
+                void *extra)
+{
+    PPPoETag *tag = extra;
+
+    if (type == TAG_HOST_UNIQ && len == ntohs(tag->length))
+       tag->length = memcmp(data, tag->payload, len);
+}
+
+/**********************************************************************
+*%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.
+***********************************************************************/
+static int
+packetIsForMe(PPPoEConnection *conn, PPPoEPacket *packet)
+{
+    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;
+}
+
+/**********************************************************************
+*%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
+***********************************************************************/
+static void
+parsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data,
+             void *extra)
+{
+    struct PacketCriteria *pc = (struct PacketCriteria *) extra;
+    PPPoEConnection *conn = pc->conn;
+    UINT16_t mru;
+    int i;
+
+    switch(type) {
+    case TAG_AC_NAME:
+       pc->seenACName = 1;
+       if (conn->printACNames) {
+           info("Access-Concentrator: %.*s", (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->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);
+       break;
+    case TAG_RELAY_SESSION_ID:
+       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;
+               conn->seenMaxPayload = 1;
+           }
+       }
+       break;
+    case TAG_SERVICE_NAME_ERROR:
+       error("PADO: Service-Name-Error: %.*s", (int) len, data);
+       conn->error = 1;
+       break;
+    case TAG_AC_SYSTEM_ERROR:
+       error("PADO: System-Error: %.*s", (int) len, data);
+       conn->error = 1;
+       break;
+    case TAG_GENERIC_ERROR:
+       error("PADO: Generic-Error: %.*s", (int) len, data);
+       conn->error = 1;
+       break;
+    }
+}
+
+/**********************************************************************
+*%FUNCTION: parsePADSTags
+*%ARGUMENTS:
+* type -- tag type
+* len -- tag length
+* data -- tag data
+* extra -- extra user data (pointer to PPPoEConnection structure)
+*%RETURNS:
+* Nothing
+*%DESCRIPTION:
+* Picks interesting tags out of a PADS packet
+***********************************************************************/
+static void
+parsePADSTags(UINT16_t type, UINT16_t len, unsigned char *data,
+             void *extra)
+{
+    PPPoEConnection *conn = (PPPoEConnection *) extra;
+    UINT16_t mru;
+    switch(type) {
+    case TAG_SERVICE_NAME:
+       dbglog("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;
+               conn->seenMaxPayload = 1;
+           }
+       }
+       break;
+    case TAG_SERVICE_NAME_ERROR:
+       error("PADS: Service-Name-Error: %.*s", (int) len, data);
+       conn->error = 1;
+       break;
+    case TAG_AC_SYSTEM_ERROR:
+       error("PADS: System-Error: %.*s", (int) len, data);
+       conn->error = 1;
+       break;
+    case TAG_GENERIC_ERROR:
+       error("PADS: Generic-Error: %.*s", (int) len, data);
+       conn->error = 1;
+       break;
+    case TAG_RELAY_SESSION_ID:
+       conn->relayId.type = htons(type);
+       conn->relayId.length = htons(len);
+       memcpy(conn->relayId.payload, data, len);
+       break;
+    }
+}
+
+/***********************************************************************
+*%FUNCTION: sendPADI
+*%ARGUMENTS:
+* conn -- PPPoEConnection structure
+*%RETURNS:
+* Nothing
+*%DESCRIPTION:
+* Sends a PADI packet
+***********************************************************************/
+static void
+sendPADI(PPPoEConnection *conn)
+{
+    PPPoEPacket packet;
+    unsigned char *cursor = packet.payload;
+    PPPoETag *svc = (PPPoETag *) (&packet.payload);
+    UINT16_t namelen = 0;
+    UINT16_t plen;
+    int omit_service_name = 0;
+
+    if (conn->serviceName) {
+       namelen = (UINT16_t) strlen(conn->serviceName);
+       if (!strcmp(conn->serviceName, "NO-SERVICE-NAME-NON-RFC-COMPLIANT")) {
+           omit_service_name = 1;
+       }
+    }
+
+    /* 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;
+
+    if (!omit_service_name) {
+       plen = TAG_HDR_SIZE + namelen;
+       CHECK_ROOM(cursor, packet.payload, plen);
+
+       svc->type = TAG_SERVICE_NAME;
+       svc->length = htons(namelen);
+
+       if (conn->serviceName) {
+           memcpy(svc->payload, conn->serviceName, strlen(conn->serviceName));
+       }
+       cursor += namelen + TAG_HDR_SIZE;
+    } else {
+       plen = 0;
+    }
+
+    /* 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;
+    }
+
+    /* Add our maximum MTU/MRU */
+    if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) {
+       PPPoETag maxPayload;
+       UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru));
+       maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD);
+       maxPayload.length = htons(sizeof(mru));
+       memcpy(maxPayload.payload, &mru, sizeof(mru));
+       CHECK_ROOM(cursor, packet.payload, sizeof(mru) + TAG_HDR_SIZE);
+       memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE);
+       cursor += sizeof(mru) + TAG_HDR_SIZE;
+       plen += sizeof(mru) + TAG_HDR_SIZE;
+    }
+
+    packet.length = htons(plen);
+
+    sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE));
+}
+
+/**********************************************************************
+*%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)
+{
+    fd_set readable;
+    int r;
+    struct timeval tv;
+    struct timeval expire_at;
+
+    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->seenMaxPayload = 0;
+    conn->error = 0;
+
+    if (get_time(&expire_at) < 0) {
+       error("get_time (waitForPADO): %m");
+       return;
+    }
+    expire_at.tv_sec += timeout;
+
+    do {
+       if (BPF_BUFFER_IS_EMPTY) {
+           if (!time_left(&tv, &expire_at))
+               return;         /* Timed out */
+
+           FD_ZERO(&readable);
+           FD_SET(conn->discoverySocket, &readable);
+
+           while(1) {
+               r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);
+               if (r >= 0 || errno != EINTR || got_sigterm) break;
+           }
+           if (r < 0) {
+               error("select (waitForPADO): %m");
+               return;
+           }
+           if (r == 0)
+               return;         /* Timed out */
+       }
+
+       /* Get the packet */
+       receivePacket(conn->discoverySocket, &packet, &len);
+
+       /* Check length */
+       if (ntohs(packet.length) + HDR_SIZE > len) {
+           error("Bogus PPPoE length field (%u)",
+                  (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 it's not for us, loop again */
+       if (!packetIsForMe(conn, &packet)) continue;
+
+       if (packet.code == CODE_PADO) {
+           if (NOT_UNICAST(packet.ethHdr.h_source)) {
+               error("Ignoring PADO packet from non-unicast MAC address");
+               continue;
+           }
+           if (conn->req_peer
+               && memcmp(packet.ethHdr.h_source, conn->req_peer_mac, ETH_ALEN) != 0) {
+               warn("Ignoring PADO packet from wrong MAC address");
+               continue;
+           }
+           if (parsePacket(&packet, parsePADOTags, &pc) < 0)
+               return;
+           if (conn->error)
+               return;
+           if (!pc.seenACName) {
+               error("Ignoring PADO packet with no AC-Name tag");
+               continue;
+           }
+           if (!pc.seenServiceName) {
+               error("Ignoring PADO packet with no Service-Name tag");
+               continue;
+           }
+           conn->numPADOs++;
+           if (pc.acNameOK && pc.serviceNameOK) {
+               memcpy(conn->peerEth, packet.ethHdr.h_source, ETH_ALEN);
+               conn->discoveryState = STATE_RECEIVED_PADO;
+               break;
+           }
+       }
+    } while (conn->discoveryState != STATE_RECEIVED_PADO);
+}
+
+/***********************************************************************
+*%FUNCTION: sendPADR
+*%ARGUMENTS:
+* conn -- PPPoE connection structur
+*%RETURNS:
+* Nothing
+*%DESCRIPTION:
+* Sends a PADR packet
+***********************************************************************/
+static void
+sendPADR(PPPoEConnection *conn)
+{
+    PPPoEPacket packet;
+    PPPoETag *svc = (PPPoETag *) packet.payload;
+    unsigned char *cursor = 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);
+
+    memcpy(packet.ethHdr.h_dest, conn->peerEth, 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_PADR;
+    packet.session = 0;
+
+    svc->type = TAG_SERVICE_NAME;
+    svc->length = htons(namelen);
+    if (conn->serviceName) {
+       memcpy(svc->payload, conn->serviceName, namelen);
+    }
+    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;
+    }
+
+    /* Add our maximum MTU/MRU */
+    if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) {
+       PPPoETag maxPayload;
+       UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru));
+       maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD);
+       maxPayload.length = htons(sizeof(mru));
+       memcpy(maxPayload.payload, &mru, sizeof(mru));
+       CHECK_ROOM(cursor, packet.payload, sizeof(mru) + TAG_HDR_SIZE);
+       memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE);
+       cursor += sizeof(mru) + TAG_HDR_SIZE;
+       plen += sizeof(mru) + TAG_HDR_SIZE;
+    }
+
+    /* Copy cookie and relay-ID if needed */
+    if (conn->cookie.type) {
+       CHECK_ROOM(cursor, packet.payload,
+                  ntohs(conn->cookie.length) + TAG_HDR_SIZE);
+       memcpy(cursor, &conn->cookie, ntohs(conn->cookie.length) + TAG_HDR_SIZE);
+       cursor += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
+       plen += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
+    }
+
+    if (conn->relayId.type) {
+       CHECK_ROOM(cursor, packet.payload,
+                  ntohs(conn->relayId.length) + TAG_HDR_SIZE);
+       memcpy(cursor, &conn->relayId, ntohs(conn->relayId.length) + TAG_HDR_SIZE);
+       cursor += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
+       plen += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
+    }
+
+    packet.length = htons(plen);
+    sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE));
+}
+
+/**********************************************************************
+*%FUNCTION: waitForPADS
+*%ARGUMENTS:
+* conn -- PPPoE connection info
+* timeout -- how long to wait (in seconds)
+*%RETURNS:
+* Nothing
+*%DESCRIPTION:
+* Waits for a PADS packet and copies useful information
+***********************************************************************/
+static void
+waitForPADS(PPPoEConnection *conn, int timeout)
+{
+    fd_set readable;
+    int r;
+    struct timeval tv;
+    struct timeval expire_at;
+
+    PPPoEPacket packet;
+    int len;
+
+    if (get_time(&expire_at) < 0) {
+       error("get_time (waitForPADS): %m");
+       return;
+    }
+    expire_at.tv_sec += timeout;
+
+    conn->error = 0;
+    do {
+       if (BPF_BUFFER_IS_EMPTY) {
+           if (!time_left(&tv, &expire_at))
+               return;         /* Timed out */
+
+           FD_ZERO(&readable);
+           FD_SET(conn->discoverySocket, &readable);
+
+           while(1) {
+               r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);
+               if (r >= 0 || errno != EINTR || got_sigterm) break;
+           }
+           if (r < 0) {
+               error("select (waitForPADS): %m");
+               return;
+           }
+           if (r == 0)
+               return;         /* Timed out */
+       }
+
+       /* Get the packet */
+       receivePacket(conn->discoverySocket, &packet, &len);
+
+       /* Check length */
+       if (ntohs(packet.length) + HDR_SIZE > len) {
+           error("Bogus PPPoE length field (%u)",
+                  (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 it's not from the AC, it's not for me */
+       if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) continue;
+
+       /* If it's not for us, loop again */
+       if (!packetIsForMe(conn, &packet)) continue;
+
+       /* Is it PADS?  */
+       if (packet.code == CODE_PADS) {
+           /* Parse for goodies */
+           if (parsePacket(&packet, parsePADSTags, conn) < 0)
+               return;
+           if (conn->error)
+               return;
+           conn->discoveryState = STATE_SESSION;
+           break;
+       }
+    } while (conn->discoveryState != STATE_SESSION);
+
+    /* Don't bother with ntohs; we'll just end up converting it back... */
+    conn->session = packet.session;
+
+    info("PPP session is %d", (int) ntohs(conn->session));
+
+    /* RFC 2516 says session id MUST NOT be zero or 0xFFFF */
+    if (ntohs(conn->session) == 0 || ntohs(conn->session) == 0xFFFF) {
+       error("Access concentrator used a session value of %x -- the AC is violating RFC 2516", (unsigned int) ntohs(conn->session));
+    }
+}
+
+/**********************************************************************
+*%FUNCTION: discovery
+*%ARGUMENTS:
+* conn -- PPPoE connection info structure
+*%RETURNS:
+* Nothing
+*%DESCRIPTION:
+* Performs the PPPoE discovery phase
+***********************************************************************/
+void
+discovery(PPPoEConnection *conn)
+{
+    int padiAttempts = 0;
+    int padrAttempts = 0;
+    int timeout = conn->discoveryTimeout;
+
+    do {
+       padiAttempts++;
+       if (got_sigterm || padiAttempts > conn->discoveryAttempts) {
+           warn("Timeout waiting for PADO packets");
+           close(conn->discoverySocket);
+           conn->discoverySocket = -1;
+           return;
+       }
+       sendPADI(conn);
+       conn->discoveryState = STATE_SENT_PADI;
+       waitForPADO(conn, timeout);
+
+       timeout *= 2;
+    } while (conn->discoveryState == STATE_SENT_PADI);
+
+    timeout = conn->discoveryTimeout;
+    do {
+       padrAttempts++;
+       if (got_sigterm || padrAttempts > conn->discoveryAttempts) {
+           warn("Timeout waiting for PADS packets");
+           close(conn->discoverySocket);
+           conn->discoverySocket = -1;
+           return;
+       }
+       sendPADR(conn);
+       conn->discoveryState = STATE_SENT_PADR;
+       waitForPADS(conn, timeout);
+       timeout *= 2;
+    } while (conn->discoveryState == STATE_SENT_PADR);
+
+    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;
+    }
+
+    /* We're done. */
+    close(conn->discoverySocket);
+    conn->discoverySocket = -1;
+    conn->discoveryState = STATE_SESSION;
+    return;
+}
diff --git a/pppd/plugins/pppoe/if.c b/pppd/plugins/pppoe/if.c
new file mode 100644 (file)
index 0000000..225dd56
--- /dev/null
@@ -0,0 +1,242 @@
+/***********************************************************************
+*
+* if.c
+*
+* Implementation of user-space PPPoE redirector for Linux.
+*
+* Functions for opening a raw socket and reading/writing raw Ethernet frames.
+*
+* 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: if.c,v 1.2 2008/06/09 08:34:23 paulus Exp $";
+
+#define _GNU_SOURCE 1
+#include "pppoe.h"
+#include "pppd/pppd.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_NETPACKET_PACKET_H
+#include <netpacket/packet.h>
+#elif defined(HAVE_LINUX_IF_PACKET_H)
+#include <linux/if_packet.h>
+#endif
+
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_NET_IF_ARP_H
+#include <net/if_arp.h>
+#endif
+
+/* 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) {
+       error("Invalid ether type 0x%x", 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)
+{
+    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.");
+       }
+       error("Can't open socket for pppoe: %m");
+       return -1;
+    }
+
+    if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) {
+       error("Can't set socket options for pppoe: %m");
+       close(fd);
+       return -1;
+    }
+
+    /* Fill in hardware address */
+    if (hwaddr) {
+       strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+       if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
+           error("Can't get hardware address for %s: %m", ifname);
+           close(fd);
+           return -1;
+       }
+       memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+#ifdef ARPHRD_ETHER
+       if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
+           warn("Interface %.16s is not Ethernet", ifname);
+       }
+#endif
+       if (NOT_UNICAST(hwaddr)) {
+           fatal("Can't use interface %.16s: it has broadcast/multicast MAC address",
+                 ifname);
+       }
+    }
+
+    /* Sanity check on MTU */
+    strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+    if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) {
+       error("Can't get MTU for %s: %m", ifname);
+    } else if (ifr.ifr_mtu < ETH_DATA_LEN) {
+       error("Interface %.16s has MTU of %d -- should be at least %d.",
+             ifname, ifr.ifr_mtu, ETH_DATA_LEN);
+       error("This may cause serious connection problems.");
+    }
+
+#ifdef HAVE_STRUCT_SOCKADDR_LL
+    /* Get interface index */
+    sa.sll_family = AF_PACKET;
+    sa.sll_protocol = htons(type);
+
+    strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+    if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
+       error("Could not get interface index for %s: %m", ifname);
+       close(fd);
+       return -1;
+    }
+    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) {
+       error("Failed to bind to interface %s: %m", ifname);
+       close(fd);
+       return -1;
+    }
+
+    return fd;
+}
+
+
+/***********************************************************************
+*%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)
+{
+    int err;
+
+    if (debug)
+       pppoe_log_packet("Send ", pkt);
+#if defined(HAVE_STRUCT_SOCKADDR_LL)
+    err = send(sock, pkt, size, 0);
+#else
+    struct sockaddr sa;
+
+    strcpy(sa.sa_data, conn->ifName);
+    err = sendto(sock, pkt, size, 0, &sa, sizeof(sa));
+#endif
+    if (err < 0) {
+       error("error sending pppoe packet: %m");
+       return -1;
+    }
+    return 0;
+}
+
+/***********************************************************************
+*%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)
+{
+    if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) {
+       error("error receiving pppoe packet: %m");
+       return -1;
+    }
+    if (debug)
+       pppoe_log_packet("Recv ", pkt);
+    return 0;
+}
diff --git a/pppd/plugins/pppoe/plugin.c b/pppd/plugins/pppoe/plugin.c
new file mode 100644 (file)
index 0000000..e840bef
--- /dev/null
@@ -0,0 +1,462 @@
+/***********************************************************************
+*
+* plugin.c
+*
+* pppd plugin for kernel-mode PPPoE on Linux
+*
+* Copyright (C) 2001 by Roaring Penguin Software Inc., Michal Ostrowski
+* and Jamal Hadi Salim.
+*
+* Much code and many ideas derived from pppoe plugin by Michal
+* Ostrowski and Jamal Hadi Salim, which carries this copyright:
+*
+* Copyright 2000 Michal Ostrowski <mostrows@styx.uwaterloo.ca>,
+*                Jamal Hadi Salim <hadi@cyberus.ca>
+* Borrows heavily from the PPPoATM plugin by Mitchell Blank Jr.,
+* which is based in part on work from Jens Axboe and Paul Mackerras.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version
+* 2 of the License, or (at your option) any later version.
+*
+***********************************************************************/
+
+static char const RCSID[] =
+"$Id: plugin.c,v 1.17 2008/06/15 04:35:50 paulus Exp $";
+
+#define _GNU_SOURCE 1
+#include "pppoe.h"
+
+#include "pppd/pppd.h"
+#include "pppd/fsm.h"
+#include "pppd/lcp.h"
+#include "pppd/ipcp.h"
+#include "pppd/ccp.h"
+/* #include "pppd/pathnames.h" */
+
+#include <linux/types.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <net/if_arp.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_pppox.h>
+
+#ifndef _ROOT_PATH
+#define _ROOT_PATH ""
+#endif
+
+#define _PATH_ETHOPT         _ROOT_PATH "/etc/ppp/options."
+
+char pppd_version[] = VERSION;
+
+/* From sys-linux.c in pppd -- MUST FIX THIS! */
+extern int new_style_driver;
+
+char *pppd_pppoe_service = NULL;
+static char *acName = NULL;
+static char *existingSession = NULL;
+static int printACNames = 0;
+static char *pppoe_reqd_mac = NULL;
+unsigned char pppoe_reqd_mac_addr[6];
+static char *host_uniq;
+static int pppoe_padi_timeout = PADI_TIMEOUT;
+static int pppoe_padi_attempts = MAX_PADI_ATTEMPTS;
+
+static int PPPoEDevnameHook(char *cmd, char **argv, int doit);
+static option_t Options[] = {
+    { "device name", o_wild, (void *) &PPPoEDevnameHook,
+      "PPPoE device name",
+      OPT_DEVNAM | OPT_PRIVFIX | OPT_NOARG  | OPT_A2STRVAL | OPT_STATIC,
+      devnam},
+    { "rp_pppoe_service", o_string, &pppd_pppoe_service,
+      "Desired PPPoE service name" },
+    { "rp_pppoe_ac",      o_string, &acName,
+      "Desired PPPoE access concentrator name" },
+    { "rp_pppoe_sess",    o_string, &existingSession,
+      "Attach to existing session (sessid:macaddr)" },
+    { "rp_pppoe_verbose", o_int, &printACNames,
+      "Be verbose about discovered access concentrators"},
+    { "pppoe-mac", o_string, &pppoe_reqd_mac,
+      "Only connect to specified MAC address" },
+    { "host-uniq", o_string, &host_uniq,
+      "Set the Host-Uniq to the supplied hex string" },
+    { "pppoe-padi-timeout", o_int, &pppoe_padi_timeout,
+      "Initial timeout for discovery packets in seconds" },
+    { "pppoe-padi-attempts", o_int, &pppoe_padi_attempts,
+      "Number of discovery attempts" },
+    { NULL }
+};
+int (*OldDevnameHook)(char *cmd, char **argv, int doit) = NULL;
+static PPPoEConnection *conn = NULL;
+
+/**********************************************************************
+ * %FUNCTION: PPPOEInitDevice
+ * %ARGUMENTS:
+ * None
+ * %RETURNS:
+ *
+ * %DESCRIPTION:
+ * Initializes PPPoE device.
+ ***********************************************************************/
+static int
+PPPOEInitDevice(void)
+{
+    conn = malloc(sizeof(PPPoEConnection));
+    if (!conn) {
+       novm("PPPoE session data");
+    }
+    memset(conn, 0, sizeof(PPPoEConnection));
+    conn->ifName = devnam;
+    conn->discoverySocket = -1;
+    conn->sessionSocket = -1;
+    conn->printACNames = printACNames;
+    conn->discoveryTimeout = pppoe_padi_timeout;
+    conn->discoveryAttempts = pppoe_padi_attempts;
+    return 1;
+}
+
+/**********************************************************************
+ * %FUNCTION: PPPOEConnectDevice
+ * %ARGUMENTS:
+ * None
+ * %RETURNS:
+ * Non-negative if all goes well; -1 otherwise
+ * %DESCRIPTION:
+ * Connects PPPoE device.
+ ***********************************************************************/
+static int
+PPPOEConnectDevice(void)
+{
+    struct sockaddr_pppox sp;
+    struct ifreq ifr;
+    int s;
+
+    /* Open session socket before discovery phase, to avoid losing session */
+    /* packets sent by peer just after PADS packet (noted on some Cisco    */
+    /* server equipment).                                                  */
+    /* Opening this socket just before waitForPADS in the discovery()      */
+    /* function would be more appropriate, but it would mess-up the code   */
+    conn->sessionSocket = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_OE);
+    if (conn->sessionSocket < 0) {
+       error("Failed to create PPPoE socket: %m");
+       return -1;
+    }
+
+    /* Restore configuration */
+    lcp_allowoptions[0].mru = conn->mtu;
+    lcp_wantoptions[0].mru = conn->mru;
+
+    /* Update maximum MRU */
+    s = socket(AF_INET, SOCK_DGRAM, 0);
+    if (s < 0) {
+       error("Can't get MTU for %s: %m", conn->ifName);
+       goto errout;
+    }
+    strlcpy(ifr.ifr_name, conn->ifName, sizeof(ifr.ifr_name));
+    if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
+       error("Can't get MTU for %s: %m", conn->ifName);
+       close(s);
+       goto errout;
+    }
+    close(s);
+
+    if (lcp_allowoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD)
+       lcp_allowoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD;
+    if (lcp_wantoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD)
+       lcp_wantoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD;
+
+    if (host_uniq) {
+       if (!parseHostUniq(host_uniq, &conn->hostUniq))
+           fatal("Illegal value for host-uniq option");
+    } else {
+       /* if a custom host-uniq is not supplied, use our PID */
+       pid_t pid = getpid();
+       conn->hostUniq.type = htons(TAG_HOST_UNIQ);
+       conn->hostUniq.length = htons(sizeof(pid));
+       memcpy(conn->hostUniq.payload, &pid, sizeof(pid));
+    }
+
+    conn->acName = acName;
+    conn->serviceName = pppd_pppoe_service;
+    strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam));
+    if (existingSession) {
+       unsigned int mac[ETH_ALEN];
+       int i, ses;
+       if (sscanf(existingSession, "%d:%x:%x:%x:%x:%x:%x",
+                  &ses, &mac[0], &mac[1], &mac[2],
+                  &mac[3], &mac[4], &mac[5]) != 7) {
+           fatal("Illegal value for rp_pppoe_sess option");
+       }
+       conn->session = htons(ses);
+       for (i=0; i<ETH_ALEN; i++) {
+           conn->peerEth[i] = (unsigned char) mac[i];
+       }
+    } else {
+       conn->discoverySocket =
+            openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth);
+       discovery(conn);
+       if (conn->discoveryState != STATE_SESSION) {
+           error("Unable to complete PPPoE Discovery");
+           goto errout;
+       }
+    }
+
+    /* Set PPPoE session-number for further consumption */
+    ppp_session_number = ntohs(conn->session);
+
+    sp.sa_family = AF_PPPOX;
+    sp.sa_protocol = PX_PROTO_OE;
+    sp.sa_addr.pppoe.sid = conn->session;
+    memcpy(sp.sa_addr.pppoe.dev, conn->ifName, IFNAMSIZ);
+    memcpy(sp.sa_addr.pppoe.remote, conn->peerEth, ETH_ALEN);
+
+    /* Set remote_number for ServPoET */
+    sprintf(remote_number, "%02X:%02X:%02X:%02X:%02X:%02X",
+           (unsigned) conn->peerEth[0],
+           (unsigned) conn->peerEth[1],
+           (unsigned) conn->peerEth[2],
+           (unsigned) conn->peerEth[3],
+           (unsigned) conn->peerEth[4],
+           (unsigned) conn->peerEth[5]);
+
+    warn("Connected to %02X:%02X:%02X:%02X:%02X:%02X via interface %s",
+        (unsigned) conn->peerEth[0],
+        (unsigned) conn->peerEth[1],
+        (unsigned) conn->peerEth[2],
+        (unsigned) conn->peerEth[3],
+        (unsigned) conn->peerEth[4],
+        (unsigned) conn->peerEth[5],
+        conn->ifName);
+
+    script_setenv("MACREMOTE", remote_number, 0);
+
+    if (connect(conn->sessionSocket, (struct sockaddr *) &sp,
+               sizeof(struct sockaddr_pppox)) < 0) {
+       error("Failed to connect PPPoE socket: %d %m", errno);
+       goto errout;
+    }
+
+    return conn->sessionSocket;
+
+ errout:
+    if (conn->discoverySocket >= 0) {
+       sendPADT(conn, NULL);
+       close(conn->discoverySocket);
+       conn->discoverySocket = -1;
+    }
+    close(conn->sessionSocket);
+    return -1;
+}
+
+static void
+PPPOERecvConfig(int mru,
+               u_int32_t asyncmap,
+               int pcomp,
+               int accomp)
+{
+#if 0 /* broken protocol, but no point harrassing the users I guess... */
+    if (mru > MAX_PPPOE_MTU)
+       warn("Couldn't increase MRU to %d", mru);
+#endif
+}
+
+/**********************************************************************
+ * %FUNCTION: PPPOEDisconnectDevice
+ * %ARGUMENTS:
+ * None
+ * %RETURNS:
+ * Nothing
+ * %DESCRIPTION:
+ * Disconnects PPPoE device
+ ***********************************************************************/
+static void
+PPPOEDisconnectDevice(void)
+{
+    struct sockaddr_pppox sp;
+
+    sp.sa_family = AF_PPPOX;
+    sp.sa_protocol = PX_PROTO_OE;
+    sp.sa_addr.pppoe.sid = 0;
+    memcpy(sp.sa_addr.pppoe.dev, conn->ifName, IFNAMSIZ);
+    memcpy(sp.sa_addr.pppoe.remote, conn->peerEth, ETH_ALEN);
+    if (connect(conn->sessionSocket, (struct sockaddr *) &sp,
+               sizeof(struct sockaddr_pppox)) < 0 && errno != EALREADY)
+       error("Failed to disconnect PPPoE socket: %d %m", errno);
+    close(conn->sessionSocket);
+    if (conn->discoverySocket >= 0) {
+        sendPADT(conn, NULL);
+       close(conn->discoverySocket);
+    }
+}
+
+static void
+PPPOEDeviceOptions(void)
+{
+    char buf[MAXPATHLEN];
+
+    strlcpy(buf, _PATH_ETHOPT, MAXPATHLEN);
+    strlcat(buf, devnam, MAXPATHLEN);
+    if (!options_from_file(buf, 0, 0, 1))
+       exit(EXIT_OPTION_ERROR);
+
+}
+
+struct channel pppoe_channel;
+
+/**********************************************************************
+ * %FUNCTION: PPPoEDevnameHook
+ * %ARGUMENTS:
+ * cmd -- the command (actually, the device name
+ * argv -- argument vector
+ * doit -- if non-zero, set device name.  Otherwise, just check if possible
+ * %RETURNS:
+ * 1 if we will handle this device; 0 otherwise.
+ * %DESCRIPTION:
+ * Checks if name is a valid interface name; if so, returns 1.  Also
+ * sets up devnam (string representation of device).
+ ***********************************************************************/
+static int
+PPPoEDevnameHook(char *cmd, char **argv, int doit)
+{
+    int r = 1;
+    int fd;
+    struct ifreq ifr;
+
+    /*
+     * Take any otherwise-unrecognized option as a possible device name,
+     * and test if it is the name of a network interface with a
+     * hardware address whose sa_family is ARPHRD_ETHER.
+     */
+    if (strlen(cmd) > 4 && !strncmp(cmd, "nic-", 4)) {
+       /* Strip off "nic-" */
+       cmd += 4;
+    }
+
+    /* Open a socket */
+    if ((fd = socket(PF_PACKET, SOCK_RAW, 0)) < 0) {
+       r = 0;
+    }
+
+    /* Try getting interface index */
+    if (r) {
+       strlcpy(ifr.ifr_name, cmd, sizeof(ifr.ifr_name));
+       if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
+           r = 0;
+       } else {
+           if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
+               r = 0;
+           } else {
+               if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
+                   if (doit)
+                       error("Interface %s not Ethernet", cmd);
+                   r = 0;
+               }
+           }
+       }
+    }
+
+    /* Close socket */
+    close(fd);
+    if (r && doit) {
+       strlcpy(devnam, cmd, sizeof(devnam));
+       if (the_channel != &pppoe_channel) {
+
+           the_channel = &pppoe_channel;
+           modem = 0;
+
+           PPPOEInitDevice();
+       }
+       return 1;
+    }
+
+    return r;
+}
+
+/**********************************************************************
+ * %FUNCTION: plugin_init
+ * %ARGUMENTS:
+ * None
+ * %RETURNS:
+ * Nothing
+ * %DESCRIPTION:
+ * Initializes hooks for pppd plugin
+ ***********************************************************************/
+void
+plugin_init(void)
+{
+    if (!ppp_available() && !new_style_driver) {
+       fatal("Linux kernel does not support PPPoE -- are you running 2.4.x?");
+    }
+
+    add_options(Options);
+
+    info("PPPoE plugin from pppd %s", VERSION);
+}
+
+void pppoe_check_options(void)
+{
+    unsigned int mac[6];
+    int i;
+
+    if (pppoe_reqd_mac != NULL) {
+       if (sscanf(pppoe_reqd_mac, "%x:%x:%x:%x:%x:%x",
+                  &mac[0], &mac[1], &mac[2], &mac[3],
+                  &mac[4], &mac[5]) != 6) {
+           option_error("cannot parse pppoe-mac option value");
+           exit(EXIT_OPTION_ERROR);
+       }
+       for (i = 0; i < 6; ++i)
+           conn->req_peer_mac[i] = mac[i];
+       conn->req_peer = 1;
+    }
+
+    lcp_allowoptions[0].neg_accompression = 0;
+    lcp_wantoptions[0].neg_accompression = 0;
+
+    lcp_allowoptions[0].neg_asyncmap = 0;
+    lcp_wantoptions[0].neg_asyncmap = 0;
+
+    lcp_allowoptions[0].neg_pcompression = 0;
+    lcp_wantoptions[0].neg_pcompression = 0;
+
+    if (lcp_allowoptions[0].mru > MAX_PPPOE_MTU)
+       lcp_allowoptions[0].mru = MAX_PPPOE_MTU;
+    if (lcp_wantoptions[0].mru > MAX_PPPOE_MTU)
+       lcp_wantoptions[0].mru = MAX_PPPOE_MTU;
+
+    /* Save configuration */
+    conn->mtu = lcp_allowoptions[0].mru;
+    conn->mru = lcp_wantoptions[0].mru;
+
+    ccp_allowoptions[0].deflate = 0;
+    ccp_wantoptions[0].deflate = 0;
+
+    ipcp_allowoptions[0].neg_vj = 0;
+    ipcp_wantoptions[0].neg_vj = 0;
+
+    ccp_allowoptions[0].bsd_compress = 0;
+    ccp_wantoptions[0].bsd_compress = 0;
+}
+
+struct channel pppoe_channel = {
+    .options = Options,
+    .process_extra_options = &PPPOEDeviceOptions,
+    .check_options = pppoe_check_options,
+    .connect = &PPPOEConnectDevice,
+    .disconnect = &PPPOEDisconnectDevice,
+    .establish_ppp = &generic_establish_ppp,
+    .disestablish_ppp = &generic_disestablish_ppp,
+    .send_config = NULL,
+    .recv_config = &PPPOERecvConfig,
+    .close = NULL,
+    .cleanup = NULL
+};
diff --git a/pppd/plugins/pppoe/pppoe-discovery.c b/pppd/plugins/pppoe/pppoe-discovery.c
new file mode 100644 (file)
index 0000000..34b77e8
--- /dev/null
@@ -0,0 +1,791 @@
+/*
+ * Perform PPPoE discovery
+ *
+ * Copyright (C) 2000-2001 by Roaring Penguin Software Inc.
+ * Copyright (C) 2004 Marco d'Itri <md@linux.it>
+ *
+ * This program may be distributed according to the terms of the GNU
+ * General Public License, version 2 or (at your option) any later version.
+ *
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+
+#include "pppoe.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_NETPACKET_PACKET_H
+#include <netpacket/packet.h>
+#elif defined(HAVE_LINUX_IF_PACKET_H)
+#include <linux/if_packet.h>
+#endif
+
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_NET_IF_ARP_H
+#include <net/if_arp.h>
+#endif
+
+char *xstrdup(const char *s);
+void usage(void);
+
+void die(int status)
+{
+       exit(status);
+}
+
+void error(char *fmt, ...)
+{
+    va_list pvar;
+    va_start(pvar, fmt);
+    vfprintf(stderr, fmt, pvar);
+    va_end(pvar);
+}
+
+/* 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)
+{
+    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) {
+           rp_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) {
+           char buffer[256];
+           sprintf(buffer, "Interface %.16s is not Ethernet", ifname);
+           rp_fatal(buffer);
+       }
+#endif
+       if (NOT_UNICAST(hwaddr)) {
+           char buffer[256];
+           sprintf(buffer,
+                   "Interface %.16s has broadcast/multicast MAC address??",
+                   ifname);
+           rp_fatal(buffer);
+       }
+    }
+
+    /* 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;
+}
+
+
+/***********************************************************************
+*%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)
+{
+#if defined(HAVE_STRUCT_SOCKADDR_LL)
+    if (send(sock, pkt, size, 0) < 0) {
+       sysErr("send (sendPacket)");
+       return -1;
+    }
+#else
+    struct sockaddr sa;
+
+    if (!conn) {
+       rp_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) {
+       sysErr("sendto (sendPacket)");
+       return -1;
+    }
+#endif
+    return 0;
+}
+
+/***********************************************************************
+*%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)
+{
+    if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) {
+       sysErr("recv (receivePacket)");
+       return -1;
+    }
+    return 0;
+}
+
+/**********************************************************************
+*%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)
+{
+    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)
+{
+    PPPoETag *tag = extra;
+
+    if (type == TAG_HOST_UNIQ && len == ntohs(tag->length))
+       tag->length = memcmp(data, tag->payload, len);
+}
+
+/**********************************************************************
+*%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)
+{
+    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;
+}
+
+/**********************************************************************
+*%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)
+{
+    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);
+       }
+       break;
+    case TAG_GENERIC_ERROR:
+       if (conn->printACNames) {
+           printf("Got a Generic-Error tag: %.*s\n", (int) len, data);
+       }
+       break;
+    }
+}
+
+/***********************************************************************
+*%FUNCTION: sendPADI
+*%ARGUMENTS:
+* conn -- PPPoEConnection structure
+*%RETURNS:
+* Nothing
+*%DESCRIPTION:
+* Sends a PADI packet
+***********************************************************************/
+void
+sendPADI(PPPoEConnection *conn)
+{
+    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);
+    }
+}
+
+/**********************************************************************
+*%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)
+{
+    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);
+}
+
+/**********************************************************************
+*%FUNCTION: discovery
+*%ARGUMENTS:
+* conn -- PPPoE connection info structure
+*%RETURNS:
+* Nothing
+*%DESCRIPTION:
+* Performs the PPPoE discovery phase
+***********************************************************************/
+void
+discovery(PPPoEConnection *conn)
+{
+    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);
+}
+
+int main(int argc, char *argv[])
+{
+    int opt;
+    PPPoEConnection *conn;
+
+    conn = malloc(sizeof(PPPoEConnection));
+    if (!conn)
+       fatalSys("malloc");
+
+    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:W:t:a:h")) > 0) {
+       switch(opt) {
+       case 'S':
+           conn->serviceName = xstrdup(optarg);
+           break;
+       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':
+           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");
+           if (!conn->debugFile) {
+               fprintf(stderr, "Could not open %s: %s\n",
+                       optarg, strerror(errno));
+               exit(1);
+           }
+           fprintf(conn->debugFile, "pppoe-discovery from pppd %s\n", VERSION);
+           break;
+       case 'I':
+           conn->ifName = xstrdup(optarg);
+           break;
+       case 'Q':
+           conn->printACNames = 0;
+           break;
+       case 'V':
+       case 'h':
+           usage();
+           exit(0);
+       default:
+           usage();
+           exit(1);
+       }
+    }
+
+    /* default interface name */
+    if (!conn->ifName)
+       conn->ifName = strdup("eth0");
+
+    conn->discoverySocket = -1;
+    conn->sessionSocket = -1;
+
+    discovery(conn);
+
+    if (!conn->numPADOs)
+       exit(1);
+    else
+       exit(0);
+}
+
+void rp_fatal(char const *str)
+{
+    fprintf(stderr, "%s\n", str);
+    exit(1);
+}
+
+void fatalSys(char const *str)
+{
+    perror(str);
+    exit(1);
+}
+
+void sysErr(char const *str)
+{
+    rp_fatal(str);
+}
+
+char *xstrdup(const char *s)
+{
+    register char *ret = strdup(s);
+    if (!ret)
+       sysErr("strdup");
+    return ret;
+}
+
+void usage(void)
+{
+    fprintf(stderr, "Usage: pppoe-discovery [options]\n");
+    fprintf(stderr, "Options:\n");
+    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, "\npppoe-discovery from pppd " VERSION "\n");
+}
diff --git a/pppd/plugins/pppoe/pppoe.h b/pppd/plugins/pppoe/pppoe.h
new file mode 100644 (file)
index 0000000..e2dc2ff
--- /dev/null
@@ -0,0 +1,331 @@
+/***********************************************************************
+*
+* pppoe.h
+*
+* Declaration of various PPPoE constants
+*
+* Copyright (C) 2000 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.
+*
+* $Id: pppoe.h,v 1.4 2008/06/15 04:35:50 paulus Exp $
+*
+***********************************************************************/
+
+#include "config.h"
+
+#include <stdio.h>             /* For FILE */
+#include <sys/types.h>         /* For pid_t */
+#include <ctype.h>
+#include <string.h>
+
+#include "pppd/pppd.h"         /* For error */
+
+/* How do we access raw Ethernet devices? */
+#undef USE_LINUX_PACKET
+#undef USE_BPF
+
+#if defined(HAVE_NETPACKET_PACKET_H) || defined(HAVE_LINUX_IF_PACKET_H)
+#define USE_LINUX_PACKET 1
+#elif defined(HAVE_SYS_DLPI_H)
+#define USE_DLPI
+#elif defined(HAVE_NET_BPF_H)
+#define USE_BPF 1
+#endif
+
+/* Sanity check */
+#if !defined(USE_BPF) && !defined(USE_LINUX_PACKET) && !defined(USE_DLPI)
+#error Unknown method for accessing raw Ethernet frames
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+/* This has to be included before Linux 4.8's linux/in.h
+ * gets dragged in. */
+#include <netinet/in.h>
+
+/* Ugly header files on some Linux boxes... */
+#if defined(HAVE_LINUX_IF_H)
+#include <linux/if.h>
+#elif defined(HAVE_NET_IF_H)
+#include <net/if.h>
+#endif
+
+#ifdef HAVE_NET_IF_TYPES_H
+#include <net/if_types.h>
+#endif
+
+#define BPF_BUFFER_IS_EMPTY 1
+#define BPF_BUFFER_HAS_DATA 0
+
+/* Define various integer types -- assumes a char is 8 bits */
+#if SIZEOF_UNSIGNED_SHORT == 2
+typedef unsigned short UINT16_t;
+#elif SIZEOF_UNSIGNED_INT == 2
+typedef unsigned int UINT16_t;
+#else
+#error Could not find a 16-bit integer type
+#endif
+
+#if SIZEOF_UNSIGNED_SHORT == 4
+typedef unsigned short UINT32_t;
+#elif SIZEOF_UNSIGNED_INT == 4
+typedef unsigned int UINT32_t;
+#elif SIZEOF_UNSIGNED_LONG == 4
+typedef unsigned long UINT32_t;
+#else
+#error Could not find a 32-bit integer type
+#endif
+
+#ifdef HAVE_LINUX_IF_ETHER_H
+#include <linux/if_ether.h>
+#else
+
+#ifdef HAVE_NETINET_IF_ETHER_H
+#include <sys/types.h>
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifndef HAVE_SYS_DLPI_H
+#include <netinet/if_ether.h>
+#endif
+#endif
+#endif
+
+/* Ethernet frame types according to RFC 2516 */
+#define ETH_PPPOE_DISCOVERY 0x8863
+#define ETH_PPPOE_SESSION   0x8864
+
+/* But some brain-dead peers disobey the RFC, so frame types are variables */
+extern UINT16_t Eth_PPPOE_Discovery;
+extern UINT16_t Eth_PPPOE_Session;
+
+/* PPPoE codes */
+#define CODE_PADI           0x09
+#define CODE_PADO           0x07
+#define CODE_PADR           0x19
+#define CODE_PADS           0x65
+#define CODE_PADT           0xA7
+
+/* Extensions from draft-carrel-info-pppoe-ext-00 */
+/* I do NOT like PADM or PADN, but they are here for completeness */
+#define CODE_PADM           0xD3
+#define CODE_PADN           0xD4
+
+#define CODE_SESS           0x00
+
+/* PPPoE Tags */
+#define TAG_END_OF_LIST        0x0000
+#define TAG_SERVICE_NAME       0x0101
+#define TAG_AC_NAME            0x0102
+#define TAG_HOST_UNIQ          0x0103
+#define TAG_AC_COOKIE          0x0104
+#define TAG_VENDOR_SPECIFIC    0x0105
+#define TAG_RELAY_SESSION_ID   0x0110
+#define TAG_PPP_MAX_PAYLOAD    0x0120
+#define TAG_SERVICE_NAME_ERROR 0x0201
+#define TAG_AC_SYSTEM_ERROR    0x0202
+#define TAG_GENERIC_ERROR      0x0203
+
+/* Extensions from draft-carrel-info-pppoe-ext-00 */
+/* I do NOT like these tags one little bit */
+#define TAG_HURL               0x111
+#define TAG_MOTM               0x112
+#define TAG_IP_ROUTE_ADD       0x121
+
+/* Discovery phase states */
+#define STATE_SENT_PADI     0
+#define STATE_RECEIVED_PADO 1
+#define STATE_SENT_PADR     2
+#define STATE_SESSION       3
+#define STATE_TERMINATED    4
+
+/* How many PADI/PADS attempts? */
+#define MAX_PADI_ATTEMPTS 3
+
+/* Initial timeout for PADO/PADS */
+#define PADI_TIMEOUT 5
+
+/* States for scanning PPP frames */
+#define STATE_WAITFOR_FRAME_ADDR 0
+#define STATE_DROP_PROTO         1
+#define STATE_BUILDING_PACKET    2
+
+/* Special PPP frame characters */
+#define FRAME_ESC    0x7D
+#define FRAME_FLAG   0x7E
+#define FRAME_ADDR   0xFF
+#define FRAME_CTRL   0x03
+#define FRAME_ENC    0x20
+
+#define IPV4ALEN     4
+#define SMALLBUF   256
+
+/* There are other fixed-size buffers preventing
+   this from being increased to 16110. The buffer
+   sizes would need to be properly de-coupled from
+   the default MRU. For now, getting up to 1500 is
+   enough. */
+#define ETH_JUMBO_LEN 1508
+
+/* A PPPoE Packet, including Ethernet headers */
+typedef struct PPPoEPacketStruct {
+    struct ethhdr ethHdr;      /* Ethernet header */
+    unsigned int vertype:8;    /* PPPoE Version and Type (must both be 1) */
+    unsigned int code:8;       /* PPPoE code */
+    unsigned int session:16;   /* PPPoE session */
+    unsigned int length:16;    /* Payload length */
+    unsigned char payload[ETH_JUMBO_LEN]; /* A bit of room to spare */
+} PPPoEPacket;
+
+#define PPPOE_VER(vt)          ((vt) >> 4)
+#define PPPOE_TYPE(vt)         ((vt) & 0xf)
+#define PPPOE_VER_TYPE(v, t)   (((v) << 4) | (t))
+
+/* Header size of a PPPoE packet */
+#define PPPOE_OVERHEAD 6  /* type, code, session, length */
+#define HDR_SIZE (sizeof(struct ethhdr) + PPPOE_OVERHEAD)
+#define MAX_PPPOE_PAYLOAD (ETH_JUMBO_LEN - PPPOE_OVERHEAD)
+#define PPP_OVERHEAD 2  /* protocol */
+#define MAX_PPPOE_MTU (MAX_PPPOE_PAYLOAD - PPP_OVERHEAD)
+#define TOTAL_OVERHEAD (PPPOE_OVERHEAD + PPP_OVERHEAD)
+#define ETH_PPPOE_MTU (ETH_DATA_LEN - TOTAL_OVERHEAD)
+
+/* PPPoE Tag */
+
+typedef struct PPPoETagStruct {
+    unsigned int type:16;      /* tag type */
+    unsigned int length:16;    /* Length of payload */
+    unsigned char payload[ETH_JUMBO_LEN]; /* A LOT of room to spare */
+} PPPoETag;
+/* Header size of a PPPoE tag */
+#define TAG_HDR_SIZE 4
+
+/* Chunk to read from stdin */
+#define READ_CHUNK 4096
+
+/* Function passed to parsePacket */
+typedef void ParseFunc(UINT16_t type,
+                      UINT16_t len,
+                      unsigned char *data,
+                      void *extra);
+
+#define PPPINITFCS16    0xffff  /* Initial FCS value */
+
+/* Keep track of the state of a connection -- collect everything in
+   one spot */
+
+typedef struct PPPoEConnectionStruct {
+    int discoveryState;                /* Where we are in discovery */
+    int discoverySocket;       /* Raw socket for discovery frames */
+    int sessionSocket;         /* Raw socket for session frames */
+    unsigned char myEth[ETH_ALEN]; /* My MAC address */
+    unsigned char peerEth[ETH_ALEN]; /* Peer's MAC address */
+    unsigned char req_peer_mac[ETH_ALEN]; /* required peer MAC address */
+    unsigned char req_peer;    /* require mac addr to match req_peer_mac */
+    UINT16_t session;          /* Session ID */
+    char *ifName;              /* Interface name */
+    char *serviceName;         /* Desired service name, if any */
+    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 */
+} PPPoEConnection;
+
+/* Structure used to determine acceptable PADO or PADS packet */
+struct PacketCriteria {
+    PPPoEConnection *conn;
+    int acNameOK;
+    int serviceNameOK;
+    int seenACName;
+    int seenServiceName;
+};
+
+/* Function Prototypes */
+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 rp_fatal(char const *str);
+void printErr(char const *str);
+void sysErr(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);
+void asyncReadFromPPP(PPPoEConnection *conn, PPPoEPacket *packet);
+void asyncReadFromEth(PPPoEConnection *conn, int sock, int clampMss);
+void syncReadFromEth(PPPoEConnection *conn, int sock, int clampMss);
+char *strDup(char const *str);
+void sendPADT(PPPoEConnection *conn, char const *msg);
+void sendSessionPacket(PPPoEConnection *conn,
+                      PPPoEPacket *packet, int len);
+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);
+unsigned char *findTag(PPPoEPacket *packet, UINT16_t tagType,
+                      PPPoETag *tag);
+
+void pppoe_printpkt(PPPoEPacket *packet,
+                   void (*printer)(void *, char *, ...), void *arg);
+void pppoe_log_packet(const char *prefix, PPPoEPacket *packet);
+
+static inline int parseHostUniq(const char *uniq, PPPoETag *tag)
+{
+    unsigned i, len = strlen(uniq);
+
+#define hex(x) \
+    (((x) <= '9') ? ((x) - '0') : \
+        (((x) <= 'F') ? ((x) - 'A' + 10) : \
+            ((x) - 'a' + 10)))
+
+    if (!len || len % 2 || len / 2 > sizeof(tag->payload))
+        return 0;
+
+    for (i = 0; i < len; i += 2) {
+        if (!isxdigit(uniq[i]) || !isxdigit(uniq[i+1]))
+            return 0;
+
+        tag->payload[i / 2] = (char)(hex(uniq[i]) << 4 | hex(uniq[i+1]));
+    }
+
+#undef hex
+
+    tag->type = htons(TAG_HOST_UNIQ);
+    tag->length = htons(len / 2);
+    return 1;
+}
+
+#define SET_STRING(var, val) do { if (var) free(var); var = strDup(val); } while(0);
+
+#define CHECK_ROOM(cursor, start, len) \
+do {\
+    if (((cursor)-(start))+(len) > MAX_PPPOE_PAYLOAD) { \
+       error("Would create too-long packet");  \
+        return; \
+    } \
+} while(0)
+
+/* True if Ethernet address is broadcast or multicast */
+#define NOT_UNICAST(e) ((e[0] & 0x01) != 0)
+#define BROADCAST(e) ((e[0] & e[1] & e[2] & e[3] & e[4] & e[5]) == 0xFF)
+#define NOT_BROADCAST(e) ((e[0] & e[1] & e[2] & e[3] & e[4] & e[5]) != 0xFF)
diff --git a/pppd/plugins/rp-pppoe/.gitignore b/pppd/plugins/rp-pppoe/.gitignore
deleted file mode 100644 (file)
index 00c7f9c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-pppoe-discovery
diff --git a/pppd/plugins/rp-pppoe/Makefile.linux b/pppd/plugins/rp-pppoe/Makefile.linux
deleted file mode 100644 (file)
index 2c93f4a..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-# Generated automatically from Makefile.in by configure.
-#***********************************************************************
-#
-# Makefile
-#
-# Makefile for Roaring Penguin's Linux PPPoE plugin.
-# Modified for integration with pppd sources by Paul Mackerras.
-#
-# Copyright (C) 2001 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.
-#
-# $Id: Makefile.linux,v 1.8 2008/06/09 08:34:23 paulus Exp $
-#***********************************************************************
-
-DESTDIR = $(INSTROOT)@DESTDIR@
-BINDIR = $(DESTDIR)/sbin
-LIBDIR = $(DESTDIR)/lib/pppd/$(PPPDVERSION)
-
-PPPDVERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h)
-
-INSTALL        = install
-
-# Version is set ONLY IN THE MAKEFILE!  Don't delete this!
-RP_VERSION=3.8p
-
-COPTS=-O2 -g
-CFLAGS=$(COPTS) -I../../../include '-DRP_VERSION="$(RP_VERSION)"'
-all: rp-pppoe.so pppoe-discovery
-
-pppoe-discovery: pppoe-discovery.o debug.o
-       $(CC) $(LDFLAGS) -o pppoe-discovery pppoe-discovery.o debug.o
-
-pppoe-discovery.o: pppoe-discovery.c
-       $(CC) $(CFLAGS) -I../../.. -c -o pppoe-discovery.o pppoe-discovery.c
-
-debug.o: debug.c
-       $(CC) $(CFLAGS) -I../../.. -c -o debug.o debug.c
-
-rp-pppoe.so: plugin.o discovery.o if.o common.o
-       $(CC) $(LDFLAGS) -o rp-pppoe.so -shared plugin.o discovery.o if.o common.o
-
-install: all
-       $(INSTALL) -d -m 755 $(LIBDIR)
-       $(INSTALL) -c -m 4550 rp-pppoe.so $(LIBDIR)
-       $(INSTALL) -d -m 755 $(BINDIR)
-       $(INSTALL) -c -m 555 pppoe-discovery $(BINDIR)
-
-clean:
-       rm -f *.o *.so pppoe-discovery
-
-plugin.o: plugin.c
-       $(CC) $(CFLAGS) -I../../.. -c -o plugin.o -fPIC plugin.c
-
-discovery.o: discovery.c
-       $(CC) $(CFLAGS) -I../../.. -c -o discovery.o -fPIC discovery.c
-
-if.o: if.c
-       $(CC) $(CFLAGS) -I../../.. -c -o if.o -fPIC if.c
-
-common.o: common.c
-       $(CC) $(CFLAGS) -I../../.. -c -o common.o -fPIC common.c
-
diff --git a/pppd/plugins/rp-pppoe/common.c b/pppd/plugins/rp-pppoe/common.c
deleted file mode 100644 (file)
index 9ea7fd6..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-/***********************************************************************
-*
-* common.c
-*
-* Implementation of user-space PPPoE redirector for Linux.
-*
-* Common functions used by PPPoE client and server
-*
-* 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: common.c,v 1.3 2008/06/09 08:34:23 paulus Exp $";
-
-#define _GNU_SOURCE 1
-#include "pppoe.h"
-#include "pppd/pppd.h"
-
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <syslog.h>    /* for LOG_DEBUG */
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-/**********************************************************************
-*%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)
-{
-    UINT16_t len = ntohs(packet->length);
-    unsigned char *curTag;
-    UINT16_t tagType, tagLen;
-
-    if (PPPOE_VER(packet->vertype) != 1) {
-       error("Invalid PPPoE version (%d)", PPPOE_VER(packet->vertype));
-       return -1;
-    }
-    if (PPPOE_TYPE(packet->vertype) != 1) {
-       error("Invalid PPPoE type (%d)", 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 */
-       error("Invalid PPPoE packet length (%u)", len);
-       return -1;
-    }
-
-    /* Step through the tags */
-    curTag = packet->payload;
-    while (curTag - packet->payload + TAG_HDR_SIZE <= 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) {
-           error("Invalid PPPoE tag length (%u)", tagLen);
-           return -1;
-       }
-       func(tagType, tagLen, curTag+TAG_HDR_SIZE, extra);
-       curTag = curTag + TAG_HDR_SIZE + tagLen;
-    }
-    return 0;
-}
-
-/***********************************************************************
-*%FUNCTION: sendPADT
-*%ARGUMENTS:
-* conn -- PPPoE connection
-* msg -- if non-NULL, extra error message to include in PADT packet.
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Sends a PADT packet
-***********************************************************************/
-void
-sendPADT(PPPoEConnection *conn, char const *msg)
-{
-    PPPoEPacket packet;
-    unsigned char *cursor = packet.payload;
-
-    UINT16_t plen = 0;
-
-    /* Do nothing if no session established yet */
-    if (!conn->session) return;
-
-    /* Do nothing if no discovery socket */
-    if (conn->discoverySocket < 0) return;
-
-    memcpy(packet.ethHdr.h_dest, conn->peerEth, 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_PADT;
-    packet.session = conn->session;
-
-    /* Reset Session to zero so there is no possibility of
-       recursive calls to this function by any signal handler */
-    conn->session = 0;
-
-    /* If we're using Host-Uniq, copy it over */
-    if (conn->hostUniq.length) {
-       int len = ntohs(conn->hostUniq.length);
-       memcpy(cursor, &conn->hostUniq, len + TAG_HDR_SIZE);
-       cursor += len + TAG_HDR_SIZE;
-       plen += len + TAG_HDR_SIZE;
-    }
-
-    /* Copy error message */
-    if (msg) {
-       PPPoETag err;
-       size_t elen = strlen(msg);
-       err.type = htons(TAG_GENERIC_ERROR);
-       err.length = htons(elen);
-       strcpy(err.payload, msg);
-       memcpy(cursor, &err, elen + TAG_HDR_SIZE);
-       cursor += elen + TAG_HDR_SIZE;
-       plen += elen + TAG_HDR_SIZE;
-    }
-
-    /* Copy cookie and relay-ID if needed */
-    if (conn->cookie.type) {
-       CHECK_ROOM(cursor, packet.payload,
-                  ntohs(conn->cookie.length) + TAG_HDR_SIZE);
-       memcpy(cursor, &conn->cookie, ntohs(conn->cookie.length) + TAG_HDR_SIZE);
-       cursor += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
-       plen += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
-    }
-
-    if (conn->relayId.type) {
-       CHECK_ROOM(cursor, packet.payload,
-                  ntohs(conn->relayId.length) + TAG_HDR_SIZE);
-       memcpy(cursor, &conn->relayId, ntohs(conn->relayId.length) + TAG_HDR_SIZE);
-       cursor += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
-       plen += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
-    }
-
-    packet.length = htons(plen);
-    sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE));
-    info("Sent PADT");
-}
-
-#define EH(x)  (x)[0], (x)[1], (x)[2], (x)[3], (x)[4], (x)[5]
-
-/* Print out a PPPOE packet for debugging */
-void pppoe_printpkt(PPPoEPacket *packet,
-                   void (*printer)(void *, char *, ...), void *arg)
-{
-    int len = ntohs(packet->length);
-    int i, tag, tlen, text;
-
-    switch (ntohs(packet->ethHdr.h_proto)) {
-    case ETH_PPPOE_DISCOVERY:
-       printer(arg, "PPPOE Discovery V%dT%d ", PPPOE_VER(packet->vertype),
-               PPPOE_TYPE(packet->vertype));
-       switch (packet->code) {
-       case CODE_PADI:
-           printer(arg, "PADI");
-           break;
-       case CODE_PADO:
-           printer(arg, "PADO");
-           break;
-       case CODE_PADR:
-           printer(arg, "PADR");
-           break;
-       case CODE_PADS:
-           printer(arg, "PADS");
-           break;
-       case CODE_PADT:
-           printer(arg, "PADT");
-           break;
-       default:
-           printer(arg, "unknown code %x", packet->code);
-       }
-       printer(arg, " session 0x%x length %d\n", ntohs(packet->session), len);
-       break;
-    case ETH_PPPOE_SESSION:
-       printer(arg, "PPPOE Session V%dT%d", PPPOE_VER(packet->vertype),
-               PPPOE_TYPE(packet->vertype));
-       printer(arg, " code 0x%x session 0x%x length %d\n", packet->code,
-               ntohs(packet->session), len);
-       break;
-    default:
-       printer(arg, "Unknown ethernet frame with proto = 0x%x\n",
-               ntohs(packet->ethHdr.h_proto));
-    }
-
-    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 (ntohs(packet->ethHdr.h_proto) != ETH_PPPOE_DISCOVERY)
-       return;
-
-    for (i = 0; i + TAG_HDR_SIZE <= len; i += tlen) {
-       tag = (packet->payload[i] << 8) + packet->payload[i+1];
-       tlen = (packet->payload[i+2] << 8) + packet->payload[i+3];
-       if (i + tlen + TAG_HDR_SIZE > len)
-           break;
-       text = 0;
-       i += TAG_HDR_SIZE;
-       printer(arg, " [");
-       switch (tag) {
-       case TAG_END_OF_LIST:
-           printer(arg, "end-of-list");
-           break;
-       case TAG_SERVICE_NAME:
-           printer(arg, "service-name");
-           text = 1;
-           break;
-       case TAG_AC_NAME:
-           printer(arg, "AC-name");
-           text = 1;
-           break;
-       case TAG_HOST_UNIQ:
-           printer(arg, "host-uniq");
-           break;
-       case TAG_AC_COOKIE:
-           printer(arg, "AC-cookie");
-           break;
-       case TAG_VENDOR_SPECIFIC:
-           printer(arg, "vendor-specific");
-           break;
-       case TAG_RELAY_SESSION_ID:
-           printer(arg, "relay-session-id");
-           break;
-       case TAG_PPP_MAX_PAYLOAD:
-           printer(arg, "PPP-max-payload");
-           break;
-       case TAG_SERVICE_NAME_ERROR:
-           printer(arg, "service-name-error");
-           text = 1;
-           break;
-       case TAG_AC_SYSTEM_ERROR:
-           printer(arg, "AC-system-error");
-           text = 1;
-           break;
-       case TAG_GENERIC_ERROR:
-           printer(arg, "generic-error");
-           text = 1;
-           break;
-       default:
-           printer(arg, "unknown tag 0x%x", tag);
-       }
-       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, "]");
-    }
-    printer(arg, "\n");
-}
-
-void pppoe_log_packet(const char *prefix, PPPoEPacket *packet)
-{
-    init_pr_log(prefix, LOG_DEBUG);
-    pppoe_printpkt(packet, pr_log, NULL);
-    end_pr_log();
-}
diff --git a/pppd/plugins/rp-pppoe/config.h b/pppd/plugins/rp-pppoe/config.h
deleted file mode 100644 (file)
index a708859..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/* config.h.  Generated automatically by configure.  */
-/* config.h.in.  Generated automatically from configure.in by autoheader.  */
-
-/* Define to empty if the keyword does not work.  */
-/* #undef const */
-
-/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to `int' if <sys/types.h> doesn't define.  */
-/* #undef pid_t */
-
-/* Define as the return type of signal handlers (int or void).  */
-#define RETSIGTYPE void
-
-/* Define if the setvbuf function takes the buffering type as its second
-   argument and the buffer pointer as the third, as on System V
-   before release 3.  */
-/* #undef SETVBUF_REVERSED */
-
-/* Define if you have the ANSI C header files.  */
-#define STDC_HEADERS 1
-
-/* Define if you can safely include both <sys/time.h> and <time.h>.  */
-#define TIME_WITH_SYS_TIME 1
-
-/* Define if your <sys/time.h> declares struct tm.  */
-/* #undef TM_IN_SYS_TIME */
-
-#define HAVE_STRUCT_SOCKADDR_LL 1
-
-/* The number of bytes in a unsigned int.  */
-#define SIZEOF_UNSIGNED_INT 4
-
-/* The number of bytes in a unsigned long.  */
-#define SIZEOF_UNSIGNED_LONG 4
-
-/* The number of bytes in a unsigned short.  */
-#define SIZEOF_UNSIGNED_SHORT 2
-
-/* Define if you have the select function.  */
-#define HAVE_SELECT 1
-
-/* Define if you have the socket function.  */
-#define HAVE_SOCKET 1
-
-/* Define if you have the strerror function.  */
-#define HAVE_STRERROR 1
-
-/* Define if you have the strtol function.  */
-#define HAVE_STRTOL 1
-
-/* Define if you have the <asm/types.h> header file.  */
-#define HAVE_ASM_TYPES_H 1
-
-/* Define if you have the <fcntl.h> header file.  */
-#define HAVE_FCNTL_H 1
-
-/* Define if you have the <getopt.h> header file.  */
-#define HAVE_GETOPT_H 1
-
-/* Define if you have the <linux/if_ether.h> header file.  */
-#define HAVE_LINUX_IF_ETHER_H 1
-
-/* Define if you have kernel-mode PPPoE in Linux file.  */
-#define HAVE_LINUX_KERNEL_PPPOE 1
-
-/* Define if you have the <linux/if_packet.h> header file.  */
-#define HAVE_LINUX_IF_PACKET_H 1
-
-/* Define if you have the <linux/if_pppox.h> header file.  */
-#define HAVE_LINUX_IF_PPPOX_H 1
-
-/* Define if you have the <net/bpf.h> header file.  */
-#define HAVE_NET_BPF_H 1
-
-/* Define if you have the <net/if_arp.h> header file.  */
-#define HAVE_NET_IF_ARP_H 1
-
-/* Define if you have the <net/ethernet.h> header file.  */
-#define HAVE_NET_ETHERNET_H 1
-
-/* Define if you have the <net/if.h> header file.  */
-#define HAVE_NET_IF_H 1
-
-/* Define if you have the <linux/if.h> header file.  */
-#define HAVE_LINUX_IF_H 1
-
-/* Define if you have the <net/if_dl.h> header file.  */
-/* #undef HAVE_NET_IF_DL_H */
-
-/* Define if you have the <net/if_ether.h> header file.  */
-/* #undef HAVE_NET_IF_ETHER_H */
-
-/* Define if you have the <net/if_types.h> header file.  */
-/* #undef HAVE_NET_IF_TYPES_H */
-
-/* Define if you have the <netinet/if_ether.h> header file.  */
-#define HAVE_NETINET_IF_ETHER_H 1
-
-/* Define if you have the <netpacket/packet.h> header file.  */
-#define HAVE_NETPACKET_PACKET_H 1
-
-/* Define if you have the <sys/dlpi.h> header file.  */
-/* #undef HAVE_SYS_DLPI_H */
-
-/* Define if you have the <sys/ioctl.h> header file.  */
-#define HAVE_SYS_IOCTL_H 1
-
-/* Define if you have the <sys/param.h> header file.  */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define if you have the <sys/socket.h> header file.  */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define if you have the <sys/time.h> header file.  */
-#define HAVE_SYS_TIME_H 1
-
-/* Define if you have the <sys/uio.h> header file.  */
-#define HAVE_SYS_UIO_H 1
-
-/* Define if you have the <syslog.h> header file.  */
-#define HAVE_SYSLOG_H 1
-
-/* Define if you have the <unistd.h> header file.  */
-#define HAVE_UNISTD_H 1
-
-/* Define if you have the N_HDLC line discipline in linux/termios.h */
-#define HAVE_N_HDLC 1
diff --git a/pppd/plugins/rp-pppoe/debug.c b/pppd/plugins/rp-pppoe/debug.c
deleted file mode 100644 (file)
index a6e6981..0000000
+++ /dev/null
@@ -1,145 +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 $";
-
-#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));
-}
diff --git a/pppd/plugins/rp-pppoe/discovery.c b/pppd/plugins/rp-pppoe/discovery.c
deleted file mode 100644 (file)
index 23089df..0000000
+++ /dev/null
@@ -1,666 +0,0 @@
-/***********************************************************************
-*
-* discovery.c
-*
-* Perform PPPoE discovery
-*
-* Copyright (C) 1999 by Roaring Penguin Software Inc.
-*
-***********************************************************************/
-
-static char const RCSID[] =
-"$Id: discovery.c,v 1.6 2008/06/15 04:35:50 paulus Exp $";
-
-#define _GNU_SOURCE 1
-#include "pppoe.h"
-#include "pppd/pppd.h"
-#include "pppd/fsm.h"
-#include "pppd/lcp.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#ifdef HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef USE_LINUX_PACKET
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#endif
-
-#include <signal.h>
-
-/* Calculate time remaining until *exp, return 0 if now >= *exp */
-static int time_left(struct timeval *diff, struct timeval *exp)
-{
-    struct timeval now;
-
-    if (get_time(&now) < 0) {
-       error("get_time: %m");
-       return 0;
-    }
-
-    if (now.tv_sec > exp->tv_sec
-       || (now.tv_sec == exp->tv_sec && now.tv_usec >= exp->tv_usec))
-       return 0;
-
-    diff->tv_sec = exp->tv_sec - now.tv_sec;
-    diff->tv_usec = exp->tv_usec - now.tv_usec;
-    if (diff->tv_usec < 0) {
-       diff->tv_usec += 1000000;
-       --diff->tv_sec;
-    }
-
-    return 1;
-}
-
-/**********************************************************************
-*%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.
-***********************************************************************/
-static void
-parseForHostUniq(UINT16_t type, UINT16_t len, unsigned char *data,
-                void *extra)
-{
-    PPPoETag *tag = extra;
-
-    if (type == TAG_HOST_UNIQ && len == ntohs(tag->length))
-       tag->length = memcmp(data, tag->payload, len);
-}
-
-/**********************************************************************
-*%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.
-***********************************************************************/
-static int
-packetIsForMe(PPPoEConnection *conn, PPPoEPacket *packet)
-{
-    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;
-}
-
-/**********************************************************************
-*%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
-***********************************************************************/
-static void
-parsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data,
-             void *extra)
-{
-    struct PacketCriteria *pc = (struct PacketCriteria *) extra;
-    PPPoEConnection *conn = pc->conn;
-    UINT16_t mru;
-    int i;
-
-    switch(type) {
-    case TAG_AC_NAME:
-       pc->seenACName = 1;
-       if (conn->printACNames) {
-           info("Access-Concentrator: %.*s", (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->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);
-       break;
-    case TAG_RELAY_SESSION_ID:
-       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;
-               conn->seenMaxPayload = 1;
-           }
-       }
-       break;
-    case TAG_SERVICE_NAME_ERROR:
-       error("PADO: Service-Name-Error: %.*s", (int) len, data);
-       conn->error = 1;
-       break;
-    case TAG_AC_SYSTEM_ERROR:
-       error("PADO: System-Error: %.*s", (int) len, data);
-       conn->error = 1;
-       break;
-    case TAG_GENERIC_ERROR:
-       error("PADO: Generic-Error: %.*s", (int) len, data);
-       conn->error = 1;
-       break;
-    }
-}
-
-/**********************************************************************
-*%FUNCTION: parsePADSTags
-*%ARGUMENTS:
-* type -- tag type
-* len -- tag length
-* data -- tag data
-* extra -- extra user data (pointer to PPPoEConnection structure)
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Picks interesting tags out of a PADS packet
-***********************************************************************/
-static void
-parsePADSTags(UINT16_t type, UINT16_t len, unsigned char *data,
-             void *extra)
-{
-    PPPoEConnection *conn = (PPPoEConnection *) extra;
-    UINT16_t mru;
-    switch(type) {
-    case TAG_SERVICE_NAME:
-       dbglog("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;
-               conn->seenMaxPayload = 1;
-           }
-       }
-       break;
-    case TAG_SERVICE_NAME_ERROR:
-       error("PADS: Service-Name-Error: %.*s", (int) len, data);
-       conn->error = 1;
-       break;
-    case TAG_AC_SYSTEM_ERROR:
-       error("PADS: System-Error: %.*s", (int) len, data);
-       conn->error = 1;
-       break;
-    case TAG_GENERIC_ERROR:
-       error("PADS: Generic-Error: %.*s", (int) len, data);
-       conn->error = 1;
-       break;
-    case TAG_RELAY_SESSION_ID:
-       conn->relayId.type = htons(type);
-       conn->relayId.length = htons(len);
-       memcpy(conn->relayId.payload, data, len);
-       break;
-    }
-}
-
-/***********************************************************************
-*%FUNCTION: sendPADI
-*%ARGUMENTS:
-* conn -- PPPoEConnection structure
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Sends a PADI packet
-***********************************************************************/
-static void
-sendPADI(PPPoEConnection *conn)
-{
-    PPPoEPacket packet;
-    unsigned char *cursor = packet.payload;
-    PPPoETag *svc = (PPPoETag *) (&packet.payload);
-    UINT16_t namelen = 0;
-    UINT16_t plen;
-    int omit_service_name = 0;
-
-    if (conn->serviceName) {
-       namelen = (UINT16_t) strlen(conn->serviceName);
-       if (!strcmp(conn->serviceName, "NO-SERVICE-NAME-NON-RFC-COMPLIANT")) {
-           omit_service_name = 1;
-       }
-    }
-
-    /* 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;
-
-    if (!omit_service_name) {
-       plen = TAG_HDR_SIZE + namelen;
-       CHECK_ROOM(cursor, packet.payload, plen);
-
-       svc->type = TAG_SERVICE_NAME;
-       svc->length = htons(namelen);
-
-       if (conn->serviceName) {
-           memcpy(svc->payload, conn->serviceName, strlen(conn->serviceName));
-       }
-       cursor += namelen + TAG_HDR_SIZE;
-    } else {
-       plen = 0;
-    }
-
-    /* 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;
-    }
-
-    /* Add our maximum MTU/MRU */
-    if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) {
-       PPPoETag maxPayload;
-       UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru));
-       maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD);
-       maxPayload.length = htons(sizeof(mru));
-       memcpy(maxPayload.payload, &mru, sizeof(mru));
-       CHECK_ROOM(cursor, packet.payload, sizeof(mru) + TAG_HDR_SIZE);
-       memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE);
-       cursor += sizeof(mru) + TAG_HDR_SIZE;
-       plen += sizeof(mru) + TAG_HDR_SIZE;
-    }
-
-    packet.length = htons(plen);
-
-    sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE));
-}
-
-/**********************************************************************
-*%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)
-{
-    fd_set readable;
-    int r;
-    struct timeval tv;
-    struct timeval expire_at;
-
-    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->seenMaxPayload = 0;
-    conn->error = 0;
-
-    if (get_time(&expire_at) < 0) {
-       error("get_time (waitForPADO): %m");
-       return;
-    }
-    expire_at.tv_sec += timeout;
-
-    do {
-       if (BPF_BUFFER_IS_EMPTY) {
-           if (!time_left(&tv, &expire_at))
-               return;         /* Timed out */
-
-           FD_ZERO(&readable);
-           FD_SET(conn->discoverySocket, &readable);
-
-           while(1) {
-               r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);
-               if (r >= 0 || errno != EINTR || got_sigterm) break;
-           }
-           if (r < 0) {
-               error("select (waitForPADO): %m");
-               return;
-           }
-           if (r == 0)
-               return;         /* Timed out */
-       }
-
-       /* Get the packet */
-       receivePacket(conn->discoverySocket, &packet, &len);
-
-       /* Check length */
-       if (ntohs(packet.length) + HDR_SIZE > len) {
-           error("Bogus PPPoE length field (%u)",
-                  (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 it's not for us, loop again */
-       if (!packetIsForMe(conn, &packet)) continue;
-
-       if (packet.code == CODE_PADO) {
-           if (NOT_UNICAST(packet.ethHdr.h_source)) {
-               error("Ignoring PADO packet from non-unicast MAC address");
-               continue;
-           }
-           if (conn->req_peer
-               && memcmp(packet.ethHdr.h_source, conn->req_peer_mac, ETH_ALEN) != 0) {
-               warn("Ignoring PADO packet from wrong MAC address");
-               continue;
-           }
-           if (parsePacket(&packet, parsePADOTags, &pc) < 0)
-               return;
-           if (conn->error)
-               return;
-           if (!pc.seenACName) {
-               error("Ignoring PADO packet with no AC-Name tag");
-               continue;
-           }
-           if (!pc.seenServiceName) {
-               error("Ignoring PADO packet with no Service-Name tag");
-               continue;
-           }
-           conn->numPADOs++;
-           if (pc.acNameOK && pc.serviceNameOK) {
-               memcpy(conn->peerEth, packet.ethHdr.h_source, ETH_ALEN);
-               conn->discoveryState = STATE_RECEIVED_PADO;
-               break;
-           }
-       }
-    } while (conn->discoveryState != STATE_RECEIVED_PADO);
-}
-
-/***********************************************************************
-*%FUNCTION: sendPADR
-*%ARGUMENTS:
-* conn -- PPPoE connection structur
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Sends a PADR packet
-***********************************************************************/
-static void
-sendPADR(PPPoEConnection *conn)
-{
-    PPPoEPacket packet;
-    PPPoETag *svc = (PPPoETag *) packet.payload;
-    unsigned char *cursor = 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);
-
-    memcpy(packet.ethHdr.h_dest, conn->peerEth, 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_PADR;
-    packet.session = 0;
-
-    svc->type = TAG_SERVICE_NAME;
-    svc->length = htons(namelen);
-    if (conn->serviceName) {
-       memcpy(svc->payload, conn->serviceName, namelen);
-    }
-    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;
-    }
-
-    /* Add our maximum MTU/MRU */
-    if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) {
-       PPPoETag maxPayload;
-       UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru));
-       maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD);
-       maxPayload.length = htons(sizeof(mru));
-       memcpy(maxPayload.payload, &mru, sizeof(mru));
-       CHECK_ROOM(cursor, packet.payload, sizeof(mru) + TAG_HDR_SIZE);
-       memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE);
-       cursor += sizeof(mru) + TAG_HDR_SIZE;
-       plen += sizeof(mru) + TAG_HDR_SIZE;
-    }
-
-    /* Copy cookie and relay-ID if needed */
-    if (conn->cookie.type) {
-       CHECK_ROOM(cursor, packet.payload,
-                  ntohs(conn->cookie.length) + TAG_HDR_SIZE);
-       memcpy(cursor, &conn->cookie, ntohs(conn->cookie.length) + TAG_HDR_SIZE);
-       cursor += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
-       plen += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
-    }
-
-    if (conn->relayId.type) {
-       CHECK_ROOM(cursor, packet.payload,
-                  ntohs(conn->relayId.length) + TAG_HDR_SIZE);
-       memcpy(cursor, &conn->relayId, ntohs(conn->relayId.length) + TAG_HDR_SIZE);
-       cursor += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
-       plen += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
-    }
-
-    packet.length = htons(plen);
-    sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE));
-}
-
-/**********************************************************************
-*%FUNCTION: waitForPADS
-*%ARGUMENTS:
-* conn -- PPPoE connection info
-* timeout -- how long to wait (in seconds)
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Waits for a PADS packet and copies useful information
-***********************************************************************/
-static void
-waitForPADS(PPPoEConnection *conn, int timeout)
-{
-    fd_set readable;
-    int r;
-    struct timeval tv;
-    struct timeval expire_at;
-
-    PPPoEPacket packet;
-    int len;
-
-    if (get_time(&expire_at) < 0) {
-       error("get_time (waitForPADS): %m");
-       return;
-    }
-    expire_at.tv_sec += timeout;
-
-    conn->error = 0;
-    do {
-       if (BPF_BUFFER_IS_EMPTY) {
-           if (!time_left(&tv, &expire_at))
-               return;         /* Timed out */
-
-           FD_ZERO(&readable);
-           FD_SET(conn->discoverySocket, &readable);
-
-           while(1) {
-               r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);
-               if (r >= 0 || errno != EINTR || got_sigterm) break;
-           }
-           if (r < 0) {
-               error("select (waitForPADS): %m");
-               return;
-           }
-           if (r == 0)
-               return;         /* Timed out */
-       }
-
-       /* Get the packet */
-       receivePacket(conn->discoverySocket, &packet, &len);
-
-       /* Check length */
-       if (ntohs(packet.length) + HDR_SIZE > len) {
-           error("Bogus PPPoE length field (%u)",
-                  (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 it's not from the AC, it's not for me */
-       if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) continue;
-
-       /* If it's not for us, loop again */
-       if (!packetIsForMe(conn, &packet)) continue;
-
-       /* Is it PADS?  */
-       if (packet.code == CODE_PADS) {
-           /* Parse for goodies */
-           if (parsePacket(&packet, parsePADSTags, conn) < 0)
-               return;
-           if (conn->error)
-               return;
-           conn->discoveryState = STATE_SESSION;
-           break;
-       }
-    } while (conn->discoveryState != STATE_SESSION);
-
-    /* Don't bother with ntohs; we'll just end up converting it back... */
-    conn->session = packet.session;
-
-    info("PPP session is %d", (int) ntohs(conn->session));
-
-    /* RFC 2516 says session id MUST NOT be zero or 0xFFFF */
-    if (ntohs(conn->session) == 0 || ntohs(conn->session) == 0xFFFF) {
-       error("Access concentrator used a session value of %x -- the AC is violating RFC 2516", (unsigned int) ntohs(conn->session));
-    }
-}
-
-/**********************************************************************
-*%FUNCTION: discovery
-*%ARGUMENTS:
-* conn -- PPPoE connection info structure
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Performs the PPPoE discovery phase
-***********************************************************************/
-void
-discovery(PPPoEConnection *conn)
-{
-    int padiAttempts = 0;
-    int padrAttempts = 0;
-    int timeout = conn->discoveryTimeout;
-
-    do {
-       padiAttempts++;
-       if (got_sigterm || padiAttempts > conn->discoveryAttempts) {
-           warn("Timeout waiting for PADO packets");
-           close(conn->discoverySocket);
-           conn->discoverySocket = -1;
-           return;
-       }
-       sendPADI(conn);
-       conn->discoveryState = STATE_SENT_PADI;
-       waitForPADO(conn, timeout);
-
-       timeout *= 2;
-    } while (conn->discoveryState == STATE_SENT_PADI);
-
-    timeout = conn->discoveryTimeout;
-    do {
-       padrAttempts++;
-       if (got_sigterm || padrAttempts > conn->discoveryAttempts) {
-           warn("Timeout waiting for PADS packets");
-           close(conn->discoverySocket);
-           conn->discoverySocket = -1;
-           return;
-       }
-       sendPADR(conn);
-       conn->discoveryState = STATE_SENT_PADR;
-       waitForPADS(conn, timeout);
-       timeout *= 2;
-    } while (conn->discoveryState == STATE_SENT_PADR);
-
-    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;
-    }
-
-    /* We're done. */
-    close(conn->discoverySocket);
-    conn->discoverySocket = -1;
-    conn->discoveryState = STATE_SESSION;
-    return;
-}
diff --git a/pppd/plugins/rp-pppoe/if.c b/pppd/plugins/rp-pppoe/if.c
deleted file mode 100644 (file)
index 225dd56..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-/***********************************************************************
-*
-* if.c
-*
-* Implementation of user-space PPPoE redirector for Linux.
-*
-* Functions for opening a raw socket and reading/writing raw Ethernet frames.
-*
-* 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: if.c,v 1.2 2008/06/09 08:34:23 paulus Exp $";
-
-#define _GNU_SOURCE 1
-#include "pppoe.h"
-#include "pppd/pppd.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_NETPACKET_PACKET_H
-#include <netpacket/packet.h>
-#elif defined(HAVE_LINUX_IF_PACKET_H)
-#include <linux/if_packet.h>
-#endif
-
-#ifdef HAVE_ASM_TYPES_H
-#include <asm/types.h>
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_NET_IF_ARP_H
-#include <net/if_arp.h>
-#endif
-
-/* 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) {
-       error("Invalid ether type 0x%x", 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)
-{
-    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.");
-       }
-       error("Can't open socket for pppoe: %m");
-       return -1;
-    }
-
-    if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) {
-       error("Can't set socket options for pppoe: %m");
-       close(fd);
-       return -1;
-    }
-
-    /* Fill in hardware address */
-    if (hwaddr) {
-       strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
-       if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
-           error("Can't get hardware address for %s: %m", ifname);
-           close(fd);
-           return -1;
-       }
-       memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
-#ifdef ARPHRD_ETHER
-       if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
-           warn("Interface %.16s is not Ethernet", ifname);
-       }
-#endif
-       if (NOT_UNICAST(hwaddr)) {
-           fatal("Can't use interface %.16s: it has broadcast/multicast MAC address",
-                 ifname);
-       }
-    }
-
-    /* Sanity check on MTU */
-    strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
-    if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) {
-       error("Can't get MTU for %s: %m", ifname);
-    } else if (ifr.ifr_mtu < ETH_DATA_LEN) {
-       error("Interface %.16s has MTU of %d -- should be at least %d.",
-             ifname, ifr.ifr_mtu, ETH_DATA_LEN);
-       error("This may cause serious connection problems.");
-    }
-
-#ifdef HAVE_STRUCT_SOCKADDR_LL
-    /* Get interface index */
-    sa.sll_family = AF_PACKET;
-    sa.sll_protocol = htons(type);
-
-    strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
-    if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
-       error("Could not get interface index for %s: %m", ifname);
-       close(fd);
-       return -1;
-    }
-    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) {
-       error("Failed to bind to interface %s: %m", ifname);
-       close(fd);
-       return -1;
-    }
-
-    return fd;
-}
-
-
-/***********************************************************************
-*%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)
-{
-    int err;
-
-    if (debug)
-       pppoe_log_packet("Send ", pkt);
-#if defined(HAVE_STRUCT_SOCKADDR_LL)
-    err = send(sock, pkt, size, 0);
-#else
-    struct sockaddr sa;
-
-    strcpy(sa.sa_data, conn->ifName);
-    err = sendto(sock, pkt, size, 0, &sa, sizeof(sa));
-#endif
-    if (err < 0) {
-       error("error sending pppoe packet: %m");
-       return -1;
-    }
-    return 0;
-}
-
-/***********************************************************************
-*%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)
-{
-    if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) {
-       error("error receiving pppoe packet: %m");
-       return -1;
-    }
-    if (debug)
-       pppoe_log_packet("Recv ", pkt);
-    return 0;
-}
diff --git a/pppd/plugins/rp-pppoe/plugin.c b/pppd/plugins/rp-pppoe/plugin.c
deleted file mode 100644 (file)
index 93c0906..0000000
+++ /dev/null
@@ -1,463 +0,0 @@
-/***********************************************************************
-*
-* plugin.c
-*
-* pppd plugin for kernel-mode PPPoE on Linux
-*
-* Copyright (C) 2001 by Roaring Penguin Software Inc., Michal Ostrowski
-* and Jamal Hadi Salim.
-*
-* Much code and many ideas derived from pppoe plugin by Michal
-* Ostrowski and Jamal Hadi Salim, which carries this copyright:
-*
-* Copyright 2000 Michal Ostrowski <mostrows@styx.uwaterloo.ca>,
-*                Jamal Hadi Salim <hadi@cyberus.ca>
-* Borrows heavily from the PPPoATM plugin by Mitchell Blank Jr.,
-* which is based in part on work from Jens Axboe and Paul Mackerras.
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License
-* as published by the Free Software Foundation; either version
-* 2 of the License, or (at your option) any later version.
-*
-***********************************************************************/
-
-static char const RCSID[] =
-"$Id: plugin.c,v 1.17 2008/06/15 04:35:50 paulus Exp $";
-
-#define _GNU_SOURCE 1
-#include "pppoe.h"
-
-#include "pppd/pppd.h"
-#include "pppd/fsm.h"
-#include "pppd/lcp.h"
-#include "pppd/ipcp.h"
-#include "pppd/ccp.h"
-/* #include "pppd/pathnames.h" */
-
-#include <linux/types.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <net/if_arp.h>
-#include <linux/ppp_defs.h>
-#include <linux/if_pppox.h>
-
-#ifndef _ROOT_PATH
-#define _ROOT_PATH ""
-#endif
-
-#define _PATH_ETHOPT         _ROOT_PATH "/etc/ppp/options."
-
-char pppd_version[] = VERSION;
-
-/* From sys-linux.c in pppd -- MUST FIX THIS! */
-extern int new_style_driver;
-
-char *pppd_pppoe_service = NULL;
-static char *acName = NULL;
-static char *existingSession = NULL;
-static int printACNames = 0;
-static char *pppoe_reqd_mac = NULL;
-unsigned char pppoe_reqd_mac_addr[6];
-static char *host_uniq;
-static int pppoe_padi_timeout = PADI_TIMEOUT;
-static int pppoe_padi_attempts = MAX_PADI_ATTEMPTS;
-
-static int PPPoEDevnameHook(char *cmd, char **argv, int doit);
-static option_t Options[] = {
-    { "device name", o_wild, (void *) &PPPoEDevnameHook,
-      "PPPoE device name",
-      OPT_DEVNAM | OPT_PRIVFIX | OPT_NOARG  | OPT_A2STRVAL | OPT_STATIC,
-      devnam},
-    { "rp_pppoe_service", o_string, &pppd_pppoe_service,
-      "Desired PPPoE service name" },
-    { "rp_pppoe_ac",      o_string, &acName,
-      "Desired PPPoE access concentrator name" },
-    { "rp_pppoe_sess",    o_string, &existingSession,
-      "Attach to existing session (sessid:macaddr)" },
-    { "rp_pppoe_verbose", o_int, &printACNames,
-      "Be verbose about discovered access concentrators"},
-    { "pppoe-mac", o_string, &pppoe_reqd_mac,
-      "Only connect to specified MAC address" },
-    { "host-uniq", o_string, &host_uniq,
-      "Set the Host-Uniq to the supplied hex string" },
-    { "pppoe-padi-timeout", o_int, &pppoe_padi_timeout,
-      "Initial timeout for discovery packets in seconds" },
-    { "pppoe-padi-attempts", o_int, &pppoe_padi_attempts,
-      "Number of discovery attempts" },
-    { NULL }
-};
-int (*OldDevnameHook)(char *cmd, char **argv, int doit) = NULL;
-static PPPoEConnection *conn = NULL;
-
-/**********************************************************************
- * %FUNCTION: PPPOEInitDevice
- * %ARGUMENTS:
- * None
- * %RETURNS:
- *
- * %DESCRIPTION:
- * Initializes PPPoE device.
- ***********************************************************************/
-static int
-PPPOEInitDevice(void)
-{
-    conn = malloc(sizeof(PPPoEConnection));
-    if (!conn) {
-       novm("PPPoE session data");
-    }
-    memset(conn, 0, sizeof(PPPoEConnection));
-    conn->ifName = devnam;
-    conn->discoverySocket = -1;
-    conn->sessionSocket = -1;
-    conn->printACNames = printACNames;
-    conn->discoveryTimeout = pppoe_padi_timeout;
-    conn->discoveryAttempts = pppoe_padi_attempts;
-    return 1;
-}
-
-/**********************************************************************
- * %FUNCTION: PPPOEConnectDevice
- * %ARGUMENTS:
- * None
- * %RETURNS:
- * Non-negative if all goes well; -1 otherwise
- * %DESCRIPTION:
- * Connects PPPoE device.
- ***********************************************************************/
-static int
-PPPOEConnectDevice(void)
-{
-    struct sockaddr_pppox sp;
-    struct ifreq ifr;
-    int s;
-
-    /* Open session socket before discovery phase, to avoid losing session */
-    /* packets sent by peer just after PADS packet (noted on some Cisco    */
-    /* server equipment).                                                  */
-    /* Opening this socket just before waitForPADS in the discovery()      */
-    /* function would be more appropriate, but it would mess-up the code   */
-    conn->sessionSocket = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_OE);
-    if (conn->sessionSocket < 0) {
-       error("Failed to create PPPoE socket: %m");
-       return -1;
-    }
-
-    /* Restore configuration */
-    lcp_allowoptions[0].mru = conn->mtu;
-    lcp_wantoptions[0].mru = conn->mru;
-
-    /* Update maximum MRU */
-    s = socket(AF_INET, SOCK_DGRAM, 0);
-    if (s < 0) {
-       error("Can't get MTU for %s: %m", conn->ifName);
-       goto errout;
-    }
-    strlcpy(ifr.ifr_name, conn->ifName, sizeof(ifr.ifr_name));
-    if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
-       error("Can't get MTU for %s: %m", conn->ifName);
-       close(s);
-       goto errout;
-    }
-    close(s);
-
-    if (lcp_allowoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD)
-       lcp_allowoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD;
-    if (lcp_wantoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD)
-       lcp_wantoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD;
-
-    if (host_uniq) {
-       if (!parseHostUniq(host_uniq, &conn->hostUniq))
-           fatal("Illegal value for host-uniq option");
-    } else {
-       /* if a custom host-uniq is not supplied, use our PID */
-       pid_t pid = getpid();
-       conn->hostUniq.type = htons(TAG_HOST_UNIQ);
-       conn->hostUniq.length = htons(sizeof(pid));
-       memcpy(conn->hostUniq.payload, &pid, sizeof(pid));
-    }
-
-    conn->acName = acName;
-    conn->serviceName = pppd_pppoe_service;
-    strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam));
-    if (existingSession) {
-       unsigned int mac[ETH_ALEN];
-       int i, ses;
-       if (sscanf(existingSession, "%d:%x:%x:%x:%x:%x:%x",
-                  &ses, &mac[0], &mac[1], &mac[2],
-                  &mac[3], &mac[4], &mac[5]) != 7) {
-           fatal("Illegal value for rp_pppoe_sess option");
-       }
-       conn->session = htons(ses);
-       for (i=0; i<ETH_ALEN; i++) {
-           conn->peerEth[i] = (unsigned char) mac[i];
-       }
-    } else {
-       conn->discoverySocket =
-            openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth);
-       discovery(conn);
-       if (conn->discoveryState != STATE_SESSION) {
-           error("Unable to complete PPPoE Discovery");
-           goto errout;
-       }
-    }
-
-    /* Set PPPoE session-number for further consumption */
-    ppp_session_number = ntohs(conn->session);
-
-    sp.sa_family = AF_PPPOX;
-    sp.sa_protocol = PX_PROTO_OE;
-    sp.sa_addr.pppoe.sid = conn->session;
-    memcpy(sp.sa_addr.pppoe.dev, conn->ifName, IFNAMSIZ);
-    memcpy(sp.sa_addr.pppoe.remote, conn->peerEth, ETH_ALEN);
-
-    /* Set remote_number for ServPoET */
-    sprintf(remote_number, "%02X:%02X:%02X:%02X:%02X:%02X",
-           (unsigned) conn->peerEth[0],
-           (unsigned) conn->peerEth[1],
-           (unsigned) conn->peerEth[2],
-           (unsigned) conn->peerEth[3],
-           (unsigned) conn->peerEth[4],
-           (unsigned) conn->peerEth[5]);
-
-    warn("Connected to %02X:%02X:%02X:%02X:%02X:%02X via interface %s",
-        (unsigned) conn->peerEth[0],
-        (unsigned) conn->peerEth[1],
-        (unsigned) conn->peerEth[2],
-        (unsigned) conn->peerEth[3],
-        (unsigned) conn->peerEth[4],
-        (unsigned) conn->peerEth[5],
-        conn->ifName);
-
-    script_setenv("MACREMOTE", remote_number, 0);
-
-    if (connect(conn->sessionSocket, (struct sockaddr *) &sp,
-               sizeof(struct sockaddr_pppox)) < 0) {
-       error("Failed to connect PPPoE socket: %d %m", errno);
-       goto errout;
-    }
-
-    return conn->sessionSocket;
-
- errout:
-    if (conn->discoverySocket >= 0) {
-       sendPADT(conn, NULL);
-       close(conn->discoverySocket);
-       conn->discoverySocket = -1;
-    }
-    close(conn->sessionSocket);
-    return -1;
-}
-
-static void
-PPPOERecvConfig(int mru,
-               u_int32_t asyncmap,
-               int pcomp,
-               int accomp)
-{
-#if 0 /* broken protocol, but no point harrassing the users I guess... */
-    if (mru > MAX_PPPOE_MTU)
-       warn("Couldn't increase MRU to %d", mru);
-#endif
-}
-
-/**********************************************************************
- * %FUNCTION: PPPOEDisconnectDevice
- * %ARGUMENTS:
- * None
- * %RETURNS:
- * Nothing
- * %DESCRIPTION:
- * Disconnects PPPoE device
- ***********************************************************************/
-static void
-PPPOEDisconnectDevice(void)
-{
-    struct sockaddr_pppox sp;
-
-    sp.sa_family = AF_PPPOX;
-    sp.sa_protocol = PX_PROTO_OE;
-    sp.sa_addr.pppoe.sid = 0;
-    memcpy(sp.sa_addr.pppoe.dev, conn->ifName, IFNAMSIZ);
-    memcpy(sp.sa_addr.pppoe.remote, conn->peerEth, ETH_ALEN);
-    if (connect(conn->sessionSocket, (struct sockaddr *) &sp,
-               sizeof(struct sockaddr_pppox)) < 0 && errno != EALREADY)
-       error("Failed to disconnect PPPoE socket: %d %m", errno);
-    close(conn->sessionSocket);
-    if (conn->discoverySocket >= 0) {
-        sendPADT(conn, NULL);
-       close(conn->discoverySocket);
-    }
-}
-
-static void
-PPPOEDeviceOptions(void)
-{
-    char buf[MAXPATHLEN];
-
-    strlcpy(buf, _PATH_ETHOPT, MAXPATHLEN);
-    strlcat(buf, devnam, MAXPATHLEN);
-    if (!options_from_file(buf, 0, 0, 1))
-       exit(EXIT_OPTION_ERROR);
-
-}
-
-struct channel pppoe_channel;
-
-/**********************************************************************
- * %FUNCTION: PPPoEDevnameHook
- * %ARGUMENTS:
- * cmd -- the command (actually, the device name
- * argv -- argument vector
- * doit -- if non-zero, set device name.  Otherwise, just check if possible
- * %RETURNS:
- * 1 if we will handle this device; 0 otherwise.
- * %DESCRIPTION:
- * Checks if name is a valid interface name; if so, returns 1.  Also
- * sets up devnam (string representation of device).
- ***********************************************************************/
-static int
-PPPoEDevnameHook(char *cmd, char **argv, int doit)
-{
-    int r = 1;
-    int fd;
-    struct ifreq ifr;
-
-    /*
-     * Take any otherwise-unrecognized option as a possible device name,
-     * and test if it is the name of a network interface with a
-     * hardware address whose sa_family is ARPHRD_ETHER.
-     */
-    if (strlen(cmd) > 4 && !strncmp(cmd, "nic-", 4)) {
-       /* Strip off "nic-" */
-       cmd += 4;
-    }
-
-    /* Open a socket */
-    if ((fd = socket(PF_PACKET, SOCK_RAW, 0)) < 0) {
-       r = 0;
-    }
-
-    /* Try getting interface index */
-    if (r) {
-       strlcpy(ifr.ifr_name, cmd, sizeof(ifr.ifr_name));
-       if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
-           r = 0;
-       } else {
-           if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
-               r = 0;
-           } else {
-               if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
-                   if (doit)
-                       error("Interface %s not Ethernet", cmd);
-                   r = 0;
-               }
-           }
-       }
-    }
-
-    /* Close socket */
-    close(fd);
-    if (r && doit) {
-       strlcpy(devnam, cmd, sizeof(devnam));
-       if (the_channel != &pppoe_channel) {
-
-           the_channel = &pppoe_channel;
-           modem = 0;
-
-           PPPOEInitDevice();
-       }
-       return 1;
-    }
-
-    return r;
-}
-
-/**********************************************************************
- * %FUNCTION: plugin_init
- * %ARGUMENTS:
- * None
- * %RETURNS:
- * Nothing
- * %DESCRIPTION:
- * Initializes hooks for pppd plugin
- ***********************************************************************/
-void
-plugin_init(void)
-{
-    if (!ppp_available() && !new_style_driver) {
-       fatal("Linux kernel does not support PPPoE -- are you running 2.4.x?");
-    }
-
-    add_options(Options);
-
-    info("RP-PPPoE plugin version %s compiled against pppd %s",
-        RP_VERSION, VERSION);
-}
-
-void pppoe_check_options(void)
-{
-    unsigned int mac[6];
-    int i;
-
-    if (pppoe_reqd_mac != NULL) {
-       if (sscanf(pppoe_reqd_mac, "%x:%x:%x:%x:%x:%x",
-                  &mac[0], &mac[1], &mac[2], &mac[3],
-                  &mac[4], &mac[5]) != 6) {
-           option_error("cannot parse pppoe-mac option value");
-           exit(EXIT_OPTION_ERROR);
-       }
-       for (i = 0; i < 6; ++i)
-           conn->req_peer_mac[i] = mac[i];
-       conn->req_peer = 1;
-    }
-
-    lcp_allowoptions[0].neg_accompression = 0;
-    lcp_wantoptions[0].neg_accompression = 0;
-
-    lcp_allowoptions[0].neg_asyncmap = 0;
-    lcp_wantoptions[0].neg_asyncmap = 0;
-
-    lcp_allowoptions[0].neg_pcompression = 0;
-    lcp_wantoptions[0].neg_pcompression = 0;
-
-    if (lcp_allowoptions[0].mru > MAX_PPPOE_MTU)
-       lcp_allowoptions[0].mru = MAX_PPPOE_MTU;
-    if (lcp_wantoptions[0].mru > MAX_PPPOE_MTU)
-       lcp_wantoptions[0].mru = MAX_PPPOE_MTU;
-
-    /* Save configuration */
-    conn->mtu = lcp_allowoptions[0].mru;
-    conn->mru = lcp_wantoptions[0].mru;
-
-    ccp_allowoptions[0].deflate = 0;
-    ccp_wantoptions[0].deflate = 0;
-
-    ipcp_allowoptions[0].neg_vj = 0;
-    ipcp_wantoptions[0].neg_vj = 0;
-
-    ccp_allowoptions[0].bsd_compress = 0;
-    ccp_wantoptions[0].bsd_compress = 0;
-}
-
-struct channel pppoe_channel = {
-    .options = Options,
-    .process_extra_options = &PPPOEDeviceOptions,
-    .check_options = pppoe_check_options,
-    .connect = &PPPOEConnectDevice,
-    .disconnect = &PPPOEDisconnectDevice,
-    .establish_ppp = &generic_establish_ppp,
-    .disestablish_ppp = &generic_disestablish_ppp,
-    .send_config = NULL,
-    .recv_config = &PPPOERecvConfig,
-    .close = NULL,
-    .cleanup = NULL
-};
diff --git a/pppd/plugins/rp-pppoe/pppoe-discovery.c b/pppd/plugins/rp-pppoe/pppoe-discovery.c
deleted file mode 100644 (file)
index c970337..0000000
+++ /dev/null
@@ -1,791 +0,0 @@
-/*
- * Perform PPPoE discovery
- *
- * Copyright (C) 2000-2001 by Roaring Penguin Software Inc.
- * Copyright (C) 2004 Marco d'Itri <md@linux.it>
- *
- * This program may be distributed according to the terms of the GNU
- * General Public License, version 2 or (at your option) any later version.
- *
- */
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <time.h>
-
-#include "pppoe.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_NETPACKET_PACKET_H
-#include <netpacket/packet.h>
-#elif defined(HAVE_LINUX_IF_PACKET_H)
-#include <linux/if_packet.h>
-#endif
-
-#ifdef HAVE_ASM_TYPES_H
-#include <asm/types.h>
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_NET_IF_ARP_H
-#include <net/if_arp.h>
-#endif
-
-char *xstrdup(const char *s);
-void usage(void);
-
-void die(int status)
-{
-       exit(status);
-}
-
-void error(char *fmt, ...)
-{
-    va_list pvar;
-    va_start(pvar, fmt);
-    vfprintf(stderr, fmt, pvar);
-    va_end(pvar);
-}
-
-/* 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)
-{
-    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) {
-           rp_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) {
-           char buffer[256];
-           sprintf(buffer, "Interface %.16s is not Ethernet", ifname);
-           rp_fatal(buffer);
-       }
-#endif
-       if (NOT_UNICAST(hwaddr)) {
-           char buffer[256];
-           sprintf(buffer,
-                   "Interface %.16s has broadcast/multicast MAC address??",
-                   ifname);
-           rp_fatal(buffer);
-       }
-    }
-
-    /* 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;
-}
-
-
-/***********************************************************************
-*%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)
-{
-#if defined(HAVE_STRUCT_SOCKADDR_LL)
-    if (send(sock, pkt, size, 0) < 0) {
-       sysErr("send (sendPacket)");
-       return -1;
-    }
-#else
-    struct sockaddr sa;
-
-    if (!conn) {
-       rp_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) {
-       sysErr("sendto (sendPacket)");
-       return -1;
-    }
-#endif
-    return 0;
-}
-
-/***********************************************************************
-*%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)
-{
-    if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) {
-       sysErr("recv (receivePacket)");
-       return -1;
-    }
-    return 0;
-}
-
-/**********************************************************************
-*%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)
-{
-    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)
-{
-    PPPoETag *tag = extra;
-
-    if (type == TAG_HOST_UNIQ && len == ntohs(tag->length))
-       tag->length = memcmp(data, tag->payload, len);
-}
-
-/**********************************************************************
-*%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)
-{
-    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;
-}
-
-/**********************************************************************
-*%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)
-{
-    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);
-       }
-       break;
-    case TAG_GENERIC_ERROR:
-       if (conn->printACNames) {
-           printf("Got a Generic-Error tag: %.*s\n", (int) len, data);
-       }
-       break;
-    }
-}
-
-/***********************************************************************
-*%FUNCTION: sendPADI
-*%ARGUMENTS:
-* conn -- PPPoEConnection structure
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Sends a PADI packet
-***********************************************************************/
-void
-sendPADI(PPPoEConnection *conn)
-{
-    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);
-    }
-}
-
-/**********************************************************************
-*%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)
-{
-    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);
-}
-
-/**********************************************************************
-*%FUNCTION: discovery
-*%ARGUMENTS:
-* conn -- PPPoE connection info structure
-*%RETURNS:
-* Nothing
-*%DESCRIPTION:
-* Performs the PPPoE discovery phase
-***********************************************************************/
-void
-discovery(PPPoEConnection *conn)
-{
-    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);
-}
-
-int main(int argc, char *argv[])
-{
-    int opt;
-    PPPoEConnection *conn;
-
-    conn = malloc(sizeof(PPPoEConnection));
-    if (!conn)
-       fatalSys("malloc");
-
-    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:W:t:a:h")) > 0) {
-       switch(opt) {
-       case 'S':
-           conn->serviceName = xstrdup(optarg);
-           break;
-       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':
-           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");
-           if (!conn->debugFile) {
-               fprintf(stderr, "Could not open %s: %s\n",
-                       optarg, strerror(errno));
-               exit(1);
-           }
-           fprintf(conn->debugFile, "pppoe-discovery %s\n", RP_VERSION);
-           break;
-       case 'I':
-           conn->ifName = xstrdup(optarg);
-           break;
-       case 'Q':
-           conn->printACNames = 0;
-           break;
-       case 'V':
-       case 'h':
-           usage();
-           exit(0);
-       default:
-           usage();
-           exit(1);
-       }
-    }
-
-    /* default interface name */
-    if (!conn->ifName)
-       conn->ifName = strdup("eth0");
-
-    conn->discoverySocket = -1;
-    conn->sessionSocket = -1;
-
-    discovery(conn);
-
-    if (!conn->numPADOs)
-       exit(1);
-    else
-       exit(0);
-}
-
-void rp_fatal(char const *str)
-{
-    fprintf(stderr, "%s\n", str);
-    exit(1);
-}
-
-void fatalSys(char const *str)
-{
-    perror(str);
-    exit(1);
-}
-
-void sysErr(char const *str)
-{
-    rp_fatal(str);
-}
-
-char *xstrdup(const char *s)
-{
-    register char *ret = strdup(s);
-    if (!ret)
-       sysErr("strdup");
-    return ret;
-}
-
-void usage(void)
-{
-    fprintf(stderr, "Usage: pppoe-discovery [options]\n");
-    fprintf(stderr, "Options:\n");
-    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");
-}
diff --git a/pppd/plugins/rp-pppoe/pppoe.h b/pppd/plugins/rp-pppoe/pppoe.h
deleted file mode 100644 (file)
index e2dc2ff..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-/***********************************************************************
-*
-* pppoe.h
-*
-* Declaration of various PPPoE constants
-*
-* Copyright (C) 2000 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.
-*
-* $Id: pppoe.h,v 1.4 2008/06/15 04:35:50 paulus Exp $
-*
-***********************************************************************/
-
-#include "config.h"
-
-#include <stdio.h>             /* For FILE */
-#include <sys/types.h>         /* For pid_t */
-#include <ctype.h>
-#include <string.h>
-
-#include "pppd/pppd.h"         /* For error */
-
-/* How do we access raw Ethernet devices? */
-#undef USE_LINUX_PACKET
-#undef USE_BPF
-
-#if defined(HAVE_NETPACKET_PACKET_H) || defined(HAVE_LINUX_IF_PACKET_H)
-#define USE_LINUX_PACKET 1
-#elif defined(HAVE_SYS_DLPI_H)
-#define USE_DLPI
-#elif defined(HAVE_NET_BPF_H)
-#define USE_BPF 1
-#endif
-
-/* Sanity check */
-#if !defined(USE_BPF) && !defined(USE_LINUX_PACKET) && !defined(USE_DLPI)
-#error Unknown method for accessing raw Ethernet frames
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-/* This has to be included before Linux 4.8's linux/in.h
- * gets dragged in. */
-#include <netinet/in.h>
-
-/* Ugly header files on some Linux boxes... */
-#if defined(HAVE_LINUX_IF_H)
-#include <linux/if.h>
-#elif defined(HAVE_NET_IF_H)
-#include <net/if.h>
-#endif
-
-#ifdef HAVE_NET_IF_TYPES_H
-#include <net/if_types.h>
-#endif
-
-#define BPF_BUFFER_IS_EMPTY 1
-#define BPF_BUFFER_HAS_DATA 0
-
-/* Define various integer types -- assumes a char is 8 bits */
-#if SIZEOF_UNSIGNED_SHORT == 2
-typedef unsigned short UINT16_t;
-#elif SIZEOF_UNSIGNED_INT == 2
-typedef unsigned int UINT16_t;
-#else
-#error Could not find a 16-bit integer type
-#endif
-
-#if SIZEOF_UNSIGNED_SHORT == 4
-typedef unsigned short UINT32_t;
-#elif SIZEOF_UNSIGNED_INT == 4
-typedef unsigned int UINT32_t;
-#elif SIZEOF_UNSIGNED_LONG == 4
-typedef unsigned long UINT32_t;
-#else
-#error Could not find a 32-bit integer type
-#endif
-
-#ifdef HAVE_LINUX_IF_ETHER_H
-#include <linux/if_ether.h>
-#else
-
-#ifdef HAVE_NETINET_IF_ETHER_H
-#include <sys/types.h>
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifndef HAVE_SYS_DLPI_H
-#include <netinet/if_ether.h>
-#endif
-#endif
-#endif
-
-/* Ethernet frame types according to RFC 2516 */
-#define ETH_PPPOE_DISCOVERY 0x8863
-#define ETH_PPPOE_SESSION   0x8864
-
-/* But some brain-dead peers disobey the RFC, so frame types are variables */
-extern UINT16_t Eth_PPPOE_Discovery;
-extern UINT16_t Eth_PPPOE_Session;
-
-/* PPPoE codes */
-#define CODE_PADI           0x09
-#define CODE_PADO           0x07
-#define CODE_PADR           0x19
-#define CODE_PADS           0x65
-#define CODE_PADT           0xA7
-
-/* Extensions from draft-carrel-info-pppoe-ext-00 */
-/* I do NOT like PADM or PADN, but they are here for completeness */
-#define CODE_PADM           0xD3
-#define CODE_PADN           0xD4
-
-#define CODE_SESS           0x00
-
-/* PPPoE Tags */
-#define TAG_END_OF_LIST        0x0000
-#define TAG_SERVICE_NAME       0x0101
-#define TAG_AC_NAME            0x0102
-#define TAG_HOST_UNIQ          0x0103
-#define TAG_AC_COOKIE          0x0104
-#define TAG_VENDOR_SPECIFIC    0x0105
-#define TAG_RELAY_SESSION_ID   0x0110
-#define TAG_PPP_MAX_PAYLOAD    0x0120
-#define TAG_SERVICE_NAME_ERROR 0x0201
-#define TAG_AC_SYSTEM_ERROR    0x0202
-#define TAG_GENERIC_ERROR      0x0203
-
-/* Extensions from draft-carrel-info-pppoe-ext-00 */
-/* I do NOT like these tags one little bit */
-#define TAG_HURL               0x111
-#define TAG_MOTM               0x112
-#define TAG_IP_ROUTE_ADD       0x121
-
-/* Discovery phase states */
-#define STATE_SENT_PADI     0
-#define STATE_RECEIVED_PADO 1
-#define STATE_SENT_PADR     2
-#define STATE_SESSION       3
-#define STATE_TERMINATED    4
-
-/* How many PADI/PADS attempts? */
-#define MAX_PADI_ATTEMPTS 3
-
-/* Initial timeout for PADO/PADS */
-#define PADI_TIMEOUT 5
-
-/* States for scanning PPP frames */
-#define STATE_WAITFOR_FRAME_ADDR 0
-#define STATE_DROP_PROTO         1
-#define STATE_BUILDING_PACKET    2
-
-/* Special PPP frame characters */
-#define FRAME_ESC    0x7D
-#define FRAME_FLAG   0x7E
-#define FRAME_ADDR   0xFF
-#define FRAME_CTRL   0x03
-#define FRAME_ENC    0x20
-
-#define IPV4ALEN     4
-#define SMALLBUF   256
-
-/* There are other fixed-size buffers preventing
-   this from being increased to 16110. The buffer
-   sizes would need to be properly de-coupled from
-   the default MRU. For now, getting up to 1500 is
-   enough. */
-#define ETH_JUMBO_LEN 1508
-
-/* A PPPoE Packet, including Ethernet headers */
-typedef struct PPPoEPacketStruct {
-    struct ethhdr ethHdr;      /* Ethernet header */
-    unsigned int vertype:8;    /* PPPoE Version and Type (must both be 1) */
-    unsigned int code:8;       /* PPPoE code */
-    unsigned int session:16;   /* PPPoE session */
-    unsigned int length:16;    /* Payload length */
-    unsigned char payload[ETH_JUMBO_LEN]; /* A bit of room to spare */
-} PPPoEPacket;
-
-#define PPPOE_VER(vt)          ((vt) >> 4)
-#define PPPOE_TYPE(vt)         ((vt) & 0xf)
-#define PPPOE_VER_TYPE(v, t)   (((v) << 4) | (t))
-
-/* Header size of a PPPoE packet */
-#define PPPOE_OVERHEAD 6  /* type, code, session, length */
-#define HDR_SIZE (sizeof(struct ethhdr) + PPPOE_OVERHEAD)
-#define MAX_PPPOE_PAYLOAD (ETH_JUMBO_LEN - PPPOE_OVERHEAD)
-#define PPP_OVERHEAD 2  /* protocol */
-#define MAX_PPPOE_MTU (MAX_PPPOE_PAYLOAD - PPP_OVERHEAD)
-#define TOTAL_OVERHEAD (PPPOE_OVERHEAD + PPP_OVERHEAD)
-#define ETH_PPPOE_MTU (ETH_DATA_LEN - TOTAL_OVERHEAD)
-
-/* PPPoE Tag */
-
-typedef struct PPPoETagStruct {
-    unsigned int type:16;      /* tag type */
-    unsigned int length:16;    /* Length of payload */
-    unsigned char payload[ETH_JUMBO_LEN]; /* A LOT of room to spare */
-} PPPoETag;
-/* Header size of a PPPoE tag */
-#define TAG_HDR_SIZE 4
-
-/* Chunk to read from stdin */
-#define READ_CHUNK 4096
-
-/* Function passed to parsePacket */
-typedef void ParseFunc(UINT16_t type,
-                      UINT16_t len,
-                      unsigned char *data,
-                      void *extra);
-
-#define PPPINITFCS16    0xffff  /* Initial FCS value */
-
-/* Keep track of the state of a connection -- collect everything in
-   one spot */
-
-typedef struct PPPoEConnectionStruct {
-    int discoveryState;                /* Where we are in discovery */
-    int discoverySocket;       /* Raw socket for discovery frames */
-    int sessionSocket;         /* Raw socket for session frames */
-    unsigned char myEth[ETH_ALEN]; /* My MAC address */
-    unsigned char peerEth[ETH_ALEN]; /* Peer's MAC address */
-    unsigned char req_peer_mac[ETH_ALEN]; /* required peer MAC address */
-    unsigned char req_peer;    /* require mac addr to match req_peer_mac */
-    UINT16_t session;          /* Session ID */
-    char *ifName;              /* Interface name */
-    char *serviceName;         /* Desired service name, if any */
-    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 */
-} PPPoEConnection;
-
-/* Structure used to determine acceptable PADO or PADS packet */
-struct PacketCriteria {
-    PPPoEConnection *conn;
-    int acNameOK;
-    int serviceNameOK;
-    int seenACName;
-    int seenServiceName;
-};
-
-/* Function Prototypes */
-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 rp_fatal(char const *str);
-void printErr(char const *str);
-void sysErr(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);
-void asyncReadFromPPP(PPPoEConnection *conn, PPPoEPacket *packet);
-void asyncReadFromEth(PPPoEConnection *conn, int sock, int clampMss);
-void syncReadFromEth(PPPoEConnection *conn, int sock, int clampMss);
-char *strDup(char const *str);
-void sendPADT(PPPoEConnection *conn, char const *msg);
-void sendSessionPacket(PPPoEConnection *conn,
-                      PPPoEPacket *packet, int len);
-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);
-unsigned char *findTag(PPPoEPacket *packet, UINT16_t tagType,
-                      PPPoETag *tag);
-
-void pppoe_printpkt(PPPoEPacket *packet,
-                   void (*printer)(void *, char *, ...), void *arg);
-void pppoe_log_packet(const char *prefix, PPPoEPacket *packet);
-
-static inline int parseHostUniq(const char *uniq, PPPoETag *tag)
-{
-    unsigned i, len = strlen(uniq);
-
-#define hex(x) \
-    (((x) <= '9') ? ((x) - '0') : \
-        (((x) <= 'F') ? ((x) - 'A' + 10) : \
-            ((x) - 'a' + 10)))
-
-    if (!len || len % 2 || len / 2 > sizeof(tag->payload))
-        return 0;
-
-    for (i = 0; i < len; i += 2) {
-        if (!isxdigit(uniq[i]) || !isxdigit(uniq[i+1]))
-            return 0;
-
-        tag->payload[i / 2] = (char)(hex(uniq[i]) << 4 | hex(uniq[i+1]));
-    }
-
-#undef hex
-
-    tag->type = htons(TAG_HOST_UNIQ);
-    tag->length = htons(len / 2);
-    return 1;
-}
-
-#define SET_STRING(var, val) do { if (var) free(var); var = strDup(val); } while(0);
-
-#define CHECK_ROOM(cursor, start, len) \
-do {\
-    if (((cursor)-(start))+(len) > MAX_PPPOE_PAYLOAD) { \
-       error("Would create too-long packet");  \
-        return; \
-    } \
-} while(0)
-
-/* True if Ethernet address is broadcast or multicast */
-#define NOT_UNICAST(e) ((e[0] & 0x01) != 0)
-#define BROADCAST(e) ((e[0] & e[1] & e[2] & e[3] & e[4] & e[5]) == 0xFF)
-#define NOT_BROADCAST(e) ((e[0] & e[1] & e[2] & e[3] & e[4] & e[5]) != 0xFF)
index 85af954bf25baca2e9cc4f91953beb2a46af1787..6a11fcb17b6de7f0ac75bd76e7f790edc9ae7f2e 100644 (file)
@@ -1204,7 +1204,7 @@ Use software flow control (i.e. XON/XOFF) to control the flow of data on
 the serial port.
 .SH PPPOE OPTIONS
 To establish PPP link over Ethernet (PPPoE) it is needed to load pppd's
 the serial port.
 .SH PPPOE OPTIONS
 To establish PPP link over Ethernet (PPPoE) it is needed to load pppd's
-\fBplugin rp-pppoe.so\fR and then specify option \fBnic-\fIinterface\fR
+\fBplugin pppoe.so\fR and then specify option \fBnic-\fIinterface\fR
 instead of modem options \fIttyname\fR and \fIspeed\fR.
 Recognized pppd's PPPoE options are:
 .TP
 instead of modem options \fIttyname\fR and \fIspeed\fR.
 Recognized pppd's PPPoE options are:
 .TP