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