ale created this revision.
ale added reviewers: network, julian.
ale added subscribers: freebsd-net-list, mandree.
ale set the repository for this revision to rS FreeBSD src repository.
Herald added a subscriber: imp.
Herald added a reviewer: manpages.
REVISION SUMMARY
Add support for user-supplied Host-Uniq tag in Netgraph PPPoE.
A few ISP filter PADI requests based on such tag, to force the use of their
own routers.
The custom Host-Uniq tag is passed in the NGM_PPPOE_CONNECT control message,
so it can be used with FreeBSD ppp(8) without any other change.
TEST PLAN
I've tested the three possible Host-Uniq tags (auto-generated as before, long
plain string and long binary string) with my own ISP connection.
REPOSITORY
rS FreeBSD src repository
REVISION DETAIL
https://reviews.freebsd.org/D9270
AFFECTED FILES
share/man/man4/ng_pppoe.4
sys/netgraph/ng_pppoe.c
EMAIL PREFERENCES
https://reviews.freebsd.org/settings/panel/emailpreferences/
To: ale, #network, #manpages, julian
Cc: mandree, imp, freebsd-net-list
diff --git a/sys/netgraph/ng_pppoe.c b/sys/netgraph/ng_pppoe.c
--- a/sys/netgraph/ng_pppoe.c
+++ b/sys/netgraph/ng_pppoe.c
@@ -226,9 +226,11 @@
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 +591,20 @@
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);
}
@@ -853,23 +857,67 @@
* 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;
acnsep = 1;
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;
@@ -1061,10 +1109,6 @@
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 +1124,8 @@
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, &uniq