mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
netgraph/pppoe: user-supplied Host-Uniq tag and PADM messages
Taken from: https://reviews.freebsd.org/D9270
PR: https://forum.opnsense.org/index.php?topic=5307.0
(cherry picked from commit 0d95422960)
This commit is contained in:
parent
56281aa497
commit
6c39c7bc2f
3 changed files with 359 additions and 44 deletions
|
|
@ -35,7 +35,7 @@
|
|||
.\" $FreeBSD$
|
||||
.\" $Whistle: ng_pppoe.8,v 1.1 1999/01/25 23:46:27 archie Exp $
|
||||
.\"
|
||||
.Dd September 15, 2015
|
||||
.Dd April 4, 2017
|
||||
.Dt NG_PPPOE 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
|
@ -104,12 +104,33 @@ the state machine as a client.
|
|||
It must be newly created and a service name can be given as an argument.
|
||||
It is legal to specify a zero-length service name, this is common
|
||||
on some DSL setups.
|
||||
It is possible to request a connection to a specific
|
||||
access concentrator by its name using the "AC-Name\\Service-Name" syntax.
|
||||
A session request packet will be broadcasted on the Ethernet.
|
||||
It is possible to request a connection to a specific access concentrator,
|
||||
and/or set a specific Host-Uniq tag, required by some Internet providers,
|
||||
using the
|
||||
.Qq Li [AC-Name\\][Host-Uniq|]Service-Name
|
||||
syntax.
|
||||
To set a binary Host-Uniq, it must be encoded as a hexadecimal lowercase
|
||||
string and prefixed with
|
||||
.Qq Li 0x ,
|
||||
for example
|
||||
.Qq Li 0x6d792d746167
|
||||
is equivalent to
|
||||
.Qq Li my-tag .
|
||||
A session request packet will be broadcast on the Ethernet.
|
||||
This command uses the
|
||||
.Dv ngpppoe_init_data
|
||||
structure shown below.
|
||||
For example, this init data argument can be used to
|
||||
connect to
|
||||
.Qq Li my-isp
|
||||
service with
|
||||
.Qq Li my-host
|
||||
uniq tag, accepting only
|
||||
.Qq Li remote-ac
|
||||
as access concentrator:
|
||||
.Bd -literal -offset indent
|
||||
"remote-ac\\my-host|my-isp"
|
||||
.Ed
|
||||
.It Dv NGM_PPPOE_LISTEN Pq Ic pppoe_listen
|
||||
Tell a nominated newly created hook that its session should enter
|
||||
the state machine as a server listener.
|
||||
|
|
@ -258,7 +279,41 @@ struct ngpppoe_maxp {
|
|||
uint16_t data;
|
||||
};
|
||||
.Ed
|
||||
.It Dv NGM_PPPOE_SEND_HURL Pq Ic send_hurl
|
||||
Tell a nominated hook with an active session to send a PADM message with
|
||||
a HURL tag.
|
||||
The argument is the URL to be delivered to the client:
|
||||
.Bd -literal -offset indent
|
||||
ngctl msg fxp0:orphans send_hurl '{ hook="myHook" data="http://example.net/cpe" }'
|
||||
.Ed
|
||||
.It Dv NGM_PPPOE_SEND_MOTM Pq Ic send_motm
|
||||
Tell a nominated hook with an active session to send a PADM message with
|
||||
a MOTM tag.
|
||||
The argument is the message to be delivered to the client:
|
||||
.Bd -literal -offset indent
|
||||
ngctl msg fxp0:orphans send_motm '{ hook="myHook" data="Welcome aboard" }'
|
||||
.Ed
|
||||
.El
|
||||
.Pp
|
||||
The two commands above use the same ngpppoe_init_data structure described
|
||||
above.
|
||||
.Bl -tag -width 3n
|
||||
.It Dv NGM_PPPOE_HURL
|
||||
This command is sent to the node that started this session when a PADM
|
||||
message with a HURL tag is received, and contains a URL that the host can
|
||||
pass to a web browser for presentation to the user.
|
||||
.It Dv NGM_PPPOE_MOTM
|
||||
This command is sent to the node that started this session when a PADM
|
||||
message with a MOTM tag is received, and contains a Message Of The
|
||||
Minute that the host can display to the user.
|
||||
.El
|
||||
.Pp
|
||||
The two commands above use a common data structure:
|
||||
.Bd -literal -offset 4n
|
||||
struct ngpppoe_padm {
|
||||
char msg[PPPOE_PADM_VALUE_SIZE];
|
||||
};
|
||||
.Ed
|
||||
.Sh SHUTDOWN
|
||||
This node shuts down upon receipt of a
|
||||
.Dv NGM_SHUTDOWN
|
||||
|
|
|
|||
|
|
@ -175,6 +175,20 @@ static const struct ng_cmdlist ng_pppoe_cmds[] = {
|
|||
&ng_parse_uint16_type,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
NGM_PPPOE_COOKIE,
|
||||
NGM_PPPOE_SEND_HURL,
|
||||
"send_hurl",
|
||||
&ngpppoe_init_data_state_type,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
NGM_PPPOE_COOKIE,
|
||||
NGM_PPPOE_SEND_MOTM,
|
||||
"send_motm",
|
||||
&ngpppoe_init_data_state_type,
|
||||
NULL
|
||||
},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
|
@ -226,9 +240,11 @@ struct sess_neg {
|
|||
const struct pppoe_tag *tags[NUMTAGS];
|
||||
u_int service_len;
|
||||
u_int ac_name_len;
|
||||
u_int host_uniq_len;
|
||||
|
||||
struct datatag service;
|
||||
struct datatag ac_name;
|
||||
struct datatag host_uniq;
|
||||
};
|
||||
typedef struct sess_neg *negp;
|
||||
|
||||
|
|
@ -589,18 +605,40 @@ static hook_p
|
|||
pppoe_finduniq(node_p node, const struct pppoe_tag *tag)
|
||||
{
|
||||
hook_p hook = NULL;
|
||||
union uniq uniq;
|
||||
sessp sp;
|
||||
|
||||
bcopy(tag + 1, uniq.bytes, sizeof(void *));
|
||||
/* Cycle through all known hooks. */
|
||||
LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
|
||||
/* Skip any nonsession hook. */
|
||||
if (NG_HOOK_PRIVATE(hook) == NULL)
|
||||
continue;
|
||||
if (uniq.pointer == NG_HOOK_PRIVATE(hook))
|
||||
sp = NG_HOOK_PRIVATE(hook);
|
||||
if (sp->neg->host_uniq_len == ntohs(tag->tag_len) &&
|
||||
bcmp(sp->neg->host_uniq.data, (const char *)(tag + 1),
|
||||
sp->neg->host_uniq_len) == 0)
|
||||
break;
|
||||
}
|
||||
CTR3(KTR_NET, "%20s: matched %p for %p", __func__, hook, uniq.pointer);
|
||||
CTR3(KTR_NET, "%20s: matched %p for %p", __func__, hook, sp);
|
||||
|
||||
return (hook);
|
||||
}
|
||||
|
||||
static hook_p
|
||||
pppoe_findcookie(node_p node, const struct pppoe_tag *tag)
|
||||
{
|
||||
hook_p hook = NULL;
|
||||
union uniq cookie;
|
||||
|
||||
bcopy(tag + 1, cookie.bytes, sizeof(void *));
|
||||
/* Cycle through all known hooks. */
|
||||
LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
|
||||
/* Skip any nonsession hook. */
|
||||
if (NG_HOOK_PRIVATE(hook) == NULL)
|
||||
continue;
|
||||
if (cookie.pointer == NG_HOOK_PRIVATE(hook))
|
||||
break;
|
||||
}
|
||||
CTR3(KTR_NET, "%20s: matched %p for %p", __func__, hook, cookie.pointer);
|
||||
|
||||
return (hook);
|
||||
}
|
||||
|
|
@ -744,17 +782,29 @@ ng_pppoe_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
|||
case NGM_PPPOE_LISTEN:
|
||||
case NGM_PPPOE_OFFER:
|
||||
case NGM_PPPOE_SERVICE:
|
||||
case NGM_PPPOE_SEND_HURL:
|
||||
case NGM_PPPOE_SEND_MOTM:
|
||||
ourmsg = (struct ngpppoe_init_data *)msg->data;
|
||||
if (msg->header.arglen < sizeof(*ourmsg)) {
|
||||
log(LOG_ERR, "ng_pppoe[%x]: init data too "
|
||||
"small\n", node->nd_ID);
|
||||
LEAVE(EMSGSIZE);
|
||||
}
|
||||
if (msg->header.arglen - sizeof(*ourmsg) >
|
||||
PPPOE_SERVICE_NAME_SIZE) {
|
||||
log(LOG_ERR, "ng_pppoe[%x]: service name "
|
||||
"too big\n", node->nd_ID);
|
||||
LEAVE(EMSGSIZE);
|
||||
if (msg->header.cmd == NGM_PPPOE_SEND_HURL ||
|
||||
msg->header.cmd == NGM_PPPOE_SEND_MOTM) {
|
||||
if (msg->header.arglen - sizeof(*ourmsg) >
|
||||
PPPOE_PADM_VALUE_SIZE) {
|
||||
log(LOG_ERR, "ng_pppoe[%x]: message "
|
||||
"too big\n", node->nd_ID);
|
||||
LEAVE(EMSGSIZE);
|
||||
}
|
||||
} else {
|
||||
if (msg->header.arglen - sizeof(*ourmsg) >
|
||||
PPPOE_SERVICE_NAME_SIZE) {
|
||||
log(LOG_ERR, "ng_pppoe[%x]: service name "
|
||||
"too big\n", node->nd_ID);
|
||||
LEAVE(EMSGSIZE);
|
||||
}
|
||||
}
|
||||
if (msg->header.arglen - sizeof(*ourmsg) <
|
||||
ourmsg->data_len) {
|
||||
|
|
@ -794,6 +844,20 @@ ng_pppoe_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
|||
if (msg->header.cmd == NGM_PPPOE_SERVICE)
|
||||
break;
|
||||
|
||||
/*
|
||||
* PADM messages are set up on active sessions.
|
||||
*/
|
||||
if (msg->header.cmd == NGM_PPPOE_SEND_HURL ||
|
||||
msg->header.cmd == NGM_PPPOE_SEND_MOTM) {
|
||||
if (sp->state != PPPOE_NEWCONNECTED &&
|
||||
sp->state != PPPOE_CONNECTED) {
|
||||
log(LOG_NOTICE, "ng_pppoe[%x]: session is not "
|
||||
"active\n", node->nd_ID);
|
||||
LEAVE(EISCONN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (sp->state != PPPOE_SNONE) {
|
||||
log(LOG_NOTICE, "ng_pppoe[%x]: Session already "
|
||||
"active\n", node->nd_ID);
|
||||
|
|
@ -848,12 +912,15 @@ ng_pppoe_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
|||
* Check the hook exists and is Uninitialised.
|
||||
* Send a PADI request, and start the timeout logic.
|
||||
* Store the originator of this message so we can send
|
||||
* a success of fail message to them later.
|
||||
* a success or fail message to them later.
|
||||
* Move the session to SINIT.
|
||||
* Set up the session to the correct state and
|
||||
* start it.
|
||||
*/
|
||||
int i, acnlen = 0, acnsep = 0, srvlen;
|
||||
int acnpos, acnlen = 0, acnsep = 0;
|
||||
int hupos, hulen = 0, husep = 0;
|
||||
int i, srvpos, srvlen;
|
||||
acnpos = 0;
|
||||
for (i = 0; i < ourmsg->data_len; i++) {
|
||||
if (ourmsg->data[i] == '\\') {
|
||||
acnlen = i;
|
||||
|
|
@ -861,15 +928,56 @@ ng_pppoe_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
|||
break;
|
||||
}
|
||||
}
|
||||
srvlen = ourmsg->data_len - acnlen - acnsep;
|
||||
hupos = acnlen + acnsep;
|
||||
for (i = hupos; i < ourmsg->data_len; i++) {
|
||||
if (ourmsg->data[i] == '|') {
|
||||
hulen = i - hupos;
|
||||
husep = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
srvpos = hupos + hulen + husep;
|
||||
srvlen = ourmsg->data_len - srvpos;
|
||||
|
||||
bcopy(ourmsg->data, neg->ac_name.data, acnlen);
|
||||
bcopy(ourmsg->data + acnpos, neg->ac_name.data, acnlen);
|
||||
neg->ac_name_len = acnlen;
|
||||
|
||||
neg->host_uniq.hdr.tag_type = PTT_HOST_UNIQ;
|
||||
if (hulen == 0) {
|
||||
/* Not provided, generate one */
|
||||
neg->host_uniq.hdr.tag_len = htons(sizeof(sp));
|
||||
bcopy(&sp, neg->host_uniq.data, sizeof(sp));
|
||||
neg->host_uniq_len = sizeof(sp);
|
||||
} else if (hulen > 2 && ourmsg->data[hupos] == '0' &&
|
||||
ourmsg->data[hupos + 1] == 'x' && hulen % 2 == 0) {
|
||||
/* Hex encoded */
|
||||
static const char hexdig[16] = "0123456789abcdef";
|
||||
int j;
|
||||
|
||||
neg->host_uniq.hdr.tag_len = htons((uint16_t)(hulen / 2 - 1));
|
||||
for (i = 0; i < hulen - 2; i++) {
|
||||
for (j = 0;
|
||||
j < 16 &&
|
||||
ourmsg->data[hupos + 2 + i] != hexdig[j];
|
||||
j++);
|
||||
if (j == 16)
|
||||
LEAVE(EINVAL);
|
||||
if (i % 2 == 0)
|
||||
neg->host_uniq.data[i / 2] = j << 4;
|
||||
else
|
||||
neg->host_uniq.data[i / 2] |= j;
|
||||
}
|
||||
neg->host_uniq_len = hulen / 2 - 1;
|
||||
} else {
|
||||
/* Plain string */
|
||||
neg->host_uniq.hdr.tag_len = htons((uint16_t)hulen);
|
||||
bcopy(ourmsg->data + hupos, neg->host_uniq.data, hulen);
|
||||
neg->host_uniq_len = hulen;
|
||||
}
|
||||
|
||||
neg->service.hdr.tag_type = PTT_SRV_NAME;
|
||||
neg->service.hdr.tag_len = htons((uint16_t)srvlen);
|
||||
bcopy(ourmsg->data + acnlen + acnsep,
|
||||
neg->service.data, srvlen);
|
||||
bcopy(ourmsg->data + srvpos, neg->service.data, srvlen);
|
||||
neg->service_len = srvlen;
|
||||
pppoe_start(sp);
|
||||
break;
|
||||
|
|
@ -879,7 +987,7 @@ ng_pppoe_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
|||
* Check the hook exists and is Uninitialised.
|
||||
* Install the service matching string.
|
||||
* Store the originator of this message so we can send
|
||||
* a success of fail message to them later.
|
||||
* a success or fail message to them later.
|
||||
* Move the hook to 'LISTENING'
|
||||
*/
|
||||
neg->service.hdr.tag_type = PTT_SRV_NAME;
|
||||
|
|
@ -1019,6 +1127,92 @@ ng_pppoe_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
|||
privp->max_payload.hdr.tag_len = htons(sizeof(uint16_t));
|
||||
privp->max_payload.data = htons(*((uint16_t *)msg->data));
|
||||
break;
|
||||
case NGM_PPPOE_SEND_HURL:
|
||||
{
|
||||
struct mbuf *m;
|
||||
|
||||
/* Generate a packet of that type. */
|
||||
m = m_gethdr(M_NOWAIT, MT_DATA);
|
||||
if (m == NULL)
|
||||
log(LOG_NOTICE, "ng_pppoe[%x]: session out of "
|
||||
"mbufs\n", node->nd_ID);
|
||||
else {
|
||||
struct pppoe_full_hdr *wh;
|
||||
struct pppoe_tag *tag;
|
||||
int error = 0;
|
||||
|
||||
wh = mtod(m, struct pppoe_full_hdr *);
|
||||
bcopy(&sp->pkt_hdr, wh, sizeof(*wh));
|
||||
|
||||
/* Revert the stored header to DISC/PADM mode. */
|
||||
wh->ph.code = PADM_CODE;
|
||||
/*
|
||||
* Configure ethertype depending on what
|
||||
* was used during sessions stage.
|
||||
*/
|
||||
if (wh->eh.ether_type ==
|
||||
ETHERTYPE_PPPOE_3COM_SESS)
|
||||
wh->eh.ether_type = ETHERTYPE_PPPOE_3COM_DISC;
|
||||
else
|
||||
wh->eh.ether_type = ETHERTYPE_PPPOE_DISC;
|
||||
/*
|
||||
* Add PADM message and adjust sizes.
|
||||
*/
|
||||
tag = (void *)(&wh->ph + 1);
|
||||
tag->tag_type = PTT_HURL;
|
||||
tag->tag_len = htons(ourmsg->data_len);
|
||||
strncpy((char *)(tag + 1), ourmsg->data, ourmsg->data_len);
|
||||
m->m_pkthdr.len = m->m_len = sizeof(*wh) + sizeof(*tag) +
|
||||
ourmsg->data_len;
|
||||
wh->ph.length = htons(sizeof(*tag) + ourmsg->data_len);
|
||||
NG_SEND_DATA_ONLY(error,
|
||||
privp->ethernet_hook, m);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NGM_PPPOE_SEND_MOTM:
|
||||
{
|
||||
struct mbuf *m;
|
||||
|
||||
/* Generate a packet of that type. */
|
||||
m = m_gethdr(M_NOWAIT, MT_DATA);
|
||||
if (m == NULL)
|
||||
log(LOG_NOTICE, "ng_pppoe[%x]: session out of "
|
||||
"mbufs\n", node->nd_ID);
|
||||
else {
|
||||
struct pppoe_full_hdr *wh;
|
||||
struct pppoe_tag *tag;
|
||||
int error = 0;
|
||||
|
||||
wh = mtod(m, struct pppoe_full_hdr *);
|
||||
bcopy(&sp->pkt_hdr, wh, sizeof(*wh));
|
||||
|
||||
/* Revert the stored header to DISC/PADM mode. */
|
||||
wh->ph.code = PADM_CODE;
|
||||
/*
|
||||
* Configure ethertype depending on what
|
||||
* was used during sessions stage.
|
||||
*/
|
||||
if (wh->eh.ether_type ==
|
||||
ETHERTYPE_PPPOE_3COM_SESS)
|
||||
wh->eh.ether_type = ETHERTYPE_PPPOE_3COM_DISC;
|
||||
else
|
||||
wh->eh.ether_type = ETHERTYPE_PPPOE_DISC;
|
||||
/*
|
||||
* Add PADM message and adjust sizes.
|
||||
*/
|
||||
tag = (void *)(&wh->ph + 1);
|
||||
tag->tag_type = PTT_MOTM;
|
||||
tag->tag_len = htons(ourmsg->data_len);
|
||||
strncpy((char *)(tag + 1), ourmsg->data, ourmsg->data_len);
|
||||
m->m_pkthdr.len = m->m_len = sizeof(*wh) + sizeof(*tag) +
|
||||
ourmsg->data_len;
|
||||
wh->ph.length = htons(sizeof(*tag) + ourmsg->data_len);
|
||||
NG_SEND_DATA_ONLY(error,
|
||||
privp->ethernet_hook, m);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LEAVE(EINVAL);
|
||||
}
|
||||
|
|
@ -1061,10 +1255,6 @@ pppoe_start(sessp sp)
|
|||
node_p node = NG_HOOK_NODE(hook);
|
||||
priv_p privp = NG_NODE_PRIVATE(node);
|
||||
negp neg = sp->neg;
|
||||
struct {
|
||||
struct pppoe_tag hdr;
|
||||
union uniq data;
|
||||
} __packed uniqtag;
|
||||
struct mbuf *m0;
|
||||
int error;
|
||||
|
||||
|
|
@ -1080,11 +1270,8 @@ pppoe_start(sessp sp)
|
|||
memcpy((void *)&neg->pkt->pkt_header.eh, &privp->eh,
|
||||
sizeof(struct ether_header));
|
||||
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));
|
||||
uniqtag.data.pointer = sp;
|
||||
init_tags(sp);
|
||||
insert_tag(sp, &uniqtag.hdr);
|
||||
insert_tag(sp, &neg->host_uniq.hdr);
|
||||
insert_tag(sp, &neg->service.hdr);
|
||||
if (privp->max_payload.data != 0)
|
||||
insert_tag(sp, &privp->max_payload.hdr);
|
||||
|
|
@ -1163,6 +1350,52 @@ send_maxp(sessp sp, const struct pppoe_tag *tag)
|
|||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
send_hurl(sessp sp, const struct pppoe_tag *tag)
|
||||
{
|
||||
int error, tlen;
|
||||
struct ng_mesg *msg;
|
||||
struct ngpppoe_padm *padm;
|
||||
|
||||
CTR2(KTR_NET, "%20s: called %d", __func__, sp->Session_ID);
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_PPPOE_COOKIE, NGM_PPPOE_HURL,
|
||||
sizeof(struct ngpppoe_padm), M_NOWAIT);
|
||||
if (msg == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
padm = (struct ngpppoe_padm *)msg->data;
|
||||
tlen = min(PPPOE_PADM_VALUE_SIZE - 1, ntohs(tag->tag_len));
|
||||
strncpy(padm->msg, (const char *)(tag + 1), tlen);
|
||||
padm->msg[tlen] = '\0';
|
||||
NG_SEND_MSG_ID(error, NG_HOOK_NODE(sp->hook), msg, sp->creator, 0);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
send_motm(sessp sp, const struct pppoe_tag *tag)
|
||||
{
|
||||
int error, tlen;
|
||||
struct ng_mesg *msg;
|
||||
struct ngpppoe_padm *padm;
|
||||
|
||||
CTR2(KTR_NET, "%20s: called %d", __func__, sp->Session_ID);
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_PPPOE_COOKIE, NGM_PPPOE_MOTM,
|
||||
sizeof(struct ngpppoe_padm), M_NOWAIT);
|
||||
if (msg == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
padm = (struct ngpppoe_padm *)msg->data;
|
||||
tlen = min(PPPOE_PADM_VALUE_SIZE - 1, ntohs(tag->tag_len));
|
||||
strncpy(padm->msg, (const char *)(tag + 1), tlen);
|
||||
padm->msg[tlen] = '\0';
|
||||
NG_SEND_MSG_ID(error, NG_HOOK_NODE(sp->hook), msg, sp->creator, 0);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive data from session hook and do something with it.
|
||||
*/
|
||||
|
|
@ -1320,6 +1553,7 @@ ng_pppoe_rcvdata_ether(hook_p hook, item_p item)
|
|||
const priv_p privp = NG_NODE_PRIVATE(node);
|
||||
sessp sp;
|
||||
const struct pppoe_tag *utag = NULL, *tag = NULL;
|
||||
const struct pppoe_tag sntag = { PTT_SRV_NAME, 0 };
|
||||
const struct pppoe_full_hdr *wh;
|
||||
const struct pppoe_hdr *ph;
|
||||
negp neg = NULL;
|
||||
|
|
@ -1409,11 +1643,8 @@ ng_pppoe_rcvdata_ether(hook_p hook, item_p item)
|
|||
* processing.
|
||||
*/
|
||||
tag = get_tag(ph, PTT_SRV_NAME);
|
||||
if (tag == NULL) {
|
||||
CTR1(KTR_NET, "%20s: PADI w/o Service-Name",
|
||||
__func__);
|
||||
LEAVE(ENETUNREACH);
|
||||
}
|
||||
if (tag == NULL)
|
||||
tag = &sntag;
|
||||
|
||||
/*
|
||||
* First, try to match Service-Name against our
|
||||
|
|
@ -1438,8 +1669,7 @@ ng_pppoe_rcvdata_ether(hook_p hook, item_p item)
|
|||
* For now simply accept the first we receive.
|
||||
*/
|
||||
utag = get_tag(ph, PTT_HOST_UNIQ);
|
||||
if ((utag == NULL) ||
|
||||
(ntohs(utag->tag_len) != sizeof(sp))) {
|
||||
if (utag == NULL) {
|
||||
log(LOG_NOTICE, "ng_pppoe[%x]: no host "
|
||||
"unique field\n", node->nd_ID);
|
||||
LEAVE(ENETUNREACH);
|
||||
|
|
@ -1529,7 +1759,7 @@ ng_pppoe_rcvdata_ether(hook_p hook, item_p item)
|
|||
LEAVE(ENETUNREACH);
|
||||
}
|
||||
|
||||
sendhook = pppoe_finduniq(node, utag);
|
||||
sendhook = pppoe_findcookie(node, utag);
|
||||
if (sendhook == NULL)
|
||||
LEAVE(ENETUNREACH);
|
||||
|
||||
|
|
@ -1605,8 +1835,7 @@ ng_pppoe_rcvdata_ether(hook_p hook, item_p item)
|
|||
* set us into Session mode.
|
||||
*/
|
||||
utag = get_tag(ph, PTT_HOST_UNIQ);
|
||||
if ((utag == NULL) ||
|
||||
(ntohs(utag->tag_len) != sizeof(sp))) {
|
||||
if (utag == NULL) {
|
||||
LEAVE (ENETUNREACH);
|
||||
}
|
||||
sendhook = pppoe_finduniq(node, utag);
|
||||
|
|
@ -1659,6 +1888,19 @@ ng_pppoe_rcvdata_ether(hook_p hook, item_p item)
|
|||
/* Disconnect that hook. */
|
||||
ng_rmhook_self(sp->hook);
|
||||
break;
|
||||
case PADM_CODE:
|
||||
/*
|
||||
* We are a client:
|
||||
* find matching peer/session combination.
|
||||
*/
|
||||
sp = pppoe_findsession(privp, wh);
|
||||
if (sp == NULL)
|
||||
LEAVE (ENETUNREACH);
|
||||
if ((tag = get_tag(ph, PTT_HURL)))
|
||||
send_hurl(sp, tag);
|
||||
if ((tag = get_tag(ph, PTT_MOTM)))
|
||||
send_motm(sp, tag);
|
||||
break;
|
||||
default:
|
||||
LEAVE(EPFNOSUPPORT);
|
||||
}
|
||||
|
|
@ -1781,7 +2023,7 @@ ng_pppoe_disconnect(hook_p hook)
|
|||
struct mbuf *m;
|
||||
|
||||
/* Generate a packet of that type. */
|
||||
MGETHDR(m, M_NOWAIT, MT_DATA);
|
||||
m = m_gethdr(M_NOWAIT, MT_DATA);
|
||||
if (m == NULL)
|
||||
log(LOG_NOTICE, "ng_pppoe[%x]: session out of "
|
||||
"mbufs\n", node->nd_ID);
|
||||
|
|
@ -1791,8 +2033,6 @@ ng_pppoe_disconnect(hook_p hook)
|
|||
int msglen = strlen(SIGNOFF);
|
||||
int error = 0;
|
||||
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
m->m_pkthdr.len = m->m_len = sizeof(*wh);
|
||||
wh = mtod(m, struct pppoe_full_hdr *);
|
||||
bcopy(&sp->pkt_hdr, wh, sizeof(*wh));
|
||||
|
||||
|
|
@ -1815,8 +2055,8 @@ ng_pppoe_disconnect(hook_p hook)
|
|||
tag->tag_type = PTT_GEN_ERR;
|
||||
tag->tag_len = htons((u_int16_t)msglen);
|
||||
strncpy((char *)(tag + 1), SIGNOFF, msglen);
|
||||
m->m_pkthdr.len = (m->m_len += sizeof(*tag) +
|
||||
msglen);
|
||||
m->m_pkthdr.len = m->m_len = sizeof(*wh) + sizeof(*tag) +
|
||||
msglen;
|
||||
wh->ph.length = htons(sizeof(*tag) + msglen);
|
||||
NG_SEND_DATA_ONLY(error,
|
||||
privp->ethernet_hook, m);
|
||||
|
|
@ -1933,6 +2173,8 @@ scan_tags(sessp sp, const struct pppoe_hdr* ph)
|
|||
case PTT_SYS_ERR:
|
||||
case PTT_GEN_ERR:
|
||||
case PTT_MAX_PAYL:
|
||||
case PTT_HURL:
|
||||
case PTT_MOTM:
|
||||
break;
|
||||
}
|
||||
pt = (const struct pppoe_tag*)ptn;
|
||||
|
|
|
|||
|
|
@ -52,8 +52,10 @@
|
|||
|
||||
#define NGM_PPPOE_COOKIE 1089893072
|
||||
#define NGM_PPPOE_SETMAXP_COOKIE 1441624322
|
||||
#define NGM_PPPOE_PADM_COOKIE 1488405822
|
||||
|
||||
#define PPPOE_SERVICE_NAME_SIZE 64 /* for now */
|
||||
#define PPPOE_PADM_VALUE_SIZE 128 /* for now */
|
||||
|
||||
/* Hook names */
|
||||
#define NG_PPPOE_HOOK_ETHERNET "ethernet"
|
||||
|
|
@ -84,7 +86,11 @@ enum cmd {
|
|||
NGM_PPPOE_SETMODE = 12, /* set to standard or compat modes */
|
||||
NGM_PPPOE_GETMODE = 13, /* see current mode */
|
||||
NGM_PPPOE_SETENADDR = 14, /* set Ethernet address */
|
||||
NGM_PPPOE_SETMAXP = 15 /* Set PPP-Max-Payload value */
|
||||
NGM_PPPOE_SETMAXP = 15, /* Set PPP-Max-Payload value */
|
||||
NGM_PPPOE_SEND_HURL = 16, /* Send PADM HURL message */
|
||||
NGM_PPPOE_HURL = 17, /* HURL for informational purposes */
|
||||
NGM_PPPOE_SEND_MOTM = 18, /* Send PADM MOTM message */
|
||||
NGM_PPPOE_MOTM = 19 /* MOTM for informational purposes */
|
||||
};
|
||||
|
||||
/***********************
|
||||
|
|
@ -157,6 +163,13 @@ struct ngpppoe_maxp {
|
|||
uint16_t data;
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure is used to send PADM messages from server to client.
|
||||
*/
|
||||
struct ngpppoe_padm {
|
||||
char msg[PPPOE_PADM_VALUE_SIZE];
|
||||
};
|
||||
|
||||
/********************************************************************
|
||||
* Constants and definitions specific to pppoe
|
||||
********************************************************************/
|
||||
|
|
@ -171,6 +184,7 @@ struct ngpppoe_maxp {
|
|||
#define PADR_CODE 0x19
|
||||
#define PADS_CODE 0x65
|
||||
#define PADT_CODE 0xa7
|
||||
#define PADM_CODE 0xd3
|
||||
|
||||
/* Tag identifiers */
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
|
|
@ -181,6 +195,8 @@ struct ngpppoe_maxp {
|
|||
#define PTT_AC_COOKIE (0x0104)
|
||||
#define PTT_VENDOR (0x0105)
|
||||
#define PTT_RELAY_SID (0x0110)
|
||||
#define PTT_HURL (0x0111) /* PPPoE Extensions (CARREL) */
|
||||
#define PTT_MOTM (0x0112) /* PPPoE Extensions (CARREL) */
|
||||
#define PTT_MAX_PAYL (0x0120) /* PPP-Max-Payload (RFC4638) */
|
||||
#define PTT_SRV_ERR (0x0201)
|
||||
#define PTT_SYS_ERR (0x0202)
|
||||
|
|
@ -198,6 +214,8 @@ struct ngpppoe_maxp {
|
|||
#define PTT_AC_COOKIE (0x0401)
|
||||
#define PTT_VENDOR (0x0501)
|
||||
#define PTT_RELAY_SID (0x1001)
|
||||
#define PTT_HURL (0x1101) /* PPPoE Extensions (CARREL) */
|
||||
#define PTT_MOTM (0x1201) /* PPPoE Extensions (CARREL) */
|
||||
#define PTT_MAX_PAYL (0x2001) /* PPP-Max-Payload (RFC4638) */
|
||||
#define PTT_SRV_ERR (0x0102)
|
||||
#define PTT_SYS_ERR (0x0202)
|
||||
|
|
|
|||
Loading…
Reference in a new issue