*/
#ifndef lint
-static char rcsid[] = "$Id: sys-sunos4.c,v 1.2 1995/12/19 02:04:40 paulus Exp $";
+static char rcsid[] = "$Id: sys-sunos4.c,v 1.8 1997/04/30 05:58:52 paulus Exp $";
#endif
#include <stdio.h>
#if defined(sun) && defined(sparc)
#include <alloca.h>
+#ifndef __GNUC__
+extern void *alloca();
+#endif
#endif /*sparc*/
static int pppfd;
static struct winsize wsinfo; /* Initial window size info */
static pid_t parent_pid; /* PID of our parent */
+extern u_char inpacket_buf[]; /* borrowed from main.c */
+
static int link_mtu, link_mru;
#define NMODULES 32
static char tty_modules[NMODULES][FMNAMESZ+1];
static int if_is_up; /* Interface has been marked up */
+static u_int32_t ifaddrs[2]; /* local and remote addresses */
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 */
void
sys_init()
{
- openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
- setlogmask(LOG_UPTO(LOG_INFO));
- if (debug)
- setlogmask(LOG_UPTO(LOG_DEBUG));
+ int x;
/* Get an internet socket for doing socket ioctl's on. */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
* parent process.
*/
parent_pid = getppid();
+
+ /*
+ * Open the ppp device.
+ */
+ pppfd = open("/dev/ppp", O_RDWR | O_NONBLOCK, 0);
+ if (pppfd < 0) {
+ syslog(LOG_ERR, "Can't open /dev/ppp: %m");
+ die(1);
+ }
+ if (kdebugflag) {
+ x = PPPDBG_LOG + PPPDBG_DRIVER;
+ strioctl(pppfd, PPPIO_DEBUG, &x, sizeof(int), 0);
+ }
+
+ /* Assign a new PPA and get its unit number. */
+ if (strioctl(pppfd, PPPIO_NEWPPA, &ifunit, 0, sizeof(int)) < 0) {
+ syslog(LOG_ERR, "Can't create new PPP interface: %m");
+ die(1);
+ }
+
+ /*
+ * Open the ppp device again and push the if_ppp module on it.
+ */
+ iffd = open("/dev/ppp", O_RDWR, 0);
+ if (iffd < 0) {
+ syslog(LOG_ERR, "Can't open /dev/ppp (2): %m");
+ die(1);
+ }
+ if (kdebugflag) {
+ x = PPPDBG_LOG + PPPDBG_DRIVER;
+ strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0);
+ }
+ if (strioctl(iffd, PPPIO_ATTACH, &ifunit, sizeof(int), 0) < 0) {
+ syslog(LOG_ERR, "Couldn't attach ppp interface to device: %m");
+ die(1);
+ }
+ if (ioctl(iffd, I_PUSH, "if_ppp") < 0) {
+ syslog(LOG_ERR, "Can't push ppp interface module: %m");
+ die(1);
+ }
+ if (kdebugflag) {
+ x = PPPDBG_LOG + PPPDBG_IF;
+ strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0);
+ }
+ if (strioctl(iffd, PPPIO_NEWPPA, &ifunit, sizeof(int), 0) < 0) {
+ syslog(LOG_ERR, "Couldn't create ppp interface unit: %m");
+ die(1);
+ }
+ x = PPP_IP;
+ if (strioctl(iffd, PPPIO_BIND, &x, sizeof(int), 0) < 0) {
+ syslog(LOG_ERR, "Couldn't bind ppp interface to IP SAP: %m");
+ die(1);
+ }
}
/*
* 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()
{
- struct ifreq ifr;
-
if (if_is_up)
sifdown(0);
+ if (ifaddrs[0])
+ cifaddr(0, ifaddrs[0], ifaddrs[1]);
if (default_route_gateway)
- cifdefaultroute(0, default_route_gateway);
+ cifdefaultroute(0, 0, default_route_gateway);
if (proxy_arp_addr)
cifproxyarp(0, proxy_arp_addr);
}
+/*
+ * sys_close - Clean up in a child process before execing.
+ */
+void
+sys_close()
+{
+ close(iffd);
+ close(pppfd);
+ close(sockfd);
+}
+
+/*
+ * sys_check_options - check the options that the user specified
+ */
+void
+sys_check_options()
+{
+}
+
+
/*
* daemon - Detach us from controlling terminal session.
*/
return 0;
}
-/*
- * note_debug_level - note a change in the debug level.
- */
-void
-note_debug_level()
-{
- if (debug) {
- syslog(LOG_INFO, "Debug turned ON, Level %d", debug);
- setlogmask(LOG_UPTO(LOG_DEBUG));
- } else {
- setlogmask(LOG_UPTO(LOG_WARNING));
- }
-}
-
/*
* ppp_available - check whether the system has any ppp interfaces
*/
* establish_ppp - Turn the serial port into a ppp interface.
*/
void
-establish_ppp()
+establish_ppp(fd)
+ int fd;
{
- int i, x;
- struct ifreq ifr;
-
- pppfd = open("/dev/ppp", O_RDWR | O_NONBLOCK, 0);
- if (pppfd < 0) {
- syslog(LOG_ERR, "Can't open /dev/ppp: %m");
- die(1);
- }
- if (kdebugflag) {
- x = PPPDBG_LOG + PPPDBG_DRIVER;
- strioctl(pppfd, PPPIO_DEBUG, &x, sizeof(int), 0);
- }
-
- /* Assign a new PPA and get its unit number. */
- if (strioctl(pppfd, PPPIO_NEWPPA, &ifunit, 0, sizeof(int)) < 0) {
- syslog(LOG_ERR, "Can't create new PPP interface: %m");
- die(1);
- }
-
- /*
- * Open the ppp device again and push the if_ppp module on it.
- */
- iffd = open("/dev/ppp", O_RDWR, 0);
- if (iffd < 0) {
- syslog(LOG_ERR, "Can't open /dev/ppp (2): %m");
- die(1);
- }
- if (kdebugflag) {
- x = PPPDBG_LOG + PPPDBG_DRIVER;
- strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0);
- }
- if (strioctl(iffd, PPPIO_ATTACH, &ifunit, sizeof(int), 0) < 0) {
- syslog(LOG_ERR, "Couldn't attach ppp interface to device: %m");
- die(1);
- }
- if (ioctl(iffd, I_PUSH, "if_ppp") < 0) {
- syslog(LOG_ERR, "Can't push ppp interface module: %m");
- die(1);
- }
- if (kdebugflag) {
- x = PPPDBG_LOG + PPPDBG_IF;
- strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0);
- }
- if (strioctl(iffd, PPPIO_NEWPPA, &ifunit, sizeof(int), 0) < 0) {
- syslog(LOG_ERR, "Couldn't create ppp interface unit: %m");
- die(1);
- }
- x = PPP_IP;
- if (strioctl(iffd, PPPIO_BIND, &x, sizeof(int), 0) < 0) {
- syslog(LOG_ERR, "Couldn't bind ppp interface to IP SAP: %m");
- die(1);
- }
+ int i;
/* Pop any existing modules off the tty stream. */
for (i = 0;; ++i)
syslog(LOG_ERR, "Can't link tty to PPP mux: %m");
die(1);
}
+}
- do {
- char buf[PPP_MRU];
-
- i = read(fd, buf, PPP_MRU);
- syslog(LOG_DEBUG, "read %d bytes from fd", i);
- } while (i > 0);
+/*
+ * restore_loop - reattach the ppp unit to the loopback.
+ * This doesn't need to do anything because disestablish_ppp does it.
+ */
+void
+restore_loop()
+{
}
/*
* disestablish_ppp - Restore the serial port to normal operation.
- * This shouldn't call die() because it's called from die().
+ * It attempts to reconstruct the stream with the previously popped
+ * modules. This shouldn't call die() because it's called from die().
*/
void
-disestablish_ppp()
+disestablish_ppp(fd)
+ int fd;
{
int i;
}
}
+/*
+ * Check whether the link seems not to be 8-bit clean.
+ */
+void
+clean_check()
+{
+ int x;
+ char *s;
+
+ if (strioctl(pppfd, PPPIO_GCLEAN, &x, 0, sizeof(x)) < 0)
+ return;
+ s = NULL;
+ switch (~x) {
+ case RCV_B7_0:
+ s = "bit 7 set to 1";
+ break;
+ case RCV_B7_1:
+ s = "bit 7 set to 0";
+ break;
+ case RCV_EVNP:
+ s = "odd parity";
+ break;
+ case RCV_ODDP:
+ s = "even parity";
+ break;
+ }
+ if (s != NULL) {
+ syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
+ syslog(LOG_WARNING, "All received characters had %s", s);
+ }
+}
+
/*
* List of valid speeds.
*/
* restore_tty - restore the terminal to the saved settings.
*/
void
-restore_tty()
+restore_tty(fd)
+ int fd;
{
if (restore_term) {
if (!default_device) {
ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
}
+/*
+ * open_loopback - open the device we use for getting packets
+ * in demand mode. Under Solaris 2, we use our existing fd
+ * to the ppp driver.
+ */
+void
+open_ppp_loopback()
+{
+}
+
/*
* output - Output PPP packet.
*/
struct pollfd pfd;
if (debug)
- log_packet(p, len, "sent ");
+ log_packet(p, len, "sent ", LOG_DEBUG);
data.len = len;
data.buf = (caddr_t) p;
+ retries = 4;
while (putmsg(pppfd, NULL, &data, 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.fd = pppfd;
pfd.events = POLLOUT;
poll(&pfd, 1, 250); /* wait for up to 0.25 seconds */
}
}
+
/*
* wait_input - wait until there is data available on fd,
* for the length of time specified by *timo (indefinite
}
}
+/*
+ * wait_loop_output - wait until there is data available on the
+ * loopback, for the length of time specified by *timo (indefinite
+ * if timo is NULL).
+ */
+void
+wait_loop_output(timo)
+ struct timeval *timo;
+{
+ wait_input(timo);
+}
+
+/*
+ * wait_time - wait for a given length of time or until a
+ * signal is received.
+ */
+void
+wait_time(timo)
+ struct timeval *timo;
+{
+ int n;
+
+ n = select(0, NULL, NULL, NULL, timo);
+ if (n < 0 && errno != EINTR) {
+ syslog(LOG_ERR, "select: %m");
+ die(1);
+ }
+}
+
+
/*
* read_packet - get a PPP packet from the serial device.
*/
}
}
+/*
+ * get_loop_output - get outgoing packets from the ppp device,
+ * and detect when we want to bring the real link up.
+ * Return value is 1 if we need to bring up the link, 0 otherwise.
+ */
+int
+get_loop_output()
+{
+ int len;
+ int rv = 0;
+
+ while ((len = read_packet(inpacket_buf)) > 0) {
+ if (loop_frame(inpacket_buf, len))
+ rv = 1;
+ }
+ return rv;
+}
+
/*
* ppp_send_config - configure the transmit characteristics of
* the ppp interface.
int pcomp, accomp;
{
int cf[2];
+ struct ifreq ifr;
link_mtu = mtu;
if (strioctl(pppfd, PPPIO_MTU, &mtu, sizeof(mtu), 0) < 0) {
if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
syslog(LOG_ERR, "Couldn't set prot/AC compression: %m");
}
+
+ /* set mtu for ip as well */
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ ifr.ifr_metric = link_mtu;
+ if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) {
+ syslog(LOG_ERR, "Couldn't set IP MTU: %m");
+ }
}
/*
}
}
+/*
+ * get_idle_time - return how long the link has been idle.
+ */
+int
+get_idle_time(u, ip)
+ int u;
+ struct ppp_idle *ip;
+{
+ return strioctl(pppfd, PPPIO_GIDLE, ip, 0, sizeof(struct ppp_idle)) >= 0;
+}
+
+
/*
* ccp_fatal_error - returns 1 if decompression was disabled as a
* result of an error detected after decompression of a packet,
return 1;
}
+/*
+ * sifnpmode - Set the mode for handling packets for a given NP.
+ */
+int
+sifnpmode(u, proto, mode)
+ int u;
+ int proto;
+ enum NPmode mode;
+{
+ int npi[2];
+
+ npi[0] = proto;
+ npi[1] = (int) mode;
+ if (strioctl(pppfd, PPPIO_NPMODE, npi, 2 * sizeof(int), 0) < 0) {
+ syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode);
+ return 0;
+ }
+ return 1;
+}
+
#define INET_ADDR(x) (((struct sockaddr_in *) &(x))->sin_addr.s_addr)
/*
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
ifr.ifr_addr.sa_family = AF_INET;
+ INET_ADDR(ifr.ifr_addr) = m;
+ if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
+ syslog(LOG_ERR, "Couldn't set IP netmask: %m");
+ }
+ ifr.ifr_addr.sa_family = AF_INET;
INET_ADDR(ifr.ifr_addr) = o;
if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
syslog(LOG_ERR, "Couldn't set local IP address: %m");
if (ioctl(sockfd, SIOCSIFDSTADDR, &ifr) < 0) {
syslog(LOG_ERR, "Couldn't set remote IP address: %m");
}
- ifr.ifr_addr.sa_family = AF_INET;
- INET_ADDR(ifr.ifr_addr) = m;
- if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
- syslog(LOG_ERR, "Couldn't set IP netmask: %m");
- }
+#if 0 /* now done in ppp_send_config */
ifr.ifr_metric = link_mtu;
if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) {
syslog(LOG_ERR, "Couldn't set IP MTU: %m");
}
+#endif
+ ifaddrs[0] = o;
+ ifaddrs[1] = h;
return 1;
}
{
struct rtentry rt;
+ bzero(&rt, sizeof(rt));
rt.rt_dst.sa_family = AF_INET;
INET_ADDR(rt.rt_dst) = h;
rt.rt_gateway.sa_family = AF_INET;
INET_ADDR(rt.rt_gateway) = o;
rt.rt_flags = RTF_HOST;
- ioctl(sockfd, SIOCDELRT, &rt);
+ if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
+ syslog(LOG_ERR, "Couldn't delete route through interface: %m");
+ ifaddrs[0] = 0;
return 1;
}
* sifdefaultroute - assign a default route through the address given.
*/
int
-sifdefaultroute(u, g)
+sifdefaultroute(u, l, g)
int u;
- u_int32_t g;
+ u_int32_t l, g;
{
struct rtentry rt;
+ bzero(&rt, sizeof(rt));
rt.rt_dst.sa_family = AF_INET;
INET_ADDR(rt.rt_dst) = 0;
rt.rt_gateway.sa_family = AF_INET;
* cifdefaultroute - delete a default route through the address given.
*/
int
-cifdefaultroute(u, g)
+cifdefaultroute(u, l, g)
int u;
- u_int32_t g;
+ u_int32_t l, g;
{
struct rtentry rt;
+ bzero(&rt, sizeof(rt));
rt.rt_dst.sa_family = AF_INET;
INET_ADDR(rt.rt_dst) = 0;
rt.rt_gateway.sa_family = AF_INET;
#define WTMPFILE "/usr/adm/wtmp"
-int
+void
logwtmp(line, name, host)
- char *line, *name, *host;
+ const char *line, *name, *host;
{
int fd;
struct stat buf;
{
return (unsigned long) strtol(str, ptr, base);
}
+
+/*
+ * Or strerror :-(
+ */
+extern char *sys_errlist[];
+extern int sys_nerr;
+
+char *
+strerror(n)
+ int n;
+{
+ static char unknown[32];
+
+ if (n > 0 && n < sys_nerr)
+ return sys_errlist[n];
+ sprintf(unknown, "Error %d", n);
+ return unknown;
+}