]> git.ozlabs.org Git - ppp.git/commitdiff
Rest of IPV6 merge which got lost somehow, plus some minor fixes.
authorPaul Mackerras <paulus@samba.org>
Tue, 24 Aug 1999 05:31:12 +0000 (05:31 +0000)
committerPaul Mackerras <paulus@samba.org>
Tue, 24 Aug 1999 05:31:12 +0000 (05:31 +0000)
pppd/Makefile.linux
pppd/ipcp.c
pppd/ipv6cp.c
pppd/ipxcp.c
pppd/main.c
pppd/pppd.8
pppd/pppd.h
pppd/sys-linux.c

index 67c012cb10c794ffbbc1dcd6fe3886d49a485ef2..bf2bcc55cd774542bb3641a466f60d98e438e82b 100644 (file)
@@ -1,6 +1,6 @@
 #
 # pppd makefile for Linux
 #
 # pppd makefile for Linux
-# $Id: Makefile.linux,v 1.32 1999/08/12 03:59:07 paulus Exp $
+# $Id: Makefile.linux,v 1.33 1999/08/24 05:31:08 paulus Exp $
 #
 
 # Default installation locations
 #
 
 # Default installation locations
@@ -44,6 +44,7 @@ endif
 
 HAS_SHADOW=y
 #USE_PAM=y
 
 HAS_SHADOW=y
 #USE_PAM=y
+#HAVE_INET6=y
 
 INCLUDE_DIRS= -I../include
 
 
 INCLUDE_DIRS= -I../include
 
@@ -84,6 +85,14 @@ LIBS     := -llock $(LIBS)
 CFLAGS   += -DLOCKLIB=1
 endif
 
 CFLAGS   += -DLOCKLIB=1
 endif
 
+ifdef HAVE_INET6
+     PPPDSRCS += ipv6cp.c eui64.c
+     HEADERS  += ipv6cp.h eui64.h
+     PPPDOBJS += ipv6cp.o eui64.o
+     CFLAGS   += -DINET6=1
+endif
+
+
 INSTALL= install -o root
 
 install: pppd
 INSTALL= install -o root
 
 install: pppd
index d3682a032b5243a8c7b6625b37bfe5c399f89bae..a652cbb641b51374129a4d447c99d98a13134ef2 100644 (file)
@@ -17,7 +17,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define RCSID  "$Id: ipcp.c,v 1.49 1999/08/13 06:46:12 paulus Exp $"
+#define RCSID  "$Id: ipcp.c,v 1.50 1999/08/24 05:31:09 paulus Exp $"
 
 /*
  * TODO:
 
 /*
  * TODO:
@@ -1307,17 +1307,6 @@ ip_check_options()
                wo->ouraddr = local;
        }
     }
                wo->ouraddr = local;
        }
     }
-
-    if (demand && wo->hisaddr == 0) {
-       option_error("remote IP address required for demand-dialling\n");
-       exit(1);
-    }
-#if 0
-    if (demand && wo->accept_remote) {
-       option_error("ipcp-accept-remote is incompatible with demand\n");
-       exit(1);
-    }
-#endif
 }
 
 
 }
 
 
@@ -1331,6 +1320,17 @@ ip_demand_conf(u)
 {
     ipcp_options *wo = &ipcp_wantoptions[u];
 
 {
     ipcp_options *wo = &ipcp_wantoptions[u];
 
+    if (wo->hisaddr == 0) {
+       /* make up an arbitrary address for the peer */
+       wo->hisaddr = htonl(0x0a707070 + ifunit);
+       wo->accept_remote = 1;
+    }
+    if (wo->ouraddr == 0) {
+       /* make up an arbitrary address for us */
+       wo->ouraddr = htonl(0x0a404040 + ifunit);
+       wo->accept_local = 1;
+       disable_defaultip = 1;  /* don't tell the peer this address */
+    }
     if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
        return 0;
     if (!sifup(u))
     if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
        return 0;
     if (!sifup(u))
@@ -1545,6 +1545,7 @@ ipcp_down(f)
     if (demand) {
        sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
     } else {
     if (demand) {
        sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
     } else {
+       sifnpmode(f->unit, PPP_IP, NPMODE_DROP);
        sifdown(f->unit);
        ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
                         ipcp_hisoptions[f->unit].hisaddr);
        sifdown(f->unit);
        ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
                         ipcp_hisoptions[f->unit].hisaddr);
index 94f2f67e6e945265c79d47c4f051a4ec77e62004..38cb22bbb5f60bf7585d5cd1c3dcfaebfc79578a 100644 (file)
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * $Id: ipv6cp.c,v 1.2 1999/08/13 06:46:13 paulus Exp $ 
+ * $Id: ipv6cp.c,v 1.3 1999/08/24 05:31:09 paulus Exp $ 
  *
  *
  * Original version by Inria (www.inria.fr)
  * Modified to match RFC2472 by Tommi Komulainen <Tommi.Komulainen@iki.fi>
  */
 
  *
  *
  * Original version by Inria (www.inria.fr)
  * Modified to match RFC2472 by Tommi Komulainen <Tommi.Komulainen@iki.fi>
  */
 
