summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/ng_pppoe.c
diff options
context:
space:
mode:
authoryar <yar@FreeBSD.org>2003-12-18 16:38:35 +0000
committeryar <yar@FreeBSD.org>2003-12-18 16:38:35 +0000
commit431cb9e4dc78564e06e4ba15074b17419df2a740 (patch)
tree92c38e0c47e7447045521bd2d5650c853ad0e90d /sys/netgraph/ng_pppoe.c
parent9509c3737c193d2a5033b506b83ef3d489ad2368 (diff)
downloadFreeBSD-src-431cb9e4dc78564e06e4ba15074b17419df2a740.zip
FreeBSD-src-431cb9e4dc78564e06e4ba15074b17419df2a740.tar.gz
There are two modes of ng_pppoe operation, standard and
nonstandard. They differ in the values of certain fields in the PPPoE frame. Previously, ng_pppoe would start in standard mode, yet switch to nonstandard one upon reception of a single nonstandard frame. After having done so, ng_pppoe would be unable to interact with standard PPPoE peers. Thus, a DoS condition existed that could be triggered by a buggy peer or malicious party. Since few people have expressed their displeasure WRT this problem, the default operation of ng_pppoe is left untouched for now. However, a new value for the sysctl net.graph.nonstandard_pppoe is introduced, -1, which will force ng_pppoe stay in standard mode regardless of any bogus frames floating around. PR: kern/47920 Submitted by: Gleb Smirnoff <glebius <at> cell.sick.ru> MFC after: 1 week
Diffstat (limited to 'sys/netgraph/ng_pppoe.c')
-rw-r--r--sys/netgraph/ng_pppoe.c49
1 files changed, 38 insertions, 11 deletions
diff --git a/sys/netgraph/ng_pppoe.c b/sys/netgraph/ng_pppoe.c
index 886747e..faa7549 100644
--- a/sys/netgraph/ng_pppoe.c
+++ b/sys/netgraph/ng_pppoe.c
@@ -54,6 +54,7 @@
#include <sys/malloc.h>
#include <sys/errno.h>
#include <sys/sysctl.h>
+#include <sys/syslog.h>
#include <net/ethernet.h>
#include <netgraph/ng_message.h>
@@ -244,23 +245,36 @@ struct ether_header eh_prototype =
{0x00,0x00,0x00,0x00,0x00,0x00},
ETHERTYPE_PPPOE_DISC};
-static int nonstandard;
+#define PPPOE_KEEPSTANDARD -1 /* never switch to nonstandard mode */
+#define PPPOE_STANDARD 0 /* try standard mode (default) */
+#define PPPOE_NONSTANDARD 1 /* just be in nonstandard mode */
+static int pppoe_mode = PPPOE_STANDARD;
+
static int
ngpppoe_set_ethertype(SYSCTL_HANDLER_ARGS)
{
int error;
int val;
- val = nonstandard;
+ val = pppoe_mode;
error = sysctl_handle_int(oidp, &val, sizeof(int), req);
if (error != 0 || req->newptr == NULL)
return (error);
- if (val == 1) {
- nonstandard = 1;
+ switch (val) {
+ case PPPOE_NONSTANDARD:
+ pppoe_mode = PPPOE_NONSTANDARD;
eh_prototype.ether_type = ETHERTYPE_PPPOE_STUPID_DISC;
- } else {
- nonstandard = 0;
+ break;
+ case PPPOE_STANDARD:
+ pppoe_mode = PPPOE_STANDARD;
eh_prototype.ether_type = ETHERTYPE_PPPOE_DISC;
+ break;
+ case PPPOE_KEEPSTANDARD:
+ pppoe_mode = PPPOE_KEEPSTANDARD;
+ eh_prototype.ether_type = ETHERTYPE_PPPOE_DISC;
+ break;
+ default:
+ return (EINVAL);
}
return (0);
}
@@ -982,8 +996,21 @@ AAA
length = ntohs(wh->ph.length);
switch(wh->eh.ether_type) {
case ETHERTYPE_PPPOE_STUPID_DISC:
- nonstandard = 1;
- eh_prototype.ether_type = ETHERTYPE_PPPOE_STUPID_DISC;
+ if (pppoe_mode == PPPOE_STANDARD) {
+ pppoe_mode = PPPOE_NONSTANDARD;
+ eh_prototype.ether_type =
+ ETHERTYPE_PPPOE_STUPID_DISC;
+ log(LOG_NOTICE,
+ "Switched to nonstandard PPPoE mode due to "
+ "packet from %*D\n",
+ sizeof(wh->eh.ether_shost),
+ wh->eh.ether_shost, ":");
+ } else if (pppoe_mode == PPPOE_KEEPSTANDARD)
+ log(LOG_NOTICE,
+ "Ignored nonstandard PPPoE packet "
+ "from %*D\n",
+ sizeof(wh->eh.ether_shost),
+ wh->eh.ether_shost, ":");
/* fall through */
case ETHERTYPE_PPPOE_DISC:
/*
@@ -1185,7 +1212,7 @@ AAA
* from NEWCONNECTED to CONNECTED
*/
sp->pkt_hdr = neg->pkt->pkt_header;
- if (nonstandard)
+ if (pppoe_mode == PPPOE_NONSTANDARD)
sp->pkt_hdr.eh.ether_type
= ETHERTYPE_PPPOE_STUPID_SESS;
else
@@ -1237,7 +1264,7 @@ AAA
* Keep a copy of the header we will be using.
*/
sp->pkt_hdr = neg->pkt->pkt_header;
- if (nonstandard)
+ if (pppoe_mode == PPPOE_NONSTANDARD)
sp->pkt_hdr.eh.ether_type
= ETHERTYPE_PPPOE_STUPID_SESS;
else
@@ -1519,7 +1546,7 @@ AAA
/* revert the stored header to DISC/PADT mode */
wh = &sp->pkt_hdr;
wh->ph.code = PADT_CODE;
- if (nonstandard)
+ if (pppoe_mode == PPPOE_NONSTANDARD)
wh->eh.ether_type = ETHERTYPE_PPPOE_STUPID_DISC;
else
wh->eh.ether_type = ETHERTYPE_PPPOE_DISC;
OpenPOWER on IntegriCloud