NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/40690: pppoe(4) doesn't work when PPPoE relays are present



>Number:         40690
>Category:       kern
>Synopsis:       pppoe(4) doesn't work when PPPoE relays are present
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Feb 19 15:00:00 +0000 2009
>Originator:     Jordan Gordeev
>Release:        5.0-RC1
>Organization:
>Environment:
>Description:
The RFC on PPPoE says that if you receive a relay session id TAG, you must copy 
it in responses. The pppoe(4) driver doesn't do that.
As a result, attempts to use pppoe(4) to connect to an Access Concentrator 
behind a PPPoE relay fail. This makes connecting to the Internet impossible for 
some users.

>How-To-Repeat:
Use pppoe(4) to connect to an AC behind a PPPoE relay.
>Fix:
The following patch (adapted from revision 1.15 of OpenBSD's if_pppoe.c) fixes 
the problem.
Index: sys/net/if_pppoe.c
===================================================================
RCS file: /cvs-mirror/nbsd/src/sys/net/if_pppoe.c,v
retrieving revision 1.93
diff -u -r1.93 if_pppoe.c
--- sys/net/if_pppoe.c  15 Oct 2008 20:08:33 -0000      1.93
+++ sys/net/if_pppoe.c  19 Feb 2009 15:53:23 -0000
@@ -138,6 +138,8 @@
        char *sc_concentrator_name;     /* if != NULL: requested concentrator 
id */
        uint8_t *sc_ac_cookie;          /* content of AC cookie we must echo 
back */
        size_t sc_ac_cookie_len;        /* length of cookie data */
+       uint8_t *sc_relay_sid;          /* content of relay SID we must echo 
back */
+       size_t sc_relay_sid_len;        /* length of relay SID data */
 #ifdef PPPOE_SERVER
        uint8_t *sc_hunique;            /* content of host unique we must echo 
back */
        size_t sc_hunique_len;          /* length of host unique */
@@ -283,6 +285,8 @@
                free(sc->sc_service_name, M_DEVBUF);
        if (sc->sc_ac_cookie)
                free(sc->sc_ac_cookie, M_DEVBUF);
+       if (sc->sc_relay_sid)
+               free(sc->sc_relay_sid, M_DEVBUF);
        callout_destroy(&sc->sc_timeout);
        free(sc, M_DEVBUF);
 
@@ -400,6 +404,8 @@
        char *error;
        uint8_t *ac_cookie;
        size_t ac_cookie_len;
+       uint8_t *relay_sid;
+       size_t relay_sid_len;
 #ifdef PPPOE_SERVER
        uint8_t *hunique;
        size_t hunique_len;
@@ -423,6 +429,8 @@
 
        ac_cookie = NULL;
        ac_cookie_len = 0;
+       relay_sid = NULL;
+       relay_sid_len = 0;
 #ifdef PPPOE_SERVER
        hunique = NULL;
        hunique_len = 0;
@@ -528,6 +536,19 @@
                                ac_cookie_len = len;
                        }
                        break;
+               case PPPOE_TAG_RELAYSID:
+                       if (relay_sid == NULL) {
+                               n = m_pulldown(m, off + sizeof(*pt), len,
+                                   &noff);
+                               if (!n) {
+                                       err_msg = "TAG RELAYSID ERROR";
+                                       m = NULL;
+                                       break;
+                               }
+                               relay_sid = mtod(n, char *) + noff;
+                               relay_sid_len = len;
+                       }
+                       break;
                case PPPOE_TAG_SNAME_ERR:
                        err_msg = "SERVICE NAME ERROR";
                        errortag = 1;
@@ -669,6 +690,20 @@
                        sc->sc_ac_cookie_len = ac_cookie_len;
                        memcpy(sc->sc_ac_cookie, ac_cookie, ac_cookie_len);
                }
+               if (relay_sid) {
+                       if (sc->sc_relay_sid)
+                               free(sc->sc_relay_sid, M_DEVBUF);
+                       sc->sc_relay_sid = malloc(relay_sid_len, M_DEVBUF,
+                           M_DONTWAIT);
+                       if (sc->sc_relay_sid == NULL) {
+                               printf("%s: FATAL: could not allocate memory "
+                                   "for relay SID\n",
+                                   sc->sc_sppp.pp_if.if_xname);
+                               goto done;
+                       }
+                       sc->sc_relay_sid_len = relay_sid_len;
+                       memcpy(sc->sc_relay_sid, relay_sid, relay_sid_len);
+               }
                memcpy(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest);
                callout_stop(&sc->sc_timeout);
                sc->sc_padr_retried = 0;
@@ -1200,6 +1235,11 @@
                sc->sc_ac_cookie = NULL;
        }
        sc->sc_ac_cookie_len = 0;
+       if (sc->sc_relay_sid) {
+               free(sc->sc_relay_sid, M_DEVBUF);
+               sc->sc_relay_sid = NULL;
+       }
+       sc->sc_relay_sid_len = 0;
 #ifdef PPPOE_SERVER
        if (sc->sc_hunique) {
                free(sc->sc_hunique, M_DEVBUF);
@@ -1251,6 +1291,8 @@
        }
        if (sc->sc_ac_cookie_len > 0)
                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 */
        m0 = pppoe_get_mbuf(len + PPPOE_HEADERLEN);
        if (!m0)
                return ENOBUFS;
@@ -1270,6 +1312,12 @@
                memcpy(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len);
                p += sc->sc_ac_cookie_len;
        }
+       if (sc->sc_relay_sid_len > 0) {
+               PPPOE_ADD_16(p, PPPOE_TAG_RELAYSID);
+               PPPOE_ADD_16(p, sc->sc_relay_sid_len);
+               memcpy(p, sc->sc_relay_sid, sc->sc_relay_sid_len);
+               p += sc->sc_relay_sid_len;
+       }
        PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
        PPPOE_ADD_16(p, sizeof(sc));
        memcpy(p, &sc, sizeof sc);
@@ -1508,6 +1556,10 @@
                free(sc->sc_ac_cookie, M_DEVBUF);
                sc->sc_ac_cookie = NULL;
        }
+       if (sc->sc_relay_sid) {
+               free(sc->sc_relay_sid, M_DEVBUF);
+               sc->sc_relay_sid = NULL;
+       }
        sc->sc_ac_cookie_len = 0;
        sc->sc_session = 0;
 }



Home | Main Index | Thread Index | Old Index