-#define RCSID  "$Id: ipv6cp.c,v 1.2 1999/08/13 06:46:13 paulus Exp $"
+#define RCSID  "$Id: ipv6cp.c,v 1.3 1999/08/24 05:31:09 paulus Exp $"
 
 /*
  * TODO: 
 
 /*
  * TODO: 
@@ -46,6 +46,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <arpa/inet.h>
 
 #include "pppd.h"
 #include "fsm.h"
 
 #include "pppd.h"
 #include "fsm.h"
@@ -202,8 +203,8 @@ setifaceid(arg)
     ipv6cp_options *wo = &ipv6cp_wantoptions[0];
     struct in6_addr addr;
     
     ipv6cp_options *wo = &ipv6cp_wantoptions[0];
     struct in6_addr addr;
     
-#define VALIDID(a) (   ((a).s6_addr64[0] == 0) && \
-                       ((a).s6_addr64[1] != 0) )
+#define VALIDID(a) ( (((a).s6_addr32[0] == 0) && ((a).s6_addr32[1] == 0)) && \
+                       (((a).s6_addr32[2] != 0) || ((a).s6_addr32[3] != 0)) )
     
     if ((comma = strchr(arg, ',')) == NULL)
        comma = arg + strlen(arg);
     
     if ((comma = strchr(arg, ',')) == NULL)
        comma = arg + strlen(arg);
@@ -955,13 +956,13 @@ ipv6_demand_conf(u)
     ipv6cp_options *wo = &ipv6cp_wantoptions[u];
 
 #if defined(__linux__) || (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
     ipv6cp_options *wo = &ipv6cp_wantoptions[u];
 
 #if defined(__linux__) || (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
-    if (!sifup(u, PPP_IPV6))
+    if (!sifup(u))
        return 0;
 #endif    
     if (!sif6addr(u, wo->ourid, wo->hisid))
        return 0;
 #if !defined(__linux__) && !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
        return 0;
 #endif    
     if (!sif6addr(u, wo->ourid, wo->hisid))
        return 0;
 #if !defined(__linux__) && !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
-    if (!sifup(u, PPP_IPV6))
+    if (!sifup(u))
        return 0;
 #endif
     if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE))
        return 0;
 #endif
     if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE))
@@ -1063,7 +1064,7 @@ ipv6cp_up(f)
 #endif
 
        /* bring the interface up for IPv6 */
 #endif
 
        /* bring the interface up for IPv6 */
-       if (!sifup(f->unit, PPP_IPV6)) {
+       if (!sifup(f->unit)) {
            if (debug)
                warn("sif6up failed");
            ipv6cp_close(f->unit, "Interface configuration failed");
            if (debug)
                warn("sif6up failed");
            ipv6cp_close(f->unit, "Interface configuration failed");
@@ -1126,11 +1127,12 @@ ipv6cp_down(f)
        sifnpmode(f->unit, PPP_IPV6, NPMODE_QUEUE);
     } else {
 #if !defined(__linux__) && !(defined(SVR4) && (defined(SNI) || defined(__USLC)))
        sifnpmode(f->unit, PPP_IPV6, NPMODE_QUEUE);
     } else {
 #if !defined(__linux__) && !(defined(SVR4) && (defined(SNI) || defined(__USLC)))
-       sifdown(f->unit, PPP_IPV6);
+       sifnpmode(f->unit, PPP_IPV6, NPMODE_DROP);
+       sifdown(f->unit);
 #endif
        ipv6cp_clear_addrs(f->unit);
 #if defined(__linux__) || (defined(SVR4) && (defined(SNI) || defined(__USLC)))
 #endif
        ipv6cp_clear_addrs(f->unit);
 #if defined(__linux__) || (defined(SVR4) && (defined(SNI) || defined(__USLC)))
-       sifdown(f->unit, PPP_IPV6);
+       sifdown(f->unit);
 #endif
     }
 
 #endif
     }
 
index 937dea1095cc55dac734b8173b0cf0e3546b78dd..8b45f89116efc5348538196a34067df84da99b3f 100644 (file)
@@ -19,7 +19,7 @@
 
 #ifdef IPX_CHANGE
 
 
 #ifdef IPX_CHANGE
 
-#define RCSID  "$Id: ipxcp.c,v 1.17 1999/08/13 06:46:14 paulus Exp $"
+#define RCSID  "$Id: ipxcp.c,v 1.18 1999/08/24 05:31:09 paulus Exp $"
 
 /*
  * TODO:
 
 /*
  * TODO:
@@ -1266,6 +1266,7 @@ ipxcp_up(f)
        ipxcp_close(unit, "Interface configuration failed");
        return;
     }
        ipxcp_close(unit, "Interface configuration failed");
        return;
     }
+    ipxcp_is_up = 1;
 
     /* set the network number for IPX */
     if (!sipxfaddr(unit, go->network, go->our_node)) {
 
     /* set the network number for IPX */
     if (!sipxfaddr(unit, go->network, go->our_node)) {
@@ -1275,7 +1276,6 @@ ipxcp_up(f)
        return;
     }
 
        return;
     }
 
-    ipxcp_is_up = 1;
     np_up(f->unit, PPP_IPX);
 
     /*
     np_up(f->unit, PPP_IPX);
 
     /*
@@ -1299,11 +1299,12 @@ ipxcp_down(f)
 {
     IPXCPDEBUG(("ipxcp: down"));
 
 {
     IPXCPDEBUG(("ipxcp: down"));
 
-    if (ipxcp_is_up) {
-       ipxcp_is_up = 0;
-       np_down(f->unit, PPP_IPX);
-    }
-    cipxfaddr (f->unit);
+    if (!ipxcp_is_up)
+       return;
+    ipxcp_is_up = 0;
+    np_down(f->unit, PPP_IPX);
+    cipxfaddr(f->unit);
+    sifnpmode(f->unit, PPP_IPX, NPMODE_DROP);
     sifdown(f->unit);
     ipxcp_script (f, _PATH_IPXDOWN);
 }
     sifdown(f->unit);
     ipxcp_script (f, _PATH_IPXDOWN);
 }
index 4da0b9af4bc73b2eaf9dea34abcea2ec18368938..e484069687ac58a6348226d65505cbf3b4dcbf64 100644 (file)
@@ -17,7 +17,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define RCSID  "$Id: main.c,v 1.83 1999/08/13 06:46:15 paulus Exp $"
+#define RCSID  "$Id: main.c,v 1.84 1999/08/24 05:31:10 paulus Exp $"
 
 #include <stdio.h>
 #include <ctype.h>
 
 #include <stdio.h>
 #include <ctype.h>
@@ -46,6 +46,9 @@
 #include "fsm.h"
 #include "lcp.h"
 #include "ipcp.h"
 #include "fsm.h"
 #include "lcp.h"
 #include "ipcp.h"
+#ifdef INET6
+#include "ipv6cp.h"
+#endif
 #include "upap.h"
 #include "chap.h"
 #include "ccp.h"
 #include "upap.h"
 #include "chap.h"
 #include "ccp.h"
@@ -160,7 +163,7 @@ static void open_ccp __P((int));
 static void bad_signal __P((int));
 static void holdoff_end __P((void *));
 static int device_script __P((char *, int, int, int));
 static void bad_signal __P((int));
 static void holdoff_end __P((void *));
 static int device_script __P((char *, int, int, int));
-static void reap_kids __P((int waitfor));
+static int reap_kids __P((int waitfor));
 static void record_child __P((int, char *, void (*) (void *), void *));
 static int start_charshunt __P((int, int));
 static void charshunt_done __P((void *));
 static void record_child __P((int, char *, void (*) (void *), void *));
 static int start_charshunt __P((int, int));
 static void charshunt_done __P((void *));
@@ -194,6 +197,9 @@ struct protent *protocols[] = {
     &cbcp_protent,
 #endif
     &ipcp_protent,
     &cbcp_protent,
 #endif
     &ipcp_protent,
+#ifdef INET6
+    &ipv6cp_protent,
+#endif
     &ccp_protent,
 #ifdef IPX_CHANGE
     &ipxcp_protent,
     &ccp_protent,
 #ifdef IPX_CHANGE
     &ipxcp_protent,
@@ -251,6 +257,12 @@ main(argc, argv)
 
     ngroups = getgroups(NGROUPS_MAX, groups);
 
 
     ngroups = getgroups(NGROUPS_MAX, groups);
 
+    /*
+     * Initialize magic number generator now so that protocols may
+     * use magic numbers in initialization.
+     */
+    magic_init();
+
     /*
      * Initialize to the standard option set, then parse, in order,
      * the system options file, the user's options file,
     /*
      * Initialize to the standard option set, then parse, in order,
      * the system options file, the user's options file,
@@ -373,10 +385,9 @@ main(argc, argv)
     script_setenv("DEVICE", devnam);
 
     /*
     script_setenv("DEVICE", devnam);
 
     /*
-     * Initialize system-dependent stuff and magic number package.
+     * Initialize system-dependent stuff.
      */
     sys_init();
      */
     sys_init();
-    magic_init();
     if (debug)
        setlogmask(LOG_UPTO(LOG_DEBUG));
 
     if (debug)
        setlogmask(LOG_UPTO(LOG_DEBUG));
 
@@ -814,6 +825,18 @@ main(argc, argv)
                 link_stats.bytes_out, link_stats.bytes_in);
        }
 
                 link_stats.bytes_out, link_stats.bytes_in);
        }
 
+       /*
+        * Delete pid file before disestablishing ppp.  Otherwise it
+        * can happen that another pppd gets the same unit and then
+        * we delete its pid file.
+        */
+       if (!demand) {
+           if (pidfilename[0] != 0
+               && unlink(pidfilename) < 0 && errno != ENOENT) 
+               warn("unable to delete pid file %s: %m", pidfilename);
+           pidfilename[0] = 0;
+       }
+
        /*
         * If we may want to bring the link up again, transfer
         * the ppp unit back to the loopback.  Set the
        /*
         * If we may want to bring the link up again, transfer
         * the ppp unit back to the loopback.  Set the
@@ -905,7 +928,8 @@ main(argc, argv)
            for (chp = children; chp != NULL; chp = chp->next)
                dbglog("  script %s, pid %d", chp->prog, chp->pid);
        }
            for (chp = children; chp != NULL; chp = chp->next)
                dbglog("  script %s, pid %d", chp->prog, chp->pid);
        }
-       reap_kids(1);
+       if (reap_kids(1) < 0)
+           break;
     }
 
     die(status);
     }
 
     die(status);
@@ -1665,7 +1689,7 @@ record_child(pid, prog, done, arg)
  * reap_kids - get status from any dead child processes,
  * and log a message for abnormal terminations.
  */
  * reap_kids - get status from any dead child processes,
  * and log a message for abnormal terminations.
  */
-static void
+static int
 reap_kids(waitfor)
     int waitfor;
 {
 reap_kids(waitfor)
     int waitfor;
 {
@@ -1695,8 +1719,13 @@ reap_kids(waitfor)
        if (chp)
            free(chp);
     }
        if (chp)
            free(chp);
     }
-    if (pid == -1 && errno != ECHILD && errno != EINTR)
-       error("Error waiting for child process: %m");
+    if (pid == -1) {
+       if (errno == ECHILD)
+           return -1;
+       if (errno != EINTR)
+           error("Error waiting for child process: %m");
+    }
+    return 0;
 }
 
 
 }
 
 
index be3fcab908cdb46ff5a6866434b567b17b5994d9..67b5d3299378461a390d66daaf1f3038b2bd3e81 100644 (file)
@@ -1,5 +1,5 @@
 .\" manual page [] for pppd 2.3
 .\" manual page [] for pppd 2.3
-.\" $Id: pppd.8,v 1.45 1999/08/13 13:42:35 johnsonm Exp $
+.\" $Id: pppd.8,v 1.46 1999/08/24 05:31:10 paulus Exp $
 .\" SH section heading
 .\" SS subsection heading
 .\" LP paragraph
 .\" SH section heading
 .\" SS subsection heading
 .\" LP paragraph
@@ -148,13 +148,14 @@ Set the MRU [Maximum Receive Unit] value to \fIn\fR. Pppd
 will ask the peer to send packets of no more than \fIn\fR bytes.  The
 minimum MRU value is 128.  The default MRU value is 1500.  A value of
 296 is recommended for slow links (40 bytes for TCP/IP header + 256
 will ask the peer to send packets of no more than \fIn\fR bytes.  The
 minimum MRU value is 128.  The default MRU value is 1500.  A value of
 296 is recommended for slow links (40 bytes for TCP/IP header + 256
-bytes of data).
+bytes of data).  (Note that for IPv6 MRU must be at least 1280)
 .TP
 .B mtu \fIn
 Set the MTU [Maximum Transmit Unit] value to \fIn\fR.  Unless the
 peer requests a smaller value via MRU negotiation, pppd will
 request that the kernel networking code send data packets of no more
 .TP
 .B mtu \fIn
 Set the MTU [Maximum Transmit Unit] value to \fIn\fR.  Unless the
 peer requests a smaller value via MRU negotiation, pppd will
 request that the kernel networking code send data packets of no more
-than \fIn\fR bytes through the PPP network interface. 
+than \fIn\fR bytes through the PPP network interface.  (Note that for 
+IPv6 MTU must be at least 1280)
 .TP
 .B passive
 Enables the "passive" option in the LCP.  With this option, pppd will
 .TP
 .B passive
 Enables the "passive" option in the LCP.  With this option, pppd will
@@ -177,6 +178,14 @@ will not accept a different value from the peer in the IPCP
 negotiation, unless the \fIipcp-accept-local\fR and/or
 \fIipcp-accept-remote\fR options are given, respectively.
 .TP
 negotiation, unless the \fIipcp-accept-local\fR and/or
 \fIipcp-accept-remote\fR options are given, respectively.
 .TP
+.B ipv6 \fI<local_interface_identifier>\fR,\fI<remote_interface_identifier>
+Set the local and/or remote 64-bit interface identifier. Either one may be
+omitted. The identifier must be specified in standard ascii notation of
+IPv6 addresses (e.g. ::dead:beef). If the
+\fIipv6cp-use-ipaddr\fR
+option is given, the local identifier is the local IPv4 address (see above).
+Otherwise the identifier is randomized.
+.TP
 .B active-filter \fIfilter-expression
 Specifies a packet filter to be applied to data packets to determine
 which packets are to be regarded as link activity, and therefore reset
 .B active-filter \fIfilter-expression
 Specifies a packet filter to be applied to data packets to determine
 which packets are to be regarded as link activity, and therefore reset
@@ -320,6 +329,22 @@ Provides an extra parameter to the ip-up and ip-down scripts.  If this
 option is given, the \fIstring\fR supplied is given as the 6th
 parameter to those scripts.
 .TP
 option is given, the \fIstring\fR supplied is given as the 6th
 parameter to those scripts.
 .TP
+.B ipv6cp-max-configure \fIn
+Set the maximum number of IPv6CP configure-request transmissions to
+\fIn\fR (default 10).
+.TP
+.B ipv6cp-max-failure \fIn
+Set the maximum number of IPv6CP configure-NAKs returned before starting
+to send configure-Rejects instead to \fIn\fR (default 10).
+.TP
+.B ipv6cp-max-terminate \fIn
+Set the maximum number of IPv6CP terminate-request transmissions to
+\fIn\fR (default 3).
+.TP
+.B ipv6cp-restart \fIn
+Set the IPv6CP restart interval (retransmission timeout) to \fIn\fR
+seconds (default 3).
+.TP
 .B ipx
 Enable the IPXCP and IPX protocols.  This option is presently only
 supported under Linux, and only if your kernel has been configured to
 .B ipx
 Enable the IPXCP and IPX protocols.  This option is presently only
 supported under Linux, and only if your kernel has been configured to
@@ -557,6 +582,11 @@ Disable IPCP negotiation and IP communication.  This option should
 only be required if the peer is buggy and gets confused by requests
 from pppd for IPCP negotiation.
 .TP
 only be required if the peer is buggy and gets confused by requests
 from pppd for IPCP negotiation.
 .TP
+.B noipv6
+Disable IPv6CP negotiation and IPv6 communication. This option should
+only be required if the peer is buggy and gets confused by requests
+from pppd for IPv6CP negotiation.
+.TP
 .B noipdefault
 Disables the default behaviour when no local IP address is specified,
 which is to determine (if possible) the local IP address from the
 .B noipdefault
 Disables the default behaviour when no local IP address is specified,
 which is to determine (if possible) the local IP address from the
@@ -1257,6 +1287,18 @@ used for undoing the effects of the /etc/ppp/ip-up script.  It is
 invoked in the same manner and with the same parameters as the ip-up
 script.
 .TP
 invoked in the same manner and with the same parameters as the ip-up
 script.
 .TP
+.B /etc/ppp/ipv6-up
+Like /etc/ppp/ip-up, except that it is executed when the link is available 
+for sending and receiving IPv6 packets. It is executed with the parameters
+.IP
+\fIinterface-name tty-device speed local-link-local-address
+remote-link-local-address ipparam\fR
+.TP
+.B /etc/ppp/ipv6-down
+Similar to /etc/ppp/ip-down, but it is executed when IPv6 packets can no
+longer be transmitted on the link. It is executed with the same parameters 
+as the ipv6-up script.
+.TP
 .B /etc/ppp/ipx-up
 A program or script which is executed when the link is available for
 sending and receiving IPX packets (that is, IPXCP has come up).  It is
 .B /etc/ppp/ipx-up
 A program or script which is executed when the link is available for
 sending and receiving IPX packets (that is, IPXCP has come up).  It is
@@ -1354,6 +1396,11 @@ July 1994.
 Simpson, W.A.
 .I PPP in HDLC-like Framing.
 July 1994.
 Simpson, W.A.
 .I PPP in HDLC-like Framing.
 July 1994.
+.TP
+.B RFC2472
+Haskin, D.
+.I IP Version 6 over PPP
+December 1998.
 .SH NOTES
 The following signals have the specified effect when sent to pppd.
 .TP
 .SH NOTES
 The following signals have the specified effect when sent to pppd.
 .TP
index 2e7c5cabb5133072e6416f6a7a43d23a080909c7..8e4472be3db7f2f61aa3c4d7c3cbd20c919afc17 100644 (file)
@@ -16,7 +16,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * $Id: pppd.h,v 1.44 1999/08/13 01:57:37 paulus Exp $
+ * $Id: pppd.h,v 1.45 1999/08/24 05:31:11 paulus Exp $
  */
 
 /*
  */
 
 /*
 #define volatile
 #endif
 
 #define volatile
 #endif
 
+#if INET6
+#include "eui64.h"
+#endif
+
 /*
  * Limits.
  */
 /*
  * Limits.
  */
@@ -385,14 +389,22 @@ int  get_ppp_stats __P((int, struct pppd_stats *));
                                /* Return link statistics */
 int  sifvjcomp __P((int, int, int, int));
                                /* Configure VJ TCP header compression */
                                /* Return link statistics */
 int  sifvjcomp __P((int, int, int, int));
                                /* Configure VJ TCP header compression */
-int  sifup __P((int));         /* Configure i/f up (for IP) */
+int  sifup __P((int));         /* Configure i/f up for one protocol */
 int  sifnpmode __P((int u, int proto, enum NPmode mode));
                                /* Set mode for handling packets for proto */
 int  sifnpmode __P((int u, int proto, enum NPmode mode));
                                /* Set mode for handling packets for proto */
-int  sifdown __P((int));       /* Configure i/f down (for IP) */
+int  sifdown __P((int));       /* Configure i/f down for one protocol */
 int  sifaddr __P((int, u_int32_t, u_int32_t, u_int32_t));
 int  sifaddr __P((int, u_int32_t, u_int32_t, u_int32_t));
-                               /* Configure IP addresses for i/f */
+                               /* Configure IPv4 addresses for i/f */
 int  cifaddr __P((int, u_int32_t, u_int32_t));
                                /* Reset i/f IP addresses */
 int  cifaddr __P((int, u_int32_t, u_int32_t));
                                /* Reset i/f IP addresses */
+#if INET6
+int  sif6up __P((int));                /* Configure i/f up (for IPv6) */
+int  sif6down __P((int));      /* Configure i/f down (for IPv6) */
+int  sif6addr __P((int, eui64_t, eui64_t));
+                               /* Configure IPv6 addresses for i/f */
+int  cif6addr __P((int, eui64_t, eui64_t));
+                               /* Remove an IPv6 address from i/f */
+#endif
 int  sifdefaultroute __P((int, u_int32_t, u_int32_t));
                                /* Create default route through i/f */
 int  cifdefaultroute __P((int, u_int32_t, u_int32_t));
 int  sifdefaultroute __P((int, u_int32_t, u_int32_t));
                                /* Create default route through i/f */
 int  cifdefaultroute __P((int, u_int32_t, u_int32_t));
@@ -545,6 +557,7 @@ extern struct option_info ptycommand_info;
 #define DEBUGFSM       1
 #define DEBUGLCP       1
 #define DEBUGIPCP      1
 #define DEBUGFSM       1
 #define DEBUGLCP       1
 #define DEBUGIPCP      1
+#define DEBUGIPV6CP    1
 #define DEBUGUPAP      1
 #define DEBUGCHAP      1
 #endif
 #define DEBUGUPAP      1
 #define DEBUGCHAP      1
 #endif
@@ -552,7 +565,7 @@ extern struct option_info ptycommand_info;
 #ifndef LOG_PPP                        /* we use LOG_LOCAL2 for syslog by default */
 #if defined(DEBUGMAIN) || defined(DEBUGFSM) || defined(DEBUGSYS) \
   || defined(DEBUGLCP) || defined(DEBUGIPCP) || defined(DEBUGUPAP) \
 #ifndef LOG_PPP                        /* we use LOG_LOCAL2 for syslog by default */
 #if defined(DEBUGMAIN) || defined(DEBUGFSM) || defined(DEBUGSYS) \
   || defined(DEBUGLCP) || defined(DEBUGIPCP) || defined(DEBUGUPAP) \
-  || defined(DEBUGCHAP) || defined(DEBUG)
+  || defined(DEBUGCHAP) || defined(DEBUG) || defined(DEBUGIPV6CP)
 #define LOG_PPP LOG_LOCAL2
 #else
 #define LOG_PPP LOG_DAEMON
 #define LOG_PPP LOG_LOCAL2
 #else
 #define LOG_PPP LOG_DAEMON
@@ -589,6 +602,12 @@ extern struct option_info ptycommand_info;
 #define IPCPDEBUG(x)
 #endif
 
 #define IPCPDEBUG(x)
 #endif
 
+#ifdef DEBUGIPV6CP
+#define IPV6CPDEBUG(x)  if (debug) dbglog x
+#else
+#define IPV6CPDEBUG(x)
+#endif
+
 #ifdef DEBUGUPAP
 #define UPAPDEBUG(x)   if (debug) dbglog x
 #else
 #ifdef DEBUGUPAP
 #define UPAPDEBUG(x)   if (debug) dbglog x
 #else
index c25758ed4a193294d918db76b0c07a8bfb1b1541..fedfccc02f9eb3a6c4ffb8a44f97b0021710ed31 100644 (file)
@@ -26,6 +26,7 @@
 #include <sys/file.h>
 #include <sys/stat.h>
 #include <sys/utsname.h>
 #include <sys/file.h>
 #include <sys/stat.h>
 #include <sys/utsname.h>
+#include <sys/sysmacros.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/locks.h>
 #endif
 
 #include <sys/locks.h>
 #endif
 
-#ifndef RTF_DEFAULT  /* Normally in <linux/route.h> from <net/route.h> */
-#define RTF_DEFAULT  0
+#ifdef INET6
+#ifndef _LINUX_IN6_H
+/*
+ *    This is in linux/include/net/ipv6.h.
+ */
+
+struct in6_ifreq {
+    struct in6_addr ifr6_addr;
+    __u32 ifr6_prefixlen;
+    unsigned int ifr6_ifindex;
+};
 #endif
 
 #endif
 
+#define IN6_LLADDR_FROM_EUI64(sin6, eui64) do {                        \
+       memset(&sin6.s6_addr, 0, sizeof(struct in6_addr));      \
+       sin6.s6_addr16[0] = htons(0xfe80);                      \
+       eui64_copy(eui64, sin6.s6_addr32[2]);                   \
+       } while (0)
+
+#endif /* INET6 */
+
 /* We can get an EIO error on an ioctl if the modem has hung up */
 #define ok_error(num) ((num)==EIO)
 
 /* We can get an EIO error on an ioctl if the modem has hung up */
 #define ok_error(num) ((num)==EIO)
 
@@ -102,6 +120,9 @@ static int ppp_fd = -1;             /* fd which is set to PPP discipline */
 static int sock_fd = -1;       /* socket for doing interface ioctls */
 static int slave_fd = -1;
 static int master_fd = -1;
 static int sock_fd = -1;       /* socket for doing interface ioctls */
 static int slave_fd = -1;
 static int master_fd = -1;
+#ifdef INET6
+static int sock6_fd = -1;
+#endif /* INET6 */
 static int ppp_dev_fd = -1;    /* fd for /dev/ppp (new style driver) */
 
 static fd_set in_fds;          /* set of fds that wait_input waits for */
 static int ppp_dev_fd = -1;    /* fd for /dev/ppp (new style driver) */
 
 static fd_set in_fds;          /* set of fds that wait_input waits for */
@@ -249,10 +270,14 @@ void sys_init(void)
 
     /* Get an internet socket for doing socket ioctls. */
     sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
 
     /* Get an internet socket for doing socket ioctls. */
     sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
-    if (sock_fd < 0) {
-       if ( ! ok_error ( errno ))
-           fatal("Couldn't create IP socket: %m(%d)", errno);
-    }
+    if (sock_fd < 0)
+       fatal("Couldn't create IP socket: %m(%d)", errno);
+
+#ifdef INET6
+    sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0);
+    if (sock6_fd < 0)
+       fatal("Couldn't create IPv6 socket: %m(%d)", errno);
+#endif
 
     FD_ZERO(&in_fds);
     max_in_fd = 0;
 
     FD_ZERO(&in_fds);
     max_in_fd = 0;
@@ -275,8 +300,10 @@ void sys_cleanup(void)
 /*
  * Take down the device
  */
 /*
  * Take down the device
  */
-    if (if_is_up)
+    if (if_is_up) {
+       if_is_up = 0;
        sifdown(0);
        sifdown(0);
+    }
 /*
  * Delete any routes through the device.
  */
 /*
  * Delete any routes through the device.
  */
@@ -1012,54 +1039,65 @@ int ccp_fatal_error (int unit)
     return x & SC_DC_FERROR;
 }
 
     return x & SC_DC_FERROR;
 }
 
-/*
- * path_to_route - determine the path to the proc file system data
- */
-#define ROUTE_MAX_COLS 12
-FILE *route_fd = (FILE *) 0;
-static char route_buffer [512];
-static int route_dev_col, route_dest_col, route_gw_col;
-static int route_flags_col, route_mask_col;
-static int route_num_cols;
-
-static char *path_to_route (void);
-static int open_route_table (void);
-static void close_route_table (void);
-static int read_route_table (struct rtentry *rt);
-
 /********************************************************************
  *
  * path_to_procfs - find the path to the proc file system mount point
  */
 /********************************************************************
  *
  * path_to_procfs - find the path to the proc file system mount point
  */
+static char proc_path[MAXPATHLEN];
+static int proc_path_len;
 
 
-static int path_to_procfs (const char *tail)
+static char *path_to_procfs(const char *tail)
 {
     struct mntent *mntent;
     FILE *fp;
 
 {
     struct mntent *mntent;
     FILE *fp;
 
-    fp = fopen(MOUNTED, "r");
-    if (fp == NULL) {
-       /* Default the mount location of /proc */
-       strlcpy (route_buffer, "/proc", sizeof (route_buffer));
-       strlcat (route_buffer, tail, sizeof(route_buffer));
-       return 1;
-    }
+    if (proc_path_len == 0) {
+       fp = fopen(MOUNTED, "r");
+       if (fp == NULL) {
+           /* Default the mount location of /proc */
+           strlcpy (proc_path, "/proc", sizeof(proc_path));
+           proc_path_len = 5;
 
 
-    while ((mntent = getmntent(fp)) != NULL) {
-       if (strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0)
-           continue;
-       if (strcmp(mntent->mnt_type, "proc") == 0)
-           break;
+       } else {
+           while ((mntent = getmntent(fp)) != NULL) {
+               if (strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0)
+                   continue;
+               if (strcmp(mntent->mnt_type, "proc") == 0)
+                   break;
+           }
+           fclose (fp);
+           if (mntent == 0)
+               proc_path_len = -1;
+           else {
+               strlcpy(proc_path, mntent->mnt_dir, sizeof(proc_path));
+               proc_path_len = strlen(proc_path);
+           }
+       }
     }
     }
-    fclose (fp);
-    if (mntent == 0)
+
+    if (proc_path_len < 0)
        return 0;
 
        return 0;
 
-    strlcpy(route_buffer, mntent->mnt_dir, sizeof (route_buffer));
-    strlcat (route_buffer, tail, sizeof(route_buffer));
-    return 1;
+    strlcpy(proc_path + proc_path_len, tail,
+           sizeof(proc_path) - proc_path_len);
+    return proc_path;
 }
 
 }
 
+/*
+ * path_to_route - determine the path to the proc file system data
+ */
+#define ROUTE_MAX_COLS 12
+FILE *route_fd = (FILE *) 0;
+static char route_buffer[512];
+static int route_dev_col, route_dest_col, route_gw_col;
+static int route_flags_col, route_mask_col;
+static int route_num_cols;
+
+static char *path_to_route (void);
+static int open_route_table (void);
+static void close_route_table (void);
+static int read_route_table (struct rtentry *rt);
+
 /********************************************************************
  *
  * path_to_route - find the path to the route tables in the proc file system
 /********************************************************************
  *
  * path_to_route - find the path to the route tables in the proc file system
@@ -1067,11 +1105,12 @@ static int path_to_procfs (const char *tail)
 
 static char *path_to_route (void)
 {
 
 static char *path_to_route (void)
 {
-    if (!path_to_procfs("/net/route")) {
+    char *path;
+
+    path = path_to_procfs("/net/route");
+    if (path == 0)
        error("proc file system not mounted");
        error("proc file system not mounted");
-       return 0;
-    }
-    return (route_buffer);
+    return path;
 }
 
 /********************************************************************
 }
 
 /********************************************************************
@@ -1268,7 +1307,7 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
 
     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
     
 
     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
     
-    rt.rt_flags = RTF_UP | RTF_GATEWAY | RTF_DEFAULT;
+    rt.rt_flags = RTF_UP | RTF_GATEWAY;
     if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
        if ( ! ok_error ( errno ))
            error("default route ioctl(SIOCADDRT): %m(%d)", errno);
     if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
        if ( ! ok_error ( errno ))
            error("default route ioctl(SIOCADDRT): %m(%d)", errno);
@@ -1301,7 +1340,7 @@ int cifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
 
     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
     
 
     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
     
-    rt.rt_flags = RTF_UP | RTF_GATEWAY | RTF_DEFAULT;
+    rt.rt_flags = RTF_UP | RTF_GATEWAY;
     if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
        if (still_ppp()) {
            if ( ! ok_error ( errno ))
     if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
        if (still_ppp()) {
            if ( ! ok_error ( errno ))
@@ -1321,6 +1360,7 @@ int cifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
 int sifproxyarp (int unit, u_int32_t his_adr)
 {
     struct arpreq arpreq;
 int sifproxyarp (int unit, u_int32_t his_adr)
 {
     struct arpreq arpreq;
+    char *forw_path;
 
     if (has_proxy_arp == 0) {
        memset (&arpreq, '\0', sizeof(arpreq));
 
     if (has_proxy_arp == 0) {
        memset (&arpreq, '\0', sizeof(arpreq));
@@ -1346,6 +1386,15 @@ int sifproxyarp (int unit, u_int32_t his_adr)
        }
        proxy_arp_addr = his_adr;
        has_proxy_arp = 1;
        }
        proxy_arp_addr = his_adr;
        has_proxy_arp = 1;
+
+       forw_path = path_to_procfs("/sys/net/ipv4/ip_forward");
+       if (forw_path != 0) {
+           int fd = open(forw_path, O_WRONLY);
+           if (fd >= 0) {
+               write(fd, "1", 1);
+               close(fd);
+           }
+       }
     }
 
     return 1;
     }
 
     return 1;
@@ -1848,7 +1897,7 @@ int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
  * sifup - Config the interface up and enable IP packets to pass.
  */
 
  * sifup - Config the interface up and enable IP packets to pass.
  */
 
-int sifup (int u)
+int sifup(int u)
 {
     struct ifreq ifr;
 
 {
     struct ifreq ifr;
 
@@ -1866,20 +1915,23 @@ int sifup (int u)
            error("ioctl(SIOCSIFFLAGS): %m(%d)", errno);
        return 0;
     }
            error("ioctl(SIOCSIFFLAGS): %m(%d)", errno);
        return 0;
     }
