From: Paul Mackerras Date: Tue, 24 Aug 1999 05:31:12 +0000 (+0000) Subject: Rest of IPV6 merge which got lost somehow, plus some minor fixes. X-Git-Tag: ppp-2.4.7~649 X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=2e53641535da26bf8c3c424172758ed81d908581 Rest of IPV6 merge which got lost somehow, plus some minor fixes. --- diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux index 67c012c..bf2bcc5 100644 --- a/pppd/Makefile.linux +++ b/pppd/Makefile.linux @@ -1,6 +1,6 @@ # # 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 @@ -44,6 +44,7 @@ endif HAS_SHADOW=y #USE_PAM=y +#HAVE_INET6=y INCLUDE_DIRS= -I../include @@ -84,6 +85,14 @@ LIBS := -llock $(LIBS) 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 diff --git a/pppd/ipcp.c b/pppd/ipcp.c index d3682a0..a652cbb 100644 --- a/pppd/ipcp.c +++ b/pppd/ipcp.c @@ -17,7 +17,7 @@ * 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: @@ -1307,17 +1307,6 @@ ip_check_options() 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]; + 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)) @@ -1545,6 +1545,7 @@ ipcp_down(f) 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); diff --git a/pppd/ipv6cp.c b/pppd/ipv6cp.c index 94f2f67..38cb22b 100644 --- a/pppd/ipv6cp.c +++ b/pppd/ipv6cp.c @@ -21,14 +21,14 @@ * 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 */ -#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: @@ -46,6 +46,7 @@ #include #include #include +#include #include "pppd.h" #include "fsm.h" @@ -202,8 +203,8 @@ setifaceid(arg) 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); @@ -955,13 +956,13 @@ ipv6_demand_conf(u) 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__))) - if (!sifup(u, PPP_IPV6)) + if (!sifup(u)) return 0; #endif if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE)) @@ -1063,7 +1064,7 @@ ipv6cp_up(f) #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"); @@ -1126,11 +1127,12 @@ ipv6cp_down(f) 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))) - sifdown(f->unit, PPP_IPV6); + sifdown(f->unit); #endif } diff --git a/pppd/ipxcp.c b/pppd/ipxcp.c index 937dea1..8b45f89 100644 --- a/pppd/ipxcp.c +++ b/pppd/ipxcp.c @@ -19,7 +19,7 @@ #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: @@ -1266,6 +1266,7 @@ ipxcp_up(f) 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)) { @@ -1275,7 +1276,6 @@ ipxcp_up(f) return; } - ipxcp_is_up = 1; np_up(f->unit, PPP_IPX); /* @@ -1299,11 +1299,12 @@ ipxcp_down(f) { 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); } diff --git a/pppd/main.c b/pppd/main.c index 4da0b9a..e484069 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -17,7 +17,7 @@ * 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 #include @@ -46,6 +46,9 @@ #include "fsm.h" #include "lcp.h" #include "ipcp.h" +#ifdef INET6 +#include "ipv6cp.h" +#endif #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 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 *)); @@ -194,6 +197,9 @@ struct protent *protocols[] = { &cbcp_protent, #endif &ipcp_protent, +#ifdef INET6 + &ipv6cp_protent, +#endif &ccp_protent, #ifdef IPX_CHANGE &ipxcp_protent, @@ -251,6 +257,12 @@ main(argc, argv) 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, @@ -373,10 +385,9 @@ main(argc, argv) script_setenv("DEVICE", devnam); /* - * Initialize system-dependent stuff and magic number package. + * Initialize system-dependent stuff. */ sys_init(); - magic_init(); if (debug) setlogmask(LOG_UPTO(LOG_DEBUG)); @@ -814,6 +825,18 @@ main(argc, argv) 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 @@ -905,7 +928,8 @@ main(argc, argv) 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); @@ -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. */ -static void +static int reap_kids(waitfor) int waitfor; { @@ -1695,8 +1719,13 @@ reap_kids(waitfor) 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; } diff --git a/pppd/pppd.8 b/pppd/pppd.8 index be3fcab..67b5d32 100644 --- a/pppd/pppd.8 +++ b/pppd/pppd.8 @@ -1,5 +1,5 @@ .\" 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 @@ -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 -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 -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 @@ -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 +.B ipv6 \fI\fR,\fI +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 @@ -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 +.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 @@ -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 +.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 @@ -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 +.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 @@ -1354,6 +1396,11 @@ 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 diff --git a/pppd/pppd.h b/pppd/pppd.h index 2e7c5ca..8e4472b 100644 --- a/pppd/pppd.h +++ b/pppd/pppd.h @@ -16,7 +16,7 @@ * 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 $ */ /* @@ -43,6 +43,10 @@ #define volatile #endif +#if INET6 +#include "eui64.h" +#endif + /* * 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 */ -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 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)); - /* 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 */ +#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)); @@ -545,6 +557,7 @@ extern struct option_info ptycommand_info; #define DEBUGFSM 1 #define DEBUGLCP 1 #define DEBUGIPCP 1 +#define DEBUGIPV6CP 1 #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) \ - || defined(DEBUGCHAP) || defined(DEBUG) + || defined(DEBUGCHAP) || defined(DEBUG) || defined(DEBUGIPV6CP) #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 +#ifdef DEBUGIPV6CP +#define IPV6CPDEBUG(x) if (debug) dbglog x +#else +#define IPV6CPDEBUG(x) +#endif + #ifdef DEBUGUPAP #define UPAPDEBUG(x) if (debug) dbglog x #else diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c index c25758e..fedfccc 100644 --- a/pppd/sys-linux.c +++ b/pppd/sys-linux.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -88,10 +89,27 @@ #include #endif -#ifndef RTF_DEFAULT /* Normally in from */ -#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 +#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) @@ -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; +#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 */ @@ -249,10 +270,14 @@ void sys_init(void) /* 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; @@ -275,8 +300,10 @@ void sys_cleanup(void) /* * Take down the device */ - if (if_is_up) + if (if_is_up) { + if_is_up = 0; sifdown(0); + } /* * Delete any routes through the device. */ @@ -1012,54 +1039,65 @@ int ccp_fatal_error (int unit) 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 */ +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; - 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; - 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 @@ -1067,11 +1105,12 @@ static int path_to_procfs (const char *tail) 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"); - 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; - 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); @@ -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; - 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 )) @@ -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; + char *forw_path; 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; + + 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; @@ -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. */ -int sifup (int u) +int sifup(int u) { struct ifreq ifr; @@ -1866,20 +1915,23 @@ int sifup (int u) error("ioctl(SIOCSIFFLAGS): %m(%d)", errno); return 0; } - if_is_up = 1; + if_is_up++; + 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; - 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)); @@ -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) { - struct rtentry rt; + struct ifreq ifr; 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); @@ -2016,8 +2069,102 @@ int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr) 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; } +#endif /* INET6 */ /* * 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) { - 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) { @@ -2318,10 +2465,13 @@ sys_check_options(void) /* * 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 (!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; } @@ -2333,5 +2483,13 @@ sys_check_options(void) 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; }