Added -vjccid and vj-max-slots options, and reorganized in
[ppp.git] / pppd / sys-ultrix.c
1 /*
2  * sys-ultrix.c - System-dependent procedures for setting up
3  * PPP interfaces on Ultrix systems.
4  *
5  * Copyright (c) 1989 Carnegie Mellon University.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by Carnegie Mellon University.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20
21 #ifndef lint
22 static char rcsid[] = "$Id: sys-ultrix.c,v 1.14 1995/08/11 02:36:26 paulus Exp $";
23 #endif
24
25 /*
26  * TODO:
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <syslog.h>
32 #include <string.h>
33 #include <termios.h>
34 #include <utmp.h>
35 #include <sys/types.h>
36 #include <sys/file.h>
37 #include <sys/socket.h>
38 #include <sys/ioctl.h>
39 #include <sys/time.h>
40 #include <sys/errno.h>
41 #include <sys/stat.h>
42
43 #include <net/if.h>
44 #include <net/ppp_defs.h>
45 #include <net/if_ppp.h>
46 #include <net/route.h>
47 #include <netinet/in.h>
48
49 #include "pppd.h"
50
51 static int initdisc = -1;       /* Initial TTY discipline */
52
53 static int      restore_term;   /* 1 => we've munged the terminal */
54 static struct termios inittermios; /* Initial TTY termios */
55 static struct winsize wsinfo;   /* Initial window size info */
56
57 static char *lock_file;
58
59 int sockfd;                     /* socket for doing interface ioctls */
60
61 /*
62  * sys_init - System-dependent initialization.
63  */
64 void
65 sys_init()
66 {
67     openlog("pppd", LOG_PID);
68
69     /* Get an internet socket for doing socket ioctl's on. */
70     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
71         syslog(LOG_ERR, "Couldn't create IP socket: %m");
72         die(1);
73     }
74 }
75
76 /*
77  * note_debug_level - note a change in the debug level.
78  */
79 void
80 note_debug_level()
81 {
82 }
83
84
85 /*
86  * daemon - Detach us from the terminal session.
87  */
88 int
89 daemon(nochdir, noclose)
90     int nochdir, noclose;
91 {
92     int pid;
93
94     if ((pid = fork()) < 0)
95         return -1;
96     if (pid != 0)
97         exit(0);                /* parent dies */
98     setsid();
99     if (!nochdir)
100         chdir("/");
101     if (!noclose) {
102         fclose(stdin);          /* don't need stdin, stdout, stderr */
103         fclose(stdout);
104         fclose(stderr);
105     }
106     return 0;
107 }
108
109
110 /*
111  * ppp_available - check whether the system has any ppp interfaces
112  * (in fact we check whether we can do an ioctl on ppp0).
113  */
114
115 int
116 ppp_available()
117 {
118     int s, ok;
119     struct ifreq ifr;
120
121     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
122         return 1;               /* can't tell - maybe we're not root */
123
124     strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
125     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
126     close(s);
127
128     return ok;
129 }
130
131
132 /*
133  * establish_ppp - Turn the serial port into a ppp interface.
134  */
135 void
136 establish_ppp()
137 {
138     int pppdisc = PPPDISC;
139     int x;
140
141     if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
142         syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
143         die(1);
144     }
145     if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
146         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
147         die(1);
148     }
149
150     /*
151      * Find out which interface we were given.
152      */
153     if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {  
154         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
155         die(1);
156     }
157
158     /*
159      * Enable debug in the driver if requested.
160      */
161     if (kdebugflag) {
162         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
163             syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
164         } else {
165             x |= (kdebugflag & 0xFF) * SC_DEBUG;
166             if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
167                 syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
168         }
169     }
170 }
171
172
173 /*
174  * disestablish_ppp - Restore the serial port to normal operation.
175  * This shouldn't call die() because it's called from die().
176  */
177 void
178 disestablish_ppp()
179 {
180     int x;
181     char *s;
182
183     if (initdisc >= 0) {
184         /*
185          * Check whether the link seems not to be 8-bit clean.
186          */
187         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
188             s = NULL;
189             switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
190             case SC_RCV_B7_0:
191                 s = "bit 7 set to 1";
192                 break;
193             case SC_RCV_B7_1:
194                 s = "bit 7 set to 0";
195                 break;
196             case SC_RCV_EVNP:
197                 s = "odd parity";
198                 break;
199             case SC_RCV_ODDP:
200                 s = "even parity";
201                 break;
202             }
203             if (s != NULL) {
204                 syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
205                 syslog(LOG_WARNING, "All received characters had %s", s);
206             }
207         }
208         if (ioctl(fd, TIOCSETD, &initdisc) < 0)
209             syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
210     }
211 }
212
213
214 /*
215  * List of valid speeds.
216  */
217 struct speed {
218     int speed_int, speed_val;
219 } speeds[] = {
220 #ifdef B50
221     { 50, B50 },
222 #endif
223 #ifdef B75
224     { 75, B75 },
225 #endif
226 #ifdef B110
227     { 110, B110 },
228 #endif
229 #ifdef B134
230     { 134, B134 },
231 #endif
232 #ifdef B150
233     { 150, B150 },
234 #endif
235 #ifdef B200
236     { 200, B200 },
237 #endif
238 #ifdef B300
239     { 300, B300 },
240 #endif
241 #ifdef B600
242     { 600, B600 },
243 #endif
244 #ifdef B1200
245     { 1200, B1200 },
246 #endif
247 #ifdef B1800
248     { 1800, B1800 },
249 #endif
250 #ifdef B2000
251     { 2000, B2000 },
252 #endif
253 #ifdef B2400
254     { 2400, B2400 },
255 #endif
256 #ifdef B3600
257     { 3600, B3600 },
258 #endif
259 #ifdef B4800
260     { 4800, B4800 },
261 #endif
262 #ifdef B7200
263     { 7200, B7200 },
264 #endif
265 #ifdef B9600
266     { 9600, B9600 },
267 #endif
268 #ifdef B19200
269     { 19200, B19200 },
270 #endif
271 #ifdef B38400
272     { 38400, B38400 },
273 #endif
274 #ifdef EXTA
275     { 19200, EXTA },
276 #endif
277 #ifdef EXTB
278     { 38400, EXTB },
279 #endif
280 #ifdef B57600
281     { 57600, B57600 },
282 #endif
283 #ifdef B115200
284     { 115200, B115200 },
285 #endif
286     { 0, 0 }
287 };
288
289 /*
290  * Translate from bits/second to a speed_t.
291  */
292 int
293 translate_speed(bps)
294     int bps;
295 {
296     struct speed *speedp;
297
298     if (bps == 0)
299         return 0;
300     for (speedp = speeds; speedp->speed_int; speedp++)
301         if (bps == speedp->speed_int)
302             return speedp->speed_val;
303     syslog(LOG_WARNING, "speed %d not supported", bps);
304     return 0;
305 }
306
307 /*
308  * Translate from a speed_t to bits/second.
309  */
310 int
311 baud_rate_of(speed)
312     int speed;
313 {
314     struct speed *speedp;
315
316     if (speed == 0)
317         return 0;
318     for (speedp = speeds; speedp->speed_int; speedp++)
319         if (speed == speedp->speed_val)
320             return speedp->speed_int;
321     return 0;
322 }
323
324 /*
325  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
326  * at the requested speed, etc.  If `local' is true, set CLOCAL
327  * regardless of whether the modem option was specified.
328  */
329 set_up_tty(fd, local)
330     int fd, local;
331 {
332     int speed, x;
333     struct termios tios;
334
335     if (tcgetattr(fd, &tios) < 0) {
336         syslog(LOG_ERR, "tcgetattr: %m");
337         die(1);
338     }
339
340     if (!restore_term) {
341         inittermios = tios;
342         ioctl(fd, TIOCGWINSZ, &wsinfo);
343     }
344
345     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
346 #ifdef CRTSCTS
347     if (crtscts > 0)
348         tios.c_cflag |= CRTSCTS;
349     else if (crtscts < 0)
350         tios.c_cflag &= ~CRTSCTS;
351 #endif  /* CRTSCTS */
352
353     tios.c_cflag |= CS8 | CREAD | HUPCL;
354     if (local || !modem)
355         tios.c_cflag |= CLOCAL;
356     tios.c_iflag = IGNBRK | IGNPAR;
357     tios.c_oflag = 0;
358     tios.c_lflag = 0;
359     tios.c_cc[VMIN] = 1;
360     tios.c_cc[VTIME] = 0;
361
362     if (crtscts == 2) {
363         tios.c_iflag |= IXOFF;
364         tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
365         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
366     }
367
368     speed = translate_speed(inspeed);
369     if (speed) {
370         cfsetospeed(&tios, speed);
371         cfsetispeed(&tios, speed);
372     } else {
373         speed = cfgetospeed(&tios);
374         /*
375          * We can't proceed if the serial port speed is B0,
376          * since that implies that the serial port is disabled.
377          */
378         if (speed == B0) {
379             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
380                    devnam);
381             die(1);
382         }
383     }
384
385     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
386         syslog(LOG_ERR, "tcsetattr: %m");
387         die(1);
388     }
389
390     x = 0;
391     if (ioctl(fd, (crtscts || modem)? TIOCMODEM: TIOCNMODEM, &x) < 0)
392         syslog(LOG_WARNING, "TIOC(N)MODEM: %m");
393     if (ioctl(fd, (local || !modem)? TIOCNCAR: TIOCCAR) < 0)
394         syslog(LOG_WARNING, "TIOC(N)CAR: %m");
395
396     baud_rate = inspeed = baud_rate_of(speed);
397     restore_term = TRUE;
398 }
399
400 /*
401  * restore_tty - restore the terminal to the saved settings.
402  */
403 void
404 restore_tty()
405 {
406     if (restore_term) {
407         if (!default_device) {
408             /*
409              * Turn off echoing, because otherwise we can get into
410              * a loop with the tty and the modem echoing to each other.
411              * We presume we are the sole user of this tty device, so
412              * when we close it, it will revert to its defaults anyway.
413              */
414             inittermios.c_lflag &= ~(ECHO | ECHONL);
415         }
416         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
417             if (errno != ENXIO)
418                 syslog(LOG_WARNING, "tcsetattr: %m");
419         ioctl(fd, TIOCSWINSZ, &wsinfo);
420         restore_term = FALSE;
421     }
422 }
423
424 /*
425  * setdtr - control the DTR line on the serial port.
426  * This is called from die(), so it shouldn't call die().
427  */
428 setdtr(fd, on)
429 int fd, on;
430 {
431     int modembits = TIOCM_DTR;
432
433     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
434 }
435
436
437 /*
438  * output - Output PPP packet.
439  */
440 void
441 output(unit, p, len)
442     int unit;
443     u_char *p;
444     int len;
445 {
446     if (unit != 0)
447         MAINDEBUG((LOG_WARNING, "output: unit != 0!"));
448     if (debug)
449         log_packet(p, len, "sent ");
450
451     if (write(fd, p, len) < 0) {
452         syslog(LOG_ERR, "write: %m");
453         die(1);
454     }
455 }
456
457
458 /*
459  * wait_input - wait until there is data available on fd,
460  * for the length of time specified by *timo (indefinite
461  * if timo is NULL).
462  */
463 wait_input(timo)
464     struct timeval *timo;
465 {
466     fd_set ready;
467     int n;
468
469     FD_ZERO(&ready);
470     FD_SET(fd, &ready);
471     n = select(fd+1, &ready, NULL, &ready, timo);
472     if (n < 0 && errno != EINTR) {
473         syslog(LOG_ERR, "select: %m");
474         die(1);
475     }
476 }
477
478
479 /*
480  * read_packet - get a PPP packet from the serial device.
481  */
482 int
483 read_packet(buf)
484     u_char *buf;
485 {
486     int len;
487
488     if ((len = read(fd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
489         if (errno == EWOULDBLOCK || errno == EINTR) {
490             MAINDEBUG((LOG_DEBUG, "read(fd): %m"));
491             return -1;
492         }
493         syslog(LOG_ERR, "read(fd): %m");
494         die(1);
495     }
496     return len;
497 }
498
499
500 /*
501  * ppp_send_config - configure the transmit characteristics of
502  * the ppp interface.
503  */
504 void
505 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
506     int unit, mtu;
507     u_int32_t asyncmap;
508     int pcomp, accomp;
509 {
510     u_int x;
511
512     if (ioctl(fd, PPPIOCSMTU, &mtu) < 0) {
513         syslog(LOG_ERR, "ioctl(PPPIOCSMTU): %m");
514         quit();
515     }
516
517     if (ioctl(fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
518         syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
519         quit();
520     }
521
522     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
523         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
524         quit();
525     }
526     x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
527     x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
528     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
529         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
530         quit();
531     }
532 }
533
534
535 /*
536  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
537  */
538 void
539 ppp_set_xaccm(unit, accm)
540     int unit;
541     ext_accm accm;
542 {
543     if (ioctl(fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
544         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
545 }
546
547
548 /*
549  * ppp_recv_config - configure the receive-side characteristics of
550  * the ppp interface.
551  */
552 void
553 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
554     int unit, mru;
555     u_int32_t asyncmap;
556     int pcomp, accomp;
557 {
558     int x;
559
560     if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
561         syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
562         quit();
563     }
564     if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
565         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
566         quit();
567     }
568     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
569         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
570         quit();
571     }
572     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
573     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
574         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
575         quit();
576     }
577 }
578
579 /*
580  * ccp_test - ask kernel whether a given compression method
581  * is acceptable for use.
582  */
583 ccp_test(unit, opt_ptr, opt_len, for_transmit)
584     int unit, opt_len, for_transmit;
585     u_char *opt_ptr;
586 {
587     struct ppp_option_data data;
588
589     data.ptr = opt_ptr;
590     data.length = opt_len;
591     data.transmit = for_transmit;
592     return ioctl(fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0;
593 }
594
595 /*
596  * ccp_flags_set - inform kernel about the current state of CCP.
597  */
598 void
599 ccp_flags_set(unit, isopen, isup)
600     int unit, isopen, isup;
601 {
602     int x;
603
604     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
605         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
606         return;
607     }
608     x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
609     x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
610     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
611         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
612 }
613
614 /*
615  * ccp_fatal_error - returns 1 if decompression was disabled as a
616  * result of an error detected after decompression of a packet,
617  * 0 otherwise.  This is necessary because of patent nonsense.
618  */
619 int
620 ccp_fatal_error(unit)
621     int unit;
622 {
623     int x;
624
625     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
626         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
627         return 0;
628     }
629     return x & SC_DC_FERROR;
630 }
631
632 /*
633  * sifvjcomp - config tcp header compression
634  */
635 int
636 sifvjcomp(u, vjcomp, cidcomp, maxcid)
637     int u, vjcomp, cidcomp, maxcid;
638 {
639     u_int x;
640
641     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
642         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
643         return 0;
644     }
645     x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
646     x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
647     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
648         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
649         return 0;
650     }
651     if (ioctl(fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
652         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
653         return 0;
654     }
655     return 1;
656 }
657
658 /*
659  * sifup - Config the interface up and enable IP packets to pass.
660  */
661 #ifndef SC_ENABLE_IP
662 #define SC_ENABLE_IP    0x100   /* compat for old versions of kernel code */
663 #endif
664
665 int
666 sifup(u)
667     int u;
668 {
669     struct ifreq ifr;
670     u_int x;
671     struct npioctl npi;
672
673     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
674     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
675         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
676         return 0;
677     }
678     ifr.ifr_flags |= IFF_UP;
679     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
680         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
681         return 0;
682     }
683     npi.protocol = PPP_IP;
684     npi.mode = NPMODE_PASS;
685     if (ioctl(fd, PPPIOCSNPMODE, &npi) < 0) {
686         if (errno != ENOTTY) {
687             syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE): %m");
688             return 0;
689         }
690         /* for backwards compatibility */
691         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
692             syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
693             return 0;
694         }
695         x |= SC_ENABLE_IP;
696         if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
697             syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
698             return 0;
699         }
700     }
701     return 1;
702 }
703
704 /*
705  * sifdown - Config the interface down and disable IP.
706  */
707 int
708 sifdown(u)
709     int u;
710 {
711     struct ifreq ifr;
712     u_int x;
713     int rv;
714     struct npioctl npi;
715
716     rv = 1;
717     npi.protocol = PPP_IP;
718     npi.mode = NPMODE_ERROR;
719     if (ioctl(fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) {
720         if (errno != ENOTTY) {
721             syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE): %m");
722             rv = 0;
723         } else {
724             /* backwards compatibility */
725             if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
726                 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
727                 rv = 0;
728             } else {
729                 x &= ~SC_ENABLE_IP;
730                 if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
731                     syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
732                     rv = 0;
733                 }
734             }
735         }
736     }
737
738     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
739     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
740         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
741         rv = 0;
742     } else {
743         ifr.ifr_flags &= ~IFF_UP;
744         if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
745             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
746             rv = 0;
747         }
748     }
749     return rv;
750 }
751
752 /*
753  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
754  * if it exists.
755  */
756 #define SET_SA_FAMILY(addr, family)             \
757     BZERO((char *) &(addr), sizeof(addr));      \
758     addr.sa_family = (family); 
759
760 /*
761  * sifaddr - Config the interface IP addresses and netmask.
762  */
763 int
764 sifaddr(u, o, h, m)
765     int u;
766     u_int32_t o, h, m;
767 {
768     int ret;
769     struct ifreq ifr;
770
771     ret = 1;
772     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
773     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
774     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
775     if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
776         syslog(LOG_ERR, "ioctl(SIOCSIFADDR): %m");
777         ret = 0;
778     }
779     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = h;
780     if (ioctl(sockfd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
781         syslog(LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m");
782         ret = 0;
783     }
784     if (m != 0) {
785         ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = m;
786         syslog(LOG_INFO, "Setting interface mask to %s\n", ip_ntoa(m));
787         if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
788             syslog(LOG_ERR, "ioctl(SIOCSIFNETMASK): %m");
789             ret = 0;
790         }
791     }
792     return ret;
793 }
794
795 /*
796  * cifaddr - Clear the interface IP addresses, and delete routes
797  * through the interface if possible.
798  */
799 int
800 cifaddr(u, o, h)
801     int u;
802     u_int32_t o, h;
803 {
804     struct rtentry rt;
805
806     SET_SA_FAMILY(rt.rt_dst, AF_INET);
807     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = h;
808     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
809     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = o;
810     rt.rt_flags = RTF_HOST;
811     if (ioctl(sockfd, SIOCDELRT, (caddr_t) &rt) < 0) {
812         syslog(LOG_ERR, "ioctl(SIOCDELRT): %m");
813         return 0;
814     }
815     return 1;
816 }
817
818 /*
819  * sifdefaultroute - assign a default route through the address given.
820  */
821 int
822 sifdefaultroute(u, g)
823 {
824     struct rtentry rt;
825
826     SET_SA_FAMILY(rt.rt_dst, AF_INET);
827     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
828     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
829     rt.rt_flags = RTF_GATEWAY;
830     if (ioctl(sockfd, SIOCADDRT, &rt) < 0) {
831         syslog(LOG_ERR, "default route ioctl(SIOCADDRT): %m");
832         return 0;
833     }
834     return 1;
835 }
836
837 /*
838  * cifdefaultroute - delete a default route through the address given.
839  */
840 int
841 cifdefaultroute(u, g)
842 {
843     struct rtentry rt;
844
845     SET_SA_FAMILY(rt.rt_dst, AF_INET);
846     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
847     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
848     rt.rt_flags = RTF_GATEWAY;
849     if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
850         syslog(LOG_WARNING, "default route ioctl(SIOCDELRT): %m");
851 }
852
853 /*
854  * sifproxyarp - Make a proxy ARP entry for the peer.
855  */
856 int
857 sifproxyarp(unit, hisaddr)
858     int unit;
859     u_int32_t hisaddr;
860 {
861     struct arpreq arpreq;
862
863     BZERO(&arpreq, sizeof(arpreq));
864
865     /*
866      * Get the hardware address of an interface on the same subnet
867      * as our local address.
868      */
869     if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
870         syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
871         return 0;
872     }
873
874     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
875     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
876     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
877     if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
878         syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
879         return 0;
880     }
881
882     return 1;
883 }
884
885 /*
886  * cifproxyarp - Delete the proxy ARP entry for the peer.
887  */
888 int
889 cifproxyarp(unit, hisaddr)
890     int unit;
891     u_int32_t hisaddr;
892 {
893     struct arpreq arpreq;
894
895     BZERO(&arpreq, sizeof(arpreq));
896     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
897     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
898     if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
899         syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
900         return 0;
901     }
902     return 1;
903 }
904
905 /*
906  * get_ether_addr - get the hardware address of an interface on the
907  * the same subnet as ipaddr.
908  */
909 #define MAX_IFS         32
910
911 int
912 get_ether_addr(ipaddr, hwaddr)
913     u_int32_t ipaddr;
914     struct sockaddr *hwaddr;
915 {
916     struct ifreq *ifr, *ifend;
917     u_int32_t ina, mask;
918     struct ifreq ifreq;
919     struct ifconf ifc;
920     struct ifreq ifs[MAX_IFS];
921     struct ifdevea ifdevea;
922
923     ifc.ifc_len = sizeof(ifs);
924     ifc.ifc_req = ifs;
925     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
926         syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
927         return 0;
928     }
929
930     /*
931      * Scan through looking for an interface with an Internet
932      * address on the same subnet as `ipaddr'.
933      */
934     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
935     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
936             ((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
937         if (ifr->ifr_addr.sa_family == AF_INET) {
938             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
939             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
940             /*
941              * Check that the interface is up, and not point-to-point
942              * or loopback.
943              */
944             if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
945                 continue;
946             if ((ifreq.ifr_flags &
947                  (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
948                  != (IFF_UP|IFF_BROADCAST))
949                 continue;
950             /*
951              * Get its netmask and check that it's on the right subnet.
952              */
953             if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
954                 continue;
955             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
956             if ((ipaddr & mask) != (ina & mask))
957                 continue;
958
959             break;
960         }
961     }
962
963     if (ifr >= ifend)
964         return 0;
965     syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
966
967     /*
968      * Grab the physical address for this interface.
969      */
970     strncpy(ifdevea.ifr_name, ifr->ifr_name, sizeof(ifdevea.ifr_name));
971     if (ioctl(sockfd, SIOCRPHYSADDR, &ifdevea) < 0) {
972         syslog(LOG_ERR, "Couldn't get h/w address for %s: %m", ifr->ifr_name);
973         return 0;
974     }
975
976     hwaddr->sa_family = AF_UNSPEC;
977     BCOPY(ifdevea.current_pa, hwaddr->sa_data, 6);
978     return 1;
979 }
980
981 /*
982  * Return user specified netmask, modified by any mask we might determine
983  * for address `addr' (in network byte order).
984  * Here we scan through the system's list of interfaces, looking for
985  * any non-point-to-point interfaces which might appear to be on the same
986  * network as `addr'.  If we find any, we OR in their netmask to the
987  * user-specified netmask.
988  */
989 u_int32_t
990 GetMask(addr)
991     u_int32_t addr;
992 {
993     u_int32_t mask, nmask, ina;
994     struct ifreq *ifr, *ifend, ifreq;
995     struct ifconf ifc;
996     struct ifreq ifs[MAX_IFS];
997
998     addr = ntohl(addr);
999     if (IN_CLASSA(addr))        /* determine network mask for address class */
1000         nmask = IN_CLASSA_NET;
1001     else if (IN_CLASSB(addr))
1002         nmask = IN_CLASSB_NET;
1003     else
1004         nmask = IN_CLASSC_NET;
1005     /* class D nets are disallowed by bad_ip_adrs */
1006     mask = netmask | htonl(nmask);
1007
1008     /*
1009      * Scan through the system's network interfaces.
1010      */
1011     ifc.ifc_len = sizeof(ifs);
1012     ifc.ifc_req = ifs;
1013     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1014         syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1015         return mask;
1016     }
1017     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1018     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1019                 ((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
1020         /*
1021          * Check the interface's internet address.
1022          */
1023         if (ifr->ifr_addr.sa_family != AF_INET)
1024             continue;
1025         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1026         if ((ntohl(ina) & nmask) != (addr & nmask))
1027             continue;
1028         /*
1029          * Check that the interface is up, and not point-to-point or loopback.
1030          */
1031         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1032         if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1033             continue;
1034         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1035             != IFF_UP)
1036             continue;
1037         /*
1038          * Get its netmask and OR it into our mask.
1039          */
1040         if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1041             continue;
1042         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1043     }
1044
1045     return mask;
1046 }
1047
1048
1049 /*
1050   Seems like strdup() is not part of string package in Ultrix.
1051   If I understood the man-page on the sun this should work.
1052
1053   Robert Olsson
1054 */
1055
1056 char *strdup( in ) char *in;
1057 {
1058   char* dup;
1059   if(! (dup = (char *) malloc( strlen( in ) +1 ))) return NULL;
1060   (void) strcpy( dup, in );
1061   return dup;
1062 }
1063
1064 /*
1065  * This logwtmp() implementation is subject to the following copyright:
1066  *
1067  * Copyright (c) 1988 The Regents of the University of California.
1068  * All rights reserved.
1069  *
1070  * Redistribution and use in source and binary forms are permitted
1071  * provided that the above copyright notice and this paragraph are
1072  * duplicated in all such forms and that any documentation,
1073  * advertising materials, and other materials related to such
1074  * distribution and use acknowledge that the software was developed
1075  * by the University of California, Berkeley.  The name of the
1076  * University may not be used to endorse or promote products derived
1077  * from this software without specific prior written permission.
1078  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1079  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1080  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1081  */
1082
1083 #define WTMPFILE        "/usr/adm/wtmp"
1084
1085 int
1086 logwtmp(line, name, host)
1087     char *line, *name, *host;
1088 {
1089     int fd;
1090     struct stat buf;
1091     struct utmp ut;
1092
1093     if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
1094         return;
1095     if (!fstat(fd, &buf)) {
1096         (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1097         (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1098         (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1099         (void)time(&ut.ut_time);
1100         if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp))
1101             (void)ftruncate(fd, buf.st_size);
1102     }
1103     close(fd);
1104 }
1105
1106 /*
1107  * Routines for locking and unlocking the serial device, moved here
1108  * from chat.c.
1109  */
1110
1111 #define LOCK_PREFIX     "/usr/spool/uucp/LCK.."
1112
1113 /*
1114  * lock - create a lock file for the named device
1115  */
1116 int
1117 lock(dev)
1118     char *dev;
1119 {
1120     int fd, pid, n;
1121     char *p;
1122
1123     if ((p = strrchr(dev, '/')) != NULL)
1124         dev = p + 1;
1125     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1126     if (lock_file == NULL)
1127         novm("lock file name");
1128     strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1129
1130     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1131         if (errno == EEXIST
1132             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1133             /* Read the lock file to find out who has the device locked */
1134             n = read(fd, &pid, sizeof(pid));
1135             if (n <= 0) {
1136                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1137                 close(fd);
1138             } else {
1139                 if (kill(pid, 0) == -1 && errno == ESRCH) {
1140                     /* pid no longer exists - remove the lock file */
1141                     if (unlink(lock_file) == 0) {
1142                         close(fd);
1143                         syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1144                                dev, pid);
1145                         continue;
1146                     } else
1147                         syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1148                                dev);
1149                 } else
1150                     syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1151                            dev, pid);
1152             }
1153             close(fd);
1154         } else
1155             syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1156         free(lock_file);
1157         lock_file = NULL;
1158         return -1;
1159     }
1160
1161     pid = getpid();
1162     write(fd, &pid, sizeof pid);
1163
1164     close(fd);
1165     return 0;
1166 }
1167
1168 /*
1169  * unlock - remove our lockfile
1170  */
1171 void
1172 unlock()
1173 {
1174     if (lock_file) {
1175         unlink(lock_file);
1176         free(lock_file);
1177         lock_file = NULL;
1178     }
1179 }