version 1.1.1.4, 2019/10/22 13:49:55
|
version 1.1.1.5.2.1, 2023/09/27 11:08:01
|
Line 15
|
Line 15
|
|
|
#include <paths.h> |
#include <paths.h> |
#include <net/ethernet.h> |
#include <net/ethernet.h> |
|
#include <net/if.h> |
#include <netgraph/ng_message.h> |
#include <netgraph/ng_message.h> |
#include <netgraph/ng_pppoe.h> |
#include <netgraph/ng_pppoe.h> |
#include <netgraph/ng_ether.h> |
#include <netgraph/ng_ether.h> |
Line 28
|
Line 29
|
* DEFINITIONS |
* DEFINITIONS |
*/ |
*/ |
|
|
|
#define PPPOE_MTU_MAX (ETHER_MAX_LEN_JUMBO - 8) |
#define PPPOE_MTU 1492 /* allow room for PPPoE overhead */ |
#define PPPOE_MTU 1492 /* allow room for PPPoE overhead */ |
#define PPPOE_MRU 1492 |
#define PPPOE_MRU 1492 |
|
|
Line 157 static u_short PppoeGetMru(Link l, int conf);
|
Line 159 static u_short PppoeGetMru(Link l, int conf);
|
static void PppoeCtrlReadEvent(int type, void *arg); |
static void PppoeCtrlReadEvent(int type, void *arg); |
static void PppoeConnectTimeout(void *arg); |
static void PppoeConnectTimeout(void *arg); |
static void PppoeStat(Context ctx); |
static void PppoeStat(Context ctx); |
static int PppoeSetCommand(Context ctx, int ac, char *av[], void *arg); | static int PppoeSetCommand(Context ctx, int ac, const char *const av[], const void *arg); |
static int PppoeOriginated(Link l); |
static int PppoeOriginated(Link l); |
static int PppoeIsSync(Link l); |
static int PppoeIsSync(Link l); |
static void PppoeGetNode(Link l); |
static void PppoeGetNode(Link l); |
Line 177 static void PppoeDoClose(Link l);
|
Line 179 static void PppoeDoClose(Link l);
|
const struct phystype gPppoePhysType = { |
const struct phystype gPppoePhysType = { |
.name = "pppoe", |
.name = "pppoe", |
.descr = "PPP over Ethernet", |
.descr = "PPP over Ethernet", |
.mtu = PPPOE_MTU, | .mtu = PPPOE_MTU_MAX, |
.mru = PPPOE_MRU, |
.mru = PPPOE_MRU, |
.tmpl = 1, |
.tmpl = 1, |
.init = PppoeInit, |
.init = PppoeInit, |
Line 213 const struct cmdtab PppoeSetCmds[] = {
|
Line 215 const struct cmdtab PppoeSetCmds[] = {
|
#endif |
#endif |
{ "mac-format {format}", "Set RADIUS attribute 31 MAC format", |
{ "mac-format {format}", "Set RADIUS attribute 31 MAC format", |
PppoeSetCommand, NULL, 2, (void *)SET_MAC_FORMAT }, |
PppoeSetCommand, NULL, 2, (void *)SET_MAC_FORMAT }, |
{ NULL } | { NULL, NULL, NULL, NULL, 0, NULL } |
}; |
}; |
|
|
/* |
/* |
Line 237 struct PppoeIf {
|
Line 239 struct PppoeIf {
|
SLIST_HEAD(, PppoeList) list; |
SLIST_HEAD(, PppoeList) list; |
}; |
}; |
|
|
int PppoeIfCount=0; | static struct PppoeIf PppoeIfs[PPPOE_MAXPARENTIFS]; |
struct PppoeIf PppoeIfs[PPPOE_MAXPARENTIFS]; | |
|
|
struct tagname { |
struct tagname { |
int tag; |
int tag; |
Line 407 PppoeOpen(Link l)
|
Line 408 PppoeOpen(Link l)
|
&cn, sizeof(cn)) < 0) { |
&cn, sizeof(cn)) < 0) { |
Perror("[%s] PPPoE: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"", |
Perror("[%s] PPPoE: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"", |
l->name, path, cn.ourhook, cn.path, cn.peerhook); |
l->name, path, cn.ourhook, cn.path, cn.peerhook); |
|
if (errno == ENOENT) { |
|
PppoeReleaseNode(l); |
|
goto fail; |
|
} |
goto fail2; |
goto fail2; |
} |
} |
|
|
Line 552 PppoeCtrlReadEvent(int type, void *arg)
|
Line 557 PppoeCtrlReadEvent(int type, void *arg)
|
PppoeInfo pi = NULL; |
PppoeInfo pi = NULL; |
|
|
struct PppoeIf *PIf = (struct PppoeIf*)arg; |
struct PppoeIf *PIf = (struct PppoeIf*)arg; |
| |
| (void)type; |
/* Read control message. */ |
/* Read control message. */ |
if (NgRecvMsg(PIf->csock, &u.resp, sizeof(u), path) < 0) { |
if (NgRecvMsg(PIf->csock, &u.resp, sizeof(u), path) < 0) { |
Perror("PPPoE: error reading message from \"%s\"", path); |
Perror("PPPoE: error reading message from \"%s\"", path); |
Line 614 PppoeCtrlReadEvent(int type, void *arg)
|
Line 620 PppoeCtrlReadEvent(int type, void *arg)
|
switch (u.resp.header.cmd) { |
switch (u.resp.header.cmd) { |
case NGM_PPPOE_SESSIONID: /* XXX: I do not know what to do with this? */ |
case NGM_PPPOE_SESSIONID: /* XXX: I do not know what to do with this? */ |
Log(LG_PHYS3, ("PPPoE: rec'd SESSIONID %u from \"%s\"", |
Log(LG_PHYS3, ("PPPoE: rec'd SESSIONID %u from \"%s\"", |
ntohs((uint16_t)u.resp.data), path)); | ntohs(*(uint16_t*)u.resp.data), path)); |
break; |
break; |
case NGM_PPPOE_SUCCESS: |
case NGM_PPPOE_SUCCESS: |
Log(LG_PHYS, ("[%s] PPPoE: connection successful", l->name)); |
Log(LG_PHYS, ("[%s] PPPoE: connection successful", l->name)); |
Line 645 PppoeCtrlReadEvent(int type, void *arg)
|
Line 651 PppoeCtrlReadEvent(int type, void *arg)
|
{ |
{ |
struct ngpppoe_maxp *maxp; |
struct ngpppoe_maxp *maxp; |
|
|
maxp = ((struct ngpppoe_maxp *)u.resp.data); | maxp = ((struct ngpppoe_maxp *)(void *)u.resp.data); |
Log(LG_PHYS, ("[%s] PPPoE: rec'd PPP-Max-Payload '%u'", |
Log(LG_PHYS, ("[%s] PPPoE: rec'd PPP-Max-Payload '%u'", |
l->name, maxp->data)); |
l->name, maxp->data)); |
if (pi->max_payload > 0) { |
if (pi->max_payload > 0) { |
Line 745 PppoeOriginated(Link l)
|
Line 751 PppoeOriginated(Link l)
|
static int |
static int |
PppoeIsSync(Link l) |
PppoeIsSync(Link l) |
{ |
{ |
|
(void)l; |
return (1); |
return (1); |
} |
} |
|
|
Line 753 PppoePeerMacAddr(Link l, void *buf, size_t buf_len)
|
Line 760 PppoePeerMacAddr(Link l, void *buf, size_t buf_len)
|
{ |
{ |
PppoeInfo const pppoe = (PppoeInfo)l->info; |
PppoeInfo const pppoe = (PppoeInfo)l->info; |
|
|
|
if (buf_len < 18) |
|
return (1); |
ether_ntoa_r((struct ether_addr *)pppoe->peeraddr, buf); |
ether_ntoa_r((struct ether_addr *)pppoe->peeraddr, buf); |
return (0); |
return (0); |
} |
} |
Line 871 PppoeGetMtu(Link l, int conf)
|
Line 880 PppoeGetMtu(Link l, int conf)
|
if (conf == 0) |
if (conf == 0) |
return (l->type->mtu); |
return (l->type->mtu); |
else |
else |
return (l->conf.mtu); | return (l->conf.mtu ? l->conf.mtu : PPPOE_MTU); |
} |
} |
|
|
static u_short |
static u_short |
Line 901 CreatePppoeNode(struct PppoeIf *PIf, const char *iface
|
Line 910 CreatePppoeNode(struct PppoeIf *PIf, const char *iface
|
uint32_t f; |
uint32_t f; |
|
|
/* Make sure interface is up. */ |
/* Make sure interface is up. */ |
if (ExecCmdNosh(LG_PHYS2, iface, "%s %s up", _PATH_IFCONFIG, iface) != 0) { | if (IfaceSetFlag(iface, IFF_UP) != 0) { |
Log(LG_ERR, ("PPPoE: can't bring up interface %s", | Perror("[%s] PPPoE: can't bring up interface", iface); |
iface)); | |
return (0); |
return (0); |
} |
} |
|
|
/* Create a new netgraph node */ |
/* Create a new netgraph node */ |
if (NgMkSockNode(NULL, &PIf->csock, &PIf->dsock) < 0) { |
if (NgMkSockNode(NULL, &PIf->csock, &PIf->dsock) < 0) { |
Perror("[%s] PPPoE: can't create ctrl socket", iface); |
Perror("[%s] PPPoE: can't create ctrl socket", iface); |
return(0); | return (0); |
} |
} |
(void)fcntl(PIf->csock, F_SETFD, 1); |
(void)fcntl(PIf->csock, F_SETFD, 1); |
(void)fcntl(PIf->dsock, F_SETFD, 1); |
(void)fcntl(PIf->dsock, F_SETFD, 1); |
Line 940 CreatePppoeNode(struct PppoeIf *PIf, const char *iface
|
Line 947 CreatePppoeNode(struct PppoeIf *PIf, const char *iface
|
} |
} |
|
|
/* Look for NG_ETHER_NODE_TYPE. */ |
/* Look for NG_ETHER_NODE_TYPE. */ |
tlist = (const struct typelist*) resp->data; | tlist = (const struct typelist*)(void *)resp->data; |
for (f = 0; f < tlist->numtypes; f++) |
for (f = 0; f < tlist->numtypes; f++) |
if (strncmp(tlist->typeinfo[f].type_name, |
if (strncmp(tlist->typeinfo[f].type_name, |
NG_ETHER_NODE_TYPE, |
NG_ETHER_NODE_TYPE, |
Line 979 CreatePppoeNode(struct PppoeIf *PIf, const char *iface
|
Line 986 CreatePppoeNode(struct PppoeIf *PIf, const char *iface
|
return (0); |
return (0); |
} |
} |
|
|
hlist = (const struct hooklist *)resp->data; | hlist = (const struct hooklist *)(void *)resp->data; |
ninfo = &hlist->nodeinfo; |
ninfo = &hlist->nodeinfo; |
|
|
/* Make sure we've got the right type of node. */ |
/* Make sure we've got the right type of node. */ |
Line 1040 CreatePppoeNode(struct PppoeIf *PIf, const char *iface
|
Line 1047 CreatePppoeNode(struct PppoeIf *PIf, const char *iface
|
snprintf(path2, sizeof(path2), "%s%s", path, hook); |
snprintf(path2, sizeof(path2), "%s%s", path, hook); |
/* Get pppoe node ID */ |
/* Get pppoe node ID */ |
if ((PIf->node_id = NgGetNodeID(PIf->csock, path2)) == 0) { |
if ((PIf->node_id = NgGetNodeID(PIf->csock, path2)) == 0) { |
Perror("[%s] Cannot get pppoe node id", iface); | Perror("[%s] Cannot get %s node id", iface, |
| NG_PPPOE_NODE_TYPE); |
close(PIf->csock); |
close(PIf->csock); |
close(PIf->dsock); |
close(PIf->dsock); |
return (0); |
return (0); |
Line 1108 get_vs_tag(const struct pppoe_hdr* ph, uint32_t idx)
|
Line 1116 get_vs_tag(const struct pppoe_hdr* ph, uint32_t idx)
|
return (NULL); |
return (NULL); |
if (pt->tag_type == PTT_VENDOR && |
if (pt->tag_type == PTT_VENDOR && |
ntohs(pt->tag_len) >= 4 && |
ntohs(pt->tag_len) >= 4 && |
*(const uint32_t*)(pt + 1) == idx) | *(const uint32_t*)(const void *)(pt + 1) == idx) |
return (pt); |
return (pt); |
|
|
pt = (const struct pppoe_tag*)ptn; |
pt = (const struct pppoe_tag*)ptn; |
Line 1167 print_tags(const struct pppoe_hdr* ph)
|
Line 1175 print_tags(const struct pppoe_hdr* ph)
|
break; |
break; |
case PTT_VENDOR: |
case PTT_VENDOR: |
if (len >= 4) { |
if (len >= 4) { |
if ((uint8_t)*(uint8_t*)v != 0) { | if ((const uint8_t)*(const uint8_t*)v != 0) { |
snprintf(buf, sizeof(buf), |
snprintf(buf, sizeof(buf), |
"First byte of VENDOR is not zero! 0x%s", |
"First byte of VENDOR is not zero! 0x%s", |
Bin2Hex(v, len)); |
Bin2Hex(v, len)); |
Line 1184 print_tags(const struct pppoe_hdr* ph)
|
Line 1192 print_tags(const struct pppoe_hdr* ph)
|
if (len != 2) { |
if (len != 2) { |
sprintf(buf, "TAG_LENGTH is not 2!"); |
sprintf(buf, "TAG_LENGTH is not 2!"); |
} else { |
} else { |
sprintf(buf, "%u", *(uint16_t*)(pt + 1)); | sprintf(buf, "%u", *(const uint16_t*)(const void *)(pt + 1)); |
} |
} |
break; |
break; |
case PTT_SRV_ERR: |
case PTT_SRV_ERR: |
Line 1249 PppoeListenEvent(int type, void *arg)
|
Line 1257 PppoeListenEvent(int type, void *arg)
|
const struct pppoe_hdr *ph; |
const struct pppoe_hdr *ph; |
const struct pppoe_tag *tag; |
const struct pppoe_tag *tag; |
|
|
|
u_int16_t length; |
|
|
union { |
union { |
u_char buf[sizeof(struct ngpppoe_init_data) + MAX_SESSION]; |
u_char buf[sizeof(struct ngpppoe_init_data) + MAX_SESSION]; |
struct ngpppoe_init_data poeid; |
struct ngpppoe_init_data poeid; |
} u; |
} u; |
struct ngpppoe_init_data *const idata = &u.poeid; |
struct ngpppoe_init_data *const idata = &u.poeid; |
|
|
|
(void)type; |
switch (sz = NgRecvData(PIf->dsock, response, sizeof(response), rhook)) { |
switch (sz = NgRecvData(PIf->dsock, response, sizeof(response), rhook)) { |
case -1: |
case -1: |
Log(LG_ERR, ("NgRecvData: %d", sz)); |
Log(LG_ERR, ("NgRecvData: %d", sz)); |
Line 1271 PppoeListenEvent(int type, void *arg)
|
Line 1282 PppoeListenEvent(int type, void *arg)
|
|
|
session = rhook + 7; |
session = rhook + 7; |
|
|
if (sz < sizeof(struct pppoe_full_hdr)) { | if ((size_t)sz < sizeof(struct pppoe_full_hdr)) { |
Log(LG_PHYS, ("Incoming truncated PPPoE connection request via %s for " |
Log(LG_PHYS, ("Incoming truncated PPPoE connection request via %s for " |
"service \"%s\"", PIf->ifnodepath, session)); |
"service \"%s\"", PIf->ifnodepath, session)); |
return; |
return; |
Line 1279 PppoeListenEvent(int type, void *arg)
|
Line 1290 PppoeListenEvent(int type, void *arg)
|
|
|
wh = (struct pppoe_full_hdr *)response; |
wh = (struct pppoe_full_hdr *)response; |
ph = &wh->ph; |
ph = &wh->ph; |
|
|
|
/* Sanity check */ |
|
length = ntohs(ph->length); |
|
if (length > (size_t)sz - sizeof(struct pppoe_full_hdr)) { |
|
Log(LG_PHYS, ("Ignored incoming PPPoE connection request " |
|
"via %s for service \"%s\" from %s " |
|
"due to bad length %hu > %u", |
|
PIf->ifnodepath, session, |
|
ether_ntoa((const struct ether_addr *)&wh->eh.ether_shost), |
|
length, |
|
(unsigned)((size_t)sz - sizeof(struct pppoe_full_hdr)))); |
|
return; |
|
} |
|
|
if ((tag = get_tag(ph, PTT_SRV_NAME))) { |
if ((tag = get_tag(ph, PTT_SRV_NAME))) { |
int len = ntohs(tag->tag_len); | size_t len = ntohs(tag->tag_len); |
if (len >= sizeof(real_session)) |
if (len >= sizeof(real_session)) |
len = sizeof(real_session)-1; |
len = sizeof(real_session)-1; |
memcpy(real_session, tag + 1, len); |
memcpy(real_session, tag + 1, len); |
Line 1291 PppoeListenEvent(int type, void *arg)
|
Line 1316 PppoeListenEvent(int type, void *arg)
|
bzero(agent_cid, sizeof(agent_cid)); |
bzero(agent_cid, sizeof(agent_cid)); |
bzero(agent_rid, sizeof(agent_rid)); |
bzero(agent_rid, sizeof(agent_rid)); |
if ((tag = get_vs_tag(ph, htonl(0x00000DE9)))) { |
if ((tag = get_vs_tag(ph, htonl(0x00000DE9)))) { |
int len = ntohs(tag->tag_len) - 4, pos = 0; | size_t len = ntohs(tag->tag_len) - 4, pos = 0; |
const char *b = (const char *)(tag + 1) + 4; |
const char *b = (const char *)(tag + 1) + 4; |
while (pos + 1 <= len) { |
while (pos + 1 <= len) { |
int len1 = b[pos + 1]; | size_t len1 = b[pos + 1]; |
if (len1 > len - pos - 2) |
if (len1 > len - pos - 2) |
break; |
break; |
if (len1 >= sizeof(agent_rid)) |
if (len1 >= sizeof(agent_rid)) |
Line 1313 PppoeListenEvent(int type, void *arg)
|
Line 1338 PppoeListenEvent(int type, void *arg)
|
|
|
Log(LG_PHYS, ("Incoming PPPoE connection request via %s for " |
Log(LG_PHYS, ("Incoming PPPoE connection request via %s for " |
"service \"%s\" from %s", PIf->ifnodepath, real_session, |
"service \"%s\" from %s", PIf->ifnodepath, real_session, |
ether_ntoa((struct ether_addr *)&wh->eh.ether_shost))); | ether_ntoa((const struct ether_addr *)&wh->eh.ether_shost))); |
|
|
if (gLogOptions & LG_PHYS3) |
if (gLogOptions & LG_PHYS3) |
print_tags(ph); |
print_tags(ph); |
Line 1673 PppoeNodeUpdate(Link l)
|
Line 1698 PppoeNodeUpdate(Link l)
|
*/ |
*/ |
|
|
static int |
static int |
PppoeSetCommand(Context ctx, int ac, char *av[], void *arg) | PppoeSetCommand(Context ctx, int ac, const char *const av[], const void *arg) |
{ |
{ |
const PppoeInfo pi = (PppoeInfo) ctx->lnk->info; |
const PppoeInfo pi = (PppoeInfo) ctx->lnk->info; |
const char *hookname = ETHER_DEFAULT_HOOK; |
const char *hookname = ETHER_DEFAULT_HOOK; |
int i; |
int i; |
#ifdef NGM_PPPOE_SETMAXP_COOKIE |
#ifdef NGM_PPPOE_SETMAXP_COOKIE |
int ap; |
int ap; |
|
uint16_t mtu; |
#endif |
#endif |
switch ((intptr_t)arg) { |
switch ((intptr_t)arg) { |
case SET_IFACE: |
case SET_IFACE: |
Line 1700 PppoeSetCommand(Context ctx, int ac, char *av[], void
|
Line 1726 PppoeSetCommand(Context ctx, int ac, char *av[], void
|
} |
} |
} |
} |
strlcpy(pi->hook, hookname, sizeof(pi->hook)); |
strlcpy(pi->hook, hookname, sizeof(pi->hook)); |
|
|
|
#ifdef NGM_PPPOE_SETMAXP_COOKIE |
|
if (pi->max_payload > 0) { |
|
mtu = GetSystemIfaceMTU(pi->iface); |
|
if (mtu == 0) |
|
mtu = ETHER_MAX_LEN; |
|
if (pi->max_payload > mtu - 8) { |
|
pi->max_payload = mtu - 8; |
|
Perror("[%s] PPPoE: PPP-Max-Payload" |
|
" value reduced to %hu", |
|
pi->iface, pi->max_payload); |
|
} |
|
} |
|
#endif |
break; |
break; |
default: |
default: |
return(-1); |
return(-1); |
Line 1730 PppoeSetCommand(Context ctx, int ac, char *av[], void
|
Line 1770 PppoeSetCommand(Context ctx, int ac, char *av[], void
|
if (ac != 1) |
if (ac != 1) |
return(-1); |
return(-1); |
ap = atoi(av[0]); |
ap = atoi(av[0]); |
if (ap < PPPOE_MRU || ap > ETHER_MAX_LEN - 8) | if (pi->iface[0] == '\0') { |
Error("PPP-Max-Payload value \"%s\"", av[0]); | if (ap < PPPOE_MRU) /* postpone check for MTU */ |
| Error("PPP-Max-Payload value \"%s\" less than %d", |
| av[0], PPPOE_MRU); |
| } else { |
| mtu = GetSystemIfaceMTU(pi->iface); |
| if (mtu == 0) |
| mtu = ETHER_MAX_LEN; |
| if (ap < PPPOE_MRU || ap > mtu - 8) |
| Error("PPP-Max-Payload value \"%s\" not in a range of %d..%hu", |
| av[0], PPPOE_MRU, mtu); |
| } |
pi->max_payload = ap; |
pi->max_payload = ap; |
break; |
break; |
#endif |
#endif |