Attached are three patches for RFC 4638 PPPoE support. The first two are
for pppoe(4) based on similar changes made to NetBSD. The third patch is
to tcpdump(8) so it recognises the additional tag type.

I've been running this on my Soekris net6501 with one of the the built
in em(4) chips hooked up to the BT Openreach-branded Huawei modem. My
/etc/hostname.em0 contains:

mtu 1508
up

and /etc/hostname.pppoe0 is configured as normal. Once up and running
the network interfaces look like this:

em0: flags=28843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,NOINET6> mtu 1508
        lladdr be:ef:be:ef:be:ef
        priority: 0
        media: Ethernet autoselect (100baseTX full-duplex,rxpause,txpause)
        status: active
pppoe0: flags=28851<UP,POINTOPOINT,RUNNING,SIMPLEX,MULTICAST,NOINET6> mtu 1500
        priority: 0
        dev: em0 state: session
        sid: 0x903 PADI retries: 3 PADR retries: 0 time: 00:28:27
        sppp: phase network authproto chap 
        groups: pppoe egress
        status: active
        inet 1.2.3.4 --> 5.6.7.8 netmask 0xffffffff

I'm aware the patch as it currently stands assumes the other end will
JFW and agree to the increased size (as does the NetBSD code). I wasn't
sure how best to handle the case when the remote end doesn't send the
max payload tag back in the PADO/PADS packets.

Matt

--- sys/net/if_pppoe.c.orig     Tue Dec 13 21:52:04 2011
+++ sys/net/if_pppoe.c  Sat Dec 17 23:12:43 2011
@@ -86,6 +86,7 @@
 #define        PPPOE_TAG_ACCOOKIE      0x0104          /* AC cookie */
 #define        PPPOE_TAG_VENDOR        0x0105          /* vendor specific */
 #define        PPPOE_TAG_RELAYSID      0x0110          /* relay session id */
+#define        PPPOE_TAG_MAX_PAYLOAD   0x0120          /* max payload */
 #define        PPPOE_TAG_SNAME_ERR     0x0201          /* service name error */
 #define        PPPOE_TAG_ACSYS_ERR     0x0202          /* AC system error */
 #define        PPPOE_TAG_GENERIC_ERR   0x0203          /* gerneric error */
@@ -531,6 +532,8 @@
                                relay_sid_len = len;
                        }
                        break;
+               case PPPOE_TAG_MAX_PAYLOAD:
+                       break;  /* ignored */
                case PPPOE_TAG_SNAME_ERR:
                        err_msg = "SERVICE NAME ERROR";
                        errortag = 1;
@@ -911,7 +914,7 @@
                                return (ENXIO);
                        }
 
