summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man4/ng_pppoe.463
-rw-r--r--sys/netgraph/ng_pppoe.c323
-rw-r--r--sys/netgraph/ng_pppoe.h20
3 files changed, 362 insertions, 44 deletions
diff --git a/share/man/man4/ng_pppoe.4 b/share/man/man4/ng_pppoe.4
index 2b367b8..7b0aee7 100644
--- a/share/man/man4/ng_pppoe.4
+++ b/share/man/man4/ng_pppoe.4
@@ -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 February 14, 2018
.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
diff --git a/sys/netgraph/ng_pppoe.c b/sys/netgraph/ng_pppoe.c
index 9a23b1b..b152082 100644
--- a/sys/netgraph/ng_pppoe.c
+++ b/sys/netgraph/ng_pppoe.c
@@ -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,43 @@ 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);
+ /* Skip already connected sessions. */
+ if (sp->neg == NULL)
+ continue;
+ 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 +785,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 +847,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 +915,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 +931,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 +990,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 +1130,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 +1258,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 +1273,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 +1353,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 +1556,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 +1646,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 +1672,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 +1762,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 +1838,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 +1891,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 +2026,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 +2036,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 +2058,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 +2176,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;
diff --git a/sys/netgraph/ng_pppoe.h b/sys/netgraph/ng_pppoe.h
index 3b74f07..43ac36f 100644
--- a/sys/netgraph/ng_pppoe.h
+++ b/sys/netgraph/ng_pppoe.h
@@ -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)
OpenPOWER on IntegriCloud