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