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