-                       if (sc->sc_sppp.pp_if.if_mtu >
+                       if (sc->sc_sppp.pp_if.if_mtu !=
                            eth_if->if_mtu - PPPOE_OVERHEAD) {
                                sc->sc_sppp.pp_if.if_mtu = eth_if->if_mtu -
                                    PPPOE_OVERHEAD;
@@ -1068,6 +1071,8 @@
                l2 = strlen(sc->sc_concentrator_name);
                len += 2 + 2 + l2;
        }
+       if (sc->sc_sppp.pp_if.if_mtu > PPPOE_MAXMTU)
+               len += 2 + 2 + 2;
 
        /* allocate a buffer */
        m0 = pppoe_get_mbuf(len + PPPOE_HEADERLEN);     /* header len + payload 
len */
@@ -1094,9 +1099,15 @@
        PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
        PPPOE_ADD_16(p, sizeof(sc->sc_unique));
        memcpy(p, &sc->sc_unique, sizeof(sc->sc_unique));
+       p += sizeof(sc->sc_unique);
 
+       if (sc->sc_sppp.pp_if.if_mtu > PPPOE_MAXMTU) {
+               PPPOE_ADD_16(p, PPPOE_TAG_MAX_PAYLOAD);
+               PPPOE_ADD_16(p, 2);
+               PPPOE_ADD_16(p, (u_int16_t)sc->sc_sppp.pp_if.if_mtu);
+       }
+
 #ifdef PPPOE_DEBUG
-       p += sizeof(sc->sc_unique);
        if (p - mtod(m0, u_int8_t *) != len + PPPOE_HEADERLEN)
                panic("pppoe_send_padi: garbled output len, should be %ld, is 
%ld",
                    (long)(len + PPPOE_HEADERLEN), (long)(p - mtod(m0, u_int8_t 
*)));
@@ -1298,6 +1309,8 @@
                len += 2 + 2 + sc->sc_ac_cookie_len;    /* AC cookie */
        if (sc->sc_relay_sid_len > 0)
                len += 2 + 2 + sc->sc_relay_sid_len;    /* Relay SID */
+       if (sc->sc_sppp.pp_if.if_mtu > PPPOE_MAXMTU)
+               len += 2 + 2 + 2;
 
        m0 = pppoe_get_mbuf(len + PPPOE_HEADERLEN);
        if (m0 == NULL)
@@ -1329,9 +1342,15 @@
        PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
        PPPOE_ADD_16(p, sizeof(sc->sc_unique));
        memcpy(p, &sc->sc_unique, sizeof(sc->sc_unique));
+       p += sizeof(sc->sc_unique);
 
+       if (sc->sc_sppp.pp_if.if_mtu > PPPOE_MAXMTU) {
+               PPPOE_ADD_16(p, PPPOE_TAG_MAX_PAYLOAD);
+               PPPOE_ADD_16(p, 2);
+               PPPOE_ADD_16(p, (u_int16_t)sc->sc_sppp.pp_if.if_mtu);
+       }
+
 #ifdef PPPOE_DEBUG
-       p += sizeof(sc->sc_unique);
        if (p - mtod(m0, u_int8_t *) != len + PPPOE_HEADERLEN)
                panic("pppoe_send_padr: garbled output len, should be %ld, is 
%ld",
                        (long)(len + PPPOE_HEADERLEN), (long)(p - mtod(m0, 
u_int8_t *)));
--- sys/net/if_spppsubr.c.orig  Tue Dec 13 22:16:00 2011
+++ sys/net/if_spppsubr.c       Tue Dec 13 22:26:23 2011
@@ -2027,7 +2027,6 @@
        sp->state[IDX_LCP] = STATE_INITIAL;
        sp->fail_counter[IDX_LCP] = 0;
        sp->lcp.protos = 0;
-       sp->lcp.mru = sp->lcp.their_mru = sp->pp_if.if_mtu;
 
        /*
         * Initialize counters and timeout values.  Note that we don't
@@ -2137,6 +2136,13 @@
 HIDE void
 sppp_lcp_open(struct sppp *sp)
 {
+       if (sp->pp_if.if_mtu < PP_MTU) {
+               sp->lcp.mru = sp->pp_if.if_mtu;
+               sp->lcp.opts |= (1 << LCP_OPT_MRU);
+       } else
+               sp->lcp.mru = PP_MTU;
+       sp->lcp.their_mru = PP_MTU;
+
        /*
         * If we are authenticator, negotiate LCP_AUTH
         */
--- usr.sbin/tcpdump/print-ppp.c.orig   Sat Feb 20 18:02:33 2010
+++ usr.sbin/tcpdump/print-ppp.c        Tue Dec 13 21:46:33 2011
@@ -240,6 +240,7 @@
 #define        PPPOE_TAG_AC_COOKIE             0x0104  /* Access Concentratr 
Cookie */
 #define        PPPOE_TAG_VENDOR_SPEC           0x0105  /* Vendor Specific */
 #define        PPPOE_TAG_RELAY_SESSION         0x0110  /* Relay Session Id */
+#define        PPPOE_TAG_MAX_PAYLOAD           0x0120  /* RFC 4638 Max Payload 
*/
 #define        PPPOE_TAG_SERVICE_NAME_ERROR    0x0201  /* Service Name Error */
 #define        PPPOE_TAG_AC_SYSTEM_ERROR       0x0202  /* Acc. Concentrator 
Error */
 #define        PPPOE_TAG_GENERIC_ERROR         0x0203  /* Generic Error */
@@ -883,6 +884,9 @@
                                break;
                        case PPPOE_TAG_RELAY_SESSION:
                                printf("Relay-Session");
+                               break;
+                       case PPPOE_TAG_MAX_PAYLOAD:
+                               printf("PPP-Max-Payload");
                                break;
                        case PPPOE_TAG_SERVICE_NAME_ERROR:
                                printf("Service-Name-Error");

Reply via email to