]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-NeXT.c
add packet filtering and demand dial support (?); fix copyright;
[ppp.git] / pppd / sys-NeXT.c
1 /*
2  * sys-next.c - System-dependent procedures for setting up
3  * PPP interfaces on NeXT 3.2/3.3  systems
4  *
5  * Copyright (c) 1989 Carnegie Mellon University.
6  * Copyright (c) 1994 Philippe-Andre Prindeville.
7  * Copyright (c) 1995 The Australian National University.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms are permitted
11  * provided that the above copyright notice and this paragraph are
12  * duplicated in all such forms and that any documentation,
13  * advertising materials, and other materials related to such
14  * distribution and use acknowledge that the software was developed
15  * by Carnegie Mellon University, Philippe-Andre Prindeville and
16  * The Australian National University.  The names of the developers
17  * may not be used to endorse or promote products derived from this
18  * software without specific prior written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
21  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  */
23
24 #ifndef lint
25 static char rcsid[] = "$Id: sys-NeXT.c,v 1.5 1996/04/04 04:04:17 paulus Exp $";
26 #endif
27
28 #include <stdio.h>
29 #include <syslog.h>
30 #include <termios.h>
31 #include <utmp.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <strings.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 #include <sys/fcntl.h>
43
44 #include <net/if.h>
45 #include <net/ppp_defs.h>
46 #include <net/if_ppp.h>
47 #include <netdb.h>
48 #include <netinet/in.h>
49 #include <netinet/in_systm.h>
50 #include <netinet/in_var.h>
51 #include <netinet/ip.h>
52 #include <netinet/if_ether.h>
53 #include <net/route.h>
54 #include <netinet/in.h>
55
56 #include <netinfo/ni.h>
57
58 #include "pppd.h"
59
60 static int initdisc = -1;       /* Initial TTY discipline for ppp_fd */
61 static int initfdflags = -1;    /* Initial file descriptor flags for ppp_fd */
62 static int ppp_fd = -1;         /* fd which is set to PPP discipline */
63
64 extern int errno;
65
66 static int restore_term;        /* 1 => we've munged the terminal */
67 static struct termios inittermios; /* Initial TTY termios */
68 static struct winsize wsinfo;   /* Initial window size info */
69
70 static char *lock_file;         /* name of lock file created */
71
72 static int loop_slave = -1;
73 static int loop_master;
74 static char loop_name[20];
75
76 static unsigned char inbuf[512]; /* buffer for chars read from loopback */
77
78 static int sockfd;              /* socket for doing interface ioctls */
79
80 #if defined(i386) && defined(HAS_BROKEN_IOCTL)
81 #define ioctl   myioctl
82 #endif
83
84 static int if_is_up;            /* the interface is currently up */
85 static u_int32_t ifaddrs[2];    /* local and remote addresses */
86 static u_int32_t default_route_gateway; /* gateway addr for default route */
87 static u_int32_t proxy_arp_addr;        /* remote addr for proxy arp */
88
89 /* Prototypes for procedures local to this file. */
90 static int translate_speed __P((int));
91 static int baud_rate_of __P((int));
92 static int dodefaultroute __P((u_int32_t, int));
93 static int get_ether_addr __P((u_int32_t, struct sockaddr *));
94 static int ether_by_host __P((char *, struct ether_addr *));
95
96
97 /*
98  * sys_init - System-dependent initialization.
99  */
100 void
101 sys_init()
102 {
103     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
104     setlogmask(LOG_UPTO(LOG_INFO));
105     if (debug)
106         setlogmask(LOG_UPTO(LOG_DEBUG));
107
108     /* Get an internet socket for doing socket ioctl's on. */
109     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
110         syslog(LOG_ERR, "Couldn't create IP socket: %m");
111         die(1);
112     }
113 }
114
115 /*
116  * sys_cleanup - restore any system state we modified before exiting:
117  * mark the interface down, delete default route and/or proxy arp entry.
118  * This should call die() because it's called from die().
119  */
120 void
121 sys_cleanup()
122 {
123     struct ifreq ifr;
124
125     if (if_is_up) {
126         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
127         if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
128             && ((ifr.ifr_flags & IFF_UP) != 0)) {
129             ifr.ifr_flags &= ~IFF_UP;
130             ioctl(sockfd, SIOCSIFFLAGS, &ifr);
131         }
132     }
133     if (ifaddrs[0])
134         cifaddr(0, ifaddrs[0], ifaddrs[1]);
135     if (default_route_gateway)
136         cifdefaultroute(0, default_route_gateway);
137     if (proxy_arp_addr)
138         cifproxyarp(0, proxy_arp_addr);
139 }
140
141 /*
142  * sys_close - Clean up in a child process before execing.
143  */
144 void
145 sys_close()
146 {
147     close(sockfd);
148     if (loop_slave >= 0) {
149         close(loop_slave);
150         close(loop_master);
151     }
152     closelog();
153 }
154
155 /*
156  * sys_check_options - check the options that the user specified
157  */
158 void
159 sys_check_options()
160 {
161 }
162
163
164 /*
165  * note_debug_level - note a change in the debug level.
166  */
167 void
168 note_debug_level()
169 {
170     if (debug) {
171         syslog(LOG_INFO, "Debug turned ON, Level %d", debug);
172         setlogmask(LOG_UPTO(LOG_DEBUG));
173     } else {
174         setlogmask(LOG_UPTO(LOG_WARNING));
175     }
176 }
177
178 /*
179  * ppp_available - check whether the system has any ppp interfaces
180  * (in fact we check whether we can do an ioctl on ppp0).
181  */
182 int
183 ppp_available()
184 {
185     int s, ok;
186     struct ifreq ifr;
187
188     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
189         return 1;               /* can't tell - maybe we're not root */
190
191     strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
192     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
193     close(s);
194
195     return ok;
196 }
197
198 /*
199  * establish_ppp - Turn the serial port into a ppp interface.
200  */
201 void
202 establish_ppp(fd)
203     int fd;
204 {
205     int pppdisc = PPPDISC;
206     int x;
207
208     if (demand) {
209         /*
210          * Demand mode - prime the old ppp device to relinquish the unit.
211          */
212         if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) {
213             syslog(LOG_ERR, "ioctl(transfer ppp unit): %m");
214             die(1);
215         }
216     }
217
218     /*
219      * Save the old line discipline of fd, and set it to PPP.
220      */
221     if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
222         syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
223         die(1);
224     }
225     if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
226         syslog(LOG_ERR, "ioctl(establish TIOCSETD): %m");
227         die(1);
228     }
229
230     if (!demand) {
231         /*
232          * Find out which interface we were given.
233          */
234         if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {      
235             syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
236             die(1);
237         }
238     } else {
239         /*
240          * Check that we got the same unit again.
241          */
242         if (ioctl(fd, PPPIOCGUNIT, &x) < 0) {   
243             syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
244             die(1);
245         }
246         if (x != ifunit) {
247             syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
248                    ifunit, x);
249             die(1);
250         }
251         x = TTYDISC;
252         ioctl(loop_slave, TIOCSETD, &x);
253     }
254
255     ppp_fd = fd;
256
257     /*
258      * Enable debug in the driver if requested.
259      */
260     if (kdebugflag) {
261         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
262             syslog(LOG_WARNING, "ioctl(PPPIOCGFLAGS): %m");
263         } else {
264             x |= (kdebugflag & 0xFF) * SC_DEBUG;
265             if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
266                 syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
267         }
268     }
269
270     /*
271      * Set device for non-blocking reads.
272      */
273     if ((initfdflags = fcntl(fd, F_GETFL)) == -1
274         || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
275         syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m");
276     }
277 }
278
279 /*
280  * restore_loop - reattach the ppp unit to the loopback.
281  */
282 void
283 restore_loop()
284 {
285     int x;
286
287     /*
288      * Transfer the ppp interface back to the loopback.
289      */
290     if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) {
291         syslog(LOG_ERR, "ioctl(transfer ppp unit): %m");
292         die(1);
293     }
294     x = PPPDISC;
295     if (ioctl(loop_slave, TIOCSETD, &x) < 0) {
296         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
297         die(1);
298     }
299
300     /*
301      * Check that we got the same unit again.
302      */
303     if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0) {       
304         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
305         die(1);
306     }
307     if (x != ifunit) {
308         syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
309                ifunit, x);
310         die(1);
311     }
312     ppp_fd = loop_slave;
313 }
314
315
316 /*
317  * disestablish_ppp - Restore the serial port to normal operation.
318  * This shouldn't call die() because it's called from die().
319  */
320 void
321 disestablish_ppp(fd)
322     int fd;
323 {
324     /* Reset non-blocking mode on fd. */
325     if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
326         syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
327     initfdflags = -1;
328
329     /* Restore old line discipline. */
330     if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0)
331         syslog(LOG_ERR, "ioctl(disestablish TIOCSETD): %m");
332     initdisc = -1;
333
334     if (fd == ppp_fd)
335         ppp_fd = -1;
336 }
337
338 /*
339  * Check whether the link seems not to be 8-bit clean.
340  */
341 void
342 clean_check()
343 {
344     int x;
345     char *s;
346
347     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
348         s = NULL;
349         switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
350         case SC_RCV_B7_0:
351             s = "bit 7 set to 1";
352             break;
353         case SC_RCV_B7_1:
354             s = "bit 7 set to 0";
355             break;
356         case SC_RCV_EVNP:
357             s = "odd parity";
358             break;
359         case SC_RCV_ODDP:
360             s = "even parity";
361             break;
362         }
363         if (s != NULL) {
364             syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
365             syslog(LOG_WARNING, "All received characters had %s", s);
366         }
367     }
368 }
369
370 /*
371  * List of valid speeds.
372  */
373 struct speed {
374     int speed_int, speed_val;
375 } speeds[] = {
376 #ifdef B50
377     { 50, B50 },
378 #endif
379 #ifdef B75
380     { 75, B75 },
381 #endif
382 #ifdef B110
383     { 110, B110 },
384 #endif
385 #ifdef B134
386     { 134, B134 },
387 #endif
388 #ifdef B150
389     { 150, B150 },
390 #endif
391 #ifdef B200
392     { 200, B200 },
393 #endif
394 #ifdef B300
395     { 300, B300 },
396 #endif
397 #ifdef B600
398     { 600, B600 },
399 #endif
400 #ifdef B1200
401     { 1200, B1200 },
402 #endif
403 #ifdef B1800
404     { 1800, B1800 },
405 #endif
406 #ifdef B2000
407     { 2000, B2000 },
408 #endif
409 #ifdef B2400
410     { 2400, B2400 },
411 #endif
412 #ifdef B3600
413     { 3600, B3600 },
414 #endif
415 #ifdef B4800
416     { 4800, B4800 },
417 #endif
418 #ifdef B7200
419     { 7200, B7200 },
420 #endif
421 #ifdef B9600
422     { 9600, B9600 },
423 #endif
424 #ifdef B19200
425     { 19200, B19200 },
426 #endif
427 #ifdef B38400
428     { 38400, B38400 },
429 #endif
430 #ifdef EXTA
431     { 19200, EXTA },
432 #endif
433 #ifdef EXTB
434     { 38400, EXTB },
435 #endif
436 #ifdef B14400
437     { 14400, B14400 },
438 #endif
439 #ifdef B28800
440     { 28800, B28800 },
441 #endif
442 #ifdef B43200
443     { 43200, B43200 },
444 #endif
445 #ifdef B57600
446     { 57600, B57600 },
447 #endif
448 /*
449 #ifndef B115200
450 #warning Defining B115200
451 #define B115200 20
452 #endif
453 */
454 #ifdef B115200
455     { 115200, B115200 },
456 #endif
457     { 0, 0 }
458 };
459
460 /*
461  * Translate from bits/second to a speed_t.
462  */
463 int
464 translate_speed(bps)
465     int bps;
466 {
467     struct speed *speedp;
468
469     if (bps == 0)
470         return 0;
471     for (speedp = speeds; speedp->speed_int; speedp++)
472         if (bps == speedp->speed_int)
473             return speedp->speed_val;
474     syslog(LOG_WARNING, "speed %d not supported", bps);
475     return 0;
476 }
477
478 /*
479  * Translate from a speed_t to bits/second.
480  */
481 static int
482 baud_rate_of(speed)
483     int speed;
484 {
485     struct speed *speedp;
486
487     if (speed == 0)
488         return 0;
489     for (speedp = speeds; speedp->speed_int; speedp++)
490         if (speed == speedp->speed_val)
491             return speedp->speed_int;
492     return 0;
493 }
494
495
496 /*
497  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
498  * at the requested speed, etc.  If `local' is true, set CLOCAL
499  * regardless of whether the modem option was specified.
500  */
501 void
502 set_up_tty(fd, local)
503     int fd, local;
504 {
505     int speed, x, modembits;
506     struct termios tios;
507
508     if (tcgetattr(fd, &tios) < 0) {
509         syslog(LOG_ERR, "tcgetattr: %m");
510         die(1);
511     }
512
513     if (!restore_term) {
514         inittermios = tios;
515         ioctl(fd, TIOCGWINSZ, &wsinfo);
516     }
517
518     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
519     if (crtscts > 0 && !local)
520         tios.c_cflag |= CRTSCTS;
521     else if (crtscts < 0)
522         tios.c_cflag &= ~CRTSCTS;
523
524     tios.c_cflag |= CS8 | CREAD | HUPCL;
525     if (local || !modem)
526         tios.c_cflag |= CLOCAL;
527
528     tios.c_iflag = IGNBRK | IGNPAR;
529     tios.c_oflag = 0;
530     tios.c_lflag = 0;
531     tios.c_cc[VMIN] = 1;
532     tios.c_cc[VTIME] = 0;
533
534     if (crtscts == -2) {
535         tios.c_iflag |= IXON | IXOFF;
536         tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
537         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
538     }
539
540     speed = translate_speed(inspeed);
541     if (speed) {
542         cfsetospeed(&tios, speed);
543         cfsetispeed(&tios, speed);
544     } else {
545         speed = cfgetospeed(&tios);
546     }
547
548     if (modem) {
549       modembits = TIOCM_RTS | TIOCM_CTS;
550       if (ioctl(fd, (crtscts ? TIOCMBIS : TIOCMBIC), &modembits) < 0)
551         syslog(LOG_ERR, "ioctl: TIOCMBIS/BIC: %m");
552     }
553
554     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
555         syslog(LOG_ERR, "tcsetattr: %m");
556         die(1);
557     }
558
559    baud_rate = inspeed = baud_rate_of(speed);
560    restore_term = 1;
561 }
562
563 /*
564  * restore_tty - restore the terminal to the saved settings.
565  */
566 void
567 restore_tty(fd)
568     int fd;
569 {
570     if (restore_term) {
571         if (!default_device) {
572             /*
573              * Turn off echoing, because otherwise we can get into
574              * a loop with the tty and the modem echoing to each other.
575              * We presume we are the sole user of this tty device, so
576              * when we close it, it will revert to its defaults anyway.
577              */
578             inittermios.c_lflag &= ~(ECHO | ECHONL);
579         }
580         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
581             if (errno != ENXIO)
582                 syslog(LOG_WARNING, "tcsetattr: %m");
583         ioctl(fd, TIOCSWINSZ, &wsinfo);
584         restore_term = 0;
585     }
586 }
587
588 /*
589  * setdtr - control the DTR line on the serial port.
590  * This is called from die(), so it shouldn't call die().
591  *
592  * The write hack is to get NXFax to recognize that there is
593  * activity on the port.  Not using the write nukes
594  * NXFax's capability to determine port usage.
595  *
596  */
597 void
598 setdtr(fd, on)
599 int fd, on;
600 {
601     int modembits = TIOCM_DTR;
602
603     if (!on)
604       {
605         write(fd, " ", 1);
606         sleep(1);
607       }
608
609 /*    ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); */
610     ioctl(fd, (on? TIOCSDTR: TIOCCDTR), 0);
611 }
612
613
614 /*
615  * open_ppp_loopback - open the device we use for getting
616  * packets in demand mode, and connect it to a ppp interface.
617  * Here we use a pty.
618  */
619 void
620 open_ppp_loopback()
621 {
622     int flags;
623     struct termios tios;
624     int pppdisc = PPPDISC;
625
626     if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0) {
627         syslog(LOG_ERR, "No free pty for loopback");
628         die(1);
629     }
630     SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name));
631
632     if (tcgetattr(loop_slave, &tios) == 0) {
633         tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
634         tios.c_cflag |= CS8 | CREAD;
635         tios.c_iflag = IGNPAR;
636         tios.c_oflag = 0;
637         tios.c_lflag = 0;
638         if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0)
639             syslog(LOG_WARNING, "couldn't set attributes on loopback: %m");
640     }
641
642     if ((flags = fcntl(loop_master, F_GETFL)) != -1) 
643         if (fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1)
644             syslog(LOG_WARNING, "couldn't set loopback to nonblock: %m");
645
646     ppp_fd = loop_slave;
647     if (ioctl(ppp_fd, TIOCSETD, &pppdisc) < 0) {
648         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
649         die(1);
650     }
651
652     /*
653      * Find out which interface we were given.
654      */
655     if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0) {      
656         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
657         die(1);
658     }
659
660     /*
661      * Enable debug in the driver if requested.
662      */
663     if (kdebugflag) {
664         if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0) {
665             syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
666         } else {
667             flags |= (kdebugflag & 0xFF) * SC_DEBUG;
668             if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0)
669                 syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
670         }
671     }
672
673 }
674
675
676 /*
677  * output - Output PPP packet.
678  */
679 void
680 output(unit, p, len)
681     int unit;
682     u_char *p;
683     int len;
684 {
685     if (debug)
686         log_packet(p, len, "sent ");
687
688     if (write(ttyfd, p, len) < 0) {
689         if (errno == EWOULDBLOCK || errno == ENOBUFS
690             || errno == ENXIO || errno == EIO) {
691             syslog(LOG_WARNING, "write: warning: %m");
692         } else {
693             syslog(LOG_ERR, "write: %m");
694             die(1);
695         }
696     }
697 }
698
699
700 /*
701  * wait_input - wait until there is data available on ttyfd,
702  * for the length of time specified by *timo (indefinite
703  * if timo is NULL).
704  */
705 void
706 wait_input(timo)
707     struct timeval *timo;
708 {
709     fd_set ready;
710     int n;
711
712     FD_ZERO(&ready);
713     FD_SET(ttyfd, &ready);
714     n = select(ttyfd+1, &ready, NULL, &ready, timo);
715     if (n < 0 && errno != EINTR) {
716         syslog(LOG_ERR, "select: %m");
717         die(1);
718     }
719 }
720
721
722 /*
723  * wait_loop_output - wait until there is data available on the
724  * loopback, for the length of time specified by *timo (indefinite
725  * if timo is NULL).
726  */
727 wait_loop_output(timo)
728     struct timeval *timo;
729 {
730     fd_set ready;
731     int n;
732
733     FD_ZERO(&ready);
734     FD_SET(loop_master, &ready);
735     n = select(loop_master + 1, &ready, NULL, &ready, timo);
736     if (n < 0 && errno != EINTR) {
737         syslog(LOG_ERR, "select: %m");
738         die(1);
739     }
740 }
741
742
743 /*
744  * wait_time - wait for a given length of time or until a
745  * signal is received.
746  */
747 wait_time(timo)
748     struct timeval *timo;
749 {
750     int n;
751
752     n = select(0, NULL, NULL, NULL, timo);
753     if (n < 0 && errno != EINTR) {
754         syslog(LOG_ERR, "select: %m");
755         die(1);
756     }
757 }
758
759
760 /*
761  * read_packet - get a PPP packet from the serial device.
762  */
763 int
764 read_packet(buf)
765     u_char *buf;
766 {
767     int len;
768
769     if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
770         if (errno == EWOULDBLOCK || errno == EINTR)
771             return -1;
772         syslog(LOG_ERR, "read: %m");
773         die(1);
774     }
775     return len;
776 }
777
778
779 /*
780  * get_loop_output - read characters from the loopback, form them
781  * into frames, and detect when we want to bring the real link up.
782  * Return value is 1 if we need to bring up the link, 0 otherwise.
783  */
784 int
785 get_loop_output()
786 {
787     int rv = 0;
788     int n;
789
790     while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) {
791         if (loop_chars(inbuf, n))
792             rv = 1;
793     }
794
795     if (n == 0) {
796         syslog(LOG_ERR, "eof on loopback");
797         die(1);
798     } else if (errno != EWOULDBLOCK){
799         syslog(LOG_ERR, "read from loopback: %m");
800         die(1);
801     }
802
803     return rv;
804 }
805
806
807 /*
808  * ppp_send_config - configure the transmit characteristics of
809  * the ppp interface.
810  */
811 void
812 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
813     int unit, mtu;
814     u_int32_t asyncmap;
815     int pcomp, accomp;
816 {
817     u_int x;
818     struct ifreq ifr;
819
820     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
821     ifr.ifr_mtu = mtu;
822     if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
823         syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
824         quit();
825     }
826
827     if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
828         syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
829         quit();
830     }
831
832     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
833         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
834         quit();
835     }
836     x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
837     x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
838     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
839         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
840         quit();
841     }
842 }
843
844
845 /*
846  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
847  */
848 void
849 ppp_set_xaccm(unit, accm)
850     int unit;
851     ext_accm accm;
852 {
853     if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
854         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
855 }
856
857
858 /*
859  * ppp_recv_config - configure the receive-side characteristics of
860  * the ppp interface.
861  */
862 void
863 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
864     int unit, mru;
865     u_int32_t asyncmap;
866     int pcomp, accomp;
867 {
868     int x;
869
870     if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
871         syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
872         quit();
873     }
874     if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
875         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
876         quit();
877     }
878     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
879         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
880         quit();
881     }
882     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
883     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
884         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
885         quit();
886     }
887 }
888
889 /*
890  * ccp_test - ask kernel whether a given compression method
891  * is acceptable for use.  Returns 1 if the method and parameters
892  * are OK, 0 if the method is known but the parameters are not OK
893  * (e.g. code size should be reduced), or -1 if the method is unknown.
894  */
895 int
896 ccp_test(unit, opt_ptr, opt_len, for_transmit)
897     int unit, opt_len, for_transmit;
898     u_char *opt_ptr;
899 {
900     struct ppp_option_data data;
901
902     data.ptr = opt_ptr;
903     data.length = opt_len;
904     data.transmit = for_transmit;
905     if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
906         return 1;
907     return (errno == ENOBUFS)? 0: -1;
908 }
909
910 /*
911  * ccp_flags_set - inform kernel about the current state of CCP.
912  */
913 void
914 ccp_flags_set(unit, isopen, isup)
915     int unit, isopen, isup;
916 {
917     int x;
918
919     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
920         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
921         return;
922     }
923     x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
924     x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
925     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
926         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
927 }
928
929 /*
930  * ccp_fatal_error - returns 1 if decompression was disabled as a
931  * result of an error detected after decompression of a packet,
932  * 0 otherwise.  This is necessary because of patent nonsense.
933  */
934 int
935 ccp_fatal_error(unit)
936     int unit;
937 {
938     int x;
939
940     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
941         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
942         return 0;
943     }
944     return x & SC_DC_FERROR;
945 }
946
947 /*
948  * get_idle_time - return how long the link has been idle.
949  */
950 int
951 get_idle_time(u, ip)
952     int u;
953     struct ppp_idle *ip;
954 {
955     return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
956 }
957
958
959 /*
960  * set_filters - transfer the pass and active filters to the kernel.
961  */
962 int
963 set_filters(pass, active)
964     struct bpf_program *pass, *active;
965 {
966     int ret = 1;
967
968     if (pass->bf_len > 0) {
969         if (ioctl(ppp_fd, PPPIOCSPASS, pass) < 0) {
970             syslog(LOG_ERR, "Couldn't set pass-filter in kernel: %m");
971             ret = 0;
972         }
973     }
974     if (active->bf_len > 0) {
975         if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) {
976             syslog(LOG_ERR, "Couldn't set active-filter in kernel: %m");
977             ret = 0;
978         }
979     }
980     return ret;
981 }
982
983
984 /*
985  * sifvjcomp - config tcp header compression
986  */
987 int
988 sifvjcomp(u, vjcomp, cidcomp, maxcid)
989     int u, vjcomp, cidcomp, maxcid;
990 {
991     u_int x;
992
993     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
994         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
995         return 0;
996     }
997     x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
998     x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
999     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
1000         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
1001         return 0;
1002     }
1003     if (ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
1004         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
1005         return 0;
1006     }
1007     return 1;
1008 }
1009
1010 /*
1011  * sifup - Config the interface up and enable IP packets to pass.
1012  */
1013 int
1014 sifup(u)
1015     int u;
1016 {
1017     struct ifreq ifr;
1018     struct npioctl npi;
1019
1020     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1021     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
1022         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
1023         return 0;
1024     }
1025     ifr.ifr_flags |= IFF_UP;
1026     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
1027         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
1028         return 0;
1029     }
1030     if_is_up = 1;
1031     npi.protocol = PPP_IP;
1032     npi.mode = NPMODE_PASS;
1033     if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
1034         syslog(LOG_ERR, "ioctl(set IP mode to PASS): %m");
1035         return 0;
1036     }
1037     return 1;
1038 }
1039
1040 /*
1041  * sifnpmode - Set the mode for handling packets for a given NP.
1042  */
1043 int
1044 sifnpmode(u, proto, mode)
1045     int u;
1046     int proto;
1047     enum NPmode mode;
1048 {
1049     struct npioctl npi;
1050
1051     npi.protocol = proto;
1052     npi.mode = mode;
1053     if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
1054         syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode);
1055         return 0;
1056     }
1057     return 1;
1058 }
1059
1060 /*
1061  * sifdown - Config the interface down and disable IP.
1062  */
1063 int
1064 sifdown(u)
1065     int u;
1066 {
1067     struct ifreq ifr;
1068     int rv;
1069     struct npioctl npi;
1070
1071     rv = 1;
1072     npi.protocol = PPP_IP;
1073     npi.mode = NPMODE_ERROR;
1074     ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi);
1075     /* ignore errors, because ppp_fd might have been closed by now. */
1076
1077     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1078     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
1079         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
1080         rv = 0;
1081     } else {
1082         ifr.ifr_flags &= ~IFF_UP;
1083         if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
1084             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
1085             rv = 0;
1086         } else
1087             if_is_up = 0;
1088     }
1089     return rv;
1090 }
1091
1092 /*
1093  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
1094  * if it exists.
1095  */
1096 #define SET_SA_FAMILY(addr, family)             \
1097     BZERO((char *) &(addr), sizeof(addr));      \
1098     addr.sa_family = (family); 
1099
1100 /*
1101  * sifaddr - Config the interface IP addresses and netmask.
1102  */
1103 int
1104 sifaddr(u, o, h, m)
1105     int u;
1106     u_int32_t o, h, m;
1107 {
1108     int ret;
1109     struct ifreq ifr;
1110
1111     ret = 1;
1112     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1113     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
1114     if (m != 0) {
1115         ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = m;
1116         syslog(LOG_INFO, "Setting interface mask to %s\n", ip_ntoa(m));
1117         if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
1118             syslog(LOG_ERR, "ioctl(SIOCSIFNETMASK): %m");
1119             ret = 0;
1120         }
1121     }
1122     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
1123     if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
1124         syslog(LOG_ERR, "ioctl(SIOCAIFADDR): %m");
1125         ret = 0;
1126     }
1127     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = h;
1128     if (ioctl(sockfd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
1129         syslog(LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m");
1130         ret = 0;
1131     }
1132     ifaddrs[0] = o;
1133     ifaddrs[1] = h;
1134     return ret;
1135 }
1136
1137 /*
1138  * cifaddr - Clear the interface IP addresses, and delete routes
1139  * through the interface if possible.
1140  *
1141  * N.B.: under NextStep, you can't *delete* an address on an interface,
1142  * so we change it to 0.0.0.0...  A real hack.  But it simplifies
1143  * reconnection on the server side.
1144  */
1145 int
1146 cifaddr(u, o, h)
1147     int u;
1148     u_int32_t o, h;
1149 {
1150     struct rtentry rt;
1151
1152 #if 1
1153     h = o = 0L;
1154     (void) sifaddr(u, o, h, 0L);
1155 #endif
1156     ifaddrs[0] = 0;
1157     BZERO(&rt, sizeof(rt));
1158     SET_SA_FAMILY(rt.rt_dst, AF_INET);
1159     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = h;
1160     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
1161     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = o;
1162     rt.rt_flags = RTF_HOST;
1163     if (ioctl(sockfd, SIOCDELRT, (caddr_t) &rt) < 0) {
1164         syslog(LOG_ERR, "ioctl(SIOCDELRT): %m");
1165         return 0;
1166     }
1167     return 1;
1168 }
1169
1170 /*
1171  * sifdefaultroute - assign a default route through the address given.
1172  */
1173 int
1174 sifdefaultroute(u, g)
1175     int u;
1176     u_int32_t g;
1177 {
1178     return dodefaultroute(g, 's');
1179 }
1180
1181 /*
1182  * cifdefaultroute - delete a default route through the address given.
1183  */
1184 int
1185 cifdefaultroute(u, g)
1186     int u;
1187     u_int32_t g;
1188 {
1189     return dodefaultroute(g, 'c');
1190 }
1191
1192 /*
1193  * dodefaultroute - talk to a routing socket to add/delete a default route.
1194  */
1195 int
1196 dodefaultroute(g, cmd)
1197     u_int32_t g;
1198     int cmd;
1199 {
1200     struct rtentry rt;
1201
1202     BZERO(&rt, sizeof(rt));
1203     SET_SA_FAMILY(rt.rt_dst, AF_INET);
1204     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = 0L;
1205     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
1206     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
1207     rt.rt_flags = RTF_GATEWAY;
1208     if (ioctl(sockfd, (cmd == 's') ? SIOCADDRT : SIOCDELRT, &rt) < 0) {
1209         syslog(LOG_ERR, "%cifdefaultroute: ioctl(%s): %m", cmd,
1210                (cmd == 's') ? "SIOCADDRT" : "SIOCDELRT");
1211         return 0;
1212     }
1213     default_route_gateway = (cmd == 's')? g: 0;
1214     return 1;
1215 }
1216
1217 /*
1218  * sifproxyarp - Make a proxy ARP entry for the peer.
1219  */
1220 int
1221 sifproxyarp(unit, hisaddr)
1222     int unit;
1223     u_int32_t hisaddr;
1224 {
1225     struct arpreq arpreq;
1226
1227     BZERO(&arpreq, sizeof(arpreq));
1228
1229     /*
1230      * Get the hardware address of an interface on the same subnet
1231      * as our local address.
1232      */
1233     if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
1234         syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1235         return 0;
1236     }
1237
1238     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1239     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1240     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1241     if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
1242         syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
1243         return 0;
1244     }
1245
1246     proxy_arp_addr = hisaddr;
1247     return 1;
1248 }
1249
1250 /*
1251  * cifproxyarp - Delete the proxy ARP entry for the peer.
1252  */
1253 int
1254 cifproxyarp(unit, hisaddr)
1255     int unit;
1256     u_int32_t hisaddr;
1257 {
1258     struct arpreq arpreq;
1259
1260     BZERO(&arpreq, sizeof(arpreq));
1261     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1262     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1263     if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1264         syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
1265         return 0;
1266     }
1267     proxy_arp_addr = 0;
1268     return 1;
1269 }
1270
1271 /*
1272  * get_ether_addr - get the hardware address of an interface on the
1273  * the same subnet as ipaddr.
1274  */
1275 #define MAX_IFS         32
1276
1277 int
1278 get_ether_addr(ipaddr, hwaddr)
1279     u_int32_t ipaddr;
1280     struct sockaddr *hwaddr;
1281 {
1282     struct ifreq *ifr, *ifend, *ifp;
1283     u_int32_t ina, mask;
1284     struct ether_addr dla;
1285     struct ifreq ifreq;
1286     struct ifconf ifc;
1287     struct ifreq ifs[MAX_IFS];
1288     struct hostent *hostent;
1289
1290     ifc.ifc_len = sizeof(ifs);
1291     ifc.ifc_req = ifs;
1292     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1293         syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
1294         return 0;
1295     }
1296
1297     /*
1298      * Scan through looking for an interface with an Internet
1299      * address on the same subnet as `ipaddr'.
1300      */
1301     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1302     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1303                 ((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
1304         if (ifr->ifr_addr.sa_family == AF_INET) {
1305             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1306             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1307             /*
1308              * Check that the interface is up, and not point-to-point
1309              * or loopback.
1310              */
1311             if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1312                 continue;
1313             if ((ifreq.ifr_flags &
1314                  (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1315                  != (IFF_UP|IFF_BROADCAST))
1316                 continue;
1317             /*
1318              * Get its netmask and check that it's on the right subnet.
1319              */
1320             if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1321                 continue;
1322             mask = ((struct sockaddr_in*)&ifreq.ifr_addr)->sin_addr.s_addr;
1323             if ((ipaddr & mask) != (ina & mask))
1324                 continue;
1325
1326             break;
1327         }
1328     }
1329
1330     if (ifr >= ifend)
1331         return 0;
1332     syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
1333
1334     /*
1335      * Get the hostname and look for an entry using the ethers database.
1336      * Under NeXTStep this is the best we can do for now.
1337      */
1338     if ((hostent = gethostbyaddr((char*)&ina, sizeof(ina), AF_INET)) == NULL)
1339         return 0;
1340
1341     if (ether_by_host(hostent->h_name, &dla)) {
1342         syslog(LOG_INFO, "Add entry for %s in /etc/ethers", hostent->h_name);
1343         return 0;       /* it's not there */
1344     }
1345     hwaddr->sa_family = AF_UNSPEC;
1346     BCOPY(&dla, hwaddr->sa_data, sizeof(dla));
1347     return 1;
1348 }
1349
1350 static int
1351 ether_by_host(hostname, etherptr)
1352     char *hostname;
1353     struct ether_addr *etherptr;
1354 {
1355     struct ether_addr *thisptr;
1356     void *conn;
1357     ni_id root;
1358     ni_namelist val;
1359     char path[256];
1360
1361     if (!ether_hostton(hostname, etherptr))
1362         return 0;
1363     /*
1364      * We shall now try and
1365      * find the address in the
1366      * top domain of netinfo.
1367      */
1368     strcat(strcpy(path, "/machines/"), hostname);
1369
1370     if (ni_open((void *)0, "/", &conn)
1371      || ni_root(conn, &root)
1372      || ni_pathsearch(conn, &root, path)
1373      || ni_lookupprop(conn, &root, "en_address", &val))
1374         return 1;
1375
1376     /*
1377      * Now we can convert the returned string into an ethernet address.
1378      */
1379     strcpy(path, val.ni_namelist_val[0]);
1380     ni_free(conn);
1381     if ((thisptr = (struct ether_addr*)ether_aton(path)) == NULL)
1382         return 1;
1383     BCOPY(thisptr, etherptr, sizeof(struct ether_addr));
1384     return 0;
1385 }
1386
1387
1388
1389 /*
1390  * Return user specified netmask, modified by any mask we might determine
1391  * for address `addr' (in network byte order).
1392  * Here we scan through the system's list of interfaces, looking for
1393  * any non-point-to-point interfaces which might appear to be on the same
1394  * network as `addr'.  If we find any, we OR in their netmask to the
1395  * user-specified netmask.
1396  */
1397 u_int32_t
1398 GetMask(addr)
1399     u_int32_t addr;
1400 {
1401     u_int32_t mask, nmask, ina;
1402     struct ifreq *ifr, *ifend, ifreq;
1403     struct ifconf ifc;
1404     struct ifreq ifs[MAX_IFS];
1405
1406     addr = ntohl(addr);
1407     if (IN_CLASSA(addr))        /* determine network mask for address class */
1408         nmask = IN_CLASSA_NET;
1409     else if (IN_CLASSB(addr))
1410         nmask = IN_CLASSB_NET;
1411     else
1412         nmask = IN_CLASSC_NET;
1413     /* class D nets are disallowed by bad_ip_adrs */
1414     mask = netmask | htonl(nmask);
1415
1416     /*
1417      * Scan through the system's network interfaces.
1418      */
1419     ifc.ifc_len = sizeof(ifs);
1420     ifc.ifc_req = ifs;
1421     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1422         syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1423         return mask;
1424     }
1425     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1426     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1427                 ((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
1428         /*
1429          * Check the interface's internet address.
1430          */
1431         if (ifr->ifr_addr.sa_family != AF_INET)
1432             continue;
1433         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1434         if ((ntohl(ina) & nmask) != (addr & nmask))
1435             continue;
1436         /*
1437          * Check that the interface is up, and not point-to-point or loopback.
1438          */
1439         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1440         if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1441             continue;
1442         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1443             != IFF_UP)
1444             continue;
1445         /*
1446          * Get its netmask and OR it into our mask.
1447          */
1448         if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1449             continue;
1450         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1451     }
1452
1453     return mask;
1454 }
1455
1456
1457
1458 /*
1459  * daemon - Detach us from the terminal session.
1460  */
1461 int
1462 daemon(nochdir, noclose)
1463     int nochdir, noclose;
1464 {
1465     int pid;
1466
1467     if ((pid = fork()) < 0)
1468         return -1;
1469     if (pid != 0)
1470         exit(0);                /* parent dies */
1471     (void)setsid();
1472     if (!nochdir)
1473         chdir("/");
1474     if (!noclose) {
1475         fclose(stdin);          /* don't need stdin, stdout, stderr */
1476         fclose(stdout);
1477         fclose(stderr);
1478     }
1479     return 0;
1480 }
1481
1482
1483 char *
1484 strdup(s)
1485     const char *s;
1486 {
1487     char *d = malloc(strlen(s) + 1);
1488
1489     if (d) strcpy(d, s);
1490     return d;
1491 }
1492
1493 /*
1494  * This logwtmp() implementation is subject to the following copyright:
1495  *
1496  * Copyright (c) 1988 The Regents of the University of California.
1497  * All rights reserved.
1498  *
1499  * Redistribution and use in source and binary forms are permitted
1500  * provided that the above copyright notice and this paragraph are
1501  * duplicated in all such forms and that any documentation,
1502  * advertising materials, and other materials related to such
1503  * distribution and use acknowledge that the software was developed
1504  * by the University of California, Berkeley.  The name of the
1505  * University may not be used to endorse or promote products derived
1506  * from this software without specific prior written permission.
1507  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1508  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1509  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1510  */
1511
1512 #define WTMPFILE        "/usr/adm/wtmp"
1513
1514 int
1515 logwtmp(line, name, host)
1516     char *line, *name, *host;
1517 {
1518     int fd;
1519     struct stat buf;
1520     struct utmp ut;
1521
1522     if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
1523         return;
1524     if (!fstat(fd, &buf)) {
1525         (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1526         (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1527         (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1528         (void)time(&ut.ut_time);
1529         if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp))
1530             (void)ftruncate(fd, buf.st_size);
1531     }
1532     close(fd);
1533 }
1534
1535 /*
1536  * Routines for locking and unlocking the serial device, moved here
1537  * from chat.c.
1538  */
1539
1540 #define LOCK_PREFIX     "/usr/spool/uucp/LCK/LCK.."
1541
1542 /*
1543  * lock - create a lock file for the named device
1544  */
1545 int
1546 lock(dev)
1547     char *dev;
1548 {
1549     int fd, pid, n;
1550     char *p;
1551
1552     if ((p = strrchr(dev, '/')) != NULL)
1553         dev = p + 1;
1554     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1555     if (lock_file == NULL)
1556         novm("lock file name");
1557     strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1558
1559     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1560         if (errno == EEXIST
1561             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1562             /* Read the lock file to find out who has the device locked */
1563             n = read(fd, &pid, sizeof(pid));
1564             if (n <= 0) {
1565                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1566                 close(fd);
1567             } else {
1568                 if (kill(pid, 0) == -1 && errno == ESRCH) {
1569                     /* pid no longer exists - remove the lock file */
1570                     if (unlink(lock_file) == 0) {
1571                         close(fd);
1572                         syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1573                                dev, pid);
1574                         continue;
1575                     } else
1576                         syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1577                                dev);
1578                 } else
1579                     syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1580                            dev, pid);
1581             }
1582             close(fd);
1583         } else
1584             syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1585         free(lock_file);
1586         lock_file = NULL;
1587         return -1;
1588     }
1589
1590     pid = getpid();
1591     write(fd, &pid, sizeof pid);
1592
1593     close(fd);
1594     return 0;
1595 }
1596
1597 /*
1598  * unlock - remove our lockfile
1599  */
1600 void
1601 unlock()
1602 {
1603     if (lock_file) {
1604         unlink(lock_file);
1605         free(lock_file);
1606         lock_file = NULL;
1607     }
1608 }
1609
1610 #if defined(i386) && defined(HAS_BROKEN_IOCTL)
1611 int
1612 ioctl(fd, cmd, c)
1613     int fd, cmd;
1614     caddr_t c;
1615 {
1616 #undef  ioctl
1617     int ret;
1618
1619 #ifdef DEBUGIOCTL
1620     int serrno;
1621     u_char let, code, size;
1622
1623     size = (cmd >> 16) & IOCPARM_MASK;
1624     let = (cmd >> 8);
1625     code = cmd;
1626
1627     if (let == 't' && (75 <= code && code <= 90))
1628     syslog(LOG_INFO, "ioctl(%d, 0x%x ('%c', %d, %d), 0x%x)\n", fd, cmd,
1629            let, code, size, c);
1630 #endif
1631
1632     ret = ioctl(fd, cmd, c);
1633
1634 #ifdef DEBUGIOCTL
1635     serrno = errno;
1636     if (ret == -1)
1637         syslog(LOG_INFO, "ioctl('%c', %d, %d) errno = %d (%m)\n",
1638                 let, code, size, errno);
1639     if (let == 't' && (75 <= code && code <= 90) && (cmd & IOC_OUT)) {
1640         int i, len = ((cmd >> 16) & IOCPARM_MASK);
1641         for (i = 0; i < len / 4; ++i)
1642                 syslog(LOG_INFO, "word[%d] @ 0x%06x = 0x%x\n",
1643                        i, &((int *) c)[i],((int *)c)[i]);
1644     }
1645     errno = serrno;
1646 #endif
1647
1648     if (ret == -1 && errno == EPERM)
1649         errno = ret = 0;
1650     return ret;
1651 }
1652 #endif  /* HAS_BROKEN_IOCTL */
1653
1654
1655 #if defined(FIXSIGS) && (defined (hppa) || defined(sparc))
1656
1657 /*
1658  * These redefinitions of Posix functions are necessary
1659  * because HPPA systems have an OS bug that causes 
1660  * sigaction to core dump:
1661  *
1662  * AlainF 9-Nov-1994    HACK FOR HP-PA/NEXTSTEP
1663  *                      sigaction(3) seems broken in the HP-PA NeXTSTEP 3.2
1664  *                      Posix lib. This causes pppd to SIGBUS at the expiration
1665  *                      of the first timeout (_sigtramp seems to invoke
1666  *                      the SIGALRM handler at an unreasonably low address).
1667  *                      All calls so sigaction(3) have been changed to calls
1668  *                      to sigvec(2) and sigprocmask(SIG_BLOCK,...) to
1669  *                      sigblock(2).
1670  *                      This is kind of a hack, especially since there are
1671  *                      other routines of the Posix lib still used, but
1672  *                      it worked for me.
1673  *
1674  * Dave Hess <David-Hess@net.tamu.edu> noted that 3.3 Sparc seems to
1675  * have the same bug.  Thus this fix has been enabled for SPARC also.
1676  *
1677  *
1678  */
1679
1680 int sigemptyset(sigset_t *mask)
1681 {
1682   *mask = 0;
1683 }
1684
1685 sigaddset(sigset_t *mask, int which_sig)
1686 {
1687   *mask |= sigmask(which_sig);
1688 }
1689
1690
1691 int sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
1692 {
1693    struct sigvec sv;
1694    static int in = 0;
1695
1696    sv.sv_handler = act->sa_handler;
1697    sv.sv_mask = act->sa_mask;
1698    sv.sv_flags = 0;
1699
1700    if (!in)
1701      {
1702        in = 1;
1703        syslog(LOG_WARNING, "PPPD: Inside modified HP and SPARC sigaction\n");
1704      }
1705
1706    return sigvec(sig, &sv, NULL);
1707 }
1708
1709 #endif