]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/sys-linux.c
pppd.8: Document netmask option
[ppp.git] / pppd / sys-linux.c
index dc3b4d658de4770c32a95900d9f811b4c7fc5878..c0955a05b9a89dbd60afe4e51821df9473646a38 100644 (file)
@@ -18,7 +18,7 @@
  * 3. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by Paul Mackerras
- *     <paulus@samba.org>".
+ *     <paulus@ozlabs.org>".
  *
  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_link.h>
-
-/* Attempt at retaining compile-support with older than 4.7 kernels, or kernels
- * where RTM_NEWSTATS isn't defined for whatever reason.
- */
-#ifndef RTM_NEWSTATS
-#define RTM_NEWSTATS 92
-#define RTM_GETSTATS 94
-#define IFLA_STATS_LINK_64 1
-#endif
-
 #include <linux/if_addr.h>
 
 /* glibc versions prior to 2.24 do not define SOL_NETLINK */
 #define IFLA_PPP_DEV_FD 1
 #endif
 
-#include "pppd.h"
+#include "pppd-private.h"
+#include "options.h"
 #include "fsm.h"
 #include "ipcp.h"
 
 #include "eui64.h"
 #endif /* PPP_WITH_IPV6CP */
 
+#include "multilink.h"
+
 #ifdef PPP_WITH_FILTER
 #include <pcap-bpf.h>
 #include <linux/filter.h>
@@ -547,10 +540,10 @@ void sys_cleanup(void)
 
 /********************************************************************
  *
- * sys_close - Clean up in a child process before execing.
+ * ppp_sys_close - Clean up in a child process before execing.
  */
 void
