]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/pppd/sys-bsd.c
This commit was generated by cvs2svn to compensate for changes in r162916,
[FreeBSD/FreeBSD.git] / usr.sbin / pppd / sys-bsd.c
1 /*
2  * sys-bsd.c - System-dependent procedures for setting up
3  * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.)
4  *
5  * Copyright (c) 1989 Carnegie Mellon University.
6  * Copyright (c) 1995 The Australian National University.
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 and The Australian National University.
15  * The names of the Universities may not be used to endorse or promote
16  * products derived from this software without specific prior written
17  * permission.
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21  */
22
23 #ifndef lint
24 static char rcsid[] = "$FreeBSD$";
25 #endif
26 /*      $NetBSD: sys-bsd.c,v 1.1.1.3 1997/09/26 18:53:04 christos Exp $ */
27
28 /*
29  * TODO:
30  */
31
32 #include <stdio.h>
33 #include <syslog.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <termios.h>
40 #include <signal.h>
41 #include <sys/ioctl.h>
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <sys/time.h>
45 #include <sys/stat.h>
46 #include <sys/param.h>
47 #include <sys/module.h>
48 #ifdef NetBSD1_2
49 #include <util.h>
50 #endif
51 #ifdef PPP_FILTER
52 #include <net/bpf.h>
53 #endif
54
55 #include <net/if.h>
56 #include <net/ppp_defs.h>
57 #include <net/if_ppp.h>
58 #include <net/route.h>
59 #include <net/if_dl.h>
60 #include <netinet/in.h>
61
62 #ifdef IPX_CHANGE
63 #include <netipx/ipx.h>
64 #endif
65
66 #if RTM_VERSION >= 3
67 #include <sys/param.h>
68 #if defined(NetBSD) && (NetBSD >= 199703)
69 #include <netinet/if_inarp.h>
70 #else   /* NetBSD 1.2D or later */
71 #ifdef __FreeBSD__
72 #include <netinet/if_ether.h>
73 #else
74 #include <net/if_ether.h>
75 #endif
76 #endif
77 #endif
78
79 #include <ifaddrs.h>
80
81 #include "pppd.h"
82 #include "fsm.h"
83 #include "ipcp.h"
84
85 static int initdisc = -1;       /* Initial TTY discipline for ppp_fd */
86 static int initfdflags = -1;    /* Initial file descriptor flags for ppp_fd */
87 static int ppp_fd = -1;         /* fd which is set to PPP discipline */
88 static int rtm_seq;
89
90 static int restore_term;        /* 1 => we've munged the terminal */
91 static struct termios inittermios; /* Initial TTY termios */
92 static struct winsize wsinfo;   /* Initial window size info */
93
94 static char *lock_file;         /* name of lock file created */
95
96 static int loop_slave = -1;
97 static int loop_master;
98 static char loop_name[20];
99
100 static unsigned char inbuf[512]; /* buffer for chars read from loopback */
101
102 static int sockfd;              /* socket for doing interface ioctls */
103
104 static int if_is_up;            /* the interface is currently up */
105 static u_int32_t ifaddrs[2];    /* local and remote addresses we set */
106 static u_int32_t default_route_gateway; /* gateway addr for default route */
107 static u_int32_t proxy_arp_addr;        /* remote addr for proxy arp */
108
109 /* Prototypes for procedures local to this file. */
110 static int dodefaultroute __P((u_int32_t, int));
111 static int get_ether_addr __P((u_int32_t, struct sockaddr_dl *));
112
113
114 /*
115  * sys_init - System-dependent initialization.
116  */
117 void
118 sys_init()
119 {
120     /* Get an internet socket for doing socket ioctl's on. */
121     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
122         syslog(LOG_ERR, "Couldn't create IP socket: %m");
123         die(1);
124     }
125 }
126
127 /*
128  * sys_cleanup - restore any system state we modified before exiting:
129  * mark the interface down, delete default route and/or proxy arp entry.
130  * This should call die() because it's called from die().
131  */
132 void
133 sys_cleanup()
134 {
135     struct ifreq ifr;
136
137     if (if_is_up) {
138         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
139         if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
140             && ((ifr.ifr_flags & IFF_UP) != 0)) {
141             ifr.ifr_flags &= ~IFF_UP;
142             ioctl(sockfd, SIOCSIFFLAGS, &ifr);
143         }
144     }
145     if (ifaddrs[0] != 0)
146         cifaddr(0, ifaddrs[0], ifaddrs[1]);
147     if (default_route_gateway)
148         cifdefaultroute(0, 0, default_route_gateway);
149     if (proxy_arp_addr)
150         cifproxyarp(0, proxy_arp_addr);
151 }
152
153 /*
154  * sys_close - Clean up in a child process before execing.
155  */
156 void
157 sys_close()
158 {
159     close(sockfd);
160     if (loop_slave >= 0) {
161         close(loop_slave);
162         close(loop_master);
163     }
164 }
165
166 /*
167  * sys_check_options - check the options that the user specified
168  */
169 void
170 sys_check_options()
171 {
172 }
173
174 /*
175  * ppp_available - check whether the system has the ppp module loaded
176  * or compiled in. If it doesn't, and we're actually root (not just SUID
177  * root) try loading it before giving up.
178  */
179 int
180 ppp_available()
181 {
182     const char *modname = "if_ppp";
183     extern char *no_ppp_msg;
184
185     if (modfind(modname) != -1) {
186         return 1;
187     }
188
189     if (getuid() == 0 && kldload(modname) != -1)
190         return 1;
191
192     no_ppp_msg = "\
193 This system lacks kernel support for PPP.  To include PPP support\n\
194 in the kernel, please add \"device ppp\" to your kernel config or \n\
195 load the if_ppp module.\n";
196
197     return 0;
198 }
199
200 /*
201  * establish_ppp - Turn the serial port into a ppp interface.
202  */
203 void
204 establish_ppp(fd)
205     int fd;
206 {
207     int pppdisc = PPPDISC;
208     int x;
209
210     if (demand) {
211         /*
212          * Demand mode - prime the old ppp device to relinquish the unit.
213          */
214         if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) {
215             syslog(LOG_ERR, "ioctl(transfer ppp unit): %m");
216             die(1);
217         }
218     }
219
220     /*
221      * Save the old line discipline of fd, and set it to PPP.
222      */
223     if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
224         syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
225         die(1);
226     }
227     if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
228         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
229         die(1);
230     }
231
232     if (!demand) {
233         /*
234          * Find out which interface we were given.
235          */
236         if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {      
237             syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
238             die(1);
239         }
240     } else {
241         /*
242          * Check that we got the same unit again.
243          */
244         if (ioctl(fd, PPPIOCGUNIT, &x) < 0) {   
245             syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
246             die(1);
247         }
248         if (x != ifunit) {
249             syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
250                    ifunit, x);
251             die(1);
252         }
253         x = TTYDISC;
254         ioctl(loop_slave, TIOCSETD, &x);
255     }
256
257     ppp_fd = fd;
258
259     /*
260      * Enable debug in the driver if requested.
261      */
262     if (kdebugflag) {
263         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
264             syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
265         } else {
266             x |= (kdebugflag & 0xFF) * SC_DEBUG;
267             if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
268                 syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
269         }
270     }
271
272     /*
273      * Set device for non-blocking reads.
274      */
275     if ((initfdflags = fcntl(fd, F_GETFL)) == -1
276         || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
277         syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m");
278     }
279 }
280
281 /*
282  * restore_loop - reattach the ppp unit to the loopback.
283  */
284 void
285 restore_loop()
286 {
287     int x;
288
289     /*
290      * Transfer the ppp interface back to the loopback.
291      */
292     if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) {
293         syslog(LOG_ERR, "ioctl(transfer ppp unit): %m");
294         die(1);
295     }
296     x = PPPDISC;
297     if (ioctl(loop_slave, TIOCSETD, &x) < 0) {
298         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
299         die(1);
300     }
301
302     /*
303      * Check that we got the same unit again.
304      */
305     if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0) {       
306         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
307         die(1);
308     }
309     if (x != ifunit) {
310         syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
311                ifunit, x);
312         die(1);
313     }
314     ppp_fd = loop_slave;
315 }
316
317
318 /*
319  * disestablish_ppp - Restore the serial port to normal operation.
320  * This shouldn't call die() because it's called from die().
321  */
322 void
323 disestablish_ppp(fd)
324     int fd;
325 {
326     /* Reset non-blocking mode on fd. */
327     if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
328         syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
329     initfdflags = -1;
330
331     /* Restore old line discipline. */
332     if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0)
333         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
334     initdisc = -1;
335
336     if (fd == ppp_fd)
337         ppp_fd = -1;
338 }
339
340 /*
341  * Check whether the link seems not to be 8-bit clean.
342  */
343 void
344 clean_check()
345 {
346     int x;
347     char *s;
348
349     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
350         s = NULL;
351         switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
352         case SC_RCV_B7_0:
353             s = "bit 7 set to 1";
354             break;
355         case SC_RCV_B7_1:
356             s = "bit 7 set to 0";
357             break;
358         case SC_RCV_EVNP:
359             s = "odd parity";
360             break;
361         case SC_RCV_ODDP:
362             s = "even parity";
363             break;
364         }
365         if (s != NULL) {
366             syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
367             syslog(LOG_WARNING, "All received characters had %s", s);
368         }
369     }
370 }
371
372 /*
373  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
374  * at the requested speed, etc.  If `local' is true, set CLOCAL
375  * regardless of whether the modem option was specified.
376  *
377  * For *BSD, we assume that speed_t values numerically equal bits/second.
378  */
379 void
380 set_up_tty(fd, local)
381     int fd, local;
382 {
383     struct termios tios;
384
385     if (tcgetattr(fd, &tios) < 0) {
386         syslog(LOG_ERR, "tcgetattr: %m");
387         die(1);
388     }
389
390     if (!restore_term) {
391         inittermios = tios;
392         ioctl(fd, TIOCGWINSZ, &wsinfo);
393     }
394
395     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
396     if (crtscts > 0 && !local)
397         tios.c_cflag |= CRTSCTS;
398     else if (crtscts < 0)
399         tios.c_cflag &= ~CRTSCTS;
400
401     tios.c_cflag |= CS8 | CREAD | HUPCL;
402     if (local || !modem)
403         tios.c_cflag |= CLOCAL;
404     tios.c_iflag = IGNBRK | IGNPAR;
405     tios.c_oflag = 0;
406     tios.c_lflag = 0;
407     tios.c_cc[VMIN] = 1;
408     tios.c_cc[VTIME] = 0;
409
410     if (crtscts == -2) {
411         tios.c_iflag |= IXON | IXOFF;
412         tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
413         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
414     }
415
416     if (inspeed) {
417         cfsetospeed(&tios, inspeed);
418         cfsetispeed(&tios, inspeed);
419     } else {
420         inspeed = cfgetospeed(&tios);
421         /*
422          * We can't proceed if the serial port speed is 0,
423          * since that implies that the serial port is disabled.
424          */
425         if (inspeed == 0) {
426             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
427                    devnam);
428             die(1);
429         }
430     }
431     baud_rate = inspeed;
432
433     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
434         syslog(LOG_ERR, "tcsetattr: %m");
435         die(1);
436     }
437
438     restore_term = 1;
439 }
440
441 /*
442  * restore_tty - restore the terminal to the saved settings.
443  */
444 void
445 restore_tty(fd)
446     int fd;
447 {
448     if (restore_term) {
449         if (!default_device) {
450             /*
451              * Turn off echoing, because otherwise we can get into
452              * a loop with the tty and the modem echoing to each other.
453              * We presume we are the sole user of this tty device, so
454              * when we close it, it will revert to its defaults anyway.
455              */
456             inittermios.c_lflag &= ~(ECHO | ECHONL);
457         }
458         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
459             if (errno != ENXIO)
460                 syslog(LOG_WARNING, "tcsetattr: %m");
461         ioctl(fd, TIOCSWINSZ, &wsinfo);
462         restore_term = 0;
463     }
464 }
465
466 /*
467  * setdtr - control the DTR line on the serial port.
468  * This is called from die(), so it shouldn't call die().
469  */
470 void
471 setdtr(fd, on)
472 int fd, on;
473 {
474     int modembits = TIOCM_DTR;
475
476     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
477 }
478
479
480 /*
481  * open_ppp_loopback - open the device we use for getting
482  * packets in demand mode, and connect it to a ppp interface.
483  * Here we use a pty.
484  */
485 void
486 open_ppp_loopback()
487 {
488     int flags;
489     struct termios tios;
490     int pppdisc = PPPDISC;
491
492     if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0) {
493         syslog(LOG_ERR, "No free pty for loopback");
494         die(1);
495     }
496     SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name));
497
498     if (tcgetattr(loop_slave, &tios) == 0) {
499         tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
500         tios.c_cflag |= CS8 | CREAD;
501         tios.c_iflag = IGNPAR;
502         tios.c_oflag = 0;
503         tios.c_lflag = 0;
504         if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0)
505             syslog(LOG_WARNING, "couldn't set attributes on loopback: %m");
506     }
507
508     if ((flags = fcntl(loop_master, F_GETFL)) != -1) 
509         if (fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1)
510             syslog(LOG_WARNING, "couldn't set loopback to nonblock: %m");
511
512     ppp_fd = loop_slave;
513     if (ioctl(ppp_fd, TIOCSETD, &pppdisc) < 0) {
514         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
515         die(1);
516     }
517
518     /*
519      * Find out which interface we were given.
520      */
521     if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0) {      
522         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
523         die(1);
524     }
525
526     /*
527      * Enable debug in the driver if requested.
528      */
529     if (kdebugflag) {
530         if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0) {
531             syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
532         } else {
533             flags |= (kdebugflag & 0xFF) * SC_DEBUG;
534             if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0)
535                 syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
536         }
537     }
538
539 }
540
541
542 /*
543  * output - Output PPP packet.
544  */
545 void
546 output(unit, p, len)
547     int unit;
548     u_char *p;
549     int len;
550 {
551     if (debug)
552         log_packet(p, len, "sent ", LOG_DEBUG);
553
554     if (write(ttyfd, p, len) < 0) {
555         if (errno != EIO)
556             syslog(LOG_ERR, "write: %m");
557     }
558 }
559
560
561 /*
562  * wait_input - wait until there is data available on ttyfd,
563  * for the length of time specified by *timo (indefinite
564  * if timo is NULL).
565  */
566 void
567 wait_input(timo)
568     struct timeval *timo;
569 {
570     fd_set ready;
571     int n;
572
573     if (ttyfd >= FD_SETSIZE) {
574             syslog(LOG_ERR, "descriptor too big");
575             die(1);
576     }
577     FD_ZERO(&ready);
578     FD_SET(ttyfd, &ready);
579     n = select(ttyfd+1, &ready, NULL, &ready, timo);
580     if (n < 0 && errno != EINTR) {
581         syslog(LOG_ERR, "select: %m");
582         die(1);
583     }
584 }
585
586
587 /*
588  * wait_loop_output - wait until there is data available on the
589  * loopback, for the length of time specified by *timo (indefinite
590  * if timo is NULL).
591  */
592 void
593 wait_loop_output(timo)
594     struct timeval *timo;
595 {
596     fd_set ready;
597     int n;
598
599     if (loop_master >= FD_SETSIZE) {
600             syslog(LOG_ERR, "descriptor too big");
601             die(1);
602     }
603     FD_ZERO(&ready);
604     FD_SET(loop_master, &ready);
605     n = select(loop_master + 1, &ready, NULL, &ready, timo);
606     if (n < 0 && errno != EINTR) {
607         syslog(LOG_ERR, "select: %m");
608         die(1);
609     }
610 }
611
612
613 /*
614  * wait_time - wait for a given length of time or until a
615  * signal is received.
616  */
617 void
618 wait_time(timo)
619     struct timeval *timo;
620 {
621     int n;
622
623     n = select(0, NULL, NULL, NULL, timo);
624     if (n < 0 && errno != EINTR) {
625         syslog(LOG_ERR, "select: %m");
626         die(1);
627     }
628 }
629
630
631 /*
632  * read_packet - get a PPP packet from the serial device.
633  */
634 int
635 read_packet(buf)
636     u_char *buf;
637 {
638     int len;
639
640     if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
641         if (errno == EWOULDBLOCK || errno == EINTR)
642             return -1;
643         syslog(LOG_ERR, "read: %m");
644         die(1);
645     }
646     return len;
647 }
648
649
650 /*
651  * get_loop_output - read characters from the loopback, form them
652  * into frames, and detect when we want to bring the real link up.
653  * Return value is 1 if we need to bring up the link, 0 otherwise.
654  */
655 int
656 get_loop_output()
657 {
658     int rv = 0;
659     int n;
660
661     while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) {
662         if (loop_chars(inbuf, n))
663             rv = 1;
664     }
665
666     if (n == 0) {
667         syslog(LOG_ERR, "eof on loopback");
668         die(1);
669     } else if (errno != EWOULDBLOCK){
670         syslog(LOG_ERR, "read from loopback: %m");
671         die(1);
672     }
673
674     return rv;
675 }
676
677
678 /*
679  * ppp_send_config - configure the transmit characteristics of
680  * the ppp interface.
681  */
682 void
683 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
684     int unit, mtu;
685     u_int32_t asyncmap;
686     int pcomp, accomp;
687 {
688     u_int x;
689     struct ifreq ifr;
690
691     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
692     ifr.ifr_mtu = mtu;
693     if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
694         syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
695         quit();
696     }
697
698     if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
699         syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
700         quit();
701     }
702
703     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
704         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
705         quit();
706     }
707     x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
708     x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
709     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
710         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
711         quit();
712     }
713 }
714
715
716 /*
717  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
718  */
719 void
720 ppp_set_xaccm(unit, accm)
721     int unit;
722     ext_accm accm;
723 {
724     if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
725         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
726 }
727
728
729 /*
730  * ppp_recv_config - configure the receive-side characteristics of
731  * the ppp interface.
732  */
733 void
734 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
735     int unit, mru;
736     u_int32_t asyncmap;
737     int pcomp, accomp;
738 {
739     int x;
740
741     if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
742         syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
743         quit();
744     }
745     if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
746         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
747         quit();
748     }
749     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
750         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
751         quit();
752     }
753     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
754     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
755         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
756         quit();
757     }
758 }
759
760 /*
761  * ccp_test - ask kernel whether a given compression method
762  * is acceptable for use.  Returns 1 if the method and parameters
763  * are OK, 0 if the method is known but the parameters are not OK
764  * (e.g. code size should be reduced), or -1 if the method is unknown.
765  */
766 int
767 ccp_test(unit, opt_ptr, opt_len, for_transmit)
768     int unit, opt_len, for_transmit;
769     u_char *opt_ptr;
770 {
771     struct ppp_option_data data;
772
773     data.ptr = opt_ptr;
774     data.length = opt_len;
775     data.transmit = for_transmit;
776     if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
777         return 1;
778     return (errno == ENOBUFS)? 0: -1;
779 }
780
781 /*
782  * ccp_flags_set - inform kernel about the current state of CCP.
783  */
784 void
785 ccp_flags_set(unit, isopen, isup)
786     int unit, isopen, isup;
787 {
788     int x;
789
790     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
791         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
792         return;
793     }
794     x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
795     x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
796     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
797         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
798 }
799
800 /*
801  * ccp_fatal_error - returns 1 if decompression was disabled as a
802  * result of an error detected after decompression of a packet,
803  * 0 otherwise.  This is necessary because of patent nonsense.
804  */
805 int
806 ccp_fatal_error(unit)
807     int unit;
808 {
809     int x;
810
811     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
812         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
813         return 0;
814     }
815     return x & SC_DC_FERROR;
816 }
817
818 /*
819  * get_idle_time - return how long the link has been idle.
820  */
821 int
822 get_idle_time(u, ip)
823     int u;
824     struct ppp_idle *ip;
825 {
826     return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
827 }
828
829
830 #ifdef PPP_FILTER
831 /*
832  * set_filters - transfer the pass and active filters to the kernel.
833  */
834 int
835 set_filters(pass, active)
836     struct bpf_program *pass, *active;
837 {
838     int ret = 1;
839
840     if (pass->bf_len > 0) {
841         if (ioctl(ppp_fd, PPPIOCSPASS, pass) < 0) {
842             syslog(LOG_ERR, "Couldn't set pass-filter in kernel: %m");
843             ret = 0;
844         }
845     }
846     if (active->bf_len > 0) {
847         if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) {
848             syslog(LOG_ERR, "Couldn't set active-filter in kernel: %m");
849             ret = 0;
850         }
851     }
852     return ret;
853 }
854 #endif
855
856 /*
857  * sifvjcomp - config tcp header compression
858  */
859 int
860 sifvjcomp(u, vjcomp, cidcomp, maxcid)
861     int u, vjcomp, cidcomp, maxcid;
862 {
863     u_int x;
864
865     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
866         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
867         return 0;
868     }
869     x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
870     x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
871     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
872         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
873         return 0;
874     }
875     if (vjcomp && ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
876         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
877         return 0;
878     }
879     return 1;
880 }
881
882 /*
883  * sifup - Config the interface up and enable IP packets to pass.
884  */
885 int
886 sifup(u)
887     int u;
888 {
889     struct ifreq ifr;
890
891     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
892     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
893         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
894         return 0;
895     }
896     ifr.ifr_flags |= IFF_UP;
897     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
898         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
899         return 0;
900     }
901     if_is_up = 1;
902     return 1;
903 }
904
905 /*
906  * sifnpmode - Set the mode for handling packets for a given NP.
907  */
908 int
909 sifnpmode(u, proto, mode)
910     int u;
911     int proto;
912     enum NPmode mode;
913 {
914     struct npioctl npi;
915
916     npi.protocol = proto;
917     npi.mode = mode;
918     if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
919         syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode);
920         return 0;
921     }
922     return 1;
923 }
924
925 /*
926  * sifdown - Config the interface down and disable IP.
927  */
928 int
929 sifdown(u)
930     int u;
931 {
932     struct ifreq ifr;
933     int rv;
934     struct npioctl npi;
935
936     rv = 1;
937     npi.protocol = PPP_IP;
938     npi.mode = NPMODE_ERROR;
939     ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi);
940     /* ignore errors, because ppp_fd might have been closed by now. */
941
942     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
943     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
944         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
945         rv = 0;
946     } else {
947         ifr.ifr_flags &= ~IFF_UP;
948         if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
949             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
950             rv = 0;
951         } else
952             if_is_up = 0;
953     }
954     return rv;
955 }
956
957 /*
958  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
959  * if it exists.
960  */
961 #define SET_SA_FAMILY(addr, family)             \
962     BZERO((char *) &(addr), sizeof(addr));      \
963     addr.sa_family = (family);                  \
964     addr.sa_len = sizeof(addr);
965
966 /*
967  * sifaddr - Config the interface IP addresses and netmask.
968  */
969 int
970 sifaddr(u, o, h, m)
971     int u;
972     u_int32_t o, h, m;
973 {
974     struct ifaliasreq ifra;
975     struct ifreq ifr;
976
977     strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
978     SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
979     ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
980     SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
981     ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
982     if (m != 0) {
983         SET_SA_FAMILY(ifra.ifra_mask, AF_INET);
984         ((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
985     } else
986         BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
987     BZERO(&ifr, sizeof(ifr));
988     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
989     if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) {
990         if (errno != EADDRNOTAVAIL)
991             syslog(LOG_WARNING, "Couldn't remove interface address: %m");
992     }
993     if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
994         if (errno != EEXIST) {
995             syslog(LOG_ERR, "Couldn't set interface address: %m");
996             return 0;
997         }
998         syslog(LOG_WARNING,
999                "Couldn't set interface address: Address %s already exists",
1000                 ip_ntoa(o));
1001     }
1002     ifaddrs[0] = o;
1003     ifaddrs[1] = h;
1004     return 1;
1005 }
1006
1007 /*
1008  * cifaddr - Clear the interface IP addresses, and delete routes
1009  * through the interface if possible.
1010  */
1011 int
1012 cifaddr(u, o, h)
1013     int u;
1014     u_int32_t o, h;
1015 {
1016     struct ifaliasreq ifra;
1017
1018     ifaddrs[0] = 0;
1019     strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1020     SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
1021     ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
1022     SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
1023     ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
1024     BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
1025     if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
1026         if (errno != EADDRNOTAVAIL)
1027             syslog(LOG_WARNING, "Couldn't delete interface address: %m");
1028         return 0;
1029     }
1030     return 1;
1031 }
1032
1033 /*
1034  * sifdefaultroute - assign a default route through the address given.
1035  */
1036 int
1037 sifdefaultroute(u, l, g)
1038     int u;
1039     u_int32_t l, g;
1040 {
1041     return dodefaultroute(g, 's');
1042 }
1043
1044 /*
1045  * cifdefaultroute - delete a default route through the address given.
1046  */
1047 int
1048 cifdefaultroute(u, l, g)
1049     int u;
1050     u_int32_t l, g;
1051 {
1052     return dodefaultroute(g, 'c');
1053 }
1054
1055 /*
1056  * dodefaultroute - talk to a routing socket to add/delete a default route.
1057  */
1058 static int
1059 dodefaultroute(g, cmd)
1060     u_int32_t g;
1061     int cmd;
1062 {
1063     int routes;
1064     struct {
1065         struct rt_msghdr        hdr;
1066         struct sockaddr_in      dst;
1067         struct sockaddr_in      gway;
1068         struct sockaddr_in      mask;
1069     } rtmsg;
1070
1071     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1072         syslog(LOG_ERR, "Couldn't %s default route: socket: %m",
1073                cmd=='s'? "add": "delete");
1074         return 0;
1075     }
1076
1077     memset(&rtmsg, 0, sizeof(rtmsg));
1078     rtmsg.hdr.rtm_type = cmd == 's'? RTM_ADD: RTM_DELETE;
1079     rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
1080     rtmsg.hdr.rtm_version = RTM_VERSION;
1081     rtmsg.hdr.rtm_seq = ++rtm_seq;
1082     rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
1083     rtmsg.dst.sin_len = sizeof(rtmsg.dst);
1084     rtmsg.dst.sin_family = AF_INET;
1085     rtmsg.gway.sin_len = sizeof(rtmsg.gway);
1086     rtmsg.gway.sin_family = AF_INET;
1087     rtmsg.gway.sin_addr.s_addr = g;
1088     rtmsg.mask.sin_len = sizeof(rtmsg.dst);
1089     rtmsg.mask.sin_family = AF_INET;
1090
1091     rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
1092     if (write(routes, &rtmsg, sizeof(rtmsg)) < 0) {
1093         syslog(LOG_ERR, "Couldn't %s default route: %m",
1094                cmd=='s'? "add": "delete");
1095         close(routes);
1096         return 0;
1097     }
1098
1099     close(routes);
1100     default_route_gateway = (cmd == 's')? g: 0;
1101     return 1;
1102 }
1103
1104 #if RTM_VERSION >= 3
1105
1106 /*
1107  * sifproxyarp - Make a proxy ARP entry for the peer.
1108  */
1109 static struct {
1110     struct rt_msghdr            hdr;
1111     struct sockaddr_inarp       dst;
1112     struct sockaddr_dl          hwa;
1113     char                        extra[128];
1114 } arpmsg;
1115
1116 static int arpmsg_valid;
1117
1118 int
1119 sifproxyarp(unit, hisaddr)
1120     int unit;
1121     u_int32_t hisaddr;
1122 {
1123     int routes;
1124
1125     /*
1126      * Get the hardware address of an interface on the same subnet
1127      * as our local address.
1128      */
1129     memset(&arpmsg, 0, sizeof(arpmsg));
1130     if (!get_ether_addr(hisaddr, &arpmsg.hwa)) {
1131         syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1132         return 0;
1133     }
1134
1135     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1136         syslog(LOG_ERR, "Couldn't add proxy arp entry: socket: %m");
1137         return 0;
1138     }
1139
1140     arpmsg.hdr.rtm_type = RTM_ADD;
1141     arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC;
1142     arpmsg.hdr.rtm_version = RTM_VERSION;
1143     arpmsg.hdr.rtm_seq = ++rtm_seq;
1144     arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
1145     arpmsg.hdr.rtm_inits = RTV_EXPIRE;
1146     arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
1147     arpmsg.dst.sin_family = AF_INET;
1148     arpmsg.dst.sin_addr.s_addr = hisaddr;
1149     arpmsg.dst.sin_other = SIN_PROXY;
1150
1151     arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
1152         + arpmsg.hwa.sdl_len;
1153     if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1154         syslog(LOG_ERR, "Couldn't add proxy arp entry: %m");
1155         close(routes);
1156         return 0;
1157     }
1158
1159     close(routes);
1160     arpmsg_valid = 1;
1161     proxy_arp_addr = hisaddr;
1162     return 1;
1163 }
1164
1165 /*
1166  * cifproxyarp - Delete the proxy ARP entry for the peer.
1167  */
1168 int
1169 cifproxyarp(unit, hisaddr)
1170     int unit;
1171     u_int32_t hisaddr;
1172 {
1173     int routes;
1174
1175     if (!arpmsg_valid)
1176         return 0;
1177     arpmsg_valid = 0;
1178
1179     arpmsg.hdr.rtm_type = RTM_DELETE;
1180     arpmsg.hdr.rtm_seq = ++rtm_seq;
1181
1182     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1183         syslog(LOG_ERR, "Couldn't delete proxy arp entry: socket: %m");
1184         return 0;
1185     }
1186
1187     if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1188         syslog(LOG_ERR, "Couldn't delete proxy arp entry: %m");
1189         close(routes);
1190         return 0;
1191     }
1192
1193     close(routes);
1194     proxy_arp_addr = 0;
1195     return 1;
1196 }
1197
1198 #else   /* RTM_VERSION */
1199
1200 /*
1201  * sifproxyarp - Make a proxy ARP entry for the peer.
1202  */
1203 int
1204 sifproxyarp(unit, hisaddr)
1205     int unit;
1206     u_int32_t hisaddr;
1207 {
1208     struct arpreq arpreq;
1209     struct {
1210         struct sockaddr_dl      sdl;
1211         char                    space[128];
1212     } dls;
1213
1214     BZERO(&arpreq, sizeof(arpreq));
1215
1216     /*
1217      * Get the hardware address of an interface on the same subnet
1218      * as our local address.
1219      */
1220     if (!get_ether_addr(hisaddr, &dls.sdl)) {
1221         syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1222         return 0;
1223     }
1224
1225     arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
1226     arpreq.arp_ha.sa_family = AF_UNSPEC;
1227     BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen);
1228     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1229     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1230     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1231     if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
1232         syslog(LOG_ERR, "Couldn't add proxy arp entry: %m");
1233         return 0;
1234     }
1235
1236     proxy_arp_addr = hisaddr;
1237     return 1;
1238 }
1239
1240 /*
1241  * cifproxyarp - Delete the proxy ARP entry for the peer.
1242  */
1243 int
1244 cifproxyarp(unit, hisaddr)
1245     int unit;
1246     u_int32_t hisaddr;
1247 {
1248     struct arpreq arpreq;
1249
1250     BZERO(&arpreq, sizeof(arpreq));
1251     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1252     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1253     if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1254         syslog(LOG_WARNING, "Couldn't delete proxy arp entry: %m");
1255         return 0;
1256     }
1257     proxy_arp_addr = 0;
1258     return 1;
1259 }
1260 #endif  /* RTM_VERSION */
1261
1262 #ifdef IPX_CHANGE
1263 /********************************************************************
1264  *
1265  * sipxfaddr - Config the interface IPX networknumber
1266  */
1267
1268 int
1269 sipxfaddr (int unit, unsigned long int network, unsigned char * node )
1270   {
1271     int    result = 1;
1272
1273     int    skfd; 
1274     struct sockaddr_ipx  ipx_addr;
1275     struct ifreq         ifr;
1276     struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
1277     union ipx_net_u net;
1278
1279     skfd = socket (AF_IPX, SOCK_DGRAM, 0);
1280     if (skfd < 0)
1281       { 
1282         syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno);
1283         result = 0;
1284       }
1285     else
1286       {
1287         memset (&ifr, '\0', sizeof (ifr));
1288         strcpy (ifr.ifr_name, ifname);
1289
1290         memcpy (sipx->sipx_addr.x_host.c_host, node, 6);
1291         sipx->sipx_len     = sizeof(sipx);
1292         sipx->sipx_family  = AF_IPX;
1293         sipx->sipx_port    = 0;
1294         memset(&net, 0, sizeof(net));
1295         net.long_e = htonl (network);
1296         sipx->sipx_addr.x_net = net.net_e;
1297 /*
1298  *  Set the IPX device
1299  */
1300         if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
1301           {
1302             result = 0;
1303             if (errno != EEXIST)
1304               {
1305                 syslog (LOG_DEBUG,
1306                             "ioctl(SIOCAIFADDR, CRTITF): %m(%d)", errno);
1307               }
1308             else
1309               {
1310                 syslog (LOG_WARNING,
1311                         "ioctl(SIOCAIFADDR, CRTITF): Address already exists");
1312               }
1313           }
1314         close (skfd);
1315       }
1316     return result;
1317   }
1318
1319 /********************************************************************
1320  *
1321  * cipxfaddr - Clear the information for the IPX network. The IPX routes
1322  *             are removed and the device is no longer able to pass IPX
1323  *             frames.
1324  */
1325
1326 int cipxfaddr (int unit)
1327   {
1328     int    result = 1;
1329
1330     int    skfd; 
1331     struct sockaddr_ipx  ipx_addr;
1332     struct ifreq         ifr;
1333     struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
1334
1335     skfd = socket (AF_IPX, SOCK_DGRAM, 0);
1336     if (skfd < 0)
1337       { 
1338         syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno);
1339         result = 0;
1340       }
1341     else
1342       {
1343         memset (&ifr, '\0', sizeof (ifr));
1344         strcpy (ifr.ifr_name, ifname);
1345
1346         sipx->sipx_len     = sizeof(sipx);
1347         sipx->sipx_family  = AF_IPX;
1348 /*
1349  *  Set the IPX device
1350  */
1351         if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
1352           {
1353             syslog (LOG_INFO,
1354                         "ioctl(SIOCAIFADDR, IPX_DLTITF): %m(%d)", errno);
1355             result = 0;
1356           }
1357         close (skfd);
1358       }
1359     return result;
1360   }
1361 #endif
1362
1363 /*
1364  * get_ether_addr - get the hardware address of an interface on the
1365  * the same subnet as ipaddr.
1366  */
1367 static int
1368 get_ether_addr(ipaddr, hwaddr)
1369     u_int32_t ipaddr;
1370     struct sockaddr_dl *hwaddr;
1371 {
1372     u_int32_t ina, mask;
1373     struct sockaddr_dl *dla;
1374     struct ifaddrs *ifap, *ifa, *ifp;
1375
1376     /*
1377      * Scan through looking for an interface with an Internet
1378      * address on the same subnet as `ipaddr'.
1379      */
1380     if (getifaddrs(&ifap) != 0) {
1381         syslog(LOG_ERR, "getifaddrs: %m");
1382         return 0;
1383     }
1384     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1385         if (ifa->ifa_addr->sa_family != AF_INET)
1386             continue;
1387         ina = ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr;
1388         /*
1389          * Check that the interface is up, and not point-to-point
1390          * or loopback.
1391          */
1392         if ((ifa->ifa_flags &
1393             (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1394             != (IFF_UP|IFF_BROADCAST))
1395                 continue;
1396         /*
1397          * Get its netmask and check that it's on the right subnet.
1398          */
1399         mask = ((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr;
1400         if ((ipaddr & mask) != (ina & mask))
1401                 continue;
1402         break;
1403     }
1404     if (!ifa) {
1405         freeifaddrs(ifap);
1406         return 0;
1407     }
1408     syslog(LOG_INFO, "found interface %s for proxy arp", ifa->ifa_name);
1409
1410     /*
1411      * Now scan through again looking for a link-level address
1412      * for this interface.
1413      */
1414     ifp = ifa;
1415     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1416         if (strcmp(ifp->ifa_name, ifa->ifa_name) != 0)
1417             continue;
1418         if (ifa->ifa_addr->sa_family != AF_LINK)
1419             continue;
1420         /*
1421          * Found the link-level address - copy it out
1422          */
1423         dla = (struct sockaddr_dl *) ifa->ifa_addr;
1424         BCOPY(dla, hwaddr, dla->sdl_len);
1425         freeifaddrs(ifap);
1426         return 1;
1427     }
1428
1429     freeifaddrs(ifap);
1430     return 0;
1431 }
1432
1433 /*
1434  * Return user specified netmask, modified by any mask we might determine
1435  * for address `addr' (in network byte order).
1436  * Here we scan through the system's list of interfaces, looking for
1437  * any non-point-to-point interfaces which might appear to be on the same
1438  * network as `addr'.  If we find any, we OR in their netmask to the
1439  * user-specified netmask.
1440  */
1441 u_int32_t
1442 GetMask(addr)
1443     u_int32_t addr;
1444 {
1445     u_int32_t mask, nmask, ina;
1446     struct ifaddrs *ifap, *ifa;
1447
1448     addr = ntohl(addr);
1449     if (IN_CLASSA(addr))        /* determine network mask for address class */
1450         nmask = IN_CLASSA_NET;
1451     else if (IN_CLASSB(addr))
1452         nmask = IN_CLASSB_NET;
1453     else
1454         nmask = IN_CLASSC_NET;
1455     /* class D nets are disallowed by bad_ip_adrs */
1456     mask = netmask | htonl(nmask);
1457
1458     /*
1459      * Scan through the system's network interfaces.
1460      */
1461     if (getifaddrs(&ifap) != 0) {
1462         syslog(LOG_WARNING, "getifaddrs: %m");
1463         return mask;
1464     }
1465     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1466         /*
1467          * Check the interface's internet address.
1468          */
1469         if (ifa->ifa_addr->sa_family != AF_INET)
1470             continue;
1471         ina = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
1472         if ((ntohl(ina) & nmask) != (addr & nmask))
1473             continue;
1474         /*
1475          * Check that the interface is up, and not point-to-point or loopback.
1476          */
1477         if ((ifa->ifa_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) != IFF_UP)
1478             continue;
1479         /*
1480          * Get its netmask and OR it into our mask.
1481          */
1482         mask |= ((struct sockaddr_in *)&ifa->ifa_netmask)->sin_addr.s_addr;
1483     }
1484
1485     freeifaddrs(ifap);
1486     return mask;
1487 }
1488
1489 /*
1490  * Use the hostid as part of the random number seed.
1491  */
1492 int
1493 get_host_seed()
1494 {
1495     return gethostid();
1496 }
1497
1498 /*
1499  * lock - create a lock file for the named lock device
1500  */
1501 #define LOCK_PREFIX     "/var/spool/lock/LCK.."
1502
1503 int
1504 lock(dev)
1505     char *dev;
1506 {
1507     char hdb_lock_buffer[12];
1508     int fd, pid, n;
1509     char *p;
1510
1511     if ((p = strrchr(dev, '/')) != NULL)
1512         dev = p + 1;
1513     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1514     if (lock_file == NULL)
1515         novm("lock file name");
1516     strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1517
1518     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1519         if (errno == EEXIST
1520             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1521             /* Read the lock file to find out who has the device locked */
1522             n = read(fd, hdb_lock_buffer, 11);
1523             if (n <= 0) {
1524                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1525                 close(fd);
1526             } else {
1527                 hdb_lock_buffer[n] = 0;
1528                 pid = atoi(hdb_lock_buffer);
1529                 if (kill(pid, 0) == -1 && errno == ESRCH) {
1530                     /* pid no longer exists - remove the lock file */
1531                     if (unlink(lock_file) == 0) {
1532                         close(fd);
1533                         syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1534                                dev, pid);
1535                         continue;
1536                     } else
1537                         syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1538                                dev);
1539                 } else
1540                     syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1541                            dev, pid);
1542             }
1543             close(fd);
1544         } else
1545             syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1546         free(lock_file);
1547         lock_file = NULL;
1548         return -1;
1549     }
1550
1551     sprintf(hdb_lock_buffer, "%10d\n", getpid());
1552     write(fd, hdb_lock_buffer, 11);
1553
1554     close(fd);
1555     return 0;
1556 }
1557
1558 /*
1559  * unlock - remove our lockfile
1560  */
1561 void
1562 unlock()
1563 {
1564     if (lock_file) {
1565         unlink(lock_file);
1566         free(lock_file);
1567         lock_file = NULL;
1568     }
1569 }