-    if_is_up = 1;
+    if_is_up++;
+
     return 1;
 }
 
 /********************************************************************
  *
     return 1;
 }
 
 /********************************************************************
  *
- * sifdown - Config the interface down and disable IP.
+ * sifdown - Disable the indicated protocol and config the interface
+ *          down if there are no remaining protocols.
  */
 
 int sifdown (int u)
 {
     struct ifreq ifr;
 
  */
 
 int sifdown (int u)
 {
     struct ifreq ifr;
 
-    if_is_up = 0;
+    if (if_is_up && --if_is_up > 0)
+       return 1;
 
     memset (&ifr, '\0', sizeof (ifr));
     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
 
     memset (&ifr, '\0', sizeof (ifr));
     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
@@ -1989,12 +2041,13 @@ int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
 
 int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
 {
 
 int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
 {
-    struct rtentry rt;
+    struct ifreq ifr;
 
     if (kernel_version < KVERSION(2,1,16)) {
 /*
  *  Delete the route through the device
  */
 
     if (kernel_version < KVERSION(2,1,16)) {
 /*
  *  Delete the route through the device
  */
+       struct rtentry rt;
        memset (&rt, '\0', sizeof (rt));
 
        SET_SA_FAMILY (rt.rt_dst,     AF_INET);
        memset (&rt, '\0', sizeof (rt));
 
        SET_SA_FAMILY (rt.rt_dst,     AF_INET);
@@ -2016,8 +2069,102 @@ int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
            return (0);
        }
     }
            return (0);
        }
     }
+
+    /* This way it is possible to have an IPX-only or IPv6-only interface */
+    memset(&ifr, 0, sizeof(ifr));
+    SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
+    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+    
+    if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
+       if (! ok_error (errno)) {
+           error("ioctl(SIOCSIFADDR): %m(%d)", errno);
+           return 0;
+       }
+    }
+
+    return 1;
+}
+
+#ifdef INET6
+/********************************************************************
+ * 
+ * sif6addr - Config the interface with an IPv6 link-local address
+ */
+int sif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
+{
+    struct in6_ifreq ifr6;
+    struct ifreq ifr;
+    struct in6_rtmsg rt6;
+
+    memset(&ifr, 0, sizeof (ifr));
+    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+    if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
+       error("sif6addr: ioctl(SIOCGIFINDEX): %m (%d)", errno);
+       return 0;
+    }
+    
+    /* Local interface */
+    memset(&ifr6, 0, sizeof(ifr6));
+    IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
+    ifr6.ifr6_ifindex = ifr.ifr_ifindex;
+    ifr6.ifr6_prefixlen = 10;
+
+    if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6) < 0) {
+       error("sif6addr: ioctl(SIOCSIFADDR): %m (%d)", errno);
+       return 0;
+    }
+    
+    /* Route to remote host */
+    memset(&rt6, 0, sizeof(rt6));
+    IN6_LLADDR_FROM_EUI64(rt6.rtmsg_dst, his_eui64);
+    rt6.rtmsg_flags = RTF_UP | RTF_HOST;
+    rt6.rtmsg_dst_len = 128;
+    rt6.rtmsg_ifindex = ifr.ifr_ifindex;
+    rt6.rtmsg_metric = 1;
+    
+    if (ioctl(sock6_fd, SIOCADDRT, &rt6) < 0) {
+       error("sif6addr: ioctl(SIOCADDRT): %m (%d)", errno);
+       return 0;
+    }
+
+    return 1;
+}
+
+
+/********************************************************************
+ *
+ * cif6addr - Remove IPv6 address from interface
+ */
+int cif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
+{
+    struct ifreq ifr;
+    struct in6_ifreq ifr6;
+
+    memset(&ifr, 0, sizeof(ifr));
+    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+    if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
+       error("cif6addr: ioctl(SIOCGIFINDEX): %m (%d)", errno);
+       return 0;
+    }
+    
+    memset(&ifr6, 0, sizeof(ifr6));
+    IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
+    ifr6.ifr6_ifindex = ifr.ifr_ifindex;
+    ifr6.ifr6_prefixlen = 10;
+
+    if (ioctl(sock6_fd, SIOCDIFADDR, &ifr6) < 0) {
+       if (errno != EADDRNOTAVAIL) {
+           if (! ok_error (errno))
+               error("cif6addr: ioctl(SIOCDIFADDR): %m (%d)", errno);
+       }
+        else {
+           warn("cif6addr: ioctl(SIOCDIFADDR): No such address");
+       }
+        return (0);
+    }
     return 1;
 }
     return 1;
 }
+#endif /* INET6 */
 
 /*
  * get_pty - get a pty master/slave pair and chown the slave side
 
 /*
  * get_pty - get a pty master/slave pair and chown the slave side
@@ -2163,7 +2310,7 @@ void
 restore_loop(void)
 {
     if (new_style_driver) {
 restore_loop(void)
 {
     if (new_style_driver) {
-       set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) & SC_LOOP_TRAFFIC);
+       set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) | SC_LOOP_TRAFFIC);
        return;
     }
     if (ppp_fd != slave_fd) {
        return;
     }
     if (ppp_fd != slave_fd) {
@@ -2318,10 +2465,13 @@ sys_check_options(void)
 /*
  * Disable the IPX protocol if the support is not present in the kernel.
  */
 /*
  * Disable the IPX protocol if the support is not present in the kernel.
  */
+    char *path;
+    int fd;
+
     if (ipxcp_protent.enabled_flag) {
        struct stat stat_buf;
     if (ipxcp_protent.enabled_flag) {
        struct stat stat_buf;
-        if (!path_to_procfs("/net/ipx_interface")
-           || lstat (route_buffer, &stat_buf) < 0) {
+        if ((path = path_to_procfs("/net/ipx_interface")) == 0
+           || lstat(path, &stat_buf) < 0) {
            error("IPX support is not present in the kernel\n");
            ipxcp_protent.enabled_flag = 0;
        }
            error("IPX support is not present in the kernel\n");
            ipxcp_protent.enabled_flag = 0;
        }
@@ -2333,5 +2483,13 @@ sys_check_options(void)
                     driver_patch);
        return 0;
     }
                     driver_patch);
        return 0;
     }
+    if (demand) {
+       /* set ip_dynaddr if possible */
+       path = path_to_procfs("/sys/net/ipv4/ip_dynaddr");
+       if (path != 0 && (fd = open(path, O_WRONLY)) >= 0) {
+           write(fd, "1", 1);
+           close(fd);
+       }
+    }
     return 1;
 }
     return 1;
 }