X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Fplugins%2Frp-pppoe%2Fdiscovery.c;fp=pppd%2Fplugins%2Frp-pppoe%2Fdiscovery.c;h=a856490f96fb7ba887ae2e8dda16a91eae358769;hb=fd1dcdf758418f040da3ed801ab001b5e46854e7;hp=6e25ae7361e9167b7f1ab01f58b4ba8e6d1d584c;hpb=3089132cdf5b58dbdfc2daf08ec5c08eb47f8aca;p=ppp.git diff --git a/pppd/plugins/rp-pppoe/discovery.c b/pppd/plugins/rp-pppoe/discovery.c index 6e25ae7..a856490 100644 --- a/pppd/plugins/rp-pppoe/discovery.c +++ b/pppd/plugins/rp-pppoe/discovery.c @@ -14,6 +14,8 @@ static char const RCSID[] = #define _GNU_SOURCE 1 #include "pppoe.h" #include "pppd/pppd.h" +#include "pppd/fsm.h" +#include "pppd/lcp.h" #include #include @@ -110,6 +112,7 @@ parsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data, { struct PacketCriteria *pc = (struct PacketCriteria *) extra; PPPoEConnection *conn = pc->conn; + UINT16_t mru; int i; switch(type) { @@ -140,6 +143,19 @@ parsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data, conn->relayId.length = htons(len); memcpy(conn->relayId.payload, data, len); break; + case TAG_PPP_MAX_PAYLOAD: + if (len == sizeof(mru)) { + memcpy(&mru, data, sizeof(mru)); + mru = ntohs(mru); + if (mru >= ETH_PPPOE_MTU) { + if (lcp_allowoptions[0].mru > mru) + lcp_allowoptions[0].mru = mru; + if (lcp_wantoptions[0].mru > mru) + lcp_wantoptions[0].mru = mru; + conn->seenMaxPayload = 1; + } + } + break; case TAG_SERVICE_NAME_ERROR: error("PADO: Service-Name-Error: %.*s", (int) len, data); conn->error = 1; @@ -172,10 +188,24 @@ parsePADSTags(UINT16_t type, UINT16_t len, unsigned char *data, void *extra) { PPPoEConnection *conn = (PPPoEConnection *) extra; + UINT16_t mru; switch(type) { case TAG_SERVICE_NAME: dbglog("PADS: Service-Name: '%.*s'", (int) len, data); break; + case TAG_PPP_MAX_PAYLOAD: + if (len == sizeof(mru)) { + memcpy(&mru, data, sizeof(mru)); + mru = ntohs(mru); + if (mru >= ETH_PPPOE_MTU) { + if (lcp_allowoptions[0].mru > mru) + lcp_allowoptions[0].mru = mru; + if (lcp_wantoptions[0].mru > mru) + lcp_wantoptions[0].mru = mru; + conn->seenMaxPayload = 1; + } + } + break; case TAG_SERVICE_NAME_ERROR: error("PADS: Service-Name-Error: %.*s", (int) len, data); conn->error = 1; @@ -259,6 +289,19 @@ sendPADI(PPPoEConnection *conn) plen += sizeof(pid) + TAG_HDR_SIZE; } + /* Add our maximum MTU/MRU */ + if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) { + PPPoETag maxPayload; + UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru)); + maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD); + maxPayload.length = htons(sizeof(mru)); + memcpy(maxPayload.payload, &mru, sizeof(mru)); + CHECK_ROOM(cursor, packet.payload, sizeof(mru) + TAG_HDR_SIZE); + memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE); + cursor += sizeof(mru) + TAG_HDR_SIZE; + plen += sizeof(mru) + TAG_HDR_SIZE; + } + packet.length = htons(plen); sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE)); @@ -289,6 +332,7 @@ waitForPADO(PPPoEConnection *conn, int timeout) pc.serviceNameOK = (conn->serviceName) ? 0 : 1; pc.seenACName = 0; pc.seenServiceName = 0; + conn->seenMaxPayload = 0; conn->error = 0; do { @@ -413,6 +457,19 @@ sendPADR(PPPoEConnection *conn) plen += sizeof(pid) + TAG_HDR_SIZE; } + /* Add our maximum MTU/MRU */ + if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) { + PPPoETag maxPayload; + UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru)); + maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD); + maxPayload.length = htons(sizeof(mru)); + memcpy(maxPayload.payload, &mru, sizeof(mru)); + CHECK_ROOM(cursor, packet.payload, sizeof(mru) + TAG_HDR_SIZE); + memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE); + cursor += sizeof(mru) + TAG_HDR_SIZE; + plen += sizeof(mru) + TAG_HDR_SIZE; + } + /* Copy cookie and relay-ID if needed */ if (conn->cookie.type) { CHECK_ROOM(cursor, packet.payload, @@ -566,6 +623,14 @@ discovery(PPPoEConnection *conn) timeout *= 2; } while (conn->discoveryState == STATE_SENT_PADR); + if (!conn->seenMaxPayload) { + /* RFC 4638: MUST limit MTU/MRU to 1492 */ + if (lcp_allowoptions[0].mru > ETH_PPPOE_MTU) + lcp_allowoptions[0].mru = ETH_PPPOE_MTU; + if (lcp_wantoptions[0].mru > ETH_PPPOE_MTU) + lcp_wantoptions[0].mru = ETH_PPPOE_MTU; + } + /* We're done. */ conn->discoveryState = STATE_SESSION; return;