-sys_close(void)
+ppp_sys_close(void)
 {
     if (new_style_driver && ppp_dev_fd >= 0)
        close(ppp_dev_fd);
@@ -614,7 +607,7 @@ int tty_establish_ppp (int tty_fd)
 #ifndef N_SYNC_PPP
 #define N_SYNC_PPP 14
 #endif
-    ppp_disc = (new_style_driver && sync_serial)? N_SYNC_PPP: N_PPP;
+    ppp_disc = (new_style_driver && ppp_sync_serial())? N_SYNC_PPP: N_PPP;
     if (ioctl(tty_fd, TIOCSETD, &ppp_disc) < 0) {
        if ( ! ok_error (errno) ) {
            error("Couldn't set tty to PPP discipline: %m");
@@ -622,7 +615,7 @@ int tty_establish_ppp (int tty_fd)
        }
     }
 
-    ret_fd = generic_establish_ppp(tty_fd);
+    ret_fd = ppp_generic_establish(tty_fd);
 
 #define SC_RCVB        (SC_RCV_B7_0 | SC_RCV_B7_1 | SC_RCV_EVNP | SC_RCV_ODDP)
 #define SC_LOGB        (SC_DEBUG | SC_LOG_INPKT | SC_LOG_OUTPKT | SC_LOG_RAWIN \
@@ -643,7 +636,7 @@ int tty_establish_ppp (int tty_fd)
  *
  * generic_establish_ppp - Turn the fd into a ppp interface.
  */
-int generic_establish_ppp (int fd)
+int ppp_generic_establish (int fd)
 {
     int x;
 
@@ -780,16 +773,16 @@ void tty_disestablish_ppp(int tty_fd)
 flushfailed:
     initfdflags = -1;
 
-    generic_disestablish_ppp(tty_fd);
+    ppp_generic_disestablish(tty_fd);
 }
 
 /********************************************************************
  *
- * generic_disestablish_ppp - Restore device components to normal
+ * ppp_generic_disestablish - Restore device components to normal
  * operation, and reconnect the ppp unit to the loopback if in demand
  * mode.  This shouldn't call die() because it's called from die().
  */
-void generic_disestablish_ppp(int dev_fd)
+void ppp_generic_disestablish(int dev_fd)
 {
     if (new_style_driver) {
        close(ppp_fd);
@@ -797,7 +790,7 @@ void generic_disestablish_ppp(int dev_fd)
        if (demand) {
            modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC);
            looped = 1;
-       } else if (!doing_multilink && ppp_dev_fd >= 0) {
+       } else if (!mp_on() && ppp_dev_fd >= 0) {
            close(ppp_dev_fd);
            remove_fd(ppp_dev_fd);
            ppp_dev_fd = -1;
@@ -864,7 +857,14 @@ static int make_ppp_unit_rtnetlink(void)
     nlreq.ifli.ifid.ifdata[0].rta.rta_type = IFLA_PPP_DEV_FD;
     nlreq.ifli.ifid.ifdata[0].ppp.ppp_dev_fd = ppp_dev_fd;
 
-    resp = rtnetlink_msg("RTM_NEWLINK/NLM_F_CREATE", NULL, &nlreq, sizeof(nlreq), NULL, NULL, 0);
+    /*
+     * See kernel function ppp_nl_newlink(), which may return -EBUSY to prevent
+     * possible deadlock in kernel and ask userspace to retry request again.
+     */
+    do {
+        resp = rtnetlink_msg("RTM_NEWLINK/NLM_F_CREATE", NULL, &nlreq, sizeof(nlreq), NULL, NULL, 0);
+    } while (resp == -EBUSY);
+
     if (resp) {
         /*
          * Linux kernel versions prior to 4.7 do not support creating ppp
@@ -1496,7 +1496,7 @@ int read_packet (unsigned char *buf)
            error("read /dev/ppp: %m");
        if (nr < 0 && errno == ENXIO)
            nr = 0;
-       if (nr == 0 && doing_multilink) {
+       if (nr == 0 && mp_on()) {
            remove_fd(ppp_dev_fd);
            bundle_eof = 1;
        }
@@ -1542,7 +1542,7 @@ get_loop_output(void)
  * netif_set_mtu - set the MTU on the PPP network interface.
  */
 void
-netif_set_mtu(int unit, int mtu)
+ppp_set_mtu(int unit, int mtu)
 {
     struct ifreq ifr;
 
@@ -1558,7 +1558,7 @@ netif_set_mtu(int unit, int mtu)
  * netif_get_mtu - get the MTU on the PPP network interface.
  */
 int
-netif_get_mtu(int unit)
+ppp_get_mtu(int unit)
 {
     struct ifreq ifr;
 
@@ -1593,7 +1593,7 @@ void tty_send_config(int mtu, u_int32_t asyncmap, int pcomp, int accomp)
        }
 
        x = (pcomp? SC_COMP_PROT: 0) | (accomp? SC_COMP_AC: 0)
-           | (sync_serial? SC_SYNC: 0);
+           | (ppp_sync_serial()? SC_SYNC: 0);
        modify_flags(ppp_fd, SC_COMP_PROT|SC_COMP_AC|SC_SYNC, x);
 }
 
@@ -1766,6 +1766,7 @@ get_ppp_stats_ioctl(int u, struct pppd_stats *stats)
 static int
 get_ppp_stats_rtnetlink(int u, struct pppd_stats *stats)
 {
+#ifdef RTM_NEWSTATS
     static int fd = -1;
 
     struct {
@@ -1815,6 +1816,7 @@ get_ppp_stats_rtnetlink(int u, struct pppd_stats *stats)
 err:
     close(fd);
     fd = -1;
+#endif
     return 0;
 }
 
@@ -2191,11 +2193,27 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway, bool replac
         * - this is normally only the case the doing demand: */
        if (defaultroute_exists(&tmp_rt, -1))
            del_rt = &tmp_rt;
+    } else if (!replace) {
+       /*
+        * We don't want to replace an existing route.
+        * We may however add our route along an existing route with a different
+        * metric.
+        */
+       if (defaultroute_exists(&rt, dfl_route_metric) && strcmp(rt.rt_dev, ifname) != 0) {
+          if (rt.rt_flags & RTF_GATEWAY)
+              error("not replacing existing default route via %I with metric %d",
+                    SIN_ADDR(rt.rt_gateway), dfl_route_metric);
+          else
+              error("not replacing existing default route through %s with metric %d",
+                    rt.rt_dev, dfl_route_metric);
+          return 0;
+       }
     } else if (defaultroute_exists(&old_def_rt, -1           ) &&
                            strcmp( old_def_rt.rt_dev, ifname) != 0) {
        /*
-        * We did not yet replace an existing default route, let's
-        * check if we should save and replace a default route:
+        * We want to replace an existing route and did not replace an existing
+        * default route yet, let's check if we should save and replace an
+        * existing default route:
         */
        u_int32_t old_gateway = SIN_ADDR(old_def_rt.rt_gateway);
 
@@ -2850,11 +2868,11 @@ ppp_registered(void)
 
 /********************************************************************
  *
- * ppp_available - check whether the system has any ppp interfaces
+ * ppp_check_kernel_support - check whether the system has any ppp interfaces
  * (in fact we check whether we can do an ioctl on ppp0).
  */
 
-int ppp_available(void)
+int ppp_check_kernel_support(void)
 {
     int s, ok, fd;
     struct ifreq ifr;
@@ -3667,7 +3685,7 @@ int
 get_host_seed(void)
 {
     int h;
-    char *p = hostname;
+    const char *p;
 
     h = 407;
     for (p = hostname; *p != 0; ++p)
@@ -3684,7 +3702,7 @@ int
 sys_check_options(void)
 {
     if (demand && driver_is_old) {
-       option_error("demand dialling is not supported by kernel driver "
+       ppp_option_error("demand dialling is not supported by kernel driver "
                     "version %d.%d.%d", driver_version, driver_modification,
                     driver_patch);
        return 0;
@@ -3701,7 +3719,7 @@ sys_check_options(void)
  * get_time - Get current time, monotonic if possible.
  */
 int
-get_time(struct timeval *tv)
+ppp_get_time(struct timeval *tv)
 {
 /* Old glibc (< 2.3.4) does define CLOCK_MONOTONIC, but kernel may have it.
  * Runtime checking makes it safe. */