]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/plugins/rp-pppoe/plugin.c
rp-pppoe plugin: Import some fixes from rp-pppoe-3.10
[ppp.git] / pppd / plugins / rp-pppoe / plugin.c
index 9bd66433f3fec933905f6d073814d0292d3936a1..a8c2bb4f4a6aec1cb76f30ebfa5403f852cc092f 100644 (file)
@@ -49,7 +49,6 @@ static char const RCSID[] =
 #include <net/ethernet.h>
 #include <net/if_arp.h>
 #include <linux/ppp_defs.h>
-#include <linux/if_ppp.h>
 #include <linux/if_pppox.h>
 
 #ifndef _ROOT_PATH
@@ -130,6 +129,42 @@ static int
 PPPOEConnectDevice(void)
 {
     struct sockaddr_pppox sp;
+    struct ifreq ifr;
+    int s;
+
+    /* Open session socket before discovery phase, to avoid losing session */
+    /* packets sent by peer just after PADS packet (noted on some Cisco    */
+    /* server equipment).                                                  */
+    /* Opening this socket just before waitForPADS in the discovery()      */
+    /* function would be more appropriate, but it would mess-up the code   */
+    conn->sessionSocket = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_OE);
+    if (conn->sessionSocket < 0) {
+       error("Failed to create PPPoE socket: %m");
+       return -1;
+    }
+
+    /* Restore configuration */
+    lcp_allowoptions[0].mru = conn->mtu;
+    lcp_wantoptions[0].mru = conn->mru;
+
+    /* Update maximum MRU */
+    s = socket(AF_INET, SOCK_DGRAM, 0);
+    if (s < 0) {
+       error("Can't get MTU for %s: %m", conn->ifName);
+       goto errout;
+    }
+    strncpy(ifr.ifr_name, conn->ifName, sizeof(ifr.ifr_name));
+    if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
+       error("Can't get MTU for %s: %m", conn->ifName);
+       close(s);
+       goto errout;
+    }
+    close(s);
+
+    if (lcp_allowoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD)
+       lcp_allowoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD;
+    if (lcp_wantoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD)
+       lcp_wantoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD;
 
     conn->acName = acName;
     conn->serviceName = pppd_pppoe_service;
@@ -147,22 +182,18 @@ PPPOEConnectDevice(void)
            conn->peerEth[i] = (unsigned char) mac[i];
        }
     } else {
+       conn->discoverySocket =
+            openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth);
        discovery(conn);
        if (conn->discoveryState != STATE_SESSION) {
            error("Unable to complete PPPoE Discovery");
-           return -1;
+           goto errout;
        }
     }
 
     /* Set PPPoE session-number for further consumption */
     ppp_session_number = ntohs(conn->session);
 
-    /* Make the session socket */
-    conn->sessionSocket = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_OE);
-    if (conn->sessionSocket < 0) {
-       error("Failed to create PPPoE socket: %m");
-       goto errout;
-    }
     sp.sa_family = AF_PPPOX;
     sp.sa_protocol = PX_PROTO_OE;
     sp.sa_addr.pppoe.sid = conn->session;
@@ -192,7 +223,6 @@ PPPOEConnectDevice(void)
     if (connect(conn->sessionSocket, (struct sockaddr *) &sp,
                sizeof(struct sockaddr_pppox)) < 0) {
        error("Failed to connect PPPoE socket: %d %m", errno);
-       close(conn->sessionSocket);
        goto errout;
     }
 
@@ -204,6 +234,7 @@ PPPOEConnectDevice(void)
        close(conn->discoverySocket);
        conn->discoverySocket = -1;
     }
+    close(conn->sessionSocket);
     return -1;
 }
 
@@ -381,6 +412,10 @@ void pppoe_check_options(void)
     if (lcp_wantoptions[0].mru > MAX_PPPOE_MTU)
        lcp_wantoptions[0].mru = MAX_PPPOE_MTU;
 
+    /* Save configuration */
+    conn->mtu = lcp_allowoptions[0].mru;
+    conn->mru = lcp_wantoptions[0].mru;
+
     ccp_allowoptions[0].deflate = 0;
     ccp_wantoptions[0].deflate = 0;