When node is server serve both standard RFC2516 and non-standard 3Com
clients simultaneously. When node is client its mode is configured with a control message. sysctl net.graph.nonstandard_pppoe is deprecated but kept for backward compatibility for some time. Approved by: julian
This commit is contained in:
parent
76e8a01fc9
commit
fdc755d162
@ -151,6 +151,20 @@ static const struct ng_cmdlist ng_pppoe_cmds[] = {
|
||||
&ng_pppoe_sts_state_type,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
NGM_PPPOE_COOKIE,
|
||||
NGM_PPPOE_SETMODE,
|
||||
"pppoe_setmode",
|
||||
&ng_parse_string_type,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
NGM_PPPOE_COOKIE,
|
||||
NGM_PPPOE_GETMODE,
|
||||
"pppoe_getmode",
|
||||
NULL,
|
||||
&ng_parse_string_type
|
||||
},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@ -224,6 +238,35 @@ struct sess_con {
|
||||
};
|
||||
typedef struct sess_con *sessp;
|
||||
|
||||
#define NG_PPPOE_SESSION_NODE(sp) NG_HOOK_NODE(sp->hook)
|
||||
|
||||
enum {
|
||||
PPPOE_STANDARD = 1, /* standard RFC2516 mode */
|
||||
PPPOE_NONSTANDARD, /* 3Com proprietary mode */
|
||||
};
|
||||
|
||||
struct ng_pppoe_mode_t {
|
||||
u_int8_t id;
|
||||
const struct ether_header *eh_prototype;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct ether_header eh_standard =
|
||||
{{0xff,0xff,0xff,0xff,0xff,0xff},
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
ETHERTYPE_PPPOE_DISC};
|
||||
|
||||
static const struct ether_header eh_3Com =
|
||||
{{0xff,0xff,0xff,0xff,0xff,0xff},
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
ETHERTYPE_PPPOE_STUPID_DISC};
|
||||
|
||||
static const struct ng_pppoe_mode_t ng_pppoe_modes[] = {
|
||||
{ PPPOE_STANDARD, &eh_standard, NG_PPPOE_STANDARD },
|
||||
{ PPPOE_NONSTANDARD, &eh_3Com, NG_PPPOE_NONSTANDARD },
|
||||
{ 0, NULL},
|
||||
};
|
||||
|
||||
/*
|
||||
* Information we store for each node
|
||||
*/
|
||||
@ -234,23 +277,17 @@ struct PPPOE {
|
||||
u_int packets_in; /* packets in from ethernet */
|
||||
u_int packets_out; /* packets out towards ethernet */
|
||||
u_int32_t flags;
|
||||
const struct ng_pppoe_mode_t *mode; /* standard PPPoE or 3Com? */
|
||||
/*struct sess_con *buckets[HASH_SIZE];*/ /* not yet used */
|
||||
};
|
||||
typedef struct PPPOE *priv_p;
|
||||
|
||||
/*
|
||||
* XXXRW: Leave this unsynchronized, since only a single field is modified,
|
||||
* and it's done so infrequently. Likewise, pppoe_mode.
|
||||
*/
|
||||
struct ether_header eh_prototype =
|
||||
{{0xff,0xff,0xff,0xff,0xff,0xff},
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
ETHERTYPE_PPPOE_DISC};
|
||||
|
||||
#define PPPOE_KEEPSTANDARD -1 /* never switch to nonstandard mode */
|
||||
#define PPPOE_STANDARD 0 /* try standard mode (dangerous!) */
|
||||
#define PPPOE_NONSTANDARD 1 /* just be in nonstandard mode */
|
||||
/* Deprecated sysctl, leaved here to keep compatibility for some time */
|
||||
#define PPPOE_KEEPSTANDARD -1
|
||||
#define PPPOE_STANDARD 0
|
||||
#define PPPOE_NONSTANDARD 1
|
||||
static int pppoe_mode = PPPOE_KEEPSTANDARD;
|
||||
static const struct ng_pppoe_mode_t *sysctl_mode = ng_pppoe_modes;
|
||||
|
||||
static int
|
||||
ngpppoe_set_ethertype(SYSCTL_HANDLER_ARGS)
|
||||
@ -264,20 +301,18 @@ ngpppoe_set_ethertype(SYSCTL_HANDLER_ARGS)
|
||||
return (error);
|
||||
switch (val) {
|
||||
case PPPOE_NONSTANDARD:
|
||||
pppoe_mode = PPPOE_NONSTANDARD;
|
||||
eh_prototype.ether_type = ETHERTYPE_PPPOE_STUPID_DISC;
|
||||
sysctl_mode = ng_pppoe_modes + 1;
|
||||
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;
|
||||
sysctl_mode = ng_pppoe_modes;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
pppoe_mode = val;
|
||||
printf("net.graph.nonstandard_pppoe is deprecated. See ng_pppoe(4), ppp(8).\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -600,6 +635,10 @@ AAA
|
||||
/* Link structs together; this counts as our one reference to *nodep */
|
||||
NG_NODE_SET_PRIVATE(node, privdata);
|
||||
privdata->node = node;
|
||||
|
||||
/* Initialize to standard mode (the first one in ng_pppoe_modes[]). */
|
||||
privdata->mode = sysctl_mode;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -757,7 +796,9 @@ AAA
|
||||
callout_handle_init( &neg->timeout_handle);
|
||||
neg->m->m_len = sizeof(struct pppoe_full_hdr);
|
||||
neg->pkt = mtod(neg->m, union packet*);
|
||||
neg->pkt->pkt_header.eh = eh_prototype;
|
||||
memcpy((void *)&neg->pkt->pkt_header.eh,
|
||||
(const void *)privp->mode->eh_prototype,
|
||||
sizeof(struct ether_header));
|
||||
neg->pkt->pkt_header.ph.ver = 0x1;
|
||||
neg->pkt->pkt_header.ph.type = 0x1;
|
||||
neg->pkt->pkt_header.ph.sid = 0x0000;
|
||||
@ -860,6 +901,38 @@ AAA
|
||||
ourmsg->data_len);
|
||||
neg->service_len = ourmsg->data_len;
|
||||
break;
|
||||
case NGM_PPPOE_SETMODE:
|
||||
{
|
||||
const struct ng_pppoe_mode_t *mode;
|
||||
char *s;
|
||||
size_t len;
|
||||
|
||||
if (msg->header.arglen == 0)
|
||||
LEAVE(EINVAL);
|
||||
|
||||
s = (char *)msg->data;
|
||||
len = msg->header.arglen - 1;
|
||||
|
||||
/* Search for matching mode string */
|
||||
for (mode = ng_pppoe_modes; mode->id != 0; mode++ )
|
||||
if ((strlen(mode->name) == len) &&
|
||||
!strncmp(mode->name, s, len))
|
||||
break; /* found */
|
||||
|
||||
if (mode->id != 0)
|
||||
privp->mode = mode;
|
||||
else
|
||||
LEAVE(EINVAL);
|
||||
break;
|
||||
}
|
||||
case NGM_PPPOE_GETMODE:
|
||||
NG_MKRESPONSE(resp, msg, strlen(privp->mode->name) + 1,
|
||||
M_NOWAIT);
|
||||
if (resp == NULL)
|
||||
LEAVE(ENOMEM);
|
||||
strlcpy((char *)resp->data, privp->mode->name,
|
||||
strlen(privp->mode->name) + 1);
|
||||
break;
|
||||
default:
|
||||
LEAVE(EINVAL);
|
||||
}
|
||||
@ -883,6 +956,7 @@ AAA
|
||||
static void
|
||||
pppoe_start(sessp sp)
|
||||
{
|
||||
priv_p privp = NG_NODE_PRIVATE(NG_PPPOE_SESSION_NODE(sp));
|
||||
struct {
|
||||
struct pppoe_tag hdr;
|
||||
union uniq data;
|
||||
@ -893,8 +967,11 @@ pppoe_start(sessp sp)
|
||||
*/
|
||||
AAA
|
||||
sp->state = PPPOE_SINIT;
|
||||
/* reset the packet header to broadcast */
|
||||
sp->neg->pkt->pkt_header.eh = eh_prototype;
|
||||
/* Reset the packet header to broadcast. Since we are in a client
|
||||
* mode use configured ethertype. */
|
||||
memcpy((void *)&sp->neg->pkt->pkt_header.eh,
|
||||
(const void *)privp->mode->eh_prototype,
|
||||
sizeof(struct ether_header));
|
||||
sp->neg->pkt->pkt_header.ph.code = PADI_CODE;
|
||||
uniqtag.hdr.tag_type = PTT_HOST_UNIQ;
|
||||
uniqtag.hdr.tag_len = htons((u_int16_t)sizeof(uniqtag.data));
|
||||
@ -997,23 +1074,7 @@ AAA
|
||||
wh = mtod(m, struct pppoe_full_hdr *);
|
||||
length = ntohs(wh->ph.length);
|
||||
switch(wh->eh.ether_type) {
|
||||
case 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",
|
||||
ETHER_ADDR_LEN,
|
||||
wh->eh.ether_shost, ":");
|
||||
} else if (pppoe_mode == PPPOE_KEEPSTANDARD)
|
||||
log(LOG_NOTICE,
|
||||
"Ignored nonstandard PPPoE packet "
|
||||
"from %*D\n",
|
||||
ETHER_ADDR_LEN,
|
||||
wh->eh.ether_shost, ":");
|
||||
/* fall through */
|
||||
case ETHERTYPE_PPPOE_STUPID_DISC: /* fall through */
|
||||
case ETHERTYPE_PPPOE_DISC:
|
||||
/*
|
||||
* We need to try to make sure that the tag area
|
||||
@ -1214,7 +1275,10 @@ AAA
|
||||
* from NEWCONNECTED to CONNECTED
|
||||
*/
|
||||
sp->pkt_hdr = neg->pkt->pkt_header;
|
||||
if (pppoe_mode == PPPOE_NONSTANDARD)
|
||||
/* Configure ethertype depending on what
|
||||
* ethertype was used at discovery phase */
|
||||
if (sp->pkt_hdr.eh.ether_type ==
|
||||
ETHERTYPE_PPPOE_STUPID_DISC)
|
||||
sp->pkt_hdr.eh.ether_type
|
||||
= ETHERTYPE_PPPOE_STUPID_SESS;
|
||||
else
|
||||
@ -1266,7 +1330,7 @@ AAA
|
||||
* Keep a copy of the header we will be using.
|
||||
*/
|
||||
sp->pkt_hdr = neg->pkt->pkt_header;
|
||||
if (pppoe_mode == PPPOE_NONSTANDARD)
|
||||
if (privp->mode->id == PPPOE_NONSTANDARD)
|
||||
sp->pkt_hdr.eh.ether_type
|
||||
= ETHERTYPE_PPPOE_STUPID_SESS;
|
||||
else
|
||||
@ -1407,6 +1471,8 @@ AAA
|
||||
session = ntohs(wh->ph.sid);
|
||||
length = ntohs(wh->ph.length);
|
||||
code = wh->ph.code;
|
||||
/* Use peers mode in session */
|
||||
neg->pkt->pkt_header.eh.ether_type = wh->eh.ether_type;
|
||||
if ( code != PADI_CODE) {
|
||||
LEAVE(EINVAL);
|
||||
};
|
||||
@ -1548,7 +1614,10 @@ AAA
|
||||
/* revert the stored header to DISC/PADT mode */
|
||||
wh = &sp->pkt_hdr;
|
||||
wh->ph.code = PADT_CODE;
|
||||
if (pppoe_mode == PPPOE_NONSTANDARD)
|
||||
/* Configure ethertype depending on what was used during
|
||||
* sessions stage. */
|
||||
if (sp->pkt_hdr.eh.ether_type ==
|
||||
ETHERTYPE_PPPOE_STUPID_SESS)
|
||||
wh->eh.ether_type = ETHERTYPE_PPPOE_STUPID_DISC;
|
||||
else
|
||||
wh->eh.ether_type = ETHERTYPE_PPPOE_DISC;
|
||||
|
@ -49,7 +49,7 @@
|
||||
/* Node type name. This should be unique among all netgraph node types */
|
||||
#define NG_PPPOE_NODE_TYPE "pppoe"
|
||||
|
||||
#define NGM_PPPOE_COOKIE 939032003
|
||||
#define NGM_PPPOE_COOKIE 1089893072
|
||||
|
||||
/* Number of active sessions we can handle */
|
||||
#define PPPOE_NUM_SESSIONS 16 /* for now */
|
||||
@ -62,6 +62,10 @@
|
||||
#define NG_PPPOE_HOOK_C_LEADIN "client" /* Connect message starts this */
|
||||
#define NG_PPPOE_HOOK_DEBUG "debug"
|
||||
|
||||
/* Mode names */
|
||||
#define NG_PPPOE_STANDARD "standard"
|
||||
#define NG_PPPOE_NONSTANDARD "3Com"
|
||||
|
||||
/**********************************************************************
|
||||
* Netgraph commands understood by this node type.
|
||||
* FAIL, SUCCESS, CLOSE and ACNAME are sent by the node rather than received.
|
||||
@ -77,7 +81,9 @@ enum cmd {
|
||||
NGM_PPPOE_SERVICE = 8, /* additional Service to advertise (in PADO) */
|
||||
NGM_PPPOE_ACNAME = 9, /* AC_NAME for informational purposes */
|
||||
NGM_PPPOE_GET_STATUS = 10, /* data in/out */
|
||||
NGM_PPPOE_SESSIONID = 11 /* Session_ID for informational purposes */
|
||||
NGM_PPPOE_SESSIONID = 11, /* Session_ID for informational purposes */
|
||||
NGM_PPPOE_SETMODE = 12, /* set to standard or 3Com mode */
|
||||
NGM_PPPOE_GETMODE = 13, /* see current mode */
|
||||
};
|
||||
|
||||
/***********************
|
||||
|
Loading…
Reference in New Issue
Block a user