xref: /netbsd-src/external/bsd/ppp/usr.sbin/pppd/sys-bsd.c (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
1 /*	NetBSD: sys-bsd.c,v 1.68 2013/06/24 20:43:48 christos 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 #include <sys/cdefs.h>
78 #ifndef lint
79 #if 0
80 #define RCSID	"Id: sys-bsd.c,v 1.47 2000/04/13 12:04:23 paulus Exp "
81 #else
82 __RCSID("NetBSD: sys-bsd.c,v 1.68 2013/06/24 20:43:48 christos Exp ");
83 #endif
84 #endif
85 
86 /*
87  * TODO:
88  */
89 
90 #include <stdio.h>
91 #include <string.h>
92 #include <stdlib.h>
93 #include <unistd.h>
94 #include <errno.h>
95 #include <fcntl.h>
96 #include <termios.h>
97 #include <signal.h>
98 #include <vis.h>
99 #include <sys/ioctl.h>
100 #include <sys/types.h>
101 #include <sys/socket.h>
102 #include <sys/time.h>
103 #include <sys/stat.h>
104 #include <sys/param.h>
105 #if defined(NetBSD1_2) || defined(__NetBSD_Version__)
106 #include <util.h>
107 #endif
108 #ifdef PPP_FILTER
109 #include <net/bpf.h>
110 #endif
111 
112 #include <net/if.h>
113 #include <net/ppp_defs.h>
114 #include <net/if_ppp.h>
115 #include <net/route.h>
116 #include <net/if_dl.h>
117 #include <netinet/in.h>
118 #ifdef __KAME__
119 #include <netinet6/in6_var.h>
120 #include <netinet6/nd6.h>
121 #endif
122 #include <ifaddrs.h>
123 
124 #ifndef IN6_LLADDR_FROM_EUI64
125 #ifdef __KAME__
126 #define IN6_LLADDR_FROM_EUI64(sin6, eui64) do {			\
127 	sin6.sin6_family = AF_INET6;				\
128 	sin6.sin6_len = sizeof(struct sockaddr_in6);		\
129 	sin6.sin6_addr.s6_addr[0] = 0xfe;			\
130 	sin6.sin6_addr.s6_addr[1] = 0x80;			\
131 	eui64_copy(eui64, sin6.sin6_addr.s6_addr[8]);		\
132 } while (/*CONSTCOND*/0)
133 #define IN6_IFINDEX(sin6, ifindex)	 			\
134     /* KAME ifindex hack */					\
135     *(u_int16_t *)&sin6.sin6_addr.s6_addr[2] = htons(ifindex)
136 #else
137 #define IN6_LLADDR_FROM_EUI64(sin6, eui64) do {			\
138 	memset(&sin6.s6_addr, 0, sizeof(struct in6_addr));	\
139 	sin6.s6_addr16[0] = htons(0xfe80);			\
140 	eui64_copy(eui64, sin6.s6_addr32[2]);			\
141 } while (/*CONSTCOND*/0)
142 #endif
143 #endif
144 
145 #if RTM_VERSION >= 3
146 #include <sys/param.h>
147 #if defined(NetBSD) && (NetBSD >= 199703)
148 #include <netinet/if_inarp.h>
149 #else	/* NetBSD 1.2D or later */
150 #ifdef __FreeBSD__
151 #include <netinet/if_ether.h>
152 #else
153 #include <net/if_ether.h>
154 #endif
155 #endif
156 #endif
157 
158 #include "pppd.h"
159 #include "fsm.h"
160 #include "ipcp.h"
161 
162 #ifdef RCSID
163 static const char rcsid[] = RCSID;
164 #endif
165 
166 static int initdisc = -1;	/* Initial TTY discipline for ppp_fd */
167 static int initfdflags = -1;	/* Initial file descriptor flags for ppp_fd */
168 static int ppp_fd = -1;		/* fd which is set to PPP discipline */
169 static int rtm_seq;
170 
171 static int restore_term;	/* 1 => we've munged the terminal */
172 static struct termios inittermios; /* Initial TTY termios */
173 static struct winsize wsinfo;	/* Initial window size info */
174 
175 static int loop_slave = -1;
176 static int loop_master = -1;
177 static int doing_cleanup = 0;
178 static char loop_name[20];
179 
180 static unsigned char inbuf[512]; /* buffer for chars read from loopback */
181 
182 static int sock_fd;		/* socket for doing interface ioctls */
183 #ifdef INET6
184 static int sock6_fd = -1;	/* socket for doing ipv6 interface ioctls */
185 #endif /* INET6 */
186 static int ttyfd = -1;		/* the file descriptor of the tty */
187 
188 static fd_set in_fds;		/* set of fds that wait_input waits for */
189 static int max_in_fd;		/* highest fd set in in_fds */
190 
191 static int if_is_up;		/* the interface is currently up */
192 #ifdef INET6
193 static int if6_is_up;		/* the interface is currently up */
194 #endif /* INET6 */
195 static u_int32_t ifaddrs[2];	/* local and remote addresses we set */
196 static u_int32_t default_route_gateway;	/* gateway addr for default route */
197 static u_int32_t proxy_arp_addr;	/* remote addr for proxy arp */
198 
199 /* Prototypes for procedures local to this file. */
200 static int get_flags(int);
201 static void set_flags(int, int);
202 static int dodefaultroute(u_int32_t, int);
203 static int get_ether_addr(u_int32_t, struct sockaddr_dl *);
204 static void restore_loop(void);	/* Transfer ppp unit back to loopback */
205 static int setifstate(int, int);
206 
207 
208 static void
209 set_queue_size(const char *fmt, int fd) {
210 #ifdef TIOCSQSIZE
211     int oqsize, qsize = 32768;
212 
213     /* Only for ptys */
214     if (ioctl(fd, TIOCGQSIZE, &oqsize) == -1)
215 	return;
216 
217     if (oqsize >= qsize)
218 	return;
219 
220     if (ioctl(fd, TIOCSQSIZE, &qsize) == -1)
221 	warn("%s: Cannot set tty queue size for %d from %d to %d", fmt, fd,
222 	    oqsize, qsize);
223     else
224 	notice("%s: Changed queue size of %d from %d to %d", fmt, fd, oqsize,
225 	    qsize);
226 #endif
227 }
228 
229 /********************************************************************
230  *
231  * Functions to read and set the flags value in the device driver
232  */
233 
234 static int
235 get_flags(int fd)
236 {
237     int flags;
238 
239     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &flags) == -1)
240 	fatal("%s: ioctl(PPPIOCGFLAGS): %m", __func__);
241 
242     SYSDEBUG((LOG_DEBUG, "get flags = %x\n", flags));
243     return flags;
244 }
245 
246 /********************************************************************/
247 
248 static void
249 set_flags(int fd, int flags)
250 {
251     SYSDEBUG((LOG_DEBUG, "set flags = %x\n", flags));
252 
253     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &flags) == -1)
254 	fatal("%s: ioctl(PPPIOCSFLAGS, %x): %m", __func__, flags, errno);
255 }
256 
257 /*
258  * sys_init - System-dependent initialization.
259  */
260 void
261 sys_init(void)
262 {
263     /* Get an internet socket for doing socket ioctl's on. */
264     if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
265 	fatal("%s: Couldn't create IP socket: %m", __func__);
266 
267 #ifdef INET6
268     if ((sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
269 	/* check it at runtime */
270 	sock6_fd = -1;
271     }
272 #endif
273 
274     FD_ZERO(&in_fds);
275     max_in_fd = 0;
276 }
277 
278 /*
279  * sys_cleanup - restore any system state we modified before exiting:
280  * mark the interface down, delete default route and/or proxy arp entry.
281  * This should call die() because it's called from die().
282  */
283 void
284 sys_cleanup(void)
285 {
286     struct ifreq ifr;
287 
288     doing_cleanup = 1;
289     if (if_is_up) {
290 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
291 	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) >= 0
292 	    && ((ifr.ifr_flags & IFF_UP) != 0)) {
293 	    ifr.ifr_flags &= ~IFF_UP;
294 	    ioctl(sock_fd, SIOCSIFFLAGS, &ifr);
295 	}
296     }
297     if (ifaddrs[0] != 0)
298 	cifaddr(0, ifaddrs[0], ifaddrs[1]);
299     if (default_route_gateway)
300 	cifdefaultroute(0, 0, default_route_gateway);
301     if (proxy_arp_addr)
302 	cifproxyarp(0, proxy_arp_addr);
303     doing_cleanup = 0;
304 }
305 
306 /*
307  * sys_close - Clean up in a child process before execing.
308  */
309 void
310 sys_close()
311 {
312     if (sock_fd >= 0)
313 	close(sock_fd);
314 #ifdef INET6
315     if (sock6_fd >= 0)
316 	close(sock6_fd);
317 #endif
318     if (loop_slave >= 0)
319 	close(loop_slave);
320     if (loop_master >= 0)
321 	close(loop_master);
322 }
323 
324 /*
325  * sys_check_options - check the options that the user specified
326  */
327 int
328 sys_check_options(void)
329 {
330 #ifndef CDTRCTS
331     if (crtscts == 2) {
332 	warn("%s: DTR/CTS flow control is not supported on this system",
333 	    __func__);
334 	return 0;
335     }
336 #endif
337     return 1;
338 }
339 
340 /*
341  * ppp_available - check whether the system has any ppp interfaces
342  * (in fact we check whether we can create one)
343  */
344 int
345 ppp_available(void)
346 {
347     int s;
348     extern char *no_ppp_msg;
349     struct ifreq ifr;
350 
351 
352     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
353 	fatal("%s: socket: %m", __func__);
354 
355     (void)memset(&ifr, 0, sizeof(ifr));
356     strlcpy(ifr.ifr_name, "ppp0", sizeof(ifr.ifr_name));
357     if (ioctl(s, SIOCIFCREATE, &ifr) == -1) {
358 	int notmine = errno == EEXIST;
359 	(void)close(s);
360 	if (notmine)
361 	    return 1;
362 	goto out;
363     }
364     (void)ioctl(s, SIOCIFDESTROY, &ifr);
365     (void)close(s);
366     return 1;
367 
368 out:
369     no_ppp_msg = "\
370 This system lacks kernel support for PPP.  To include PPP support\n\
371 in the kernel, please read the ppp(4) manual page.\n";
372     return 0;
373 }
374 
375 /*
376  * tty_establish_ppp - Turn the serial port into a ppp interface.
377  */
378 int
379 tty_establish_ppp(int fd)
380 {
381     int pppdisc = PPPDISC;
382     int x;
383     ttyfd = fd;
384 
385     if (demand) {
386 	/*
387 	 * Demand mode - prime the old ppp device to relinquish the unit.
388 	 */
389 	if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0)
390 	    fatal("%s: ioctl(transfer ppp unit): %m", __func__);
391     }
392 
393     set_queue_size(__func__, fd);
394     /*
395      * Save the old line discipline of fd, and set it to PPP.
396      */
397     if (ioctl(fd, TIOCGETD, &initdisc) < 0)
398 	fatal("%s: ioctl(TIOCGETD): %m", __func__);
399     if (ioctl(fd, TIOCSETD, &pppdisc) < 0)
400 	fatal("%s: ioctl(TIOCSETD): %m", __func__);
401 
402     if (ioctl(fd, PPPIOCGUNIT, &x) < 0)
403 	fatal("%s: ioctl(PPPIOCGUNIT): %m", __func__);
404     if (!demand) {
405 	/*
406 	 * Find out which interface we were given.
407 	 */
408 	ifunit = x;
409     } else {
410 	/*
411 	 * Check that we got the same unit again.
412 	 */
413 	if (x != ifunit)
414 	    fatal("%s: transfer_ppp failed: wanted unit %d, got %d",
415 		__func__, ifunit, x);
416 	x = TTYDISC;
417 	if (ioctl(loop_slave, TIOCSETD, &x) == -1)
418 	    fatal("%s: ioctl(TIOCGETD): %m", __func__);
419     }
420 
421     ppp_fd = fd;
422 
423     /*
424      * Enable debug in the driver if requested.
425      */
426     if (kdebugflag) {
427 	x = get_flags(fd);
428 	x |= (kdebugflag & 0xFF) * SC_DEBUG;
429 	set_flags(fd, x);
430     }
431 
432     /*
433      * Set device for non-blocking reads.
434      */
435     if ((initfdflags = fcntl(fd, F_GETFL)) == -1
436 	|| fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
437 	warn("%s: Couldn't set device to non-blocking mode: %m", __func__);
438     }
439 
440     return fd;
441 }
442 
443 /*
444  * restore_loop - reattach the ppp unit to the loopback.
445  */
446 static void
447 restore_loop(void)
448 {
449     int x;
450 
451     set_queue_size(__func__, loop_slave);
452     /*
453      * Transfer the ppp interface back to the loopback.
454      */
455     if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0)
456 	fatal("%s: ioctl(transfer ppp unit): %m", __func__);
457     x = PPPDISC;
458     if (ioctl(loop_slave, TIOCSETD, &x) < 0)
459 	fatal("%s: ioctl(TIOCSETD): %m", __func__);
460 
461     /*
462      * Check that we got the same unit again.
463      */
464     if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0)
465 	fatal("%s: ioctl(PPPIOCGUNIT): %m", __func__);
466     if (x != ifunit)
467 	fatal("%s: transfer_ppp failed: wanted unit %d, got %d", __func__,
468 	    ifunit, x);
469     ppp_fd = loop_slave;
470 }
471 
472 
473 /*
474  * Determine if the PPP connection should still be present.
475  */
476 extern int hungup;
477 
478 /*
479  * tty_disestablish_ppp - Restore the serial port to normal operation.
480  * and reconnect the ppp unit to the loopback if in demand mode.
481  * This shouldn't call die() because it's called from die().
482  */
483 void
484 tty_disestablish_ppp(fd)
485     int fd;
486 {
487     if (!doing_cleanup && demand)
488 	restore_loop();
489 
490     if (!hungup || demand) {
491 
492 	/* Flush the tty output buffer so that the TIOCSETD doesn't hang.  */
493 	if (tcflush(fd, TCIOFLUSH) < 0)
494 	    if (!doing_cleanup)
495 		warn("%s: tcflush failed: %m", __func__);
496 
497 	/* Restore old line discipline. */
498 	if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0)
499 	    if (!doing_cleanup)
500 		error("%s: ioctl(TIOCSETD): %m", __func__);
501 	initdisc = -1;
502 
503 	/* Reset non-blocking mode on fd. */
504 	if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
505 	    if (!doing_cleanup)
506 		warn("%s: Couldn't restore device fd flags: %m", __func__);
507     }
508     initfdflags = -1;
509 
510     if (fd == ppp_fd)
511 	ppp_fd = -1;
512 }
513 
514 /*
515  * cfg_bundle - configure the existing bundle.
516  * Used in demand mode.
517  */
518 void
519 cfg_bundle(int mrru, int mtru, int rssn, int tssn)
520 {
521     abort();
522 #ifdef notyet
523     int flags;
524     struct ifreq ifr;
525 
526     if (!new_style_driver)
527 	return;
528 
529     /* set the mrru, mtu and flags */
530     if (ioctl(ppp_dev_fd, PPPIOCSMRRU, &mrru) < 0)
531 	error("%s: Couldn't set MRRU: %m", __func__);
532     flags = get_flags(ppp_dev_fd);
533     flags &= ~(SC_MP_SHORTSEQ | SC_MP_XSHORTSEQ);
534     flags |= (rssn? SC_MP_SHORTSEQ: 0) | (tssn? SC_MP_XSHORTSEQ: 0)
535 	    | (mrru? SC_MULTILINK: 0);
536 
537     set_flags(ppp_dev_fd, flags);
538 
539     /* connect up the channel */
540     if (ioctl(ppp_fd, PPPIOCCONNECT, &ifunit) < 0)
541 	fatal("%s: Couldn't attach to PPP unit %d: %m", __func__, ifunit);
542     add_fd(ppp_dev_fd);
543 #endif
544 }
545 
546 /*
547  * make_new_bundle - create a new PPP unit (i.e. a bundle)
548  * and connect our channel to it.  This should only get called
549  * if `multilink' was set at the time establish_ppp was called.
550  * In demand mode this uses our existing bundle instead of making
551  * a new one.
552  */
553 void
554 make_new_bundle(int mrru, int mtru, int rssn, int tssn)
555 {
556     abort();
557 #ifdef notyet
558     if (!new_style_driver)
559 	return;
560 
561     /* make us a ppp unit */
562     if (make_ppp_unit() < 0)
563 	die(1);
564 
565     /* set the mrru, mtu and flags */
566     cfg_bundle(mrru, mtru, rssn, tssn);
567 #endif
568 }
569 
570 /*
571  * bundle_attach - attach our link to a given PPP unit.
572  * We assume the unit is controlled by another pppd.
573  */
574 int
575 bundle_attach(int ifnum)
576 {
577     abort();
578 #ifdef notyet
579     if (!new_style_driver)
580 	return -1;
581 
582     if (ioctl(ppp_dev_fd, PPPIOCATTACH, &ifnum) < 0) {
583 	if (errno == ENXIO)
584 	    return 0;	/* doesn't still exist */
585 	fatal("%s: Couldn't attach to interface unit %d: %m", __func__, ifnum);
586     }
587     if (ioctl(ppp_fd, PPPIOCCONNECT, &ifnum) < 0)
588 	fatal("%s: Couldn't connect to interface unit %d: %m", __func__, ifnum);
589     set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) | SC_MULTILINK);
590 
591     ifunit = ifnum;
592 #endif
593     return 1;
594 }
595 
596 /*
597  * destroy_bundle - tell the driver to destroy our bundle.
598  */
599 void destroy_bundle(void)
600 {
601 #if notyet
602 	if (ppp_dev_fd >= 0) {
603 		close(ppp_dev_fd);
604 		remove_fd(ppp_dev_fd);
605 		ppp_dev_fd = -1;
606 	}
607 #endif
608 }
609 
610 /*
611  * Check whether the link seems not to be 8-bit clean.
612  */
613 void
614 clean_check(void)
615 {
616     int x;
617     char *s;
618 
619     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
620 	s = NULL;
621 	switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
622 	case SC_RCV_B7_0:
623 	    s = "bit 7 set to 1";
624 	    break;
625 	case SC_RCV_B7_1:
626 	    s = "bit 7 set to 0";
627 	    break;
628 	case SC_RCV_EVNP:
629 	    s = "odd parity";
630 	    break;
631 	case SC_RCV_ODDP:
632 	    s = "even parity";
633 	    break;
634 	}
635 	if (s != NULL) {
636 	    struct ppp_rawin win;
637 	    char buf[4 * sizeof(win.buf) + 1];
638 	    int i;
639 	    warn("%s: Serial link is not 8-bit clean:", __func__);
640 	    warn("%s: All received characters had %s", __func__, s);
641 	    if (ioctl(ppp_fd, PPPIOCGRAWIN, &win) == -1) {
642 		warn("%s: ioctl(PPPIOCGRAWIN): %s", __func__, strerror(errno));
643 		return;
644 	    }
645 	    for (i = 0; i < sizeof(win.buf); i++)
646 		win.buf[i] = win.buf[i] & 0x7f;
647 	    strvisx(buf, (char *)win.buf, win.count, VIS_CSTYLE);
648 	    warn("%s: Last %d characters were: %s", __func__, (int)win.count,
649 		buf);
650 	}
651     }
652 }
653 
654 
655 /*
656  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
657  * at the requested speed, etc.  If `local' is true, set CLOCAL
658  * regardless of whether the modem option was specified.
659  *
660  * For *BSD, we assume that speed_t values numerically equal bits/second.
661  */
662 void
663 set_up_tty(int fd, int local)
664 {
665     struct termios tios;
666 
667     if (tcgetattr(fd, &tios) < 0)
668 	fatal("%s: tcgetattr: %m", __func__);
669 
670     if (!restore_term) {
671 	inittermios = tios;
672 	ioctl(fd, TIOCGWINSZ, &wsinfo);
673     }
674 
675     set_queue_size(__func__, fd);
676 
677     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
678     if (crtscts > 0 && !local) {
679         if (crtscts == 2) {
680 #ifdef CDTRCTS
681             tios.c_cflag |= CDTRCTS;
682 #endif
683 	} else
684 	    tios.c_cflag |= CRTSCTS;
685     } else if (crtscts < 0) {
686 	tios.c_cflag &= ~CRTSCTS;
687 #ifdef CDTRCTS
688 	tios.c_cflag &= ~CDTRCTS;
689 #endif
690     }
691 
692     tios.c_cflag |= CS8 | CREAD | HUPCL;
693     if (local || !modem)
694 	tios.c_cflag |= CLOCAL;
695     tios.c_iflag = IGNBRK | IGNPAR;
696     tios.c_oflag = 0;
697     tios.c_lflag = 0;
698     tios.c_cc[VMIN] = 1;
699     tios.c_cc[VTIME] = 0;
700 
701     if (crtscts == -2) {
702 	tios.c_iflag |= IXON | IXOFF;
703 	tios.c_cc[VSTOP] = 0x13;	/* DC3 = XOFF = ^S */
704 	tios.c_cc[VSTART] = 0x11;	/* DC1 = XON  = ^Q */
705     }
706 
707     if (inspeed) {
708 	cfsetospeed(&tios, inspeed);
709 	cfsetispeed(&tios, inspeed);
710     } else {
711 	inspeed = cfgetospeed(&tios);
712 	/*
713 	 * We can't proceed if the serial port speed is 0,
714 	 * since that implies that the serial port is disabled.
715 	 */
716 	if (inspeed == 0)
717 	    fatal("%s: Baud rate for %s is 0; need explicit baud rate",
718 		__func__, devnam);
719     }
720     baud_rate = inspeed;
721 
722     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0)
723 	fatal("%s: tcsetattr: %m", __func__);
724 
725     restore_term = 1;
726 }
727 
728 /*
729  * restore_tty - restore the terminal to the saved settings.
730  */
731 void
732 restore_tty(int fd)
733 {
734     if (restore_term) {
735 	if (!default_device) {
736 	    /*
737 	     * Turn off echoing, because otherwise we can get into
738 	     * a loop with the tty and the modem echoing to each other.
739 	     * We presume we are the sole user of this tty device, so
740 	     * when we close it, it will revert to its defaults anyway.
741 	     */
742 	    inittermios.c_lflag &= ~(ECHO | ECHONL);
743 	}
744 	if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
745 	    if (errno != ENXIO)
746 		warn("%s: tcsetattr: %m", __func__);
747 	ioctl(fd, TIOCSWINSZ, &wsinfo);
748 	restore_term = 0;
749     }
750 }
751 
752 /*
753  * setdtr - control the DTR line on the serial port.
754  * This is called from die(), so it shouldn't call die().
755  */
756 void
757 setdtr(int fd, int on)
758 {
759     int modembits = TIOCM_DTR;
760 
761     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
762 }
763 
764 #ifdef INET6
765 /*
766  * sif6addr - Config the interface with an IPv6 link-local address
767  */
768 int
769 sif6addr(int unit, eui64_t our_eui64, eui64_t his_eui64)
770 {
771 #ifdef __KAME__
772     int ifindex;
773     struct in6_aliasreq addreq6;
774 
775     if (sock6_fd < 0) {
776 	fatal("%s: No IPv6 socket available", __func__);
777 	/*NOTREACHED*/
778     }
779 
780     /* actually, this part is not kame local - RFC2553 conformant */
781     ifindex = if_nametoindex(ifname);
782     if (ifindex == 0) {
783 	error("%s: sifaddr6: no interface %s", __func__, ifname);
784 	return 0;
785     }
786 
787     memset(&addreq6, 0, sizeof(addreq6));
788     strlcpy(addreq6.ifra_name, ifname, sizeof(addreq6.ifra_name));
789 
790     /* my addr */
791     IN6_LLADDR_FROM_EUI64(addreq6.ifra_addr, our_eui64);
792     IN6_IFINDEX(addreq6.ifra_addr, ifindex);
793 
794 #ifdef notdef
795     /* his addr */
796     IN6_LLADDR_FROM_EUI64(addreq6.ifra_dstaddr, his_eui64);
797     IN6_IFINDEX(addreq6.ifra_dstaddr, ifindex);
798 #endif
799 
800     /* prefix mask: 72bit */
801     addreq6.ifra_prefixmask.sin6_family = AF_INET6;
802     addreq6.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
803     memset(&addreq6.ifra_prefixmask.sin6_addr, 0xff,
804 	sizeof(addreq6.ifra_prefixmask.sin6_addr) - sizeof(our_eui64));
805     memset((char *)&addreq6.ifra_prefixmask.sin6_addr +
806 	sizeof(addreq6.ifra_prefixmask.sin6_addr) - sizeof(our_eui64), 0x00,
807 	sizeof(our_eui64));
808 
809     /* address lifetime (infty) */
810     addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
811     addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
812 
813     if (ioctl(sock6_fd, SIOCAIFADDR_IN6, &addreq6) < 0) {
814 	error("%s: sif6addr: ioctl(SIOCAIFADDR_IN6): %m", __func__);
815 	return 0;
816     }
817 
818     return 1;
819 #else
820     struct in6_ifreq ifr6;
821     struct ifreq ifr;
822     struct in6_rtmsg rt6;
823 
824     if (sock6_fd < 0) {
825 	fatal("%s: No IPv6 socket available", __func__);
826 	/*NOTREACHED*/
827     }
828 
829     memset(&ifr, 0, sizeof (ifr));
830     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
831     if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
832 	error("%s: sif6addr: ioctl(SIOCGIFINDEX): %m", __func__);
833 	return 0;
834     }
835 
836     /* Local interface */
837     memset(&ifr6, 0, sizeof(ifr6));
838     IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
839     ifr6.ifr6_ifindex = ifindex;
840     ifr6.ifr6_prefixlen = 10;
841 
842     if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6) < 0) {
843 	error("%s: sif6addr: ioctl(SIOCSIFADDR): %m", __func__);
844 	return 0;
845     }
846 
847     /* Route to remote host */
848     memset(&rt6, 0, sizeof(rt6));
849     IN6_LLADDR_FROM_EUI64(rt6.rtmsg_dst, his_eui64);
850     rt6.rtmsg_flags = RTF_UP;
851     rt6.rtmsg_dst_len = 10;
852     rt6.rtmsg_ifindex = ifr.ifr_ifindex;
853     rt6.rtmsg_metric = 1;
854 
855     if (ioctl(sock6_fd, SIOCADDRT, &rt6) < 0) {
856 	error("%s: sif6addr: ioctl(SIOCADDRT): %m", __func__);
857 	return 0;
858     }
859 
860     return 1;
861 #endif
862 }
863 
864 
865 /*
866  * cif6addr - Remove IPv6 address from interface
867  */
868 int
869 cif6addr(int unit, eui64_t our_eui64, eui64_t his_eui64)
870 {
871 #ifdef __KAME__
872     int ifindex;
873     struct in6_ifreq delreq6;
874 
875     if (sock6_fd < 0) {
876 	fatal("%s: No IPv6 socket available", __func__);
877 	/*NOTREACHED*/
878     }
879 
880     /* actually, this part is not kame local - RFC2553 conformant */
881     ifindex = if_nametoindex(ifname);
882     if (ifindex == 0) {
883 	error("%s: cifaddr6: no interface %s", __func__, ifname);
884 	return 0;
885     }
886 
887     memset(&delreq6, 0, sizeof(delreq6));
888     strlcpy(delreq6.ifr_name, ifname, sizeof(delreq6.ifr_name));
889 
890     /* my addr */
891     IN6_LLADDR_FROM_EUI64(delreq6.ifr_ifru.ifru_addr, our_eui64);
892     IN6_IFINDEX(delreq6.ifr_ifru.ifru_addr, ifindex);
893 
894     if (ioctl(sock6_fd, SIOCDIFADDR_IN6, &delreq6) < 0) {
895 	error("%s: cif6addr: ioctl(SIOCDIFADDR_IN6): %m", __func__);
896 	return 0;
897     }
898 
899     return 1;
900 #else
901     struct ifreq ifr;
902     struct in6_ifreq ifr6;
903 
904     if (sock6_fd < 0) {
905 	fatal("%s: No IPv6 socket available", __func__);
906 	/*NOTREACHED*/
907     }
908 
909     memset(&ifr, 0, sizeof(ifr));
910     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
911     if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
912 	error("%s: cif6addr: ioctl(SIOCGIFINDEX): %m", __func__);
913 	return 0;
914     }
915 
916     memset(&ifr6, 0, sizeof(ifr6));
917     IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
918     ifr6.ifr6_ifindex = ifr.ifr_ifindex;
919     ifr6.ifr6_prefixlen = 10;
920 
921     if (ioctl(sock6_fd, SIOCDIFADDR, &ifr6) < 0) {
922 	if (errno != EADDRNOTAVAIL) {
923 	    if (! ok_error (errno))
924 		error("%s: cif6addr: ioctl(SIOCDIFADDR): %m", __func__);
925 	}
926         else {
927 	    warn("%s: cif6addr: ioctl(SIOCDIFADDR): No such address", __func__);
928 	}
929         return (0);
930     }
931     return 1;
932 #endif
933 }
934 #endif /* INET6 */
935 
936 /*
937  * get_pty - get a pty master/slave pair and chown the slave side
938  * to the uid given.  Assumes slave_name points to >= 12 bytes of space.
939  */
940 int
941 get_pty(int *master_fdp, int *slave_fdp, char *slave_name, int uid)
942 {
943     struct termios tios;
944 
945     if (openpty(master_fdp, slave_fdp, slave_name, NULL, NULL) < 0)
946 	return 0;
947 
948     set_queue_size(__func__, *master_fdp);
949     set_queue_size(__func__, *slave_fdp);
950     fchown(*slave_fdp, uid, -1);
951     fchmod(*slave_fdp, S_IRUSR | S_IWUSR);
952     if (tcgetattr(*slave_fdp, &tios) == 0) {
953 	tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
954 	tios.c_cflag |= CS8 | CREAD | CLOCAL;
955 	tios.c_iflag  = IGNPAR;
956 	tios.c_oflag  = 0;
957 	tios.c_lflag  = 0;
958 	if (tcsetattr(*slave_fdp, TCSAFLUSH, &tios) < 0)
959 	    warn("%s: couldn't set attributes on pty: %m", __func__);
960     } else
961 	warn("%s: couldn't get attributes on pty: %m", __func__);
962 
963     return 1;
964 }
965 
966 
967 /*
968  * open_ppp_loopback - open the device we use for getting
969  * packets in demand mode, and connect it to a ppp interface.
970  * Here we use a pty.
971  */
972 int
973 open_ppp_loopback(void)
974 {
975     int flags;
976     struct termios tios;
977     int pppdisc = PPPDISC;
978 
979     if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0)
980 	fatal("%s: No free pty for loopback", __func__);
981     SYSDEBUG(("using %s for loopback", loop_name));
982 
983     if (tcgetattr(loop_slave, &tios) == 0) {
984 	tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
985 	tios.c_cflag |= CS8 | CREAD | CLOCAL;
986 	tios.c_iflag = IGNPAR;
987 	tios.c_oflag = 0;
988 	tios.c_lflag = 0;
989 	if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0)
990 	    warn("%s: couldn't set attributes on loopback: %m", __func__);
991     }
992 
993     flags = fcntl(loop_master, F_GETFL);
994     if (flags == -1 || fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1)
995 	    warn("%s: couldn't set master loopback to nonblock: %m", __func__);
996 
997     flags = fcntl(loop_slave, F_GETFL);
998     if (flags == -1 || fcntl(loop_slave, F_SETFL, flags | O_NONBLOCK) == -1)
999 	    warn("%s: couldn't set slave loopback to nonblock: %m", __func__);
1000 
1001     ppp_fd = loop_slave;
1002     if (ioctl(ppp_fd, TIOCSETD, &pppdisc) < 0)
1003 	fatal("%s: ioctl(TIOCSETD): %m", __func__);
1004 
1005     /*
1006      * Find out which interface we were given.
1007      */
1008     if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
1009 	fatal("%s: ioctl(PPPIOCGUNIT): %m", __func__);
1010 
1011     /*
1012      * Enable debug in the driver if requested.
1013      */
1014     if (kdebugflag) {
1015 	flags = get_flags(ppp_fd);
1016 	flags |= (kdebugflag & 0xFF) * SC_DEBUG;
1017 	set_flags(ppp_fd, flags);
1018     }
1019 
1020     return loop_master;
1021 }
1022 
1023 
1024 /*
1025  * output - Output PPP packet.
1026  */
1027 void
1028 output(int unit, u_char *p, int len)
1029 {
1030     if (debug)
1031 	dbglog("sent %P", p, len);
1032 
1033     if (write(ttyfd, p, len) < 0) {
1034 	if (errno != EIO)
1035 	    error("%s: write: %m", __func__);
1036     }
1037 }
1038 
1039 
1040 /*
1041  * wait_input - wait until there is data available,
1042  * for the length of time specified by *timo (indefinite
1043  * if timo is NULL).
1044  */
1045 void
1046 wait_input(struct timeval *timo)
1047 {
1048     fd_set ready;
1049     int n;
1050 
1051     ready = in_fds;
1052     n = select(max_in_fd + 1, &ready, NULL, &ready, timo);
1053     if (n < 0 && errno != EINTR)
1054 	fatal("%s: select: %m", __func__);
1055 }
1056 
1057 
1058 /*
1059  * add_fd - add an fd to the set that wait_input waits for.
1060  */
1061 void add_fd(int fd)
1062 {
1063     if (fd >= FD_SETSIZE)
1064 	fatal("%s: descriptor too big", __func__);
1065     FD_SET(fd, &in_fds);
1066     if (fd > max_in_fd)
1067 	max_in_fd = fd;
1068 }
1069 
1070 /*
1071  * remove_fd - remove an fd from the set that wait_input waits for.
1072  */
1073 void remove_fd(int fd)
1074 {
1075     FD_CLR(fd, &in_fds);
1076 }
1077 
1078 #if 0
1079 /*
1080  * wait_loop_output - wait until there is data available on the
1081  * loopback, for the length of time specified by *timo (indefinite
1082  * if timo is NULL).
1083  */
1084 void
1085 wait_loop_output(struct timeval *timo)
1086 {
1087     fd_set ready;
1088     int n;
1089 
1090     FD_ZERO(&ready);
1091     if (loop_master >= FD_SETSIZE)
1092 	fatal("%s: descriptor too big", __func__);
1093     FD_SET(loop_master, &ready);
1094     n = select(loop_master + 1, &ready, NULL, &ready, timo);
1095     if (n < 0 && errno != EINTR)
1096 	fatal("%s: select: %m", __func__);
1097 }
1098 
1099 
1100 /*
1101  * wait_time - wait for a given length of time or until a
1102  * signal is received.
1103  */
1104 void
1105 wait_time(struct timeval *timo)
1106 {
1107     int n;
1108 
1109     n = select(0, NULL, NULL, NULL, timo);
1110     if (n < 0 && errno != EINTR)
1111 	fatal("%s: select: %m", __func__);
1112 }
1113 #endif
1114 
1115 
1116 /*
1117  * read_packet - get a PPP packet from the serial device.
1118  */
1119 int
1120 read_packet(u_char *buf)
1121 {
1122     int len;
1123 
1124     if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
1125 	if (errno == EWOULDBLOCK || errno == EINTR)
1126 	    return -1;
1127 	fatal("%s: read: %m", __func__);
1128     }
1129     return len;
1130 }
1131 
1132 
1133 /*
1134  * get_loop_output - read characters from the loopback, form them
1135  * into frames, and detect when we want to bring the real link up.
1136  * Return value is 1 if we need to bring up the link, 0 otherwise.
1137  */
1138 int
1139 get_loop_output(void)
1140 {
1141     int rv = 0;
1142     int n;
1143 
1144     while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) {
1145 	if (loop_chars(inbuf, n))
1146 	    rv = 1;
1147     }
1148 
1149     if (n == 0)
1150 	fatal("%s: eof on loopback", __func__);
1151     if (n == -1 && errno != EWOULDBLOCK)
1152 	fatal("%s: read from loopback: %m", __func__);
1153 
1154     return rv;
1155 }
1156 
1157 
1158 /*
1159  * netif_set_mtu - set the MTU on the PPP network interface.
1160  */
1161 void
1162 netif_set_mtu(int unit, int mtu)
1163 {
1164     struct ifreq ifr;
1165 
1166     SYSDEBUG((LOG_DEBUG, "netif_set_mtu: mtu = %d\n", mtu));
1167 
1168     memset(&ifr, '\0', sizeof (ifr));
1169     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1170     ifr.ifr_mtu = mtu;
1171 
1172     if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
1173 	fatal("%s: ioctl(SIOCSIFMTU): %m", __func__);
1174 }
1175 
1176 /*
1177  * netif_get_mtu - get the MTU on the PPP network interface.
1178  */
1179 int
1180 netif_get_mtu(int unit)
1181 {
1182     struct ifreq ifr;
1183 
1184     memset (&ifr, '\0', sizeof (ifr));
1185     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1186 
1187     if (ifunit >= 0 && ioctl(sock_fd, SIOCGIFMTU, (caddr_t) &ifr) < 0) {
1188 	error("%s: ioctl(SIOCGIFMTU): %m", __func__);
1189 	return 0;
1190     }
1191     return ifr.ifr_mtu;
1192 }
1193 
1194 /*
1195  * tty_send_config - configure the transmit characteristics of
1196  * the ppp interface.
1197  */
1198 void
1199 tty_send_config(int mtu, u_int32_t asyncmap, int pcomp, int accomp)
1200 {
1201     u_int x;
1202 #if 0
1203     /* Linux code does not do anything with the mtu here */
1204     ifnet_set_mtu(-1, mtu);
1205 #endif
1206 
1207     if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0)
1208 	fatal("%s: ioctl(PPPIOCSASYNCMAP): %m", __func__);
1209 
1210     x = get_flags(ppp_fd);
1211     x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
1212     x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
1213     x = sync_serial ? x | SC_SYNC : x & ~SC_SYNC;
1214     set_flags(ppp_fd, x);
1215 }
1216 
1217 
1218 /*
1219  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
1220  */
1221 void
1222 tty_set_xaccm(ext_accm accm)
1223 {
1224     if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
1225 	warn("%s: ioctl(set extended ACCM): %m", __func__);
1226 }
1227 
1228 
1229 /*
1230  * ppp_recv_config - configure the receive-side characteristics of
1231  * the ppp interface.
1232  */
1233 void
1234 tty_recv_config(int mru, u_int32_t asyncmap, int pcomp, int accomp)
1235 {
1236     int x;
1237 
1238     if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
1239 	fatal("%s: ioctl(PPPIOCSMRU): %m", __func__);
1240     if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0)
1241 	fatal("%s: ioctl(PPPIOCSRASYNCMAP): %m", __func__);
1242     x = get_flags(ppp_fd);
1243     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
1244     set_flags(ppp_fd, x);
1245 }
1246 
1247 /*
1248  * ccp_test - ask kernel whether a given compression method
1249  * is acceptable for use.  Returns 1 if the method and parameters
1250  * are OK, 0 if the method is known but the parameters are not OK
1251  * (e.g. code size should be reduced), or -1 if the method is unknown.
1252  */
1253 int
1254 ccp_test(int unit, u_char *opt_ptr, int opt_len, int for_transmit)
1255 {
1256     struct ppp_option_data data;
1257 
1258     data.ptr = opt_ptr;
1259     data.length = opt_len;
1260     data.transmit = for_transmit;
1261     if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
1262 	return 1;
1263     return (errno == ENOBUFS)? 0: -1;
1264 }
1265 
1266 /*
1267  * ccp_flags_set - inform kernel about the current state of CCP.
1268  */
1269 void
1270 ccp_flags_set(int unit, int isopen, int isup)
1271 {
1272     int x;
1273 
1274     x = get_flags(ppp_fd);
1275     x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
1276     x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
1277     set_flags(ppp_fd, x);
1278 }
1279 
1280 /*
1281  * ccp_fatal_error - returns 1 if decompression was disabled as a
1282  * result of an error detected after decompression of a packet,
1283  * 0 otherwise.  This is necessary because of patent nonsense.
1284  */
1285 int
1286 ccp_fatal_error(int unit)
1287 {
1288     int x;
1289 
1290     x = get_flags(ppp_fd);
1291     return x & SC_DC_FERROR;
1292 }
1293 
1294 /*
1295  * get_idle_time - return how long the link has been idle.
1296  */
1297 int
1298 get_idle_time(int u, struct ppp_idle *ip)
1299 {
1300     return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
1301 }
1302 
1303 /*
1304  * get_ppp_stats - return statistics for the link.
1305  */
1306 int
1307 get_ppp_stats(int u, struct pppd_stats *stats)
1308 {
1309     struct ifpppstatsreq req;
1310 
1311     memset (&req, 0, sizeof (req));
1312     strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name));
1313     if (ioctl(sock_fd, SIOCGPPPSTATS, &req) < 0) {
1314 	error("%s: Couldn't get PPP statistics: %m", __func__);
1315 	return 0;
1316     }
1317     stats->bytes_in = req.stats.p.ppp_ibytes;
1318     stats->bytes_out = req.stats.p.ppp_obytes;
1319     stats->pkts_in = req.stats.p.ppp_ipackets;
1320     stats->pkts_out = req.stats.p.ppp_opackets;
1321     return 1;
1322 }
1323 
1324 
1325 #ifdef PPP_FILTER
1326 /*
1327  * set_filters - transfer the pass and active filters to the kernel.
1328  */
1329 int
1330 set_filters(struct bpf_program *pass_in, struct bpf_program *pass_out,
1331     struct bpf_program *active_in, struct bpf_program *active_out)
1332 {
1333     int ret = 1;
1334 
1335     if (pass_in->bf_len > 0) {
1336 	if (ioctl(ppp_fd, PPPIOCSIPASS, pass_in) < 0) {
1337 	    error("%s: Couldn't set pass-filter-in in kernel: %m", __func__);
1338 	    ret = 0;
1339 	}
1340     }
1341 
1342     if (pass_out->bf_len > 0) {
1343 	if (ioctl(ppp_fd, PPPIOCSOPASS, pass_out) < 0) {
1344 	    error("%s: Couldn't set pass-filter-out in kernel: %m", __func__);
1345 	    ret = 0;
1346 	}
1347     }
1348 
1349     if (active_in->bf_len > 0) {
1350 	if (ioctl(ppp_fd, PPPIOCSIACTIVE, active_in) < 0) {
1351 	    error("%s: Couldn't set active-filter-in in kernel: %m", __func__);
1352 	    ret = 0;
1353 	}
1354     }
1355 
1356     if (active_out->bf_len > 0) {
1357 	if (ioctl(ppp_fd, PPPIOCSOACTIVE, active_out) < 0) {
1358 	    error("%s: Couldn't set active-filter-out in kernel: %m", __func__);
1359 	    ret = 0;
1360 	}
1361     }
1362 
1363     return ret;
1364 }
1365 #endif
1366 
1367 /*
1368  * sifvjcomp - config tcp header compression
1369  */
1370 int
1371 sifvjcomp(int u, int vjcomp, int cidcomp, int maxcid)
1372 {
1373     u_int x;
1374 
1375     x = get_flags(ppp_fd);
1376     x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
1377     x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
1378     set_flags(ppp_fd, x);
1379     if (vjcomp && ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
1380 	error("%s: ioctl(PPPIOCSMAXCID): %m", __func__);
1381 	return 0;
1382     }
1383     return 1;
1384 }
1385 
1386 /********************************************************************
1387  *
1388  * sifup - Config the interface up and enable IP packets to pass.
1389  */
1390 
1391 int sifup(int u)
1392 {
1393     int ret;
1394 
1395     if ((ret = setifstate(u, 1)))
1396 	if_is_up++;
1397 
1398     return ret;
1399 }
1400 
1401 /********************************************************************
1402  *
1403  * sifdown - Disable the indicated protocol and config the interface
1404  *	     down if there are no remaining protocols.
1405  */
1406 
1407 int sifdown (int u)
1408 {
1409     if (if_is_up && --if_is_up > 0)
1410 	return 1;
1411 
1412 #ifdef INET6
1413     if (if6_is_up)
1414 	return 1;
1415 #endif /* INET6 */
1416 
1417     return setifstate(u, 0);
1418 }
1419 
1420 #ifdef INET6
1421 /********************************************************************
1422  *
1423  * sif6up - Config the interface up for IPv6
1424  */
1425 
1426 int sif6up(int u)
1427 {
1428     int ret;
1429 
1430     if ((ret = setifstate(u, 1)))
1431 	if6_is_up = 1;
1432 
1433     return ret;
1434 }
1435 
1436 /********************************************************************
1437  *
1438  * sif6down - Disable the IPv6CP protocol and config the interface
1439  *	      down if there are no remaining protocols.
1440  */
1441 
1442 int sif6down (int u)
1443 {
1444     if6_is_up = 0;
1445 
1446     if (if_is_up)
1447 	return 1;
1448 
1449     return setifstate(u, 0);
1450 }
1451 #endif /* INET6 */
1452 
1453 /********************************************************************
1454  *
1455  * setifstate - Config the interface up or down
1456  */
1457 
1458 static int setifstate (int u, int state)
1459 {
1460     struct ifreq ifr;
1461 
1462     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1463     if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
1464 	error("%s: ioctl (SIOCGIFFLAGS): %m", __func__);
1465 	return 0;
1466     }
1467     if (state)
1468 	ifr.ifr_flags |= IFF_UP;
1469     else
1470 	ifr.ifr_flags &= ~IFF_UP;
1471     if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
1472 	error("%s: ioctl(SIOCSIFFLAGS): %m", __func__);
1473 	return 0;
1474     }
1475     if_is_up = 1;
1476     return 1;
1477 }
1478 
1479 /*
1480  * sifnpmode - Set the mode for handling packets for a given NP.
1481  */
1482 int
1483 sifnpmode(int u, int proto, enum NPmode mode)
1484 {
1485     struct npioctl npi;
1486 
1487     npi.protocol = proto;
1488     npi.mode = mode;
1489     if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
1490 	error("%s: ioctl(set NP %d mode to %d): %m", __func__, proto, mode);
1491 	return 0;
1492     }
1493     return 1;
1494 }
1495 
1496 /*
1497  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
1498  * if it exists.
1499  */
1500 #define SET_SA_FAMILY(addr, family)		\
1501     BZERO((char *) &(addr), sizeof(addr));	\
1502     addr.sa_family = (family); 			\
1503     addr.sa_len = sizeof(addr);
1504 
1505 /*
1506  * sifaddr - Config the interface IP addresses and netmask.
1507  */
1508 int
1509 sifaddr(int u, u_int32_t o, u_int32_t h, u_int32_t m)
1510 {
1511     struct ifaliasreq ifra;
1512     struct ifreq ifr;
1513 
1514     strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1515     SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
1516     ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
1517     SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
1518     ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
1519     if (m != 0) {
1520 	SET_SA_FAMILY(ifra.ifra_mask, AF_INET);
1521 	((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
1522     } else
1523 	BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
1524     BZERO(&ifr, sizeof(ifr));
1525     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1526     if (ioctl(sock_fd, SIOCDIFADDR, (caddr_t) &ifr) < 0) {
1527 	if (errno != EADDRNOTAVAIL)
1528 	    warn("%s: Couldn't remove interface address: %m", __func__);
1529     }
1530     if (ioctl(sock_fd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
1531 	if (errno != EEXIST) {
1532 	    error("%s: Couldn't set interface address: %m", __func__);
1533 	    return 0;
1534 	}
1535 	warn("%s: Couldn't set interface address: Address %I already exists",
1536 	    __func__, o);
1537     }
1538     ifaddrs[0] = o;
1539     ifaddrs[1] = h;
1540     return 1;
1541 }
1542 
1543 /*
1544  * cifaddr - Clear the interface IP addresses, and delete routes
1545  * through the interface if possible.
1546  */
1547 int
1548 cifaddr(int u, u_int32_t o, u_int32_t h)
1549 {
1550     struct ifaliasreq ifra;
1551 
1552     ifaddrs[0] = 0;
1553     strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1554     SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
1555     ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
1556     SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
1557     ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
1558     BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
1559     if (ioctl(sock_fd, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
1560 	if (!doing_cleanup && errno != EADDRNOTAVAIL)
1561 	    warn("%s: Couldn't delete interface address: %m", __func__);
1562 	return 0;
1563     }
1564     return 1;
1565 }
1566 
1567 /*
1568  * sifdefaultroute - assign a default route through the address given.
1569  */
1570 int
1571 sifdefaultroute(int u, u_int32_t l, u_int32_t g)
1572 {
1573     return dodefaultroute(g, 's');
1574 }
1575 
1576 /*
1577  * cifdefaultroute - delete a default route through the address given.
1578  */
1579 int
1580 cifdefaultroute(int u, u_int32_t l, u_int32_t g)
1581 {
1582     return dodefaultroute(g, 'c');
1583 }
1584 
1585 /*
1586  * dodefaultroute - talk to a routing socket to add/delete a default route.
1587  */
1588 static int
1589 dodefaultroute(u_int32_t g, int cmd)
1590 {
1591     int routes;
1592     struct {
1593 	struct rt_msghdr	hdr;
1594 	struct sockaddr_in	dst;
1595 	struct sockaddr_in	gway;
1596 	struct sockaddr_in	netmask;
1597 	struct sockaddr_dl	ifp;
1598     } rtmsg;
1599 
1600     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1601 	if (!doing_cleanup)
1602 	    error("%s: Couldn't %s default route: socket: %m", __func__,
1603 		cmd == 's' ? "add" : "delete");
1604 	return 0;
1605     }
1606 
1607     memset(&rtmsg, 0, sizeof(rtmsg));
1608 
1609     rtmsg.hdr.rtm_type = cmd == 's' ? RTM_ADD : RTM_DELETE;
1610     rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
1611     rtmsg.hdr.rtm_version = RTM_VERSION;
1612     rtmsg.hdr.rtm_seq = ++rtm_seq;
1613     rtmsg.hdr.rtm_addrs =
1614 	RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_IFP;
1615 
1616     rtmsg.dst.sin_len = sizeof(rtmsg.dst);
1617     rtmsg.dst.sin_family = AF_INET;
1618     rtmsg.dst.sin_addr.s_addr = 0;
1619 
1620     rtmsg.gway.sin_len = sizeof(rtmsg.gway);
1621     rtmsg.gway.sin_family = AF_INET;
1622     rtmsg.gway.sin_addr.s_addr = g;
1623 
1624     rtmsg.netmask.sin_len = sizeof(rtmsg.netmask);
1625     rtmsg.netmask.sin_family = AF_INET;
1626     rtmsg.netmask.sin_addr.s_addr = 0;
1627 
1628     rtmsg.ifp.sdl_family = AF_LINK;
1629     rtmsg.ifp.sdl_len = sizeof(rtmsg.ifp);
1630     link_addr(ifname, &rtmsg.ifp);
1631 
1632     rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
1633 
1634     if (write(routes, &rtmsg, sizeof(rtmsg)) < 0) {
1635 	if (!doing_cleanup)
1636 	    error("%s: Couldn't %s default route: %m", __func__,
1637 		cmd == 's' ? "add" : "delete");
1638 	close(routes);
1639 	return 0;
1640     }
1641 
1642     close(routes);
1643     default_route_gateway = (cmd == 's') ? g : 0;
1644     return 1;
1645 }
1646 
1647 #if RTM_VERSION >= 3
1648 
1649 /*
1650  * sifproxyarp - Make a proxy ARP entry for the peer.
1651  */
1652 static struct {
1653     struct rt_msghdr		hdr;
1654     struct sockaddr_inarp	dst;
1655     struct sockaddr_dl		hwa;
1656     char			extra[128];
1657 } arpmsg;
1658 
1659 static int arpmsg_valid;
1660 
1661 int
1662 sifproxyarp(int unit, u_int32_t hisaddr)
1663 {
1664     int routes;
1665 
1666     /*
1667      * Get the hardware address of an interface on the same subnet
1668      * as our local address.
1669      */
1670     memset(&arpmsg, 0, sizeof(arpmsg));
1671     if (!get_ether_addr(hisaddr, &arpmsg.hwa)) {
1672 	error("%s: Cannot determine ethernet address for proxy ARP", __func__);
1673 	return 0;
1674     }
1675 
1676     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1677 	error("%s: Couldn't add proxy arp entry: socket: %m", __func__);
1678 	return 0;
1679     }
1680 
1681     arpmsg.hdr.rtm_type = RTM_ADD;
1682     arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC;
1683     arpmsg.hdr.rtm_version = RTM_VERSION;
1684     arpmsg.hdr.rtm_seq = ++rtm_seq;
1685     arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
1686     arpmsg.hdr.rtm_inits = RTV_EXPIRE;
1687     arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
1688     arpmsg.dst.sin_family = AF_INET;
1689     arpmsg.dst.sin_addr.s_addr = hisaddr;
1690     arpmsg.dst.sin_other = SIN_PROXY;
1691 
1692     arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
1693 	+ RT_ROUNDUP(arpmsg.hwa.sdl_len);
1694     if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1695 	error("%s: Couldn't add proxy arp entry: %m", __func__);
1696 	close(routes);
1697 	return 0;
1698     }
1699 
1700     close(routes);
1701     arpmsg_valid = 1;
1702     proxy_arp_addr = hisaddr;
1703     return 1;
1704 }
1705 
1706 /*
1707  * cifproxyarp - Delete the proxy ARP entry for the peer.
1708  */
1709 int
1710 cifproxyarp(int unit, u_int32_t hisaddr)
1711 {
1712     int routes;
1713 
1714     if (!arpmsg_valid)
1715 	return 0;
1716     arpmsg_valid = 0;
1717 
1718     arpmsg.hdr.rtm_type = RTM_DELETE;
1719     arpmsg.hdr.rtm_seq = ++rtm_seq;
1720 
1721     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1722 	if (!doing_cleanup)
1723 	    error("%s: Couldn't delete proxy arp entry: socket: %m", __func__);
1724 	return 0;
1725     }
1726 
1727     if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1728 	if (!doing_cleanup)
1729 	    error("%s: Couldn't delete proxy arp entry: %m", __func__);
1730 	close(routes);
1731 	return 0;
1732     }
1733 
1734     close(routes);
1735     proxy_arp_addr = 0;
1736     return 1;
1737 }
1738 
1739 #else	/* RTM_VERSION */
1740 
1741 /*
1742  * sifproxyarp - Make a proxy ARP entry for the peer.
1743  */
1744 int
1745 sifproxyarp(int unit, u_int32_t hisaddr)
1746 {
1747     struct arpreq arpreq;
1748     struct {
1749 	struct sockaddr_dl	sdl;
1750 	char			space[128];
1751     } dls;
1752 
1753     BZERO(&arpreq, sizeof(arpreq));
1754 
1755     /*
1756      * Get the hardware address of an interface on the same subnet
1757      * as our local address.
1758      */
1759     if (!get_ether_addr(hisaddr, &dls.sdl)) {
1760 	error("%s: Cannot determine ethernet address for proxy ARP", __func__);
1761 	return 0;
1762     }
1763 
1764     arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
1765     arpreq.arp_ha.sa_family = AF_UNSPEC;
1766     BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen);
1767     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1768     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1769     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1770     if (ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq) < 0) {
1771 	error("%s: Couldn't add proxy arp entry: %m", __func__);
1772 	return 0;
1773     }
1774 
1775     proxy_arp_addr = hisaddr;
1776     return 1;
1777 }
1778 
1779 /*
1780  * cifproxyarp - Delete the proxy ARP entry for the peer.
1781  */
1782 int
1783 cifproxyarp(int unit, u_int32_t hisaddr)
1784 {
1785     struct arpreq arpreq;
1786 
1787     BZERO(&arpreq, sizeof(arpreq));
1788     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1789     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1790     if (ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1791 	warn("%s: Couldn't delete proxy arp entry: %m", __func__);
1792 	return 0;
1793     }
1794     proxy_arp_addr = 0;
1795     return 1;
1796 }
1797 #endif	/* RTM_VERSION */
1798 
1799 
1800 /*
1801  * get_ether_addr - get the hardware address of an interface on the
1802  * the same subnet as ipaddr.
1803  */
1804 static int
1805 get_ether_addr(u_int32_t ipaddr, struct sockaddr_dl *hwaddr)
1806 {
1807     u_int32_t ina, mask;
1808     struct sockaddr_dl *dla;
1809     struct ifaddrs *ifap, *ifa, *ifp;
1810 
1811     /*
1812      * Scan through looking for an interface with an Internet
1813      * address on the same subnet as `ipaddr'.
1814      */
1815     if (getifaddrs(&ifap) != 0) {
1816 	error("%s: getifaddrs: %m", __func__);
1817 	return 0;
1818     }
1819 
1820     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1821 	if (ifa->ifa_addr->sa_family != AF_INET)
1822 	    continue;
1823 	ina = ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr;
1824 	/*
1825 	 * Check that the interface is up, and not point-to-point
1826 	 * or loopback.
1827 	 */
1828 	if ((ifa->ifa_flags &
1829 	     (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1830 	     != (IFF_UP|IFF_BROADCAST))
1831 	    continue;
1832 	/*
1833 	 * Get its netmask and check that it's on the right subnet.
1834 	 */
1835 	mask = ((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr;
1836 	if ((ipaddr & mask) != (ina & mask))
1837 	    continue;
1838 	break;
1839     }
1840 
1841     if (!ifa) {
1842 	freeifaddrs(ifap);
1843 	return 0;
1844     }
1845     info("found interface %s for proxy arp", ifa->ifa_name);
1846 
1847     ifp = ifa;
1848 
1849     /*
1850      * Now scan through again looking for a link-level address
1851      * for this interface.
1852      */
1853     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1854 	if (strcmp(ifp->ifa_name, ifa->ifa_name) != 0)
1855 	    continue;
1856 	if (ifa->ifa_addr->sa_family != AF_LINK)
1857 	    continue;
1858 	/*
1859 	 * Found the link-level address - copy it out
1860 	 */
1861 	dla = (struct sockaddr_dl *) ifa->ifa_addr;
1862 	BCOPY(dla, hwaddr, dla->sdl_len);
1863 	freeifaddrs(ifap);
1864 	return 1;
1865     }
1866 
1867     freeifaddrs(ifap);
1868     return 0;
1869 }
1870 
1871 /*
1872  * get_if_hwaddr - get the hardware address for the specified
1873  * network interface device.
1874  */
1875 int
1876 get_if_hwaddr(u_char *addr, char *name)
1877 {
1878 
1879 #define IFREQ_SAFE (sizeof(struct ifreq) + sizeof(struct sockaddr_dl))
1880     /* XXX sockaddr_dl is larger than the sockaddr in struct ifreq! */
1881     union {			/* XXX */
1882     	struct ifreq _ifreq;	/* XXX */
1883 	char _X[IFREQ_SAFE]; 	/* XXX */
1884     } _ifreq_dontsmashstack;	/* XXX */
1885 #define ifreq_xxx _ifreq_dontsmashstack._ifreq			/* XXX */
1886 
1887     struct sockaddr_dl *sdl = (struct sockaddr_dl *) &ifreq_xxx.ifr_addr;
1888     int fd;
1889 
1890     if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1891 	return 0;
1892     (void)memset(sdl, 0, sizeof(*sdl));
1893     sdl->sdl_family = AF_LINK;
1894     (void)strlcpy(ifreq_xxx.ifr_name, name, sizeof(ifreq_xxx.ifr_name));
1895     if (ioctl(fd, SIOCGIFADDR, &ifreq_xxx) == -1) {
1896 	(void)close(fd);
1897 	return 0;
1898     }
1899     (void)close(fd);
1900     (void)memcpy(addr, LLADDR(sdl), sdl->sdl_alen);
1901     return sdl->sdl_nlen;
1902 }
1903 
1904 /*
1905  * get_first_ethernet - return the name of the first ethernet-style
1906  * interface on this system.
1907  */
1908 char *
1909 get_first_ethernet(void)
1910 {
1911     static char ifname[IFNAMSIZ];
1912     struct ifaddrs *ifap, *ifa;
1913 
1914     /*
1915      * Scan through the system's network interfaces.
1916      */
1917     if (getifaddrs(&ifap) != 0) {
1918 	warn("%s: getifaddrs: %m", __func__);
1919 	return NULL;
1920     }
1921     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1922 	/*
1923 	 * Check the interface's internet address.
1924 	 */
1925 	if (ifa->ifa_addr->sa_family != AF_INET)
1926 	    continue;
1927 	/*
1928 	 * Check that the interface is up, and not point-to-point or loopback.
1929 	 */
1930 	if ((ifa->ifa_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1931 	    != IFF_UP) {
1932 	    strlcpy(ifname, ifa->ifa_name, sizeof(ifname));
1933 	    freeifaddrs(ifap);
1934 	    return ifname;
1935 	}
1936     }
1937     freeifaddrs(ifap);
1938     return NULL;
1939 }
1940 
1941 /*
1942  * Return user specified netmask, modified by any mask we might determine
1943  * for address `addr' (in network byte order).
1944  * Here we scan through the system's list of interfaces, looking for
1945  * any non-point-to-point interfaces which might appear to be on the same
1946  * network as `addr'.  If we find any, we OR in their netmask to the
1947  * user-specified netmask.
1948  */
1949 u_int32_t
1950 GetMask(u_int32_t addr)
1951 {
1952     u_int32_t mask, nmask, ina;
1953     struct ifaddrs *ifap, *ifa;
1954 
1955     addr = ntohl(addr);
1956     if (IN_CLASSA(addr))	/* determine network mask for address class */
1957 	nmask = IN_CLASSA_NET;
1958     else if (IN_CLASSB(addr))
1959 	nmask = IN_CLASSB_NET;
1960     else
1961 	nmask = IN_CLASSC_NET;
1962     /* class D nets are disallowed by bad_ip_adrs */
1963     mask = netmask | htonl(nmask);
1964 
1965     /*
1966      * Scan through the system's network interfaces.
1967      */
1968     if (getifaddrs(&ifap) != 0) {
1969 	warn("%s: getifaddrs: %m", __func__);
1970 	return 0;
1971     }
1972 
1973     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1974 	/*
1975 	 * Check the interface's internet address.
1976 	 */
1977 	if (ifa->ifa_addr->sa_family != AF_INET)
1978 	    continue;
1979 	ina = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
1980 	if ((ntohl(ina) & nmask) != (addr & nmask))
1981 	    continue;
1982 	/*
1983 	 * Check that the interface is up, and not point-to-point or loopback.
1984 	 */
1985 	if ((ifa->ifa_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) != IFF_UP)
1986 	    continue;
1987 	/*
1988 	 * Get its netmask and OR it into our mask.
1989 	 */
1990 	mask |= ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr;
1991     }
1992 
1993     freeifaddrs(ifap);
1994     return mask;
1995 }
1996 
1997 /*
1998  * have_route_to - determine if the system has any route to
1999  * a given IP address.
2000  * For demand mode to work properly, we have to ignore routes
2001  * through our own interface.
2002  */
2003 int have_route_to(u_int32_t addr)
2004 {
2005     return -1;
2006 }
2007 
2008 /*
2009  * Use the hostid as part of the random number seed.
2010  */
2011 int
2012 get_host_seed(void)
2013 {
2014     return gethostid();
2015 }
2016 
2017 #if 0
2018 /*
2019  * lock - create a lock file for the named lock device
2020  */
2021 #define	LOCK_PREFIX	"/var/spool/lock/LCK.."
2022 
2023 static char *lock_file;		/* name of lock file created */
2024 
2025 int
2026 lock(char *dev)
2027 {
2028     char hdb_lock_buffer[12];
2029     int fd, pid, n;
2030     char *p;
2031     size_t l;
2032 
2033     if ((p = strrchr(dev, '/')) != NULL)
2034 	dev = p + 1;
2035     l = strlen(LOCK_PREFIX) + strlen(dev) + 1;
2036     lock_file = malloc(l);
2037     if (lock_file == NULL)
2038 	novm("lock file name");
2039     slprintf(lock_file, l, "%s%s", LOCK_PREFIX, dev);
2040 
2041     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
2042 	if (errno == EEXIST
2043 	    && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
2044 	    /* Read the lock file to find out who has the device locked */
2045 	    n = read(fd, hdb_lock_buffer, 11);
2046 	    if (n <= 0) {
2047 		error("%s: Can't read pid from lock file %s", __func__,
2048 		    lock_file);
2049 		close(fd);
2050 	    } else {
2051 		hdb_lock_buffer[n] = 0;
2052 		pid = atoi(hdb_lock_buffer);
2053 		if (kill(pid, 0) == -1 && errno == ESRCH) {
2054 		    /* pid no longer exists - remove the lock file */
2055 		    if (unlink(lock_file) == 0) {
2056 			close(fd);
2057 			notice("%s: Removed stale lock on %s (pid %d)",
2058 			    __func__, dev, pid);
2059 			continue;
2060 		    } else
2061 			warn("%s: Couldn't remove stale lock on %s", __func__,
2062 			    dev);
2063 		} else
2064 		    notice("%s: Device %s is locked by pid %d", __func__,
2065 			   dev, pid);
2066 	    }
2067 	    close(fd);
2068 	} else
2069 	    error("%s: Can't create lock file %s: %m", __func__, lock_file);
2070 	free(lock_file);
2071 	lock_file = NULL;
2072 	return -1;
2073     }
2074 
2075     slprintf(hdb_lock_buffer, sizeof(hdb_lock_buffer), "%10d\n", getpid());
2076     write(fd, hdb_lock_buffer, 11);
2077 
2078     close(fd);
2079     return 0;
2080 }
2081 
2082 /*
2083  * unlock - remove our lockfile
2084  */
2085 void
2086 unlock(void)
2087 {
2088     if (lock_file) {
2089 	unlink(lock_file);
2090 	free(lock_file);
2091 	lock_file = NULL;
2092     }
2093 }
2094 #endif
2095 
2096 #ifdef INET6
2097 /*
2098  * ether_to_eui64 - Convert 48-bit Ethernet address into 64-bit EUI
2099  *
2100  * convert the 48-bit MAC address of eth0 into EUI 64. caller also assumes
2101  * that the system has a properly configured Ethernet interface for this
2102  * function to return non-zero.
2103  */
2104 int
2105 ether_to_eui64(eui64_t *p_eui64)
2106 {
2107     struct ifaddrs *ifap, *ifa;
2108 
2109     if (getifaddrs(&ifap) != 0) {
2110 	warn("%s: getifaddrs: %m", __func__);
2111 	return 0;
2112     }
2113     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2114 	/*
2115 	 * Check the interface's internet address.
2116 	 */
2117 	if (ifa->ifa_addr->sa_family != AF_LINK)
2118 	    continue;
2119 	/*
2120 	 * Check that the interface is up, and not point-to-point or loopback.
2121 	 */
2122 	if ((ifa->ifa_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) == IFF_UP)
2123 	{
2124 	    /*
2125 	     * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1]
2126 	     */
2127 	    unsigned char *ptr = (void *)ifa->ifa_addr;
2128 	    p_eui64->e8[0] = ptr[0] | 0x02;
2129 	    p_eui64->e8[1] = ptr[1];
2130 	    p_eui64->e8[2] = ptr[2];
2131 	    p_eui64->e8[3] = 0xFF;
2132 	    p_eui64->e8[4] = 0xFE;
2133 	    p_eui64->e8[5] = ptr[3];
2134 	    p_eui64->e8[6] = ptr[4];
2135 	    p_eui64->e8[7] = ptr[5];
2136 	    freeifaddrs(ifap);
2137 	    return 1;
2138 	}
2139     }
2140     warn("%s: can't find a link address", __func__);
2141     freeifaddrs(ifap);
2142 
2143     return 0;
2144 }
2145 #endif
2146