*/
#ifndef lint
-static char rcsid[] = "$Id: sys-osf.c,v 1.1 1995/04/24 06:16:23 paulus Exp $";
+static char rcsid[] = "$Id: sys-osf.c,v 1.5 1995/10/27 03:47:32 paulus Exp $";
#endif
/*
static int restore_term; /* 1 => we've munged the terminal */
static struct termios inittermios; /* Initial TTY termios */
static struct winsize wsinfo; /* Initial window size info */
+static int initfdflags = -1; /* Initial file descriptor flags for fd */
-int sockfd; /* socket for doing interface ioctls */
+static int sockfd; /* socket for doing interface ioctls */
int ttyfd = -1; /* Original ttyfd if we did a streamify() */
+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 */
+
+/* Prototypes for procedures local to this file. */
+static int translate_speed __P((int));
+static int baud_rate_of __P((int));
+static int get_ether_addr __P((u_int32_t, struct sockaddr *));
+
+
/*
* sys_init - System-dependent initialization.
*/
}
}
+/*
+ * 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().
+ */
+void
+sys_cleanup()
+{
+ struct ifreq ifr;
+
+ if (if_is_up) {
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
+ && ((ifr.ifr_flags & IFF_UP) != 0)) {
+ ifr.ifr_flags &= ~IFF_UP;
+ ioctl(sockfd, SIOCSIFFLAGS, &ifr);
+ }
+ }
+
+ if (default_route_gateway)
+ cifdefaultroute(0, default_route_gateway);
+ if (proxy_arp_addr)
+ cifproxyarp(0, proxy_arp_addr);
+}
+
/*
* note_debug_level - note a change in the debug level.
*/
close(i);
closed_stdio = 1;
}
+
+ /*
+ * Set device for non-blocking reads.
+ */
+ if ((initfdflags = fcntl(fd, F_GETFL)) == -1
+ || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
+ syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m");
+ }
}
/* Debugging routine.... */
int flags;
char *s;
+ /* Reset non-blocking mode on the file descriptor. */
+ if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
+ syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
+ initfdflags = -1;
+
if (hungup) {
/* we can't push or pop modules after the stream has hung up */
str_module_count = 0;
/*
* Translate from bits/second to a speed_t.
*/
-int
+static int
translate_speed(bps)
int bps;
{
/*
* Translate from a speed_t to bits/second.
*/
-int
+static int
baud_rate_of(speed)
int speed;
{
tios.c_cc[VMIN] = 1;
tios.c_cc[VTIME] = 0;
- if (crtscts == 2) {
- tios.c_iflag |= IXOFF;
+ if (crtscts == -2) {
+ tios.c_iflag |= IXON | IXOFF;
tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */
tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */
}
restore_tty()
{
if (restore_term) {
+ if (!default_device) {
+ /*
+ * Turn off echoing, because otherwise we can get into
+ * a loop with the tty and the modem echoing to each other.
+ * We presume we are the sole user of this tty device, so
+ * when we close it, it will revert to its defaults anyway.
+ */
+ inittermios.c_lflag &= ~(ECHO | ECHONL);
+ }
if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
if (errno != ENXIO)
syslog(LOG_WARNING, "tcsetattr: %m");
u_char *p;
int len;
{
- struct strbuf str;
+ struct strbuf str;
+ int retries;
+ struct pollfd pfd;
- if (unit != 0)
- MAINDEBUG((LOG_WARNING, "output: unit != 0!"));
if (debug)
log_packet(p, len, "sent ");
str.len = len;
str.buf = (caddr_t) p;
- if (putmsg(fd, NULL, &str, 0) < 0) {
- if (errno != ENXIO) {
- syslog(LOG_ERR, "putmsg: %m");
- die(1);
+ retries = 4;
+ while (putmsg(fd, NULL, &str, 0) < 0) {
+ if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) {
+ if (errno != ENXIO)
+ syslog(LOG_ERR, "Couldn't send packet: %m");
+ break;
}
+ pfd.fd = fd;
+ pfd.events = POLLOUT;
+ poll(&pfd, 1, 250); /* wait for up to 0.25 seconds */
}
}
data.length = opt_len;
data.transmit = for_transmit;
BCOPY(opt_ptr, data.opt_data, opt_len);
- return ioctl(fd, (int)SIOCSCOMPRESS, (caddr_t) &data) >= 0;
+ if (ioctl(fd, (int)SIOCSCOMPRESS, (caddr_t) &data) >= 0)
+ return 1;
+ return (errno == ENOSR)? 0: -1;
}
/*
syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
return 0;
}
+ if_is_up = 1;
npi.protocol = PPP_IP;
npi.mode = NPMODE_PASS;
if (ioctl(fd, (int)SIOCSETNPMODE, &npi) < 0) {
if (ioctl(sockfd, (int)SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
rv = 0;
- }
+ } else
+ if_is_up = 0;
}
return rv;
}
syslog(LOG_ERR, "default route ioctl(SIOCADDRT): %m");
return 0;
}
+ default_route_gateway = g;
return 1;
}
syslog(LOG_ERR, "default route ioctl(SIOCDELRT): %m");
return 0;
}
+ default_route_gateway = 0;
return 1;
}
return 0;
}
+ proxy_arp_addr = hisaddr;
return 1;
}
syslog(LOG_ERR, "ioctl(SIOCDARP): %m");
return 0;
}
+ proxy_arp_addr = 0;
return 1;
}
int s;
-int
+static int
get_ether_addr(ipaddr, hwaddr)
u_int ipaddr;
struct sockaddr *hwaddr;
}
+/*
+ * Return user specified netmask, modified by any mask we might determine
+ * for address `addr' (in network byte order).
+ * Here we scan through the system's list of interfaces, looking for
+ * any non-point-to-point interfaces which might appear to be on the same
+ * network as `addr'. If we find any, we OR in their netmask to the
+ * user-specified netmask.
+ */
+u_int32_t
+GetMask(addr)
+ u_int32_t addr;
+{
+ u_int32_t mask, nmask, ina;
+ struct ifreq *ifr, *ifend, ifreq;
+ struct ifconf ifc;
+ struct ifreq ifs[MAX_IFS];
+
+ addr = ntohl(addr);
+ if (IN_CLASSA(addr)) /* determine network mask for address class */
+ nmask = IN_CLASSA_NET;
+ else if (IN_CLASSB(addr))
+ nmask = IN_CLASSB_NET;
+ else
+ nmask = IN_CLASSC_NET;
+ /* class D nets are disallowed by bad_ip_adrs */
+ mask = netmask | htonl(nmask);
+
+ /*
+ * Scan through the system's network interfaces.
+ */
+ ifc.ifc_len = sizeof(ifs);
+ ifc.ifc_req = ifs;
+ if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
+ syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
+ return mask;
+ }
+ ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+ for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
+ /*
+ * Check the interface's internet address.
+ */
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ continue;
+ ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
+ if ((ntohl(ina) & nmask) != (addr & nmask))
+ continue;
+ /*
+ * Check that the interface is up, and not point-to-point or loopback.
+ */
+ strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
+ continue;
+ if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
+ != IFF_UP)
+ continue;
+ /*
+ * Get its netmask and OR it into our mask.
+ */
+ if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
+ continue;
+ mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
+ }
+
+ return mask;
+}
#define WTMPFILE "/usr/adm/wtmp"