#
# 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
HAS_SHADOW=y
#USE_PAM=y
+#HAVE_INET6=y
INCLUDE_DIRS= -I../include
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
* 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:
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
}
{
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 (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);
* 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>
*/
-#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:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include "pppd.h"
#include "fsm.h"
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);
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))
#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");
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
}
#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:
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)) {
return;
}
- ipxcp_is_up = 1;
np_up(f->unit, PPP_IPX);
/*
{
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);
}
* 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 "fsm.h"
#include "lcp.h"
#include "ipcp.h"
+#ifdef INET6
+#include "ipv6cp.h"
+#endif
#include "upap.h"
#include "chap.h"
#include "ccp.h"
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 *));
&cbcp_protent,
#endif
&ipcp_protent,
+#ifdef INET6
+ &ipv6cp_protent,
+#endif
&ccp_protent,
#ifdef IPX_CHANGE
&ipxcp_protent,
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,
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));
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
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);
* 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;
{
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;
}
.\" 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
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
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
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
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
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
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
* 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
+#if INET6
+#include "eui64.h"
+#endif
+
/*
* Limits.
*/
/* 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));
#define DEBUGFSM 1
#define DEBUGLCP 1
#define DEBUGIPCP 1
+#define DEBUGIPV6CP 1
#define DEBUGUPAP 1
#define DEBUGCHAP 1
#endif
#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 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
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/utsname.h>
+#include <sys/sysmacros.h>
#include <stdio.h>
#include <stdlib.h>
#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
+#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)
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 */
/* 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;
/*
* Take down the device
*/
- if (if_is_up)
+ if (if_is_up) {
+ if_is_up = 0;
sifdown(0);
+ }
/*
* Delete any routes through the device.
*/
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
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;
}
/********************************************************************
((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);
((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 ))
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));
}
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;
* sifup - Config the interface up and enable IP packets to pass.
*/
-int sifup (int u)
+int sifup(int u)
{
struct ifreq ifr;
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));
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);
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
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) {
/*
* 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;
}
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;
}