]> 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:
 
-    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,
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
-    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
index 5a7bd7966215e97f89b774d95645fb37477a7240..e2a680e85f955140432ef832a5a22ab9b0ccfce4 100644 (file)
@@ -12,7 +12,7 @@ BINDIR = $(DESTDIR)/sbin
 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
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
-\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