1*44262Sbostic /*- 2*44262Sbostic * Copyright (c) 1990 The Regents of the University of California. 3*44262Sbostic * All rights reserved. 4*44262Sbostic * 5*44262Sbostic * %sccs.include.redist.c% 6*44262Sbostic */ 7*44262Sbostic 838272Ssam #ifndef lint 9*44262Sbostic char copyright[] = 10*44262Sbostic "@(#) Copyright (c) 1990 The Regents of the University of California.\n\ 11*44262Sbostic All rights reserved.\n"; 12*44262Sbostic #endif /* not lint */ 13*44262Sbostic 14*44262Sbostic #ifndef lint 15*44262Sbostic static char sccsid[] = "@(#)sliplogin.c 5.1 (Berkeley) 06/25/90"; 16*44262Sbostic #endif /* not lint */ 17*44262Sbostic 1840016Ssam /* from static char *sccsid = "@(#)sliplogin.c 1.3 MS/ACF 89/04/18"; */ 1938272Ssam 2038272Ssam /* 2138272Ssam * sliplogin.c 2238373Skarels * [MUST BE RUN SUID, SLOPEN DOES A SUSER()!] 2338272Ssam * 2438272Ssam * This program initializes its own tty port to be an async TCP/IP interface. 2538272Ssam * It merely sets up the SLIP module all by its lonesome on the STREAMS stack, 2638272Ssam * initializes the network interface, and pauses forever waiting for hangup. 2738272Ssam * 2838272Ssam * It is a remote descendant of several similar programs with incestuous ties: 2938272Ssam * - Kirk Smith's slipconf, modified by Richard Johnsson @ DEC WRL. 3038272Ssam * - slattach, probably by Rick Adams but touched by countless hordes. 3138272Ssam * - the original sliplogin for 4.2bsd, Doug Kingston the mover behind it. 3238272Ssam * - a simple slattach-like program used to test the STREAMS SLIP code. 3338272Ssam * 3438272Ssam * There are three basic forms of usage: 3538272Ssam * 3638272Ssam * "sliplogin" 3738272Ssam * Invoked simply as "sliplogin" and a realuid != 0, the program looks up 3838272Ssam * the uid in /etc/passwd, and then the username in the file /etc/hosts.slip. 3938272Ssam * If and entry is found, the line on fd0 is configured for SLIP operation 4038272Ssam * as specified in the file. 4138272Ssam * 4238272Ssam * "sliplogin IPhost1 </dev/ttyb" 4338272Ssam * Invoked by root with a username, the name is looked up in the 4438272Ssam * /etc/hosts.slip file and if found fd0 is configured as in case 1. 4538272Ssam * 4638272Ssam * "sliplogin 192.100.1.1 192.100.1.2 255.255.255.0 < /dev/ttyb" 4738272Ssam * Finally, if invoked with a remote addr, local addr, and optionally 4838272Ssam * a net mask, the line on fd0 is setup as specified if the user is root. 4938272Ssam * 5038272Ssam * Doug Kingston 8810?? - logging + first pass at adding I_STR ioctl's 5138272Ssam * Rayan Zachariassen 881011 - version for SunOS STREAMS SLIP 5238272Ssam */ 5338272Ssam 5438272Ssam #include <sys/types.h> 5538272Ssam #include <sys/socket.h> 5638272Ssam #include <sys/termios.h> 5738372Ssam #include <sys/ioctl.h> 5838272Ssam #include <sys/file.h> 5938272Ssam #include <sys/syslog.h> 6038272Ssam 6138272Ssam #include <netinet/in.h> 6238272Ssam #include <net/if.h> 6338373Skarels #include <net/if_slvar.h> /* XXX */ 6438272Ssam 6538272Ssam #include <stdio.h> 6638272Ssam #include <errno.h> 6738272Ssam #include <ctype.h> 6838272Ssam #include <netdb.h> 6938272Ssam 7038272Ssam #include <signal.h> 7138272Ssam #include <strings.h> 7238272Ssam #include <pwd.h> 7338272Ssam #include <ttyent.h> 7438272Ssam 7538372Ssam #define SLIPIFNAME "sl" 7638372Ssam 7738372Ssam #define ADDR 1 7838372Ssam #define MASK 2 7938372Ssam 8040016Ssam #define DCD_CHECK_INTERVAL 0 /* if > 0, time between automatic DCD checks */ 8138272Ssam #define DCD_SETTLING_TIME 1 /* time between DCD change and status check */ 8238272Ssam 8338272Ssam int gotalarm = 0; 8438272Ssam int timeleft = DCD_CHECK_INTERVAL; 8538272Ssam 8638272Ssam #if defined(SIGDCD) && SIGDCD > 0 8738272Ssam void 8838272Ssam dcd_handler() 8938272Ssam { 9038272Ssam #if DCD_SETTLING_TIME > 0 9138272Ssam timeleft = alarm(DCD_SETTLING_TIME); 9238272Ssam #else 9338272Ssam gotalarm = 1; 9438272Ssam #endif /* DCD_SETTLING_TIME */ 9538272Ssam } 9638272Ssam #endif 9738272Ssam 9840016Ssam #if DCD_CHECK_INTERVAL > 0 9940016Ssam void 10040016Ssam alarm_handler() 10140016Ssam { 10240016Ssam #ifdef SIGDCD 10340016Ssam if (timeleft > DCD_SETTLING_TIME) 10440016Ssam (void) alarm(timeleft-DCD_SETTLING_TIME); 10540016Ssam else 10640016Ssam #endif /* SIGDCD */ 10740016Ssam (void) alarm(DCD_CHECK_INTERVAL); 10840016Ssam gotalarm = 1; 10940016Ssam timeleft = 0; 11040016Ssam } 11140016Ssam 11238272Ssam /* Use TIOCMGET to test if DCD is low on the port of the passed descriptor */ 11338272Ssam 11438272Ssam int 11538272Ssam lowdcd(fd) 11638272Ssam int fd; 11738272Ssam { 11838272Ssam int mbits; 11938272Ssam 12038272Ssam if (ioctl(fd, TIOCMGET, (caddr_t)&mbits) < 0) 12138272Ssam return 1; /* port is dead, we die */ 12238272Ssam return !(mbits & TIOCM_CAR); 12338272Ssam } 12440016Ssam #endif /* DCD_CHECK_INTERVAL > 0 */ 12538272Ssam 12638272Ssam char *Accessfile = "/etc/hosts.slip"; 12738272Ssam 12838272Ssam extern char *malloc(), *ttyname(); 12938272Ssam extern struct passwd *getpwuid(); 13038272Ssam 13138272Ssam char *dstaddr, *localaddr, *netmask; 13238373Skarels int slip_mode, unit; 13338272Ssam 13438373Skarels struct slip_modes { 13538373Skarels char *sm_name; 13638373Skarels int sm_value; 13738373Skarels } modes[] = { 13838373Skarels "normal", 0, /* slip "standard" ala Rick Adams */ 13938373Skarels "compress", SC_COMPRESS, /* Van Jacobsen's tcp header comp. */ 14038373Skarels "noicmp", SC_NOICMP, /* Sam's(?) ICMP suppression */ 14138373Skarels } ; 14238373Skarels 14338373Skarels void 14440016Ssam hup_handler(s) 14540016Ssam int s; 14638373Skarels { 14740016Ssam 14840016Ssam syslog(LOG_INFO, 14940016Ssam "%s%d: connection closed: process aborted, sig %d, remote %s\n", 15040016Ssam SLIPIFNAME, unit, s, dstaddr); 15140016Ssam if (close(0) < 0) 15240016Ssam syslog(LOG_ERR, "(hup) close: %m"); 15340016Ssam else 15440016Ssam syslog(LOG_INFO, "(hup) close completed"); 15538373Skarels exit(1) ; 15638373Skarels } 15738373Skarels 15838272Ssam main(argc, argv) 15938272Ssam int argc; 16038272Ssam char *argv[]; 16138272Ssam { 16238373Skarels int fd, s, ldisc, odisc; 16338373Skarels struct termios tios, otios; 16438272Ssam struct ifreq ifr; 16538272Ssam 16638272Ssam s = getdtablesize(); 16738272Ssam for (fd = 3 ; fd < s ; fd++) 16838272Ssam close(fd); 16938272Ssam openlog("sliplogin", LOG_PID, LOG_DAEMON); 17038272Ssam if (getuid() == 0) { 17138272Ssam if (argc <= 1) { 17238272Ssam fprintf(stderr, "Usage: %s loginname\n", argv[0]); 17338272Ssam fprintf(stderr, " or: %s dstaddr localaddr [mask]\n", 17438272Ssam argv[0]); 17538272Ssam exit(1); 17638272Ssam } else if (argc == 2) { 17738272Ssam findid(argv[1]); 17838272Ssam fprintf(stderr, "local %s remote %s mask %s\n", 17938272Ssam localaddr, dstaddr, netmask); 18038272Ssam } if (argc > 2) { 18138272Ssam if (argc < 3 || argc > 4) { 18238272Ssam fprintf(stderr, 18338272Ssam "Usage: %s dstaddr localaddr [mask]\n", 18438272Ssam argv[0]); 18538272Ssam exit(1); 18638272Ssam } 18738272Ssam dstaddr = argv[1]; 18838272Ssam localaddr = argv[2]; 18938272Ssam if (argc == 4) 19038272Ssam netmask = argv[3]; 19138272Ssam else 19238272Ssam netmask = "default"; 19338272Ssam } 19440016Ssam /* 19540016Ssam * Disassociate from current controlling terminal, if any, 19640016Ssam * and ensure that the slip line is our controlling terminal. 19740016Ssam */ 19840016Ssam #if !defined(BSD) || BSD < 198810 19940016Ssam if ((fd = open("/dev/tty", O_RDONLY, 0)) >= 0) { 20040016Ssam (void) ioctl(fd, TIOCNOTTY, 0); 20140016Ssam (void) close(fd); 20240016Ssam /* open slip tty again to acquire as controlling tty? */ 20340016Ssam fd = open(ttyname(0), O_RDWR, 0); 20440016Ssam if (fd >= 0) 20540016Ssam (void) close(fd); 20640016Ssam } 20740016Ssam (void) setpgrp(0, getpid()); 20840016Ssam #else 20940016Ssam (void) setsid(); 21040016Ssam (void) ioctl(0, TIOCSCTTY, 0); /* not sure this will work */ 21140016Ssam #endif 21238272Ssam } else 21338272Ssam findid((char *)0); 21438272Ssam fchmod(0, 0600); 21538272Ssam /* set up the line parameters */ 21640016Ssam if (ioctl(0, TIOCGETA, (caddr_t)&tios) < 0) { 21740016Ssam syslog(LOG_ERR, "ioctl (TIOCGETA): %m"); 21838272Ssam exit(1); 21938272Ssam } 22040016Ssam otios = tios; 22140016Ssam tios.c_cflag = CS8|CREAD|HUPCL; 22238272Ssam tios.c_iflag = IGNBRK; 22338372Ssam tios.c_oflag = tios.c_lflag = 0; 22440016Ssam if (ioctl(0, TIOCSETA, (caddr_t)&tios) < 0) { 22540016Ssam syslog(LOG_ERR, "ioctl (TIOCSETA) (1): %m"); 22638272Ssam exit(1); 22738272Ssam } 22838373Skarels /* find out what ldisc we started with */ 22938373Skarels if (ioctl(0, TIOCGETD, (caddr_t)&odisc) < 0) { 23038373Skarels syslog(LOG_ERR, "ioctl(TIOCGETD) (1): %m"); 23138373Skarels exit(1); 23238373Skarels } 23338372Ssam ldisc = SLIPDISC; 23438372Ssam if (ioctl(0, TIOCSETD, (caddr_t)&ldisc) < 0) { 23540016Ssam syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); 23638272Ssam exit(1); 23738272Ssam } 23838272Ssam /* find out what unit number we were assigned */ 23938372Ssam if (ioctl(0, TIOCGETD, (caddr_t)&unit) < 0) { 24038373Skarels syslog(LOG_ERR, "ioctl (TIOCGETD) (2): %m"); 24138272Ssam exit(1); 24238272Ssam } 24340016Ssam syslog(LOG_INFO, "attaching %s%d: local %s remote %s mask %s\n", 24438372Ssam SLIPIFNAME, unit, localaddr, dstaddr, netmask); 24538372Ssam #ifdef notdef 24638272Ssam /* set the local and remote interface addresses */ 24738272Ssam s = socket(AF_INET, SOCK_DGRAM, 0); 24838272Ssam if (getuid() != 0 || argc == 4) { 24938272Ssam (void) sprintf(ifr.ifr_name, "%s%d", SLIPIFNAME, unit); 25038372Ssam in_getaddr(netmask, &ifr.ifr_addr, MASK); 25138272Ssam if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0) { 25238272Ssam syslog(LOG_ERR, "ioctl (SIOCSIFNETMASK): %m"); 25338272Ssam exit(1); 25438272Ssam } 25538272Ssam } 25638272Ssam (void) sprintf(ifr.ifr_name, "%s%d", SLIPIFNAME, unit); 25738372Ssam in_getaddr(dstaddr, &ifr.ifr_addr, ADDR); 25838272Ssam if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0) { 25938272Ssam syslog(LOG_ERR, "ioctl (SIOCSIFDSTADDR): %m"); 26038272Ssam exit(1); 26138272Ssam } 26238272Ssam (void) sprintf(ifr.ifr_name, "%s%d", SLIPIFNAME, unit); 26338372Ssam in_getaddr(localaddr, &ifr.ifr_addr, ADDR); 26438272Ssam /* this has the side-effect of marking the interface up */ 26538272Ssam if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0) { 26638272Ssam syslog(LOG_ERR, "ioctl (SIOCSIFADDR): %m"); 26738272Ssam exit(1); 26838272Ssam } 26938372Ssam #else 27038372Ssam /* XXX -- give up for now and just invoke ifconfig XXX */ 27138372Ssam { char cmd[256]; 27238372Ssam sprintf(cmd, "/sbin/ifconfig %s%d inet %s %s netmask %s", 27338372Ssam SLIPIFNAME, unit, localaddr, dstaddr, netmask); 27438372Ssam system(cmd); 27538372Ssam } 27640016Ssam #endif 27738373Skarels if (ioctl(0, SLIOCSFLAGS, (caddr_t)&slip_mode) < 0) { 27838373Skarels syslog(LOG_ERR, "ioctl (SLIOCSFLAGS): %m"); 27938373Skarels exit(1); 28038373Skarels } 28138272Ssam 28238272Ssam /* set up signal handlers */ 28338272Ssam #if defined(SIGDCD) && SIGDCD > 0 28438272Ssam (void) signal(SIGDCD, dcd_handler); 28538272Ssam #endif 28638272Ssam (void) sigblock(sigmask(SIGALRM)); 28738373Skarels (void) signal(SIGHUP, hup_handler); 28838373Skarels (void) signal(SIGTERM, hup_handler); 28938272Ssam 29040016Ssam #if DCD_CHECK_INTERVAL > 0 29138272Ssam /* timeleft = 60 * 60 * 24 * 365 ; (void) alarm(timeleft); */ 29240016Ssam (void) signal(SIGALRM, alarm_handler); 29338373Skarels (void) alarm(DCD_CHECK_INTERVAL); 29440016Ssam #endif 29538272Ssam 29638272Ssam /* twiddle thumbs until we get a signal */ 29738272Ssam while (1) { 29838272Ssam sigpause(0); 29940016Ssam #if DCD_CHECK_INTERVAL > 0 30038272Ssam (void) sigblock(sigmask(SIGALRM)); 30138272Ssam if (gotalarm && lowdcd(0)) 30238272Ssam break; 30338272Ssam gotalarm = 0; 30440016Ssam #endif /* DCD_CHECK_INTERVAL > 0 */ 30538272Ssam } 30638272Ssam 30740016Ssam #ifdef notdef 30838373Skarels if (lowdcd(0)) 30938373Skarels syslog(LOG_NOTICE, 31038373Skarels "connection closed: loss of carrier %s%d: remote %s\n", 31138373Skarels SLIPIFNAME, unit, dstaddr); 31240016Ssam #endif 31338373Skarels 31438373Skarels if (ioctl(0, TIOCSETD, (caddr_t)&odisc) < 0) { 31538373Skarels syslog(LOG_ERR, "ioctl(TIOCSETD) (2): %m"); 31638373Skarels exit(1); 31738373Skarels } 31840016Ssam if (ioctl(0, TIOCSETA, (caddr_t)&otios) < 0) { 31940016Ssam syslog(LOG_ERR, "ioctl (TIOCSETA) (2): %m"); 32038373Skarels exit(1); 32138373Skarels } 32240016Ssam if (close(0) < 0) { 32340016Ssam syslog(LOG_ERR, "close: %m"); 32440016Ssam exit(1); 32540016Ssam } 32638272Ssam exit(0); 32738272Ssam } 32838272Ssam 32938272Ssam findid(name) 33038272Ssam char *name; 33138272Ssam { 33238272Ssam char buf[BUFSIZ]; 33338272Ssam static char mode[16]; 33438272Ssam static char laddr[16]; 33538272Ssam static char raddr[16]; 33638272Ssam static char mask[16]; 33738272Ssam char user[16]; 33838272Ssam FILE *fp; 33938272Ssam struct passwd *pw; 34038272Ssam int n; 34138272Ssam 34238272Ssam if (name == NULL && (pw = getpwuid(getuid())) == NULL) { 34338272Ssam fprintf(stderr, "Your UID (%d) is unknown\n", getuid()); 34438272Ssam syslog(LOG_ERR, "UID (%d) is unknown\n", getuid()); 34538272Ssam exit(1); 34638272Ssam } else if (name == NULL) 34738272Ssam name = pw->pw_name; 34838272Ssam if ((fp = fopen(Accessfile, "r")) == NULL) { 34938272Ssam perror(Accessfile); 35038272Ssam syslog(LOG_ERR, "%s: %m\n", Accessfile); 35138272Ssam exit(3); 35238272Ssam } 35338272Ssam while (fgets(buf, sizeof(buf) - 1, fp)) { 35438272Ssam if (ferror(fp)) 35538272Ssam break; 35638272Ssam n = sscanf(buf, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n", 35738272Ssam user, mode, laddr, raddr, mask); 35838272Ssam if (user[0] == '#' || n != 5) 35938272Ssam continue; 36038272Ssam if (strcmp(user, name) == 0) { 36138373Skarels char *p,*q; int val, i, domore; 36238373Skarels 36338373Skarels p = q = mode; val = 0; 36438373Skarels loop: 36538373Skarels while (isalnum(*p)) p++; 36638373Skarels if(ispunct(*p) || *p == '\0') { 36738373Skarels if(ispunct(*p)) domore = 1; else domore = 0; 36838373Skarels *p++ = '\0' ; 36938373Skarels for (i = 0; i < 37038373Skarels sizeof(modes)/sizeof(struct slip_modes) 37138373Skarels ; i++) { 37238373Skarels if (strcmp(modes[i].sm_name, q) == 0) { 37338373Skarels val |= modes[i].sm_value ; 37438373Skarels break; 37538373Skarels } ; 37638373Skarels } 37738373Skarels q = p; 37838373Skarels if(domore)goto loop; 37938373Skarels } 38038373Skarels 38138373Skarels slip_mode = val ; 38238272Ssam localaddr = laddr; 38338272Ssam dstaddr = raddr; 38438272Ssam netmask = mask; 38538272Ssam fclose(fp); 38638272Ssam return 0; 38738272Ssam } 38838272Ssam if (feof(fp)) 38938272Ssam break; 39038272Ssam } 39138272Ssam fputs("SLIP access denied\n", stderr); 39238272Ssam syslog(LOG_ERR, "SLIP access denied for %s\n", name); 39338272Ssam exit(4); 39438272Ssam } 39538272Ssam 39638372Ssam in_getaddr(s, saddr, which) 39738272Ssam char *s; 39838272Ssam struct sockaddr *saddr; 39938372Ssam int which; 40038272Ssam { 40138272Ssam register struct sockaddr_in *sin = (struct sockaddr_in *)saddr; 40238272Ssam struct hostent *hp; 40338272Ssam struct netent *np; 40438272Ssam int val; 40538272Ssam extern struct in_addr inet_makeaddr(); 40638272Ssam 40738272Ssam bzero((caddr_t)saddr, sizeof *saddr); 40838372Ssam if (which == ADDR) { 40938372Ssam sin->sin_len = sizeof (*sin); 41038372Ssam sin->sin_family = AF_INET; 41138372Ssam } else 41238372Ssam sin->sin_len = 8; 41338272Ssam val = inet_addr(s); 41438272Ssam if (val != -1) { 41538272Ssam sin->sin_addr.s_addr = val; 41638272Ssam return; 41738272Ssam } 41838272Ssam hp = gethostbyname(s); 41938272Ssam if (hp) { 42038272Ssam sin->sin_family = hp->h_addrtype; 42138272Ssam bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 42238272Ssam return; 42338272Ssam } 42438272Ssam np = getnetbyname(s); 42538272Ssam if (np) { 42638272Ssam sin->sin_family = np->n_addrtype; 42738272Ssam sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 42838272Ssam return; 42938272Ssam } 43038272Ssam fprintf(stderr, "sliplogin: %s: bad value\n", s); 43138272Ssam syslog(LOG_ERR, "%s: bad value\n", s); 43238272Ssam exit(1); 43338272Ssam } 434