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