Index: mpd/src/lcp.c =================================================================== --- mpd/src/lcp.c (revision 1.88) +++ mpd/src/lcp.c (revision 1.89) @@ -226,9 +226,9 @@ /* Initialize normal LCP stuff */ lcp->peer_mru = l->conf.mtu; - lcp->want_mru = l->conf.mru; - if (l->type && (lcp->want_mru > l->type->mru)) - lcp->want_mru = l->type->mru; + lcp->want_mru = PhysGetMru(l, 1); + if (l->type && (lcp->want_mru > PhysGetMru(l, 0))) + lcp->want_mru = PhysGetMru(l, 0); lcp->peer_accmap = 0xffffffff; lcp->want_accmap = l->conf.accmap; lcp->peer_acfcomp = FALSE; Index: mpd/src/phys.c =================================================================== --- mpd/src/phys.c (revision 1.78) +++ mpd/src/phys.c (revision 1.79) @@ -465,6 +465,29 @@ } /* + * PhysGetMru() + */ + +u_short +PhysGetMru(Link l, int conf) +{ + PhysType const pt = l->type; + + if (pt) { + if (pt->getmru) + return ((*pt->getmru)(l, conf)); + if (conf == 0) { + if (pt->mru) + return (pt->mru); + else + return (0); + } else + return (l->conf.mru); + } else + return (0); +} + +/* * PhysIsBusy() * * This returns 1 if link is busy Index: mpd/src/phys.h =================================================================== --- mpd/src/phys.h (revision 1.41) +++ mpd/src/phys.h (revision 1.42) @@ -63,6 +63,7 @@ /* returns the calling number (IP, MAC, whatever) */ int (*callednum)(Link l, void *buf, size_t buf_len); /* returns the called number (IP, MAC, whatever) */ + u_short (*getmru)(Link l, int conf); /* returns actual MRU */ }; typedef struct phystype *PhysType; @@ -98,6 +99,7 @@ extern int PhysGetPeerIface(Link l, char *buf, size_t buf_len); extern int PhysGetCallingNum(Link l, char *buf, size_t buf_len); extern int PhysGetCalledNum(Link l, char *buf, size_t buf_len); + extern u_short PhysGetMru(Link l, int conf); extern int PhysIsBusy(Link l); extern int PhysInit(Link l); Index: mpd/src/pppoe.c =================================================================== --- mpd/src/pppoe.c (revision 1.139) +++ mpd/src/pppoe.c (revision 1.140) @@ -26,7 +26,6 @@ /* * DEFINITIONS */ - #define PPPOE_MTU 1492 /* allow room for PPPoE overhead */ #define PPPOE_MRU 1492 @@ -74,6 +73,7 @@ char hook[NG_HOOKSIZ]; /* hook on that node */ char session[MAX_SESSION]; /* session name */ char acname[PPPOE_SERVICE_NAME_SIZE]; /* AC name */ + uint16_t max_payload; /* PPP-Max-Payload (RFC4638) */ int mac_format; /* MAC address format */ u_char peeraddr[6]; /* Peer MAC address */ char real_session[MAX_SESSION]; /* real session name */ @@ -81,6 +81,7 @@ char agent_rid[64]; /* Agent Remote ID */ u_char incoming; /* incoming vs. outgoing */ u_char opened; /* PPPoE opened by phys */ + u_char mp_reply; /* PPP-Max-Payload reply from server */ struct optinfo options; struct PppoeIf *PIf; /* pointer on parent ng_pppoe info */ struct PppoeList *list; @@ -95,6 +96,7 @@ SET_IFACE, SET_SESSION, SET_ACNAME, + SET_MAX_PAYLOAD, SET_MAC_FORMAT }; @@ -147,6 +149,7 @@ static int PppoeCalledNum(Link l, void *buf, size_t buf_len); static int PppoeSelfName(Link l, void *buf, size_t buf_len); static int PppoePeerName(Link l, void *buf, size_t buf_len); +static u_short PppoeGetMru(Link l, int conf); static void PppoeCtrlReadEvent(int type, void *arg); static void PppoeConnectTimeout(void *arg); static void PppoeStat(Context ctx); @@ -189,6 +192,7 @@ .callednum = PppoeCalledNum, .selfname = PppoeSelfName, .peername = PppoePeerName, + .getmru = PppoeGetMru }; const struct cmdtab PppoeSetCmds[] = { @@ -198,7 +202,11 @@ PppoeSetCommand, NULL, 2, (void *)SET_SESSION }, { "acname {name}", "Set PPPoE access concentrator name", PppoeSetCommand, NULL, 2, (void *)SET_ACNAME }, - { "mac-format {format}", "set radius attribute 31 mac format", +#ifdef NGM_PPPOE_SETMAXP_COOKIE + { "max-payload {size}", "Set PPP-Max-Payload tag", + PppoeSetCommand, NULL, 2, (void *)SET_MAX_PAYLOAD }, +#endif + { "mac-format {format}", "Set RADIUS attribute 31 MAC format", PppoeSetCommand, NULL, 2, (void *)SET_MAC_FORMAT }, { NULL } }; @@ -239,12 +247,12 @@ { PTT_HOST_UNIQ, "Host-Uniq" }, { PTT_AC_COOKIE, "AC-Cookie" }, { PTT_VENDOR, "Vendor-Specific" }, - { PTT_RELAY_SID, "Relay-Session-ID" }, + { PTT_RELAY_SID, "Relay-Session-Id" }, { PTT_MAX_PAYL, "PPP-Max-Payload" }, { PTT_SRV_ERR, "Service-Name-Error" }, { PTT_SYS_ERR, "AC-System-Error" }, { PTT_GEN_ERR, "Generic-Error" }, - /* http://tools.ietf.org/html/draft-arberg-pppoe-iana-00 */ + /* RFC 4937 */ { MPD_PTT_CREDITS, "Credits" }, { MPD_PTT_METRICS, "Metrics" }, { MPD_PTT_SEQ_NUMBER, "Sequence Number" }, @@ -278,7 +286,9 @@ pe->agent_cid[0] = 0; pe->agent_rid[0] = 0; pe->PIf = NULL; + pe->max_payload = 0; pe->mac_format = MAC_UNFORMATTED; + pe->mp_reply = 0; /* Done */ return(0); @@ -393,7 +403,21 @@ l->name, path, cn.ourhook, cn.path, cn.peerhook); goto fail2; } - + +#ifdef NGM_PPPOE_SETMAXP_COOKIE + if (pe->max_payload > 0) { + const uint16_t max_payload = pe->max_payload; + Log(LG_PHYS, ("[%s] PPPoE: Set PPP-Max-Payload to '%d'", + l->name, max_payload)); + /* Tell the PPPoE node to set PPP-Max-Payload value. */ + if (NgSendMsg(pe->PIf->csock, path, NGM_PPPOE_COOKIE, NGM_PPPOE_SETMAXP, + &max_payload, sizeof(uint16_t)) < 0) { + Perror("[%s] PPPoE can't set PPP-Max-Payload value", l->name); + goto fail2; + } + } +#endif + Log(LG_PHYS, ("[%s] PPPoE: Connecting to '%s'", l->name, pe->session)); /* Tell the PPPoE node to try to connect to a server. */ @@ -417,6 +441,7 @@ strlcpy(pe->real_session, pe->session, sizeof(pe->real_session)); pe->agent_cid[0] = 0; pe->agent_rid[0] = 0; + pe->mp_reply = 0; return; fail3: @@ -499,6 +524,7 @@ pi->real_session[0] = 0; pi->agent_cid[0] = 0; pi->agent_rid[0] = 0; + pi->mp_reply = 0; } /* @@ -510,7 +536,11 @@ PppoeCtrlReadEvent(int type, void *arg) { union { +#ifdef NGM_PPPOE_SETMAXP_COOKIE + u_char buf[sizeof(struct ng_mesg) + sizeof(struct ngpppoe_maxp)]; +#else u_char buf[sizeof(struct ng_mesg) + sizeof(struct ngpppoe_sts)]; +#endif struct ng_mesg resp; } u; char path[NG_PATHSIZ]; @@ -534,6 +564,9 @@ case NGM_PPPOE_SUCCESS: case NGM_PPPOE_FAIL: case NGM_PPPOE_CLOSE: +#ifdef NGM_PPPOE_SETMAXP_COOKIE + case NGM_PPPOE_SETMAXP: +#endif { char ppphook[NG_HOOKSIZ]; char *linkname, *rest; @@ -576,6 +609,8 @@ /* Decode message. */ switch (u.resp.header.cmd) { case NGM_PPPOE_SESSIONID: /* XXX: I do not know what to do with this? */ + Log(LG_PHYS3, ("PPPoE: rec'd SESSIONID %u from \"%s\"", + ntohs((uint16_t)u.resp.data), path)); break; case NGM_PPPOE_SUCCESS: Log(LG_PHYS, ("[%s] PPPoE: connection successful", l->name)); @@ -601,6 +636,28 @@ Log(LG_PHYS, ("PPPoE: rec'd ACNAME \"%s\"", ((struct ngpppoe_sts *)u.resp.data)->hook)); break; +#ifdef NGM_PPPOE_SETMAXP_COOKIE + case NGM_PPPOE_SETMAXP: + { + struct ngpppoe_maxp *maxp; + + maxp = ((struct ngpppoe_maxp *)u.resp.data); + Log(LG_PHYS, ("[%s] PPPoE: rec'd PPP-Max-Payload '%u'", + l->name, maxp->data)); + if (pi->max_payload > 0) { + if (pi->max_payload == maxp->data) + pi->mp_reply = 1; + else + Log(LG_PHYS, + ("[%s] PPPoE: sent and returned values are not equal", + l->name)); + } else + Log(LG_PHYS, ("[%s] PPPoE: server sent tag PPP-Max-Payload" + " without request from the client", + l->name)); + break; + } +#endif default: Log(LG_PHYS, ("PPPoE: rec'd command %lu from \"%s\"", (u_long)u.resp.header.cmd, path)); @@ -639,6 +696,9 @@ Printf("\tIface Node : %s\r\n", pe->path); Printf("\tIface Hook : %s\r\n", pe->hook); Printf("\tSession : %s\r\n", pe->session); +#ifdef NGM_PPPOE_SETMAXP_COOKIE + Printf("\tMax-Payload : %d\r\n", pe->max_payload); +#endif Printf("\tMAC format : %s\r\n", buf); Printf("PPPoE status:\r\n"); if (ctx->lnk->state != PHYS_STATE_DOWN) { @@ -647,6 +707,7 @@ PppoePeerMacAddr(ctx->lnk, buf, sizeof(buf)); Printf("\tCurrent peer : %s\r\n", buf); Printf("\tSession : %s\r\n", pe->real_session); + Printf("\tMax-Payload : %s\r\n", (pe->mp_reply?"YES":"NO")); Printf("\tCircuit-ID : %s\r\n", pe->agent_cid); Printf("\tRemote-ID : %s\r\n", pe->agent_rid); } @@ -788,6 +849,20 @@ return (0); } +static u_short +PppoeGetMru(Link l, int conf) +{ + PppoeInfo const pppoe = (PppoeInfo)l->info; + + if (pppoe->max_payload > 0 && pppoe->mp_reply > 0) + return (pppoe->max_payload); + else + if (conf == 0) + return (l->type->mru); + else + return (l->conf.mru); +} + static int CreatePppoeNode(struct PppoeIf *PIf, const char *path, const char *hook) { @@ -1122,7 +1197,7 @@ /* First check our stat list for known tags */ for (k = 0; k < NUM_TAG_NAMES; k++) { if (pt->tag_type == tag2str[k].tag) { - sprintf(tag, tag2str[k].name); + sprintf(tag, "%s", tag2str[k].name); break; } } @@ -1583,7 +1658,9 @@ const PppoeInfo pi = (PppoeInfo) ctx->lnk->info; const char *hookname = ETHER_DEFAULT_HOOK; const char *colon; - +#ifdef NGM_PPPOE_SETMAXP_COOKIE + int ap; +#endif switch ((intptr_t)arg) { case SET_IFACE: switch (ac) { @@ -1620,6 +1697,16 @@ return(-1); strlcpy(pi->acname, av[0], sizeof(pi->acname)); break; +#ifdef NGM_PPPOE_SETMAXP_COOKIE + case SET_MAX_PAYLOAD: + if (ac != 1) + return(-1); + ap = atoi(av[0]); + if (ap < ETHER_MIN_LEN + 8 || ap > ETHER_MAX_LEN - 8) + Error("PPP-Max-Payload value \"%s\"", av[0]); + pi->max_payload = ap; + break; +#endif case SET_MAC_FORMAT: if (ac != 1) return(-1); @@ -1632,7 +1719,7 @@ } else if (strcmp(av[0], "ietf") == 0) { pi->mac_format = MAC_IETF; } else { - Error("Incorrect pppoe mac-format"); + Error("Incorrect PPPoE mac-format \"%s\"", av[0]); } break; default: