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