xref: /netbsd-src/external/bsd/ppp/usr.sbin/pppd/sys-bsd.c (revision 8ecbf5f02b752fcb7debe1a8fab1dc82602bc760)
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, eready;
1049     int n;
1050 
1051     ready = in_fds;
1052     eready = in_fds;
1053     n = select(max_in_fd + 1, &ready, NULL, &eready, timo);
1054     if (n < 0 && errno != EINTR)
1055 	fatal("%s: select: %m", __func__);
1056 }
1057 
1058 
1059 /*
1060  * add_fd - add an fd to the set that wait_input waits for.
1061  */
1062 void add_fd(int fd)
1063 {
1064     if (fd >= FD_SETSIZE)
1065 	fatal("%s: descriptor too big", __func__);
1066     FD_SET(fd, &in_fds);
1067     if (fd > max_in_fd)
1068 	max_in_fd = fd;
1069 }
1070 
1071 /*
1072  * remove_fd - remove an fd from the set that wait_input waits for.
1073  */
1074 void remove_fd(int fd)
1075 {
1076     FD_CLR(fd, &in_fds);
1077 }
1078 
1079 #if 0
1080 /*
1081  * wait_loop_output - wait until there is data available on the
1082  * loopback, for the length of time specified by *timo (indefinite
1083  * if timo is NULL).
1084  */
1085 void
1086 wait_loop_output(struct timeval *timo)
1087 {
1088     fd_set ready;
1089     int n;
1090 
1091     FD_ZERO(&ready);
1092     if (loop_master >= FD_SETSIZE)
1093 	fatal("%s: descriptor too big", __func__);
1094     FD_SET(loop_master, &ready);
1095     n = select(loop_master + 1, &ready, NULL, &ready, timo);
1096     if (n < 0 && errno != EINTR)
1097 	fatal("%s: select: %m", __func__);
1098 }
1099 
1100 
1101 /*
1102  * wait_time - wait for a given length of time or until a
1103  * signal is received.
1104  */
1105 void
1106 wait_time(struct timeval *timo)
1107 {
1108     int n;
1109 
1110     n = select(0, NULL, NULL, NULL, timo);
1111     if (n < 0 && errno != EINTR)
1112 	fatal("%s: select: %m", __func__);
1113 }
1114 #endif
1115 
1116 
1117 /*
1118  * read_packet - get a PPP packet from the serial device.
1119  */
1120 int
1121 read_packet(u_char *buf)
1122 {
1123     int len;
1124 
1125     if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
1126 	if (errno == EWOULDBLOCK || errno == EINTR)
1127 	    return -1;
1128 	fatal("%s: read: %m", __func__);
1129     }
1130     return len;
1131 }
1132 
1133 
1134 /*
1135  * get_loop_output - read characters from the loopback, form them
1136  * into frames, and detect when we want to bring the real link up.
1137  * Return value is 1 if we need to bring up the link, 0 otherwise.
1138  */
1139 int
1140 get_loop_output(void)
1141 {
1142     int rv = 0;
1143     int n;
1144 
1145     while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) {
1146 	if (loop_chars(inbuf, n))
1147 	    rv = 1;
1148     }
1149 
1150     if (n == 0)
1151 	fatal("%s: eof on loopback", __func__);
1152     if (n == -1 && errno != EWOULDBLOCK)
1153 	fatal("%s: read from loopback: %m", __func__);
1154 
1155     return rv;
1156 }
1157 
1158 
1159 /*
1160  * netif_set_mtu - set the MTU on the PPP network interface.
1161  */
1162 void
1163 netif_set_mtu(int unit, int mtu)
1164 {
1165     struct ifreq ifr;
1166 
1167     SYSDEBUG((LOG_DEBUG, "netif_set_mtu: mtu = %d\n", mtu));
1168 
1169     memset(&ifr, '\0', sizeof (ifr));
1170     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1171     ifr.ifr_mtu = mtu;
1172 
1173     if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
1174 	fatal("%s: ioctl(SIOCSIFMTU): %m", __func__);
1175 }
1176 
1177 /*
1178  * netif_get_mtu - get the MTU on the PPP network interface.
1179  */
1180 int
1181 netif_get_mtu(int unit)
1182 {
1183     struct ifreq ifr;
1184 
1185     memset (&ifr, '\0', sizeof (ifr));
1186     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1187 
1188     if (ifunit >= 0 && ioctl(sock_fd, SIOCGIFMTU, (caddr_t) &ifr) < 0) {
1189 	error("%s: ioctl(SIOCGIFMTU): %m", __func__);
1190 	return 0;
1191     }
1192     return ifr.ifr_mtu;
1193 }
1194 
1195 /*
1196  * tty_send_config - configure the transmit characteristics of
1197  * the ppp interface.
1198  */
1199 void
1200 tty_send_config(int mtu, u_int32_t asyncmap, int pcomp, int accomp)
1201 {
1202     u_int x;
1203 #if 0
1204     /* Linux code does not do anything with the mtu here */
1205     ifnet_set_mtu(-1, mtu);
1206 #endif
1207 
1208     if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0)
1209 	fatal("%s: ioctl(PPPIOCSASYNCMAP): %m", __func__);
1210 
1211     x = get_flags(ppp_fd);
1212     x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
1213     x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
1214     x = sync_serial ? x | SC_SYNC : x & ~SC_SYNC;
1215     set_flags(ppp_fd, x);
1216 }
1217 
1218 
1219 /*
1220  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
1221  */
1222 void
1223 tty_set_xaccm(ext_accm accm)
1224 {
1225     if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
1226 	warn("%s: ioctl(set extended ACCM): %m", __func__);
1227 }
1228 
1229 
1230 /*
1231  * ppp_recv_config - configure the receive-side characteristics of
1232  * the ppp interface.
1233  */
1234 void
1235 tty_recv_config(int mru, u_int32_t asyncmap, int pcomp, int accomp)
1236 {
1237     int x;
1238 
1239     if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
1240 	fatal("%s: ioctl(PPPIOCSMRU): %m", __func__);
1241     if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0)
1242 	fatal("%s: ioctl(PPPIOCSRASYNCMAP): %m", __func__);
1243     x = get_flags(ppp_fd);
1244     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
1245     set_flags(ppp_fd, x);
1246 }
1247 
1248 /*
1249  * ccp_test - ask kernel whether a given compression method
1250  * is acceptable for use.  Returns 1 if the method and parameters
1251  * are OK, 0 if the method is known but the parameters are not OK
1252  * (e.g. code size should be reduced), or -1 if the method is unknown.
1253  */
1254 int
1255 ccp_test(int unit, u_char *opt_ptr, int opt_len, int for_transmit)
1256 {
1257     struct ppp_option_data data;
1258 
1259     data.ptr = opt_ptr;
1260     data.length = opt_len;
1261     data.transmit = for_transmit;
1262     if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
1263 	return 1;
1264     return (errno == ENOBUFS)? 0: -1;
1265 }
1266 
1267 /*
1268  * ccp_flags_set - inform kernel about the current state of CCP.
1269  */
1270 void
1271 ccp_flags_set(int unit, int isopen, int isup)
1272 {
1273     int x;
1274 
1275     x = get_flags(ppp_fd);
1276     x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
1277     x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
1278     set_flags(ppp_fd, x);
1279 }
1280 
1281 /*
1282  * ccp_fatal_error - returns 1 if decompression was disabled as a
1283  * result of an error detected after decompression of a packet,
1284  * 0 otherwise.  This is necessary because of patent nonsense.
1285  */
1286 int
1287 ccp_fatal_error(int unit)
1288 {
1289     int x;
1290 
1291     x = get_flags(ppp_fd);
1292     return x & SC_DC_FERROR;
1293 }
1294 
1295 /*
1296  * get_idle_time - return how long the link has been idle.
1297  */
1298 int
1299 get_idle_time(int u, struct ppp_idle *ip)
1300 {
1301     return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
1302 }
1303 
1304 /*
1305  * get_ppp_stats - return statistics for the link.
1306  */
1307 int
1308 get_ppp_stats(int u, struct pppd_stats *stats)
1309 {
1310     struct ifpppstatsreq req;
1311 
1312     memset (&req, 0, sizeof (req));
1313     strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name));
1314     if (ioctl(sock_fd, SIOCGPPPSTATS, &req) < 0) {
1315 	error("%s: Couldn't get PPP statistics: %m", __func__);
1316 	return 0;
1317     }
1318     stats->bytes_in = req.stats.p.ppp_ibytes;
1319     stats->bytes_out = req.stats.p.ppp_obytes;
1320     stats->pkts_in = req.stats.p.ppp_ipackets;
1321     stats->pkts_out = req.stats.p.ppp_opackets;
1322     return 1;
1323 }
1324 
1325 
1326 #ifdef PPP_FILTER
1327 /*
1328  * set_filters - transfer the pass and active filters to the kernel.
1329  */
1330 int
1331 set_filters(struct bpf_program *pass_in, struct bpf_program *pass_out,
1332     struct bpf_program *active_in, struct bpf_program *active_out)
1333 {
1334     int ret = 1;
1335 
1336     if (pass_in->bf_len > 0) {
1337 	if (ioctl(ppp_fd, PPPIOCSIPASS, pass_in) < 0) {
1338 	    error("%s: Couldn't set pass-filter-in in kernel: %m", __func__);
1339 	    ret = 0;
1340 	}
1341     }
1342 
1343     if (pass_out->bf_len > 0) {
1344 	if (ioctl(ppp_fd, PPPIOCSOPASS, pass_out) < 0) {
1345 	    error("%s: Couldn't set pass-filter-out in kernel: %m", __func__);
1346 	    ret = 0;
1347 	}
1348     }
1349 
1350     if (active_in->bf_len > 0) {
1351 	if (ioctl(ppp_fd, PPPIOCSIACTIVE, active_in) < 0) {
1352 	    error("%s: Couldn't set active-filter-in in kernel: %m", __func__);
1353 	    ret = 0;
1354 	}
1355     }
1356 
1357     if (active_out->bf_len > 0) {
1358 	if (ioctl(ppp_fd, PPPIOCSOACTIVE, active_out) < 0) {
1359 	    error("%s: Couldn't set active-filter-out in kernel: %m", __func__);
1360 	    ret = 0;
1361 	}
1362     }
1363 
1364     return ret;
1365 }
1366 #endif
1367 
1368 /*
1369  * sifvjcomp - config tcp header compression
1370  */
1371 int
1372 sifvjcomp(int u, int vjcomp, int cidcomp, int maxcid)
1373 {
1374     u_int x;
1375 
1376     x = get_flags(ppp_fd);
1377     x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
1378     x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
1379     set_flags(ppp_fd, x);
1380     if (vjcomp && ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
1381 	error("%s: ioctl(PPPIOCSMAXCID): %m", __func__);
1382 	return 0;
1383     }
1384     return 1;
1385 }
1386 
1387 /********************************************************************
1388  *
1389  * sifup - Config the interface up and enable IP packets to pass.
1390  */
1391 
1392 int sifup(int u)
1393 {
1394     int ret;
1395 
1396     if ((ret = setifstate(u, 1)))
1397 	if_is_up++;
1398 
1399     return ret;
1400 }
1401 
1402 /********************************************************************
1403  *
1404  * sifdown - Disable the indicated protocol and config the interface
1405  *	     down if there are no remaining protocols.
1406  */
1407 
1408 int sifdown (int u)
1409 {
1410     if (if_is_up && --if_is_up > 0)
1411 	return 1;
1412 
1413 #ifdef INET6
1414     if (if6_is_up)
1415 	return 1;
1416 #endif /* INET6 */
1417 
1418     return setifstate(u, 0);
1419 }
1420 
1421 #ifdef INET6
1422 /********************************************************************
1423  *
1424  * sif6up - Config the interface up for IPv6
1425  */
1426 
1427 int sif6up(int u)
1428 {
1429     int ret;
1430 
1431     if ((ret = setifstate(u, 1)))
1432 	if6_is_up = 1;
1433 
1434     return ret;
1435 }
1436 
1437 /********************************************************************
1438  *
1439  * sif6down - Disable the IPv6CP protocol and config the interface
1440  *	      down if there are no remaining protocols.
1441  */
1442 
1443 int sif6down (int u)
1444 {
1445     if6_is_up = 0;
1446 
1447     if (if_is_up)
1448 	return 1;
1449 
1450     return setifstate(u, 0);
1451 }
1452 #endif /* INET6 */
1453 
1454 /********************************************************************
1455  *
1456  * setifstate - Config the interface up or down
1457  */
1458 
1459 static int setifstate (int u, int state)
1460 {
1461     struct ifreq ifr;
1462 
1463     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1464     if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
1465 	error("%s: ioctl (SIOCGIFFLAGS): %m", __func__);
1466 	return 0;
1467     }
1468     if (state)
1469 	ifr.ifr_flags |= IFF_UP;
1470     else
1471 	ifr.ifr_flags &= ~IFF_UP;
1472     if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
1473 	error("%s: ioctl(SIOCSIFFLAGS): %m", __func__);
1474 	return 0;
1475     }
1476     if_is_up = 1;
1477     return 1;
1478 }
1479 
1480 /*
1481  * sifnpmode - Set the mode for handling packets for a given NP.
1482  */
1483 int
1484 sifnpmode(int u, int proto, enum NPmode mode)
1485 {
1486     struct npioctl npi;
1487 
1488     npi.protocol = proto;
1489     npi.mode = mode;
1490     if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
1491 	error("%s: ioctl(set NP %d mode to %d): %m", __func__, proto, mode);
1492 	return 0;
1493     }
1494     return 1;
1495 }
1496 
1497 /*
1498  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
1499  * if it exists.
1500  */
1501 #define SET_SA_FAMILY(addr, family)		\
1502     BZERO((char *) &(addr), sizeof(addr));	\
1503     addr.sa_family = (family); 			\
1504     addr.sa_len = sizeof(addr);
1505 
1506 /*
1507  * sifaddr - Config the interface IP addresses and netmask.
1508  */
1509 int
1510 sifaddr(int u, u_int32_t o, u_int32_t h, u_int32_t m)
1511 {
1512     struct ifaliasreq ifra;
1513     struct ifreq ifr;
1514 
1515     strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1516     SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
1517     ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
1518     SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
1519     ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
1520     if (m != 0) {
1521 	SET_SA_FAMILY(ifra.ifra_mask, AF_INET);
1522 	((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
1523     } else
1524 	BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
1525     BZERO(&ifr, sizeof(ifr));
1526     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1527     if (ioctl(sock_fd, SIOCDIFADDR, (caddr_t) &ifr) < 0) {
1528 	if (errno != EADDRNOTAVAIL)
1529 	    warn("%s: Couldn't remove interface address: %m", __func__);
1530     }
1531     if (ioctl(sock_fd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
1532 	if (errno != EEXIST) {
1533 	    error("%s: Couldn't set interface address: %m", __func__);
1534 	    return 0;
1535 	}
1536 	warn("%s: Couldn't set interface address: Address %I already exists",
1537 	    __func__, o);
1538     }
1539     ifaddrs[0] = o;
1540     ifaddrs[1] = h;
1541     return 1;
1542 }
1543 
1544 /*
1545  * cifaddr - Clear the interface IP addresses, and delete routes
1546  * through the interface if possible.
1547  */
1548 int
1549 cifaddr(int u, u_int32_t o, u_int32_t h)
1550 {
1551     struct ifaliasreq ifra;
1552 
1553     ifaddrs[0] = 0;
1554     strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1555     SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
1556     ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
1557     SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
1558     ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
1559     BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
1560     if (ioctl(sock_fd, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
1561 	if (!doing_cleanup && errno != EADDRNOTAVAIL)
1562 	    warn("%s: Couldn't delete interface address: %m", __func__);
1563 	return 0;
1564     }
1565     return 1;
1566 }
1567 
1568 /*
1569  * sifdefaultroute - assign a default route through the address given.
1570  */
1571 int
1572 sifdefaultroute(int u, u_int32_t l, u_int32_t g)
1573 {
1574     return dodefaultroute(g, 's');
1575 }
1576 
1577 /*
1578  * cifdefaultroute - delete a default route through the address given.
1579  */
1580 int
1581 cifdefaultroute(int u, u_int32_t l, u_int32_t g)
1582 {
1583     return dodefaultroute(g, 'c');
1584 }
1585 
1586 /*
1587  * dodefaultroute - talk to a routing socket to add/delete a default route.
1588  */
1589 static int
1590 dodefaultroute(u_int32_t g, int cmd)
1591 {
1592     int routes;
1593     struct {
1594 	struct rt_msghdr	hdr;
1595 	struct sockaddr_in	dst;
1596 	struct sockaddr_in	gway;
1597 	struct sockaddr_in	netmask;
1598 	struct sockaddr_dl	ifp;
1599     } rtmsg;
1600 
1601     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1602 	if (!doing_cleanup)
1603 	    error("%s: Couldn't %s default route: socket: %m", __func__,
1604 		cmd == 's' ? "add" : "delete");
1605 	return 0;
1606     }
1607 
1608     memset(&rtmsg, 0, sizeof(rtmsg));
1609 
1610     rtmsg.hdr.rtm_type = cmd == 's' ? RTM_ADD : RTM_DELETE;
1611     rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
1612     rtmsg.hdr.rtm_version = RTM_VERSION;
1613     rtmsg.hdr.rtm_seq = ++rtm_seq;
1614     rtmsg.hdr.rtm_addrs =
1615 	RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_IFP;
1616 
1617     rtmsg.dst.sin_len = sizeof(rtmsg.dst);
1618     rtmsg.dst.sin_family = AF_INET;
1619     rtmsg.dst.sin_addr.s_addr = 0;
1620 
1621     rtmsg.gway.sin_len = sizeof(rtmsg.gway);
1622     rtmsg.gway.sin_family = AF_INET;
1623     rtmsg.gway.sin_addr.s_addr = g;
1624 
1625     rtmsg.netmask.sin_len = sizeof(rtmsg.netmask);
1626     rtmsg.netmask.sin_family = AF_INET;
1627     rtmsg.netmask.sin_addr.s_addr = 0;
1628 
1629     rtmsg.ifp.sdl_family = AF_LINK;
1630     rtmsg.ifp.sdl_len = sizeof(rtmsg.ifp);
1631     link_addr(ifname, &rtmsg.ifp);
1632 
1633     rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
1634 
1635     if (write(routes, &rtmsg, sizeof(rtmsg)) < 0) {
1636 	if (!doing_cleanup)
1637 	    error("%s: Couldn't %s default route: %m", __func__,
1638 		cmd == 's' ? "add" : "delete");
1639 	close(routes);
1640 	return 0;
1641     }
1642 
1643     close(routes);
1644     default_route_gateway = (cmd == 's') ? g : 0;
1645     return 1;
1646 }
1647 
1648 #if RTM_VERSION >= 3
1649 
1650 /*
1651  * sifproxyarp - Make a proxy ARP entry for the peer.
1652  */
1653 static struct {
1654     struct rt_msghdr		hdr;
1655     struct sockaddr_inarp	dst;
1656     struct sockaddr_dl		hwa;
1657     char			extra[128];
1658 } arpmsg;
1659 
1660 static int arpmsg_valid;
1661 
1662 int
1663 sifproxyarp(int unit, u_int32_t hisaddr)
1664 {
1665     int routes;
1666 
1667     /*
1668      * Get the hardware address of an interface on the same subnet
1669      * as our local address.
1670      */
1671     memset(&arpmsg, 0, sizeof(arpmsg));
1672     if (!get_ether_addr(hisaddr, &arpmsg.hwa)) {
1673 	error("%s: Cannot determine ethernet address for proxy ARP", __func__);
1674 	return 0;
1675     }
1676 
1677     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1678 	error("%s: Couldn't add proxy arp entry: socket: %m", __func__);
1679 	return 0;
1680     }
1681 
1682     arpmsg.hdr.rtm_type = RTM_ADD;
1683     arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC | RTF_LLDATA;
1684     arpmsg.hdr.rtm_version = RTM_VERSION;
1685     arpmsg.hdr.rtm_seq = ++rtm_seq;
1686     arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
1687     arpmsg.hdr.rtm_inits = RTV_EXPIRE;
1688     arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
1689     arpmsg.dst.sin_family = AF_INET;
1690     arpmsg.dst.sin_addr.s_addr = hisaddr;
1691     arpmsg.dst.sin_other = SIN_PROXY;
1692 
1693     arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
1694 	+ RT_ROUNDUP(arpmsg.hwa.sdl_len);
1695     if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1696 	error("%s: Couldn't add proxy arp entry: %m", __func__);
1697 	close(routes);
1698 	return 0;
1699     }
1700 
1701     close(routes);
1702     arpmsg_valid = 1;
1703     proxy_arp_addr = hisaddr;
1704     return 1;
1705 }
1706 
1707 /*
1708  * cifproxyarp - Delete the proxy ARP entry for the peer.
1709  */
1710 int
1711 cifproxyarp(int unit, u_int32_t hisaddr)
1712 {
1713     int routes;
1714 
1715     if (!arpmsg_valid)
1716 	return 0;
1717     arpmsg_valid = 0;
1718 
1719     arpmsg.hdr.rtm_type = RTM_DELETE;
1720     arpmsg.hdr.rtm_seq = ++rtm_seq;
1721 
1722     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1723 	if (!doing_cleanup)
1724 	    error("%s: Couldn't delete proxy arp entry: socket: %m", __func__);
1725 	return 0;
1726     }
1727 
1728     if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1729 	if (!doing_cleanup)
1730 	    error("%s: Couldn't delete proxy arp entry: %m", __func__);
1731 	close(routes);
1732 	return 0;
1733     }
1734 
1735     close(routes);
1736     proxy_arp_addr = 0;
1737     return 1;
1738 }
1739 
1740 #else	/* RTM_VERSION */
1741 
1742 /*
1743  * sifproxyarp - Make a proxy ARP entry for the peer.
1744  */
1745 int
1746 sifproxyarp(int unit, u_int32_t hisaddr)
1747 {
1748     struct arpreq arpreq;
1749     struct {
1750 	struct sockaddr_dl	sdl;
1751 	char			space[128];
1752     } dls;
1753 
1754     BZERO(&arpreq, sizeof(arpreq));
1755 
1756     /*
1757      * Get the hardware address of an interface on the same subnet
1758      * as our local address.
1759      */
1760     if (!get_ether_addr(hisaddr, &dls.sdl)) {
1761 	error("%s: Cannot determine ethernet address for proxy ARP", __func__);
1762 	return 0;
1763     }
1764 
1765     arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
1766     arpreq.arp_ha.sa_family = AF_UNSPEC;
1767     BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen);
1768     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1769     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1770     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1771     if (ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq) < 0) {
1772 	error("%s: Couldn't add proxy arp entry: %m", __func__);
1773 	return 0;
1774     }
1775 
1776     proxy_arp_addr = hisaddr;
1777     return 1;
1778 }
1779 
1780 /*
1781  * cifproxyarp - Delete the proxy ARP entry for the peer.
1782  */
1783 int
1784 cifproxyarp(int unit, u_int32_t hisaddr)
1785 {
1786     struct arpreq arpreq;
1787 
1788     BZERO(&arpreq, sizeof(arpreq));
1789     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1790     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1791     if (ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1792 	warn("%s: Couldn't delete proxy arp entry: %m", __func__);
1793 	return 0;
1794     }
1795     proxy_arp_addr = 0;
1796     return 1;
1797 }
1798 #endif	/* RTM_VERSION */
1799 
1800 
1801 /*
1802  * get_ether_addr - get the hardware address of an interface on the
1803  * the same subnet as ipaddr.
1804  */
1805 static int
1806 get_ether_addr(u_int32_t ipaddr, struct sockaddr_dl *hwaddr)
1807 {
1808     u_int32_t ina, mask;
1809     struct sockaddr_dl *dla;
1810     struct ifaddrs *ifap, *ifa, *ifp;
1811 
1812     /*
1813      * Scan through looking for an interface with an Internet
1814      * address on the same subnet as `ipaddr'.
1815      */
1816     if (getifaddrs(&ifap) != 0) {
1817 	error("%s: getifaddrs: %m", __func__);
1818 	return 0;
1819     }
1820 
1821     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1822 	if (ifa->ifa_addr->sa_family != AF_INET)
1823 	    continue;
1824 	ina = ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr;
1825 	/*
1826 	 * Check that the interface is up, and not point-to-point
1827 	 * or loopback.
1828 	 */
1829 	if ((ifa->ifa_flags &
1830 	     (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1831 	     != (IFF_UP|IFF_BROADCAST))
1832 	    continue;
1833 	/*
1834 	 * Get its netmask and check that it's on the right subnet.
1835 	 */
1836 	mask = ((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr;
1837 	if ((ipaddr & mask) != (ina & mask))
1838 	    continue;
1839 	break;
1840     }
1841 
1842     if (!ifa) {
1843 	freeifaddrs(ifap);
1844 	return 0;
1845     }
1846     info("found interface %s for proxy arp", ifa->ifa_name);
1847 
1848     ifp = ifa;
1849 
1850     /*
1851      * Now scan through again looking for a link-level address
1852      * for this interface.
1853      */
1854     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1855 	if (strcmp(ifp->ifa_name, ifa->ifa_name) != 0)
1856 	    continue;
1857 	if (ifa->ifa_addr->sa_family != AF_LINK)
1858 	    continue;
1859 	/*
1860 	 * Found the link-level address - copy it out
1861 	 */
1862 	dla = (struct sockaddr_dl *) ifa->ifa_addr;
1863 	BCOPY(dla, hwaddr, dla->sdl_len);
1864 	freeifaddrs(ifap);
1865 	return 1;
1866     }
1867 
1868     freeifaddrs(ifap);
1869     return 0;
1870 }
1871 
1872 /*
1873  * get_if_hwaddr - get the hardware address for the specified
1874  * network interface device.
1875  */
1876 int
1877 get_if_hwaddr(u_char *addr, char *name)
1878 {
1879 
1880 #define IFREQ_SAFE (sizeof(struct ifreq) + sizeof(struct sockaddr_dl))
1881     /* XXX sockaddr_dl is larger than the sockaddr in struct ifreq! */
1882     union {			/* XXX */
1883     	struct ifreq _ifreq;	/* XXX */
1884 	char _X[IFREQ_SAFE]; 	/* XXX */
1885     } _ifreq_dontsmashstack;	/* XXX */
1886 #define ifreq_xxx _ifreq_dontsmashstack._ifreq			/* XXX */
1887 
1888     struct sockaddr_dl *sdl = (struct sockaddr_dl *) &ifreq_xxx.ifr_addr;
1889     int fd;
1890 
1891     if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1892 	return 0;
1893     (void)memset(sdl, 0, sizeof(*sdl));
1894     sdl->sdl_family = AF_LINK;
1895     (void)strlcpy(ifreq_xxx.ifr_name, name, sizeof(ifreq_xxx.ifr_name));
1896     if (ioctl(fd, SIOCGIFADDR, &ifreq_xxx) == -1) {
1897 	(void)close(fd);
1898 	return 0;
1899     }
1900     (void)close(fd);
1901     (void)memcpy(addr, LLADDR(sdl), sdl->sdl_alen);
1902     return sdl->sdl_nlen;
1903 }
1904 
1905 /*
1906  * get_first_ethernet - return the name of the first ethernet-style
1907  * interface on this system.
1908  */
1909 char *
1910 get_first_ethernet(void)
1911 {
1912     static char ifname[IFNAMSIZ];
1913     struct ifaddrs *ifap, *ifa;
1914 
1915     /*
1916      * Scan through the system's network interfaces.
1917      */
1918     if (getifaddrs(&ifap) != 0) {
1919 	warn("%s: getifaddrs: %m", __func__);
1920 	return NULL;
1921     }
1922     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1923 	/*
1924 	 * Check the interface's internet address.
1925 	 */
1926 	if (ifa->ifa_addr->sa_family != AF_INET)
1927 	    continue;
1928 	/*
1929 	 * Check that the interface is up, and not point-to-point or loopback.
1930 	 */
1931 	if ((ifa->ifa_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1932 	    != IFF_UP) {
1933 	    strlcpy(ifname, ifa->ifa_name, sizeof(ifname));
1934 	    freeifaddrs(ifap);
1935 	    return ifname;
1936 	}
1937     }
1938     freeifaddrs(ifap);
1939     return NULL;
1940 }
1941 
1942 /*
1943  * Return user specified netmask, modified by any mask we might determine
1944  * for address `addr' (in network byte order).
1945  * Here we scan through the system's list of interfaces, looking for
1946  * any non-point-to-point interfaces which might appear to be on the same
1947  * network as `addr'.  If we find any, we OR in their netmask to the
1948  * user-specified netmask.
1949  */
1950 u_int32_t
1951 GetMask(u_int32_t addr)
1952 {
1953     u_int32_t mask, nmask, ina;
1954     struct ifaddrs *ifap, *ifa;
1955 
1956     addr = ntohl(addr);
1957     if (IN_CLASSA(addr))	/* determine network mask for address class */
1958 	nmask = IN_CLASSA_NET;
1959     else if (IN_CLASSB(addr))
1960 	nmask = IN_CLASSB_NET;
1961     else
1962 	nmask = IN_CLASSC_NET;
1963     /* class D nets are disallowed by bad_ip_adrs */
1964     mask = netmask | htonl(nmask);
1965 
1966     /*
1967      * Scan through the system's network interfaces.
1968      */
1969     if (getifaddrs(&ifap) != 0) {
1970 	warn("%s: getifaddrs: %m", __func__);
1971 	return 0;
1972     }
1973 
1974     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1975 	/*
1976 	 * Check the interface's internet address.
1977 	 */
1978 	if (ifa->ifa_addr->sa_family != AF_INET)
1979 	    continue;
1980 	ina = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
1981 	if ((ntohl(ina) & nmask) != (addr & nmask))
1982 	    continue;
1983 	/*
1984 	 * Check that the interface is up, and not point-to-point or loopback.
1985 	 */
1986 	if ((ifa->ifa_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) != IFF_UP)
1987 	    continue;
1988 	/*
1989 	 * Get its netmask and OR it into our mask.
1990 	 */
1991 	mask |= ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr;
1992     }
1993 
1994     freeifaddrs(ifap);
1995     return mask;
1996 }
1997 
1998 /*
1999  * have_route_to - determine if the system has any route to
2000  * a given IP address.
2001  * For demand mode to work properly, we have to ignore routes
2002  * through our own interface.
2003  */
2004 int have_route_to(u_int32_t addr)
2005 {
2006     return -1;
2007 }
2008 
2009 /*
2010  * Use the hostid as part of the random number seed.
2011  */
2012 int
2013 get_host_seed(void)
2014 {
2015     return gethostid();
2016 }
2017 
2018 #if 0
2019 /*
2020  * lock - create a lock file for the named lock device
2021  */
2022 #define	LOCK_PREFIX	"/var/spool/lock/LCK.."
2023 
2024 static char *lock_file;		/* name of lock file created */
2025 
2026 int
2027 lock(char *dev)
2028 {
2029     char hdb_lock_buffer[12];
2030     int fd, pid, n;
2031     char *p;
2032     size_t l;
2033 
2034     if ((p = strrchr(dev, '/')) != NULL)
2035 	dev = p + 1;
2036     l = strlen(LOCK_PREFIX) + strlen(dev) + 1;
2037     lock_file = malloc(l);
2038     if (lock_file == NULL)
2039 	novm("lock file name");
2040     slprintf(lock_file, l, "%s%s", LOCK_PREFIX, dev);
2041 
2042     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
2043 	if (errno == EEXIST
2044 	    && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
2045 	    /* Read the lock file to find out who has the device locked */
2046 	    n = read(fd, hdb_lock_buffer, 11);
2047 	    if (n <= 0) {
2048 		error("%s: Can't read pid from lock file %s", __func__,
2049 		    lock_file);
2050 		close(fd);
2051 	    } else {
2052 		hdb_lock_buffer[n] = 0;
2053 		pid = atoi(hdb_lock_buffer);
2054 		if (kill(pid, 0) == -1 && errno == ESRCH) {
2055 		    /* pid no longer exists - remove the lock file */
2056 		    if (unlink(lock_file) == 0) {
2057 			close(fd);
2058 			notice("%s: Removed stale lock on %s (pid %d)",
2059 			    __func__, dev, pid);
2060 			continue;
2061 		    } else
2062 			warn("%s: Couldn't remove stale lock on %s", __func__,
2063 			    dev);
2064 		} else
2065 		    notice("%s: Device %s is locked by pid %d", __func__,
2066 			   dev, pid);
2067 	    }
2068 	    close(fd);
2069 	} else
2070 	    error("%s: Can't create lock file %s: %m", __func__, lock_file);
2071 	free(lock_file);
2072 	lock_file = NULL;
2073 	return -1;
2074     }
2075 
2076     slprintf(hdb_lock_buffer, sizeof(hdb_lock_buffer), "%10d\n", getpid());
2077     write(fd, hdb_lock_buffer, 11);
2078 
2079     close(fd);
2080     return 0;
2081 }
2082 
2083 /*
2084  * unlock - remove our lockfile
2085  */
2086 void
2087 unlock(void)
2088 {
2089     if (lock_file) {
2090 	unlink(lock_file);
2091 	free(lock_file);
2092 	lock_file = NULL;
2093     }
2094 }
2095 #endif
2096 
2097 #ifdef INET6
2098 /*
2099  * ether_to_eui64 - Convert 48-bit Ethernet address into 64-bit EUI
2100  *
2101  * convert the 48-bit MAC address of eth0 into EUI 64. caller also assumes
2102  * that the system has a properly configured Ethernet interface for this
2103  * function to return non-zero.
2104  */
2105 int
2106 ether_to_eui64(eui64_t *p_eui64)
2107 {
2108     struct ifaddrs *ifap, *ifa;
2109 
2110     if (getifaddrs(&ifap) != 0) {
2111 	warn("%s: getifaddrs: %m", __func__);
2112 	return 0;
2113     }
2114     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2115 	/*
2116 	 * Check the interface's internet address.
2117 	 */
2118 	if (ifa->ifa_addr->sa_family != AF_LINK)
2119 	    continue;
2120 	/*
2121 	 * Check that the interface is up, and not point-to-point or loopback.
2122 	 */
2123 	if ((ifa->ifa_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) == IFF_UP)
2124 	{
2125 	    /*
2126 	     * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1]
2127 	     */
2128 	    unsigned char *ptr = (void *)ifa->ifa_addr;
2129 	    p_eui64->e8[0] = ptr[0] | 0x02;
2130 	    p_eui64->e8[1] = ptr[1];
2131 	    p_eui64->e8[2] = ptr[2];
2132 	    p_eui64->e8[3] = 0xFF;
2133 	    p_eui64->e8[4] = 0xFE;
2134 	    p_eui64->e8[5] = ptr[3];
2135 	    p_eui64->e8[6] = ptr[4];
2136 	    p_eui64->e8[7] = ptr[5];
2137 	    freeifaddrs(ifap);
2138 	    return 1;
2139 	}
2140     }
2141     warn("%s: can't find a link address", __func__);
2142     freeifaddrs(ifap);
2143 
2144     return 0;
2145 }
2146 #endif
2147