1*38272Ssam #ifndef lint 2*38272Ssam static char *sccsid = "@(#)sliplogin.c 1.3 MS/ACF 89/04/18"; 3*38272Ssam #endif 4*38272Ssam 5*38272Ssam /* 6*38272Ssam * sliplogin.c 7*38272Ssam * 8*38272Ssam * This program initializes its own tty port to be an async TCP/IP interface. 9*38272Ssam * It merely sets up the SLIP module all by its lonesome on the STREAMS stack, 10*38272Ssam * initializes the network interface, and pauses forever waiting for hangup. 11*38272Ssam * 12*38272Ssam * It is a remote descendant of several similar programs with incestuous ties: 13*38272Ssam * - Kirk Smith's slipconf, modified by Richard Johnsson @ DEC WRL. 14*38272Ssam * - slattach, probably by Rick Adams but touched by countless hordes. 15*38272Ssam * - the original sliplogin for 4.2bsd, Doug Kingston the mover behind it. 16*38272Ssam * - a simple slattach-like program used to test the STREAMS SLIP code. 17*38272Ssam * 18*38272Ssam * There are three basic forms of usage: 19*38272Ssam * 20*38272Ssam * "sliplogin" 21*38272Ssam * Invoked simply as "sliplogin" and a realuid != 0, the program looks up 22*38272Ssam * the uid in /etc/passwd, and then the username in the file /etc/hosts.slip. 23*38272Ssam * If and entry is found, the line on fd0 is configured for SLIP operation 24*38272Ssam * as specified in the file. 25*38272Ssam * 26*38272Ssam * "sliplogin IPhost1 </dev/ttyb" 27*38272Ssam * Invoked by root with a username, the name is looked up in the 28*38272Ssam * /etc/hosts.slip file and if found fd0 is configured as in case 1. 29*38272Ssam * 30*38272Ssam * "sliplogin 192.100.1.1 192.100.1.2 255.255.255.0 < /dev/ttyb" 31*38272Ssam * Finally, if invoked with a remote addr, local addr, and optionally 32*38272Ssam * a net mask, the line on fd0 is setup as specified if the user is root. 33*38272Ssam * 34*38272Ssam * Doug Kingston 8810?? - logging + first pass at adding I_STR ioctl's 35*38272Ssam * Rayan Zachariassen 881011 - version for SunOS STREAMS SLIP 36*38272Ssam */ 37*38272Ssam 38*38272Ssam #include <sys/types.h> 39*38272Ssam #include <sys/socket.h> 40*38272Ssam #include <sys/stropts.h> 41*38272Ssam #include <sys/termios.h> 42*38272Ssam #include <sys/ttold.h> 43*38272Ssam #include <sys/sockio.h> 44*38272Ssam #include <sys/file.h> 45*38272Ssam #include <sys/syslog.h> 46*38272Ssam 47*38272Ssam #include <sys/slip.h> 48*38272Ssam 49*38272Ssam #include <netinet/in.h> 50*38272Ssam #include <net/if.h> 51*38272Ssam 52*38272Ssam #include <stdio.h> 53*38272Ssam #include <errno.h> 54*38272Ssam #include <ctype.h> 55*38272Ssam #include <netdb.h> 56*38272Ssam 57*38272Ssam #include <signal.h> 58*38272Ssam #include <strings.h> 59*38272Ssam #include <pwd.h> 60*38272Ssam #ifdef BSD >= 43 61*38272Ssam #include <ttyent.h> 62*38272Ssam #endif 63*38272Ssam 64*38272Ssam #define DCD_CHECK_INTERVAL 0 /* if > 0, time between automatic DCD checks */ 65*38272Ssam #define DCD_SETTLING_TIME 1 /* time between DCD change and status check */ 66*38272Ssam 67*38272Ssam int gotalarm = 0; 68*38272Ssam int timeleft = DCD_CHECK_INTERVAL; 69*38272Ssam 70*38272Ssam void 71*38272Ssam alarm_handler() 72*38272Ssam { 73*38272Ssam if (timeleft > DCD_SETTLING_TIME) 74*38272Ssam (void) alarm(timeleft-DCD_SETTLING_TIME); 75*38272Ssam else 76*38272Ssam (void) alarm(DCD_CHECK_INTERVAL); 77*38272Ssam gotalarm = 1; 78*38272Ssam timeleft = 0; 79*38272Ssam } 80*38272Ssam 81*38272Ssam #if defined(SIGDCD) && SIGDCD > 0 82*38272Ssam void 83*38272Ssam dcd_handler() 84*38272Ssam { 85*38272Ssam #if DCD_SETTLING_TIME > 0 86*38272Ssam timeleft = alarm(DCD_SETTLING_TIME); 87*38272Ssam #else 88*38272Ssam gotalarm = 1; 89*38272Ssam #endif /* DCD_SETTLING_TIME */ 90*38272Ssam } 91*38272Ssam #endif 92*38272Ssam 93*38272Ssam /* Use TIOCMGET to test if DCD is low on the port of the passed descriptor */ 94*38272Ssam 95*38272Ssam int 96*38272Ssam lowdcd(fd) 97*38272Ssam int fd; 98*38272Ssam { 99*38272Ssam int mbits; 100*38272Ssam 101*38272Ssam if (ioctl(fd, TIOCMGET, (caddr_t)&mbits) < 0) 102*38272Ssam return 1; /* port is dead, we die */ 103*38272Ssam return !(mbits & TIOCM_CAR); 104*38272Ssam } 105*38272Ssam 106*38272Ssam char *Accessfile = "/etc/hosts.slip"; 107*38272Ssam 108*38272Ssam extern char *malloc(), *ttyname(); 109*38272Ssam extern struct passwd *getpwuid(); 110*38272Ssam 111*38272Ssam char *dstaddr, *localaddr, *netmask; 112*38272Ssam 113*38272Ssam main(argc, argv) 114*38272Ssam int argc; 115*38272Ssam char *argv[]; 116*38272Ssam { 117*38272Ssam int fd, s, unit; 118*38272Ssam struct termios tios; 119*38272Ssam struct ifreq ifr; 120*38272Ssam 121*38272Ssam s = getdtablesize(); 122*38272Ssam for (fd = 3 ; fd < s ; fd++) 123*38272Ssam close(fd); 124*38272Ssam 125*38272Ssam openlog("sliplogin", LOG_PID, LOG_DAEMON); 126*38272Ssam 127*38272Ssam if (getuid() == 0) { 128*38272Ssam if (argc <= 1) { 129*38272Ssam fprintf(stderr, "Usage: %s loginname\n", argv[0]); 130*38272Ssam fprintf(stderr, " or: %s dstaddr localaddr [mask]\n", 131*38272Ssam argv[0]); 132*38272Ssam exit(1); 133*38272Ssam } else if (argc == 2) { 134*38272Ssam findid(argv[1]); 135*38272Ssam fprintf(stderr, "local %s remote %s mask %s\n", 136*38272Ssam localaddr, dstaddr, netmask); 137*38272Ssam } if (argc > 2) { 138*38272Ssam if (argc < 3 || argc > 4) { 139*38272Ssam fprintf(stderr, 140*38272Ssam "Usage: %s dstaddr localaddr [mask]\n", 141*38272Ssam argv[0]); 142*38272Ssam exit(1); 143*38272Ssam } 144*38272Ssam dstaddr = argv[1]; 145*38272Ssam localaddr = argv[2]; 146*38272Ssam if (argc == 4) 147*38272Ssam netmask = argv[3]; 148*38272Ssam else 149*38272Ssam netmask = "default"; 150*38272Ssam } 151*38272Ssam } else 152*38272Ssam findid((char *)0); 153*38272Ssam 154*38272Ssam /* ensure that the slip line is our controlling terminal */ 155*38272Ssam if ((fd = open("/dev/tty", O_RDONLY, 0)) >= 0) { 156*38272Ssam (void) ioctl(fd, TIOCNOTTY, 0); 157*38272Ssam (void) close(fd); 158*38272Ssam fd = open(ttyname(0), O_RDWR, 0); 159*38272Ssam if (fd >= 0) 160*38272Ssam (void) close(fd); 161*38272Ssam (void) setpgrp(0, getpid()); 162*38272Ssam } 163*38272Ssam 164*38272Ssam fchmod(0, 0600); 165*38272Ssam 166*38272Ssam /* pop all streams modules */ 167*38272Ssam while (ioctl(0, I_POP, 0) == 0) 168*38272Ssam continue; 169*38272Ssam 170*38272Ssam /* set up the line parameters */ 171*38272Ssam if (ioctl(0, TCGETS, (caddr_t)&tios) < 0) { 172*38272Ssam syslog(LOG_ERR, "ioctl (TCGETS): %m"); 173*38272Ssam exit(1); 174*38272Ssam } 175*38272Ssam tios.c_cflag &= 0xf; /* only save the speed */ 176*38272Ssam tios.c_cflag |= CS8|CREAD|HUPCL; 177*38272Ssam tios.c_iflag = IGNBRK; 178*38272Ssam if (ioctl(0, TCSETS, (caddr_t)&tios) < 0) { 179*38272Ssam syslog(LOG_ERR, "ioctl (TCSETS): %m"); 180*38272Ssam exit(1); 181*38272Ssam } 182*38272Ssam 183*38272Ssam /* push the SLIP module */ 184*38272Ssam if (ioctl(0, I_PUSH, "slip") < 0) { 185*38272Ssam syslog(LOG_ERR, "ioctl (I_PUSH): %m"); 186*38272Ssam exit(1); 187*38272Ssam } 188*38272Ssam 189*38272Ssam /* find out what unit number we were assigned */ 190*38272Ssam if (ioctl(0, SLIOGUNIT, (caddr_t)&unit) < 0) { 191*38272Ssam syslog(LOG_ERR, "ioctl (SLIOGUNIT): %m"); 192*38272Ssam exit(1); 193*38272Ssam } 194*38272Ssam 195*38272Ssam syslog(LOG_NOTICE, "attaching slip%d: local %s remote %s mask %s\n", 196*38272Ssam unit, localaddr, dstaddr, netmask); 197*38272Ssam 198*38272Ssam /* set the local and remote interface addresses */ 199*38272Ssam s = socket(AF_INET, SOCK_DGRAM, 0); 200*38272Ssam 201*38272Ssam if (getuid() != 0 || argc == 4) { 202*38272Ssam (void) sprintf(ifr.ifr_name, "%s%d", SLIPIFNAME, unit); 203*38272Ssam in_getaddr(netmask, &ifr.ifr_addr); 204*38272Ssam if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0) { 205*38272Ssam syslog(LOG_ERR, "ioctl (SIOCSIFNETMASK): %m"); 206*38272Ssam exit(1); 207*38272Ssam } 208*38272Ssam } 209*38272Ssam 210*38272Ssam (void) sprintf(ifr.ifr_name, "%s%d", SLIPIFNAME, unit); 211*38272Ssam in_getaddr(dstaddr, &ifr.ifr_addr); 212*38272Ssam if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0) { 213*38272Ssam syslog(LOG_ERR, "ioctl (SIOCSIFDSTADDR): %m"); 214*38272Ssam exit(1); 215*38272Ssam } 216*38272Ssam 217*38272Ssam (void) sprintf(ifr.ifr_name, "%s%d", SLIPIFNAME, unit); 218*38272Ssam in_getaddr(localaddr, &ifr.ifr_addr); 219*38272Ssam /* this has the side-effect of marking the interface up */ 220*38272Ssam if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0) { 221*38272Ssam syslog(LOG_ERR, "ioctl (SIOCSIFADDR): %m"); 222*38272Ssam exit(1); 223*38272Ssam } 224*38272Ssam 225*38272Ssam /* set up signal handlers */ 226*38272Ssam #if defined(SIGDCD) && SIGDCD > 0 227*38272Ssam (void) signal(SIGDCD, dcd_handler); 228*38272Ssam #endif 229*38272Ssam (void) sigblock(sigmask(SIGALRM)); 230*38272Ssam (void) signal(SIGALRM, alarm_handler); 231*38272Ssam /* a SIGHUP will kill us */ 232*38272Ssam 233*38272Ssam /* timeleft = 60 * 60 * 24 * 365 ; (void) alarm(timeleft); */ 234*38272Ssam 235*38272Ssam /* twiddle thumbs until we get a signal */ 236*38272Ssam while (1) { 237*38272Ssam sigpause(0); 238*38272Ssam (void) sigblock(sigmask(SIGALRM)); 239*38272Ssam if (gotalarm && lowdcd(0)) 240*38272Ssam break; 241*38272Ssam gotalarm = 0; 242*38272Ssam } 243*38272Ssam 244*38272Ssam /* closing the descriptor should pop the slip module */ 245*38272Ssam exit(0); 246*38272Ssam } 247*38272Ssam 248*38272Ssam findid(name) 249*38272Ssam char *name; 250*38272Ssam { 251*38272Ssam char buf[BUFSIZ]; 252*38272Ssam static char mode[16]; 253*38272Ssam static char laddr[16]; 254*38272Ssam static char raddr[16]; 255*38272Ssam static char mask[16]; 256*38272Ssam char user[16]; 257*38272Ssam FILE *fp; 258*38272Ssam struct passwd *pw; 259*38272Ssam int n; 260*38272Ssam 261*38272Ssam if (name == NULL && (pw = getpwuid(getuid())) == NULL) { 262*38272Ssam fprintf(stderr, "Your UID (%d) is unknown\n", getuid()); 263*38272Ssam syslog(LOG_ERR, "UID (%d) is unknown\n", getuid()); 264*38272Ssam exit(1); 265*38272Ssam } else if (name == NULL) 266*38272Ssam name = pw->pw_name; 267*38272Ssam if ((fp = fopen(Accessfile, "r")) == NULL) { 268*38272Ssam perror(Accessfile); 269*38272Ssam syslog(LOG_ERR, "%s: %m\n", Accessfile); 270*38272Ssam exit(3); 271*38272Ssam } 272*38272Ssam while (fgets(buf, sizeof(buf) - 1, fp)) { 273*38272Ssam if (ferror(fp)) 274*38272Ssam break; 275*38272Ssam n = sscanf(buf, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n", 276*38272Ssam user, mode, laddr, raddr, mask); 277*38272Ssam if (user[0] == '#' || n != 5) 278*38272Ssam continue; 279*38272Ssam if (strcmp(user, name) == 0) { 280*38272Ssam /* eventually deal with "mode" */ 281*38272Ssam localaddr = laddr; 282*38272Ssam dstaddr = raddr; 283*38272Ssam netmask = mask; 284*38272Ssam fclose(fp); 285*38272Ssam return 0; 286*38272Ssam } 287*38272Ssam if (feof(fp)) 288*38272Ssam break; 289*38272Ssam } 290*38272Ssam fputs("SLIP access denied\n", stderr); 291*38272Ssam syslog(LOG_ERR, "SLIP access denied for %s\n", name); 292*38272Ssam exit(4); 293*38272Ssam } 294*38272Ssam 295*38272Ssam in_getaddr(s, saddr) 296*38272Ssam char *s; 297*38272Ssam struct sockaddr *saddr; 298*38272Ssam { 299*38272Ssam register struct sockaddr_in *sin = (struct sockaddr_in *)saddr; 300*38272Ssam struct hostent *hp; 301*38272Ssam struct netent *np; 302*38272Ssam int val; 303*38272Ssam extern struct in_addr inet_makeaddr(); 304*38272Ssam 305*38272Ssam bzero((caddr_t)saddr, sizeof *saddr); 306*38272Ssam sin->sin_family = AF_INET; 307*38272Ssam val = inet_addr(s); 308*38272Ssam if (val != -1) { 309*38272Ssam sin->sin_addr.s_addr = val; 310*38272Ssam return; 311*38272Ssam } 312*38272Ssam hp = gethostbyname(s); 313*38272Ssam if (hp) { 314*38272Ssam sin->sin_family = hp->h_addrtype; 315*38272Ssam bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 316*38272Ssam return; 317*38272Ssam } 318*38272Ssam np = getnetbyname(s); 319*38272Ssam if (np) { 320*38272Ssam sin->sin_family = np->n_addrtype; 321*38272Ssam sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 322*38272Ssam return; 323*38272Ssam } 324*38272Ssam fprintf(stderr, "sliplogin: %s: bad value\n", s); 325*38272Ssam syslog(LOG_ERR, "%s: bad value\n", s); 326*38272Ssam exit(1); 327*38272Ssam } 328*38272Ssam 329