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 proxy_arp_dev[16]; /* Device for proxy arp entry */
static char *lock_file;
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 */
*
* 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) )
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)
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);
}
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;
+ int mfd = -1;
+ int ret = 0;
- 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);
- return 0;
+ if (devnam[0] == 0) {
+ /* running with notty or pty option */
+ char slave[16];
+ if (!get_pty(&mfd, &local_fd, slave, 0))
+ return 0;
+ } else {
+ 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 &= ~O_NONBLOCK;
- fcntl(local_fd, F_SETFL, initfdflags);
/*
- * Read the initial line dicipline and try to put the device into the
+ * Read the initial line discipline 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;
- }
-
- 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;
- }
+ } else if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0) {
+ error("ioctl(TIOCSETD(PPP)): %m(%d)", errno);
+ } else if (ioctl(local_fd, TIOCSETD, &init_disc) < 0) {
+ error("ioctl(TIOCSETD(%d)): %m(%d)", init_disc, errno);
+ } else
+ ret = 1;
close (local_fd);
- return 1;
+ if (mfd >= 0)
+ close(mfd);
+ return ret;
}
/********************************************************************
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;
}
}
"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";
+ "ppp-2.3.7 distribution.\n";
/*
* This is the PPP device. Validate the version of the driver at this
memset(&ut, 0, sizeof(ut));
if (ut.ut_id[0] == 0)
- strlcpy(ut.ut_id, sizeof(ut.ut_id), line + 3);
+ strlcpy(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);
+ strlcpy(ut.ut_user, name, sizeof(ut.ut_user));
+ strlcpy(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);
+ strlcpy (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)
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 a pty master/slave pair.
+/*
+ * 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 ||
}
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);
*/
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;
}