#include "pppd.h"
#include "fsm.h"
#include "ipcp.h"
-#include "patchlevel.h"
#ifdef IPX_CHANGE
#include "ipxcp.h"
#endif
#endif /* IPX_CHANGE */
+#ifdef PPP_FILTER
+#include <net/bpf.h>
+#include <linux/filter.h>
+#endif /* PPP_FILTER */
+
#ifdef LOCKLIB
#include <sys/locks.h>
#endif
static int sock6_fd = -1;
#endif /* INET6 */
static int ppp_dev_fd = -1; /* fd for /dev/ppp (new style driver) */
+static int chindex; /* channel index (new style driver) */
static fd_set in_fds; /* set of fds that wait_input waits for */
static int max_in_fd; /* highest fd set in in_fds */
static u_int32_t our_old_addr; /* for detecting address changes */
static int dynaddr_set; /* 1 if ip_dynaddr set */
static int looped; /* 1 if using loop */
+static int link_mtu; /* mtu for the link (not bundle) */
static struct utsname utsname; /* for the kernel version */
static int kernel_version;
static void set_flags (int fd, int flags);
static int translate_speed (int bps);
static int baud_rate_of (int speed);
-static char *path_to_route (void);
static void close_route_table (void);
static int open_route_table (void);
static int read_route_table (struct rtentry *rt);
static void decode_version (char *buf, int *version, int *mod, int *patch);
static int set_kdebugflag(int level);
static int ppp_registered(void);
+static int make_ppp_unit(void);
extern u_char inpacket_buf[]; /* borrowed from main.c */
#ifdef INET6
sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0);
if (sock6_fd < 0)
- fatal("Couldn't create IPv6 socket: %m(%d)", errno);
+ sock6_fd = -errno; /* save errno for later */
#endif
FD_ZERO(&in_fds);
static int set_kdebugflag (int requested_level)
{
+ if (new_style_driver && ifunit < 0)
+ return 1;
if (ioctl(ppp_dev_fd, PPPIOCSDEBUG, &requested_level) < 0) {
if ( ! ok_error (errno) )
error("ioctl(PPPIOCSDEBUG): %m");
int establish_ppp (int tty_fd)
{
int x;
+ int fd = -1;
-/*
- * The current PPP device will be the tty file.
- */
- set_ppp_fd (tty_fd);
/*
* Ensure that the tty device is in exclusive mode.
*/
if (ioctl(tty_fd, TIOCEXCL, 0) < 0) {
if ( ! ok_error ( errno ))
- warn("ioctl(TIOCEXCL): %m");
+ warn("Couldn't make tty exclusive: %m");
}
/*
* Demand mode - prime the old ppp device to relinquish the unit.
*/
if (!new_style_driver && looped
- && ioctl(slave_fd, PPPIOCXFERUNIT, 0) < 0)
- fatal("ioctl(transfer ppp unit): %m(%d)", errno);
+ && ioctl(slave_fd, PPPIOCXFERUNIT, 0) < 0) {
+ error("ioctl(transfer ppp unit): %m");
+ return -1;
+ }
/*
* Set the current tty to the PPP discpline
*/
#ifndef N_SYNC_PPP
#define N_SYNC_PPP 14
#endif
- if (new_style_driver)
- ppp_disc = sync_serial ? N_SYNC_PPP:N_PPP;
-
+ ppp_disc = (new_style_driver && sync_serial)? N_SYNC_PPP: N_PPP;
if (ioctl(tty_fd, TIOCSETD, &ppp_disc) < 0) {
- if ( ! ok_error (errno) )
- fatal("ioctl(TIOCSETD): %m(%d)", errno);
+ if ( ! ok_error (errno) ) {
+ error("Couldn't set tty to PPP discipline: %m");
+ return -1;
+ }
}
-/*
- * Find out which interface we were given.
- */
+
if (new_style_driver) {
- if (!looped) {
- /* allocate ourselves a ppp unit */
+ /* Open another instance of /dev/ppp and connect the channel to it */
+ int flags;
+
+ if (ioctl(tty_fd, PPPIOCGCHAN, &chindex) == -1) {
+ error("Couldn't get channel number: %m");
+ goto err;
+ }
+ dbglog("using channel %d", chindex);
+ fd = open("/dev/ppp", O_RDWR);
+ if (fd < 0) {
+ error("Couldn't reopen /dev/ppp: %m");
+ goto err;
+ }
+ if (ioctl(fd, PPPIOCATTCHAN, &chindex) < 0) {
+ error("Couldn't attach to channel %d: %m", chindex);
+ goto err_close;
+ }
+ flags = fcntl(fd, F_GETFL);
+ if (flags == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
+ warn("Couldn't set /dev/ppp (channel) to nonblock: %m");
+ set_ppp_fd(fd);
+
+ if (!looped)
ifunit = -1;
- if (ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit) < 0)
- fatal("Couldn't create new ppp unit: %m");
- set_kdebugflag(kdebugflag);
- } else {
- set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) & ~SC_LOOP_TRAFFIC);
+ if (!looped && !multilink) {
+ /*
+ * Create a new PPP unit.
+ */
+ if (make_ppp_unit() < 0)
+ goto err_close;
}
- if (ioctl(tty_fd, PPPIOCATTACH, &ifunit) < 0) {
- if (errno == EIO)
- return -1;
- fatal("Couldn't attach tty to PPP unit %d: %m", ifunit);
+
+ if (looped)
+ set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) & ~SC_LOOP_TRAFFIC);
+
+ if (!multilink) {
+ add_fd(ppp_dev_fd);
+ if (ioctl(fd, PPPIOCCONNECT, &ifunit) < 0) {
+ error("Couldn't attach to PPP unit %d: %m", ifunit);
+ goto err_close;
+ }
}
+
} else {
+ /*
+ * Old-style driver: find out which interface we were given.
+ */
+ set_ppp_fd (tty_fd);
if (ioctl(tty_fd, PPPIOCGUNIT, &x) < 0) {
- if ( ! ok_error (errno))
- fatal("ioctl(PPPIOCGUNIT): %m(%d)", errno);
+ if (ok_error (errno))
+ goto err;
+ fatal("ioctl(PPPIOCGUNIT): %m(%d)", errno);
}
/* Check that we got the same unit again. */
if (looped && x != ifunit)
fatal("transfer_ppp failed: wanted unit %d, got %d", ifunit, x);
ifunit = x;
+
+ /*
+ * Fetch the initial file flags and reset blocking mode on the file.
+ */
+ initfdflags = fcntl(tty_fd, F_GETFL);
+ if (initfdflags == -1 ||
+ fcntl(tty_fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
+ if ( ! ok_error (errno))
+ warn("Couldn't set device to non-blocking mode: %m");
+ }
}
-/*
- * Enable debug in the driver if requested.
- */
+ looped = 0;
+
+ /*
+ * Enable debug in the driver if requested.
+ */
if (!looped)
set_kdebugflag (kdebugflag);
- looped = 0;
- set_flags(tty_fd, get_flags(tty_fd) & ~(SC_RCV_B7_0 | SC_RCV_B7_1 |
+ set_flags(ppp_fd, get_flags(ppp_fd) & ~(SC_RCV_B7_0 | SC_RCV_B7_1 |
SC_RCV_EVNP | SC_RCV_ODDP));
SYSDEBUG ((LOG_NOTICE, "Using version %d.%d.%d of PPP driver",
driver_version, driver_modification, driver_patch));
-/*
- * Fetch the initial file flags and reset blocking mode on the file.
- */
- initfdflags = fcntl(tty_fd, F_GETFL);
- if (initfdflags == -1 ||
- fcntl(tty_fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
- if ( ! ok_error (errno))
- warn("Couldn't set device to non-blocking mode: %m");
- }
+ return ppp_fd;
- return ppp_dev_fd;
+ err_close:
+ close(fd);
+ err:
+ if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0 && !ok_error(errno))
+ warn("Couldn't reset tty to normal line discipline: %m");
+ return -1;
}
/********************************************************************
}
}
initfdflags = -1;
- if (new_style_driver && !looped) {
- if (ioctl(ppp_dev_fd, PPPIOCDETACH) < 0) {
- if (errno == ENOTTY) {
- /* first version of new driver didn't have PPPIOCDETACH */
- int flags;
-
- close(ppp_dev_fd);
- ppp_dev_fd = open("/dev/ppp", O_RDWR);
- if (ppp_dev_fd < 0)
- fatal("Couldn't reopen /dev/ppp: %m");
- flags = fcntl(ppp_dev_fd, F_GETFL);
- if (flags == -1
- || fcntl(ppp_dev_fd, F_SETFL, flags | O_NONBLOCK) == -1)
- warn("Couldn't set /dev/ppp to nonblock: %m");
- } else
- error("Couldn't release PPP unit: %m");
- }
- set_ppp_fd(-1);
+
+ if (new_style_driver) {
+ close(ppp_fd);
+ ppp_fd = -1;
+ if (!looped && ifunit >= 0 && ioctl(ppp_dev_fd, PPPIOCDETACH) < 0)
+ error("Couldn't release PPP unit: %m");
+ if (!multilink)
+ remove_fd(ppp_dev_fd);
}
}
+/*
+ * make_ppp_unit - make a new ppp unit for ppp_dev_fd.
+ * Assumes new_style_driver.
+ */
+static int make_ppp_unit()
+{
+ int x;
+
+ ifunit = req_unit;
+ x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
+ if (x < 0 && req_unit >= 0 && errno == EEXIST) {
+ warn("Couldn't allocate PPP unit %d as it is already in use");
+ ifunit = -1;
+ x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
+ }
+ if (x < 0)
+ error("Couldn't create new ppp unit: %m");
+ return x;
+}
+
+/*
+ * cfg_bundle - configure the existing bundle.
+ * Used in demand mode.
+ */
+void cfg_bundle(int mrru, int mtru, int rssn, int tssn)
+{
+ int flags;
+
+ if (!new_style_driver)
+ return;
+
+ /* set the mrru, mtu and flags */
+ if (ioctl(ppp_dev_fd, PPPIOCSMRRU, &mrru) < 0)
+ error("Couldn't set MRRU: %m");
+ flags = get_flags(ppp_dev_fd);
+ flags &= ~(SC_MP_SHORTSEQ | SC_MP_XSHORTSEQ);
+ flags |= (rssn? SC_MP_SHORTSEQ: 0) | (tssn? SC_MP_XSHORTSEQ: 0)
+ | (mrru? SC_MULTILINK: 0);
+
+ set_flags(ppp_dev_fd, flags);
+
+ /* connect up the channel */
+ if (ioctl(ppp_fd, PPPIOCCONNECT, &ifunit) < 0)
+ fatal("Couldn't attach to PPP unit %d: %m", ifunit);
+ add_fd(ppp_dev_fd);
+}
+
+/*
+ * make_new_bundle - create a new PPP unit (i.e. a bundle)
+ * and connect our channel to it. This should only get called
+ * if `multilink' was set at the time establish_ppp was called.
+ * In demand mode this uses our existing bundle instead of making
+ * a new one.
+ */
+void make_new_bundle(int mrru, int mtru, int rssn, int tssn)
+{
+ if (!new_style_driver)
+ return;
+
+ /* make us a ppp unit */
+ if (make_ppp_unit() < 0)
+ die(1);
+
+ /* set the mrru and flags */
+ cfg_bundle(mrru, mtru, rssn, tssn);
+}
+
+/*
+ * bundle_attach - attach our link to a given PPP unit.
+ * We assume the unit is controlled by another pppd.
+ */
+int bundle_attach(int ifnum)
+{
+ if (!new_style_driver)
+ return -1;
+
+ if (ioctl(ppp_dev_fd, PPPIOCATTACH, &ifnum) < 0) {
+ if (errno == ENXIO)
+ return 0; /* doesn't still exist */
+ fatal("Couldn't attach to interface unit %d: %m\n", ifnum);
+ }
+ if (ioctl(ppp_fd, PPPIOCCONNECT, &ifnum) < 0)
+ fatal("Couldn't connect to interface unit %d: %m", ifnum);
+ set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) | SC_MULTILINK);
+
+ ifunit = ifnum;
+ return 1;
+}
+
/********************************************************************
*
* clean_check - Fetch the flags for the device and generate
#ifdef B57600
{ 57600, B57600 },
#endif
+#ifdef B76800
+ { 76800, B76800 },
+#endif
#ifdef B115200
{ 115200, B115200 },
#endif
#endif
#ifdef B460800
{ 460800, B460800 },
+#endif
+#ifdef B921600
+ { 921600, B921600 },
#endif
{ 0, 0 }
};
void output (int unit, unsigned char *p, int len)
{
+ int fd = ppp_fd;
+ int proto;
+
if (debug)
dbglog("sent %P", p, len);
if (new_style_driver) {
p += 2;
len -= 2;
+ proto = (p[0] << 8) + p[1];
+ if (ifunit >= 0 && !(proto >= 0xc000 || proto == PPP_CCPFRAG))
+ fd = ppp_dev_fd;
}
- if (write(ppp_dev_fd, p, len) < 0) {
+ if (write(fd, p, len) < 0) {
if (errno == EWOULDBLOCK || errno == ENOBUFS
|| errno == ENXIO || errno == EIO || errno == EINTR)
warn("write: warning: %m (%d)", errno);
void wait_input(struct timeval *timo)
{
- fd_set ready;
+ fd_set ready, exc;
int n;
ready = in_fds;
- n = select(max_in_fd + 1, &ready, NULL, &ready, timo);
+ exc = in_fds;
+ n = select(max_in_fd + 1, &ready, NULL, &exc, timo);
if (n < 0 && errno != EINTR)
fatal("select: %m(%d)", errno);
}
int read_packet (unsigned char *buf)
{
- int len;
+ int len, nr;
len = PPP_MRU + PPP_HDRLEN;
if (new_style_driver) {
*buf++ = PPP_UI;
len -= 2;
}
- len = read(ppp_dev_fd, buf, len);
- if (len < 0) {
- if (errno == EWOULDBLOCK || errno == EIO)
- return -1;
- fatal("read: %m(%d)", errno);
+ nr = -1;
+ if (ppp_fd >= 0) {
+ nr = read(ppp_fd, buf, len);
+ if (nr < 0 && errno != EWOULDBLOCK && errno != EIO && errno != EINTR)
+ error("read: %m");
}
- return new_style_driver? len+2: len;
+ if (nr < 0 && new_style_driver && ifunit >= 0) {
+ /* N.B. we read ppp_fd first since LCP packets come in there. */
+ nr = read(ppp_dev_fd, buf, len);
+ if (nr < 0 && errno != EWOULDBLOCK && errno != EIO && errno != EINTR)
+ error("read /dev/ppp: %m");
+ }
+ return (new_style_driver && nr > 0)? nr+2: nr;
}
/********************************************************************
return rv;
}
+/*
+ * netif_set_mtu - set the MTU on the PPP network interface.
+ */
+void
+netif_set_mtu(int unit, int mtu)
+{
+ struct ifreq ifr;
+
+ SYSDEBUG ((LOG_DEBUG, "netif_set_mtu: mtu = %d\n", mtu));
+
+ memset (&ifr, '\0', sizeof (ifr));
+ strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+ ifr.ifr_mtu = mtu;
+
+ if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
+ fatal("ioctl(SIOCSIFMTU): %m(%d)", errno);
+}
+
/********************************************************************
*
- * ppp_send_config - configure the transmit characteristics of
+ * tty_send_config - configure the transmit characteristics of
* the ppp interface.
*/
-void ppp_send_config (int unit,int mtu,u_int32_t asyncmap,int pcomp,int accomp)
+void tty_send_config (int mtu,u_int32_t asyncmap,int pcomp,int accomp)
{
u_int x;
- struct ifreq ifr;
-
- SYSDEBUG ((LOG_DEBUG, "send_config: mtu = %d\n", mtu));
+
/*
- * Set the MTU and other parameters for the ppp device
+ * Set the asyncmap and other parameters for the ppp device
*/
- memset (&ifr, '\0', sizeof (ifr));
- strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
- ifr.ifr_mtu = mtu;
-
- if (ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
- fatal("ioctl(SIOCSIFMTU): %m(%d)", errno);
-
if (!still_ppp())
return;
+ link_mtu = mtu;
SYSDEBUG ((LOG_DEBUG, "send_config: asyncmap = %lx\n", asyncmap));
if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
if (!ok_error(errno))
/********************************************************************
*
- * ppp_set_xaccm - set the extended transmit ACCM for the interface.
+ * tty_set_xaccm - set the extended transmit ACCM for the interface.
*/
-void ppp_set_xaccm (int unit, ext_accm accm)
+void tty_set_xaccm (ext_accm accm)
{
SYSDEBUG ((LOG_DEBUG, "set_xaccm: %08lx %08lx %08lx %08lx\n",
accm[0], accm[1], accm[2], accm[3]));
/********************************************************************
*
- * ppp_recv_config - configure the receive-side characteristics of
+ * tty_recv_config - configure the receive-side characteristics of
* the ppp interface.
*/
-void ppp_recv_config (int unit,int mru,u_int32_t asyncmap,int pcomp,int accomp)
+void tty_recv_config (int mru,u_int32_t asyncmap,int pcomp,int accomp)
{
SYSDEBUG ((LOG_DEBUG, "recv_config: mru = %d\n", mru));
/*
if ( ! ok_error (errno))
error("ioctl(PPPIOCSMRU): %m(%d)", errno);
}
- if (new_style_driver && ioctl(ppp_dev_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
+ if (new_style_driver && ifunit >= 0
+ && ioctl(ppp_dev_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
error("Couldn't set MRU in generic PPP layer: %m");
SYSDEBUG ((LOG_DEBUG, "recv_config: asyncmap = %lx\n", asyncmap));
}
}
+#ifdef PPP_FILTER
+/*
+ * set_filters - set the active and pass filters in the kernel driver.
+ */
+int set_filters(struct bpf_program *pass, struct bpf_program *active)
+{
+ struct sock_fprog fp;
+
+ fp.len = pass->bf_len;
+ fp.filter = (struct sock_filter *) pass->bf_insns;
+ if (ioctl(ppp_dev_fd, PPPIOCSPASS, &fp) < 0) {
+ if (errno == ENOTTY)
+ warn("kernel does not support PPP filtering");
+ else
+ error("Couldn't set pass-filter in kernel: %m");
+ return 0;
+ }
+ fp.len = active->bf_len;
+ fp.filter = (struct sock_filter *) active->bf_insns;
+ if (ioctl(ppp_dev_fd, PPPIOCSACTIVE, &fp) < 0) {
+ error("Couldn't set active-filter in kernel: %m");
+ return 0;
+ }
+ return 1;
+}
+#endif /* PPP_FILTER */
+
/********************************************************************
*
* get_idle_time - return how long the link has been idle.
FILE *fp;
if (proc_path_len == 0) {
+ /* Default the mount location of /proc */
+ strlcpy (proc_path, "/proc", sizeof(proc_path));
+ proc_path_len = 5;
fp = fopen(MOUNTED, "r");
- if (fp == NULL) {
- /* Default the mount location of /proc */
- strlcpy (proc_path, "/proc", sizeof(proc_path));
- proc_path_len = 5;
-
- } else {
+ if (fp != NULL) {
while ((mntent = getmntent(fp)) != NULL) {
if (strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0)
continue;
- if (strcmp(mntent->mnt_type, "proc") == 0)
+ if (strcmp(mntent->mnt_type, "proc") == 0) {
+ strlcpy(proc_path, mntent->mnt_dir, sizeof(proc_path));
+ proc_path_len = strlen(proc_path);
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);
- }
}
}
- if (proc_path_len < 0)
- return 0;
-
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
+ * /proc/net/route parsing stuff.
*/
#define ROUTE_MAX_COLS 12
FILE *route_fd = (FILE *) 0;
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)
-{
- char *path;
-
- path = path_to_procfs("/net/route");
- if (path == 0)
- error("proc file system not mounted");
- return path;
-}
-
/********************************************************************
*
* close_route_table - close the interface to the route table
close_route_table();
- path = path_to_route();
- if (path == NULL)
- return 0;
-
+ path = path_to_procfs("/net/route");
route_fd = fopen (path, "r");
if (route_fd == NULL) {
- error("can't open %s: %m (%d)", path, errno);
+ error("can't open routing table %s: %m", path);
return 0;
}
return 1;
}
+/*
+ * get_if_hwaddr - get the hardware address for the specified
+ * network interface device.
+ */
+int
+get_if_hwaddr(u_char *addr, char *name)
+{
+ struct ifreq ifreq;
+ int ret, sock_fd;
+
+ sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock_fd < 0)
+ return 0;
+ memset(&ifreq.ifr_hwaddr, 0, sizeof(struct sockaddr));
+ strlcpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name));
+ ret = ioctl(sock_fd, SIOCGIFHWADDR, &ifreq);
+ close(sock_fd);
+ if (ret >= 0)
+ memcpy(addr, ifreq.ifr_hwaddr.sa_data, 6);
+ return ret;
+}
+
+/*
+ * get_first_ethernet - return the name of the first ethernet-style
+ * interface on this system.
+ */
+char *
+get_first_ethernet()
+{
+ return "eth0";
+}
+
/********************************************************************
*
* Return user specified netmask, modified by any mask we might determine
sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch);
kernel_version = KVERSION(osmaj, osmin, ospatch);
- if (kernel_version >= KVERSION(2,3,13)) {
- fd = open("/dev/ppp", O_RDWR);
- if (fd < 0 && errno == ENOENT) {
- /* try making it and see if that helps. */
- if (mknod("/dev/ppp", S_IFCHR | S_IRUSR | S_IWUSR,
- makedev(108, 0)) >= 0) {
- fd = open("/dev/ppp", O_RDWR);
- if (fd >= 0)
- info("Created /dev/ppp device node");
- else
- unlink("/dev/ppp"); /* didn't work, undo the mknod */
- } else if (errno == EEXIST) {
- fd = open("/dev/ppp", O_RDWR);
- }
+ fd = open("/dev/ppp", O_RDWR);
+#if 0
+ if (fd < 0 && errno == ENOENT) {
+ /* try making it and see if that helps. */
+ if (mknod("/dev/ppp", S_IFCHR | S_IRUSR | S_IWUSR,
+ makedev(108, 0)) >= 0) {
+ fd = open("/dev/ppp", O_RDWR);
+ if (fd >= 0)
+ info("Created /dev/ppp device node");
+ else
+ unlink("/dev/ppp"); /* didn't work, undo the mknod */
+ } else if (errno == EEXIST) {
+ fd = open("/dev/ppp", O_RDWR);
}
- if (fd >= 0) {
- new_style_driver = 1;
+ }
+#endif /* 0 */
+ if (fd >= 0) {
+ new_style_driver = 1;
- /* XXX should get from driver */
- driver_version = 2;
- driver_modification = 4;
- driver_patch = 0;
- close(fd);
- return 1;
- }
+ /* XXX should get from driver */
+ driver_version = 2;
+ driver_modification = 4;
+ driver_patch = 0;
+ close(fd);
+ return 1;
}
+ if (kernel_version >= KVERSION(2,3,13))
+ return 0;
/*
* Open a socket for doing the ioctl operations.
struct ifreq ifr;
struct in6_rtmsg rt6;
+ if (sock6_fd < 0) {
+ errno = -sock6_fd;
+ error("IPv6 socket creation failed: %m");
+ return 0;
+ }
memset(&ifr, 0, sizeof (ifr));
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
struct ifreq ifr;
struct in6_ifreq ifr6;
+ if (sock6_fd < 0) {
+ errno = -sock6_fd;
+ error("IPv6 socket creation failed: %m");
+ return 0;
+ }
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
*slave_fdp = sfd;
if (tcgetattr(sfd, &tios) == 0) {
tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
- tios.c_cflag |= CS8 | CREAD;
- tios.c_iflag = IGNPAR | CLOCAL;
+ tios.c_cflag |= CS8 | CREAD | CLOCAL;
+ tios.c_iflag = IGNPAR;
tios.c_oflag = 0;
tios.c_lflag = 0;
if (tcsetattr(sfd, TCSAFLUSH, &tios) < 0)
looped = 1;
if (new_style_driver) {
/* allocate ourselves a ppp unit */
- ifunit = -1;
- if (ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit) < 0)
- fatal("Couldn't create PPP unit: %m");
+ if (make_ppp_unit() < 0)
+ die(1);
set_flags(ppp_dev_fd, SC_LOOP_TRAFFIC);
set_kdebugflag(kdebugflag);
ppp_fd = -1;
driver_patch);
return 0;
}
+ if (multilink && !new_style_driver) {
+ warn("Warning: multilink is not supported by the kernel driver");
+ multilink = 0;
+ }
return 1;
}