static int if_is_up; /* Interface has been marked up */
static u_int32_t default_route_gateway; /* Gateway for default route added */
static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */
-
-static char *lock_file;
+static char proxy_arp_dev[16]; /* Device for proxy arp entry */
static struct utsname utsname; /* for the kernel version */
static int kernel_version;
static int read_route_table (struct rtentry *rt);
static int defaultroute_exists (struct rtentry *rt);
static int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr,
- char *name);
+ char *name, int namelen);
static void decode_version (char *buf, int *version, int *mod, int *patch);
+static int set_kdebugflag(int level);
+static int ppp_registered(void);
extern u_char inpacket_buf[]; /* borrowed from main.c */
extern int hungup;
-#ifndef LOCK_PREFIX
-#define LOCK_PREFIX "/var/lock/LCK.."
-#endif
-
static void set_ppp_fd (int new_fd)
{
SYSDEBUG ((LOG_DEBUG, "setting ppp_fd to %d\n", new_fd));
*
* sys_cleanup - restore any system state we modified before exiting:
* mark the interface down, delete default route and/or proxy arp entry.
- * This should call die() because it's called from die().
+ * This shouldn't call die() because it's called from die().
*/
void sys_cleanup(void)
void
sys_close(void)
{
- close(sock_fd);
- sock_fd = -1;
+ if (sock_fd >= 0)
+ close(sock_fd);
+ if (slave_fd >= 0)
+ close(slave_fd);
+ if (master_fd >= 0)
+ close(master_fd);
closelog();
}
-/********************************************************************
- *
- * note_debug_level - note a change in the debug level.
- */
-
-void note_debug_level (void)
-{
- if (debug) {
- SYSDEBUG ((LOG_INFO, "Debug turned ON, Level %d", debug));
- setlogmask(LOG_UPTO(LOG_DEBUG));
- }
- else {
- setlogmask(LOG_UPTO(LOG_WARNING));
- }
-}
-
/********************************************************************
*
* set_kdebugflag - Define the debugging level for the kernel
*/
-int set_kdebugflag (int requested_level)
+static int set_kdebugflag (int requested_level)
{
if (ioctl(ppp_fd, PPPIOCSDEBUG, &requested_level) < 0) {
if ( ! ok_error (errno) )
/*
* Restore the previous line discipline
*/
+ tcflush(tty_fd, TCIOFLUSH);
if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0) {
if ( ! ok_error (errno))
error("ioctl(TIOCSETD, N_TTY): %m");
setdtr(tty_fd, 1);
if (tcgetattr(tty_fd, &tios) < 0) {
- if (!ok_errno(errno))
+ if (!ok_error(errno))
fatal("tcgetattr: %m(%d)", errno);
return;
}
}
if (tcsetattr(tty_fd, TCSAFLUSH, &tios) < 0)
- if (!ok_errno(errno))
+ if (!ok_error(errno))
fatal("tcsetattr: %m");
baud_rate = baud_rate_of(speed);
- restore_term = TRUE;
+ restore_term = 1;
}
/********************************************************************
* Set the MTU and other parameters for the ppp device
*/
memset (&ifr, '\0', sizeof (ifr));
- strlcpy(ifr.ifr_name, sizeof (ifr.ifr_name), ifname);
+ strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
ifr.ifr_mtu = mtu;
if (ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
SYSDEBUG ((LOG_DEBUG, "send_config: asyncmap = %lx\n", asyncmap));
if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
- if (!ok_errno(errno))
+ if (!ok_error(errno))
fatal("ioctl(PPPIOCSASYNCMAP): %m(%d)", errno);
return;
}
x = get_flags();
x = pcomp ? x | SC_COMP_PROT : x & ~SC_COMP_PROT;
x = accomp ? x | SC_COMP_AC : x & ~SC_COMP_AC;
+ x = sync_serial ? x | SC_SYNC : x & ~SC_SYNC;
set_flags(x);
}
SYSDEBUG ((LOG_DEBUG, "recv_config: asyncmap = %lx\n", asyncmap));
if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
- if (!ok_errno(errno))
+ if (!ok_error(errno))
error("ioctl(PPPIOCSRASYNCMAP): %m(%d)", errno);
}
return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
}
+/********************************************************************
+ *
+ * get_ppp_stats - return statistics for the link.
+ */
+int
+get_ppp_stats(u, stats)
+ int u;
+ struct pppd_stats *stats;
+{
+ struct ifpppstatsreq req;
+
+ memset (&req, 0, sizeof (req));
+
+ req.stats_ptr = (caddr_t) &req.stats;
+ strlcpy(req.ifr__name, ifname, sizeof(req.ifr__name));
+ if (ioctl(sock_fd, SIOCGPPPSTATS, &req) < 0) {
+ error("Couldn't get PPP statistics: %m");
+ return 0;
+ }
+ stats->bytes_in = req.stats.p.ppp_ibytes;
+ stats->bytes_out = req.stats.p.ppp_obytes;
+ return 1;
+}
+
/********************************************************************
*
* ccp_fatal_error - returns 1 if decompression was disabled as a
fp = fopen(MOUNTED, "r");
if (fp == NULL) {
/* Default the mount location of /proc */
- strlcpy (route_buffer, sizeof (route_buffer), "/proc");
+ strlcpy (route_buffer, "/proc", sizeof (route_buffer));
return 1;
}
if (mntent == 0)
return 0;
- strlcpy(route_buffer, sizeof (route_buffer), mntent->mnt_dir);
+ strlcpy(route_buffer, mntent->mnt_dir, sizeof (route_buffer));
return 1;
}
error("proc file system not mounted");
return 0;
}
- strlcat (route_buffer, sizeof(route_buffer), "/net/route");
+ strlcat (route_buffer, "/net/route", sizeof(route_buffer));
return (route_buffer);
}
* Get the hardware address of an interface on the same subnet
* as our local address.
*/
- if (!get_ether_addr(his_adr, &arpreq.arp_ha, arpreq.arp_dev)) {
+ if (!get_ether_addr(his_adr, &arpreq.arp_ha, proxy_arp_dev,
+ sizeof(proxy_arp_dev))) {
error("Cannot determine ethernet address for proxy ARP");
return 0;
}
-
+ strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
+
if (ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq) < 0) {
if ( ! ok_error ( errno ))
error("ioctl(SIOCSARP): %m(%d)", errno);
SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
arpreq.arp_flags = ATF_PERM | ATF_PUBL;
+ strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
if (ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq) < 0) {
if ( ! ok_error ( errno ))
static int get_ether_addr (u_int32_t ipaddr,
struct sockaddr *hwaddr,
- char *name)
+ char *name, int namelen)
{
struct ifreq *ifr, *ifend;
u_int32_t ina, mask;
for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
if (ifr->ifr_addr.sa_family == AF_INET) {
ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
- strlcpy(ifreq.ifr_name, sizeof(ifreq.ifr_name), ifr->ifr_name);
+ strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
SYSDEBUG ((LOG_DEBUG, "proxy arp: examining interface %s",
ifreq.ifr_name));
/*
if (ifr >= ifend)
return 0;
- memcpy (name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
+ strlcpy(name, ifreq.ifr_name, namelen);
info("found interface %s for proxy arp", name);
/*
* Now get the hardware address.
/*
* Check that the interface is up, and not point-to-point nor loopback.
*/
- strlcpy(ifreq.ifr_name, sizeof(ifreq.ifr_name), ifr->ifr_name);
+ strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
continue;
* Procedure to determine if the PPP line discipline is registered.
*/
-int
+static int
ppp_registered(void)
{
int local_fd;
- int init_disc = -1;
- int initfdflags;
-
- local_fd = open(devnam, O_NONBLOCK | O_RDWR, 0);
- if (local_fd < 0) {
- error("Failed to open %s: %m(%d)", devnam, errno);
- return 0;
- }
-
- initfdflags = fcntl(local_fd, F_GETFL);
- if (initfdflags == -1) {
- error("Couldn't get device fd flags: %m(%d)", errno);
- close (local_fd);
+ int mfd = -1;
+ int ret = 0;
+ char slave[16];
+
+ /*
+ * We used to open the serial device and set it to the ppp line
+ * discipline here, in order to create a ppp unit. But that is
+ * not a good idea - the user might have specified a device that
+ * they can't open (permission, or maybe it doesn't really exist).
+ * So we grab a pty master/slave pair and use that.
+ */
+ if (!get_pty(&mfd, &local_fd, slave, 0)) {
+ no_ppp_msg = "Couldn't determine if PPP is supported (no free ptys)";
return 0;
}
- initfdflags &= ~O_NONBLOCK;
- fcntl(local_fd, F_SETFL, initfdflags);
-/*
- * Read the initial line dicipline and try to put the device into the
- * PPP dicipline.
- */
- if (ioctl(local_fd, TIOCGETD, &init_disc) < 0) {
- error("ioctl(TIOCGETD): %m(%d)", errno);
- close (local_fd);
- return 0;
- }
-
+ /*
+ * Try to put the device into the PPP discipline.
+ */
if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0) {
- error("ioctl(TIOCSETD): %m(%d)", errno);
- close (local_fd);
- return 0;
- }
-
- if (ioctl(local_fd, TIOCSETD, &init_disc) < 0) {
- error("ioctl(TIOCSETD): %m(%d)", errno);
- close (local_fd);
- return 0;
- }
+ error("ioctl(TIOCSETD(PPP)): %m(%d)", errno);
+ } else
+ ret = 1;
- close (local_fd);
- return 1;
+ close(local_fd);
+ close(mfd);
+ return ret;
}
/********************************************************************
struct ifreq ifr;
int size;
int my_version, my_modification, my_patch;
- extern char *no_ppp_msg;
+
+ no_ppp_msg =
+ "This system lacks kernel support for PPP. This could be because\n"
+ "the PPP kernel module is not loaded, or because the kernel is\n"
+ "not configured for PPP. See the README.linux file in the\n"
+ "ppp-2.3.7 distribution.\n";
+
/*
* Open a socket for doing the ioctl operations.
*/
if (s < 0)
return 0;
- strlcpy (ifr.ifr_name, sizeof (ifr.ifr_name), "ppp0");
+ strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
/*
* If the device did not exist then attempt to create one by putting the
*/
if (!ok) {
if (ppp_registered()) {
- strlcpy (ifr.ifr_name, sizeof (ifr.ifr_name), "ppp0");
+ strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
}
}
if (ok && ((ifr.ifr_hwaddr.sa_family & ~0xFF) != ARPHRD_PPP))
ok = 0;
- if (!ok)
- no_ppp_msg =
- "This system lacks kernel support for PPP. This could be because\n"
- "the PPP kernel module is not loaded, or because the kernel is\n"
- "not configured for PPP. See the README.linux file in the\n"
- "ppp-2.3.6 distribution.\n";
-
/*
* This is the PPP device. Validate the version of the driver at this
* point to ensure that this program will work with the driver.
*/
- else {
+ if (ok) {
char abBuffer [1024];
ifr.ifr_data = abBuffer;
memset(&ut, 0, sizeof(ut));
if (ut.ut_id[0] == 0)
- strlcpy(ut.ut_id, sizeof(ut.ut_id), line + 3);
+ strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
- strlcpy(ut.ut_user, sizeof(ut.ut_user), name);
- strlcpy(ut.ut_line, sizeof(ut.ut_line), line);
+ strncpy(ut.ut_user, name, sizeof(ut.ut_user));
+ strncpy(ut.ut_line, line, sizeof(ut.ut_line));
time(&ut.ut_time);
/* Insert the host name if one is supplied */
if (*host)
- strlcpy (ut.ut_host, sizeof(ut.ut_host), host);
+ strncpy (ut.ut_host, host, sizeof(ut.ut_host));
/* Insert the IP address of the remote system if IP is enabled */
if (ipcp_protent.enabled_flag && ipcp_hisoptions[0].neg_addr)
}
}
+#if 0
/********************************************************************
* Code for locking/unlocking the serial device.
* This code is derived from chat.c.
*/
+#ifndef LOCK_PREFIX
+#define LOCK_PREFIX "/var/lock/LCK.."
+#endif
+
+static char *lock_file;
+
/*
* lock - create a lock file for the named device
*/
lock_file = NULL;
}
}
+#endif
/********************************************************************
*
struct ifreq ifr;
memset (&ifr, '\0', sizeof (ifr));
- strlcpy(ifr.ifr_name, sizeof (ifr.ifr_name), ifname);
+ strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
if (! ok_error (errno))
error("ioctl (SIOCGIFFLAGS): %m(%d)", errno);
if_is_up = 0;
memset (&ifr, '\0', sizeof (ifr));
- strlcpy(ifr.ifr_name, sizeof (ifr.ifr_name), ifname);
+ strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
if (! ok_error (errno))
error("ioctl (SIOCGIFFLAGS): %m(%d)", errno);
SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET);
SET_SA_FAMILY (ifr.ifr_netmask, AF_INET);
- strlcpy (ifr.ifr_name, sizeof (ifr.ifr_name), ifname);
+ strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
/*
* Set our IP address
*/
if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
if (errno != EEXIST) {
if (! ok_error (errno))
- error("ioctl(SIOCAIFADDR): %m(%d)", errno);
+ error("ioctl(SIOCSIFADDR): %m(%d)", errno);
}
else {
- warn("ioctl(SIOCAIFADDR): Address already exists");
+ warn("ioctl(SIOCSIFADDR): Address already exists");
}
return (0);
}
return 1;
}
-/********************************************************************
- *
- * open_loopback - open the device we use for getting packets
- * in demand mode. Under Linux, we use our existing fd
- * to the ppp driver.
+/*
+ * get_pty - get a pty master/slave pair and chown the slave side
+ * to the uid given. Assumes slave_name points to >= 12 bytes of space.
*/
int
-open_ppp_loopback(void)
+get_pty(master_fdp, slave_fdp, slave_name, uid)
+ int *master_fdp;
+ int *slave_fdp;
+ char *slave_name;
+ int uid;
{
- int flags, i;
+ int i, mfd, sfd;
+ char pty_name[12];
struct termios tios;
- master_fd = -1;
+ sfd = -1;
for (i = 0; i < 64; ++i) {
- slprintf(loop_name, sizeof(loop_name), "/dev/pty%c%x",
+ slprintf(pty_name, sizeof(pty_name), "/dev/pty%c%x",
'p' + i / 16, i % 16);
- master_fd = open(loop_name, O_RDWR | O_NOCTTY, 0);
- if (master_fd >= 0)
- break;
+ mfd = open(pty_name, O_RDWR, 0);
+ if (mfd >= 0) {
+ pty_name[5] = 't';
+ sfd = open(pty_name, O_RDWR | O_NOCTTY, 0);
+ if (sfd >= 0)
+ break;
+ close(mfd);
+ }
}
- if (master_fd < 0)
- fatal("No free pty for loopback");
- SYSDEBUG(("using %s for loopback", loop_name));
- loop_name[5] = 't';
- slave_fd = open(loop_name, O_RDWR | O_NOCTTY, 0);
- if (slave_fd < 0)
- fatal("Couldn't open %s for loopback: %m", loop_name);
-
- set_ppp_fd(slave_fd);
+ if (sfd < 0)
+ return 0;
- if (tcgetattr(ppp_fd, &tios) == 0) {
+ strlcpy(slave_name, pty_name, 12);
+ *master_fdp = mfd;
+ *slave_fdp = sfd;
+ fchown(sfd, uid, -1);
+ fchmod(sfd, S_IRUSR | S_IWUSR);
+ if (tcgetattr(sfd, &tios) == 0) {
tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
tios.c_cflag |= CS8 | CREAD;
tios.c_iflag = IGNPAR | CLOCAL;
tios.c_oflag = 0;
tios.c_lflag = 0;
- if (tcsetattr(ppp_fd, TCSAFLUSH, &tios) < 0)
- warn("couldn't set attributes on loopback: %m(%d)", errno);
- }
+ if (tcsetattr(sfd, TCSAFLUSH, &tios) < 0)
+ warn("couldn't set attributes on pty: %m");
+ } else
+ warn("couldn't get attributes on pty: %m");
+
+ return 1;
+}
+
+/********************************************************************
+ *
+ * open_loopback - open the device we use for getting packets
+ * in demand mode. Under Linux, we use a pty master/slave pair.
+ */
+int
+open_ppp_loopback(void)
+{
+ int flags;
+
+ if (!get_pty(&master_fd, &slave_fd, loop_name, 0))
+ fatal("No free pty for loopback");
+ SYSDEBUG(("using %s for loopback", loop_name));
+
+ set_ppp_fd(slave_fd);
flags = fcntl(master_fd, F_GETFL);
if (flags == -1 ||
*/
set_kdebugflag (kdebugflag);
- return ppp_fd;
+ return master_fd;
}
/********************************************************************
}
else {
memset (&ifr, '\0', sizeof (ifr));
- strlcpy (ifr.ifr_name, sizeof(ifr.ifr_name), ifname);
+ strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
memcpy (sipx->sipx_node, node, IPX_NODE_LEN);
sipx->sipx_family = AF_IPX;
result = 0;
if (errno != EEXIST) {
if (! ok_error (errno))
- dbglog("ioctl(SIOCAIFADDR, CRTITF): %m (%d)", errno);
+ dbglog("ioctl(SIOCSIFADDR, CRTITF): %m (%d)", errno);
}
else {
- warn("ioctl(SIOCAIFADDR, CRTITF): Address already exists");
+ warn("ioctl(SIOCSIFADDR, CRTITF): Address already exists");
}
}
close (skfd);
}
else {
memset (&ifr, '\0', sizeof (ifr));
- strlcpy (ifr.ifr_name, sizeof(ifr.ifr_name), ifname);
+ strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
sipx->sipx_type = IPX_FRAME_ETHERII;
sipx->sipx_action = IPX_DLTITF;
*/
if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
if (! ok_error (errno))
- info("ioctl(SIOCAIFADDR, IPX_DLTITF): %m (%d)", errno);
+ info("ioctl(SIOCSIFADDR, IPX_DLTITF): %m (%d)", errno);
result = 0;
}
close (skfd);
return result;
}
+#if 0
/*
* daemon - Detach us from controlling terminal session.
*/
}
return 0;
}
+#endif
/*
* Use the hostname as part of the random number seed.
*/
while (ipxcp_protent.enabled_flag) {
if (path_to_procfs()) {
- strlcat (route_buffer, sizeof(route_buffer), "/net/ipx_interface");
+ strlcat (route_buffer, "/net/ipx_interface", sizeof(route_buffer));
if (lstat (route_buffer, &stat_buf) >= 0)
break;
}