|
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 |