xref: /titanic_51/usr/src/cmd/cmd-inet/usr.bin/pppd/sys-solaris.c (revision ccbf80fa3b6bf6b986dca9037e5ad9d6c9f9fa65)
1 /*
2  * System-dependent procedures for pppd under Solaris 2.x (SunOS 5.x).
3  *
4  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
5  * Use is subject to license terms.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation is hereby granted, provided that the above copyright
9  * notice appears in all copies.
10  *
11  * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
12  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
13  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT.  SUN SHALL NOT BE LIABLE FOR
15  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
16  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
17  *
18  * Copyright (c) 1994 The Australian National University.
19  * All rights reserved.
20  *
21  * Permission to use, copy, modify, and distribute this software and its
22  * documentation is hereby granted, provided that the above copyright
23  * notice appears in all copies.  This software is provided without any
24  * warranty, express or implied. The Australian National University
25  * makes no representations about the suitability of this software for
26  * any purpose.
27  *
28  * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
29  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
30  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
31  * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
32  * OF SUCH DAMAGE.
33  *
34  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
36  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
37  * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
38  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
39  * OR MODIFICATIONS.
40  */
41 
42 #pragma ident	"%Z%%M%	%I%	%E% SMI"
43 #define	RCSID	"$Id: sys-solaris.c,v 1.2 2000/04/21 01:27:57 masputra Exp $"
44 
45 #include <limits.h>
46 #include <stdio.h>
47 #include <stddef.h>
48 #include <stdlib.h>
49 #include <ctype.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <unistd.h>
53 #include <netdb.h>
54 #include <termios.h>
55 #include <signal.h>
56 #include <string.h>
57 #include <stropts.h>
58 #include <utmpx.h>
59 #include <sys/types.h>
60 #include <sys/ioccom.h>
61 #include <sys/stream.h>
62 #include <sys/stropts.h>
63 #include <sys/socket.h>
64 #include <sys/sockio.h>
65 #include <sys/sysmacros.h>
66 #include <sys/systeminfo.h>
67 #include <sys/dlpi.h>
68 #include <sys/stat.h>
69 #include <net/if.h>
70 #include <net/if_arp.h>
71 #include <net/route.h>
72 #include <net/ppp_defs.h>
73 #include <net/pppio.h>
74 #include <net/if_types.h>
75 #include <net/if_dl.h>
76 #include <netinet/in.h>
77 #include <sys/tihdr.h>
78 #include <inet/mib2.h>
79 #include <inet/ip.h>
80 #include <sys/ethernet.h>
81 #include <sys/ser_sync.h>
82 
83 #include "pppd.h"
84 #include "fsm.h"
85 #include "lcp.h"
86 #include "ipcp.h"
87 #ifdef INET6
88 #include "ipv6cp.h"
89 #endif /* INET6 */
90 #include "ccp.h"
91 
92 #if !defined(lint) && !defined(_lint)
93 static const char rcsid[] = RCSID;
94 #endif
95 
96 #define	PPPSTRTIMOUT	1	/* Timeout in seconds for ioctl */
97 #define	MAX_POLLFDS	32
98 #define	NMODULES	32
99 
100 #ifndef LIFNAMSIZ
101 #define	LIFNAMSIZ	32
102 #endif /* LIFNAMSIZ */
103 
104 #ifndef MAXIFS
105 #define	MAXIFS		256
106 #endif /* MAXIFS */
107 
108 #ifndef ETHERADDRL
109 #define	ETHERADDRL	6
110 #endif /* ETHERADDRL */
111 
112 #ifdef INET6
113 #define	_IN6_LLX_FROM_EUI64(l, s, eui64, as, len)	\
114 	(s->sin6_addr.s6_addr32[0] = htonl(as),		\
115 	eui64_copy(eui64, s->sin6_addr.s6_addr32[2]),	\
116 	s->sin6_family = AF_INET6,			\
117 	l.lifr_addr.ss_family = AF_INET6,		\
118 	l.lifr_addrlen = len,				\
119 	l.lifr_addr = laddr)
120 
121 /*
122  * Generate a link-local address with an interface-id based on the given
123  * EUI64 identifier.  Note that the len field is unused by SIOCSLIFADDR.
124  */
125 #define	IN6_LLADDR_FROM_EUI64(l, s, eui64)		\
126 	_IN6_LLX_FROM_EUI64(l, s, eui64, 0xfe800000, 0)
127 
128 /*
129  * Generate an EUI64 based interface-id for use by stateless address
130  * autoconfiguration.  These are required to be 64 bits long as defined in
131  * the "Interface Identifiers" section of the IPv6 Addressing Architecture
132  * (RFC3513).
133  */
134 #define	IN6_LLTOKEN_FROM_EUI64(l, s, eui64) \
135 	_IN6_LLX_FROM_EUI64(l, s, eui64, 0, 64)
136 #endif /* INET6 */
137 
138 #define	IPCP_ENABLED	ipcp_protent.enabled_flag
139 #ifdef INET6
140 #define	IPV6CP_ENABLED	ipv6cp_protent.enabled_flag
141 #endif /* INET6 */
142 
143 /* For plug-in usage. */
144 int (*sys_read_packet_hook) __P((int retv, struct strbuf *ctrl,
145     struct strbuf *data, int flags)) = NULL;
146 bool already_ppp = 0;			/* Already in PPP mode */
147 
148 static int pppfd = -1;			/* ppp driver fd */
149 static int fdmuxid = -1;		/* driver mux fd */
150 static int ipfd = -1;			/* IPv4 fd */
151 static int ipmuxid = -1;		/* IPv4 mux fd */
152 static int ip6fd = -1;			/* IPv6 fd */
153 static int ip6muxid = -1;		/* IPv6 mux fd */
154 static bool if6_is_up = 0;		/* IPv6 if marked as up */
155 static bool if_is_up = 0;		/* IPv4 if marked as up */
156 static bool restore_term = 0;		/* Restore TTY after closing link */
157 static struct termios inittermios;	/* TTY settings */
158 static struct winsize wsinfo;		/* Initial window size info */
159 static pid_t tty_sid;			/* original sess ID for term */
160 static struct pollfd pollfds[MAX_POLLFDS]; /* array of polled fd */
161 static int n_pollfds = 0;		/* total count of polled fd */
162 static int link_mtu;			/* link Maximum Transmit Unit */
163 static int tty_nmodules;		/* total count of TTY modules used */
164 static char tty_modules[NMODULES][FMNAMESZ+1];
165 					/* array of TTY modules used */
166 static int tty_npushed;			/* total count of pushed PPP modules */
167 static u_int32_t remote_addr;		/* IP address of peer */
168 static u_int32_t default_route_gateway;	/* Gateway for default route */
169 static u_int32_t proxy_arp_addr;	/* Addr for proxy arp entry */
170 static u_int32_t lastlink_status;	/* Last link status info */
171 
172 static bool use_plink = 0;		/* Use I_LINK by default */
173 static bool plumbed = 0;		/* Use existing interface */
174 
175 /* Default is to use /dev/sppp as driver. */
176 static const char *drvnam = PPP_DEV_NAME;
177 static bool integrated_driver = 0;
178 static int extra_dev_fd = -1;		/* keep open until ready */
179 
180 static option_t solaris_option_list[] = {
181 	{ "plink", o_bool, &use_plink, "Use I_PLINK instead of I_LINK",
182 	    OPT_PRIV|1 },
183 	{ "noplink", o_bool, &use_plink, "Use I_LINK instead of I_PLINK",
184 	    OPT_PRIV|0 },
185 	{ "plumbed", o_bool, &plumbed, "Use pre-plumbed interface",
186 	    OPT_PRIV|1 },
187 	{ NULL }
188 };
189 
190 /*
191  * Prototypes for procedures local to this file.
192  */
193 static int translate_speed __P((int));
194 static int baud_rate_of __P((int));
195 static int get_ether_addr __P((u_int32_t, struct sockaddr_dl *, int));
196 static int dlpi_attach __P((int, int));
197 static int dlpi_info_req __P((int));
198 static int dlpi_get_reply __P((int, union DL_primitives *, int, int));
199 static int strioctl __P((int, int, void *, int, int));
200 static int plumb_ipif __P((int));
201 static int unplumb_ipif __P((int));
202 #ifdef INET6
203 static int plumb_ip6if __P((int));
204 static int unplumb_ip6if __P((int));
205 static int open_ip6fd(void);
206 #endif /* INET6 */
207 static int open_ipfd(void);
208 static int sifroute __P((int, u_int32_t, u_int32_t, int, const char *));
209 static int giflags __P((u_int32_t, bool *));
210 static void handle_unbind __P((u_int32_t));
211 static void handle_bind __P((u_int32_t));
212 
213 /*
214  * Wrapper for regular ioctl; masks out EINTR.
215  */
216 static int
217 myioctl(int fd, int cmd, void *arg)
218 {
219 	int retv;
220 
221 	errno = 0;
222 	while ((retv = ioctl(fd, cmd, arg)) == -1) {
223 		if (errno != EINTR)
224 			break;
225 	}
226 	return (retv);
227 }
228 
229 /*
230  * sys_check_options()
231  *
232  * Check the options that the user specified.
233  */
234 int
235 sys_check_options(void)
236 {
237 	if (plumbed) {
238 		if (req_unit == -1)
239 			req_unit = -2;
240 		ipmuxid = 0;
241 		ip6muxid = 0;
242 	}
243 	return (1);
244 }
245 
246 /*
247  * sys_options()
248  *
249  * Add or remove system-specific options.
250  */
251 void
252 sys_options(void)
253 {
254 	(void) remove_option("ktune");
255 	(void) remove_option("noktune");
256 	add_options(solaris_option_list);
257 }
258 
259 /*
260  * sys_ifname()
261  *
262  * Set ifname[] to contain name of IP interface for this unit.
263  */
264 void
265 sys_ifname(void)
266 {
267 	const char *cp;
268 
269 	if ((cp = strrchr(drvnam, '/')) == NULL)
270 		cp = drvnam;
271 	else
272 		cp++;
273 	(void) slprintf(ifname, sizeof (ifname), "%s%d", cp, ifunit);
274 }
275 
276 /*
277  * ppp_available()
278  *
279  * Check whether the system has any ppp interfaces.
280  */
281 int
282 ppp_available(void)
283 {
284 	struct stat buf;
285 	int fd;
286 	uint32_t typ;
287 
288 	if (stat(PPP_DEV_NAME, &buf) >= 0)
289 		return (1);
290 
291 	/*
292 	 * Simple check for system using Apollo POS without SUNWpppd
293 	 * (/dev/sppp) installed.  This is intentionally not kept open
294 	 * here, since the user may not have the same privileges (as
295 	 * determined later).  If Apollo were just shipped with the
296 	 * full complement of packages, this wouldn't be an issue.
297 	 */
298 	if (devnam[0] == '\0' &&
299 	    (fd = open(devnam, O_RDWR | O_NONBLOCK | O_NOCTTY)) >= 0) {
300 		if (strioctl(fd, PPPIO_GTYPE, &typ, 0, sizeof (typ)) >= 0 &&
301 		    typ == PPPTYP_MUX) {
302 			(void) close(fd);
303 			return (1);
304 		}
305 		(void) close(fd);
306 	}
307 	return (0);
308 }
309 
310 static int
311 open_ipfd(void)
312 {
313 	ipfd = open(IP_DEV_NAME, O_RDWR | O_NONBLOCK, 0);
314 	if (ipfd < 0) {
315 		error("Couldn't open IP device (%s): %m", IP_DEV_NAME);
316 	}
317 	return (ipfd);
318 }
319 
320 static int
321 read_ip_interface(int unit)
322 {
323 	struct ifreq ifr;
324 	struct sockaddr_in sin;
325 
326 	if (ipfd == -1 && open_ipfd() == -1)
327 		return (0);
328 
329 	BZERO(&ifr, sizeof (ifr));
330 	(void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
331 
332 	/* Get the existing MTU */
333 	if (myioctl(ipfd, SIOCGIFMTU, &ifr) < 0) {
334 		warn("Couldn't get IP MTU on %s: %m", ifr.ifr_name);
335 		return (0);
336 	}
337 	dbglog("got MTU %d from interface", ifr.ifr_metric);
338 	if (ifr.ifr_metric != 0 &&
339 	    (lcp_allowoptions[unit].mru == 0 ||
340 		lcp_allowoptions[unit].mru > ifr.ifr_metric))
341 		lcp_allowoptions[unit].mru = ifr.ifr_metric;
342 
343 	/* Get the local IP address */
344 	if (ipcp_wantoptions[unit].ouraddr == 0 ||
345 	    ipcp_from_hostname) {
346 		if (myioctl(ipfd, SIOCGIFADDR, &ifr) < 0) {
347 			warn("Couldn't get local IP address (%s): %m",
348 			    ifr.ifr_name);
349 			return (0);
350 		}
351 		BCOPY(&ifr.ifr_addr, &sin, sizeof (struct sockaddr_in));
352 		ipcp_wantoptions[unit].ouraddr = sin.sin_addr.s_addr;
353 		dbglog("got local address %I from interface",
354 		    ipcp_wantoptions[unit].ouraddr);
355 	}
356 
357 	/* Get the remote IP address */
358 	if (ipcp_wantoptions[unit].hisaddr == 0) {
359 		if (myioctl(ipfd, SIOCGIFDSTADDR, &ifr) < 0) {
360 			warn("Couldn't get remote IP address (%s): %m",
361 			    ifr.ifr_name);
362 			return (0);
363 		}
364 		BCOPY(&ifr.ifr_dstaddr, &sin, sizeof (struct sockaddr_in));
365 		ipcp_wantoptions[unit].hisaddr = sin.sin_addr.s_addr;
366 		dbglog("got remote address %I from interface",
367 		    ipcp_wantoptions[unit].hisaddr);
368 	}
369 	return (1);
370 }
371 
372 #ifdef INET6
373 static int
374 open_ip6fd(void)
375 {
376 	ip6fd = open(IP6_DEV_NAME, O_RDWR | O_NONBLOCK, 0);
377 	if (ip6fd < 0) {
378 		error("Couldn't open IPv6 device (%s): %m", IP6_DEV_NAME);
379 	}
380 	return (ip6fd);
381 }
382 
383 static int
384 read_ipv6_interface(int unit)
385 {
386 	struct lifreq lifr;
387 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
388 
389 	if (ip6fd == -1 && open_ip6fd() == -1)
390 		return (0);
391 
392 	BZERO(&lifr, sizeof (lifr));
393 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
394 
395 	/* Get the existing MTU */
396 	if (myioctl(ip6fd, SIOCGLIFMTU, &lifr) < 0) {
397 		warn("Couldn't get IPv6 MTU on %s: %m", lifr.lifr_name);
398 		return (0);
399 	}
400 	if (lifr.lifr_mtu != 0 &&
401 	    (lcp_allowoptions[unit].mru == 0 ||
402 		lcp_allowoptions[unit].mru > lifr.lifr_mtu))
403 		lcp_allowoptions[unit].mru = lifr.lifr_mtu;
404 
405 	/* Get the local IPv6 address */
406 	if (eui64_iszero(ipv6cp_wantoptions[unit].ourid) ||
407 	    (ipcp_from_hostname && ipv6cp_wantoptions[unit].use_ip)) {
408 		if (myioctl(ip6fd, SIOCGLIFADDR, &lifr) < 0) {
409 			warn("Couldn't get local IPv6 address (%s): %m",
410 			    lifr.lifr_name);
411 			return (0);
412 		}
413 		eui64_copy(sin6->sin6_addr.s6_addr32[2],
414 		    ipv6cp_wantoptions[unit].ourid);
415 	}
416 
417 	/* Get the remote IP address */
418 	if (eui64_iszero(ipv6cp_wantoptions[unit].hisid)) {
419 		if (myioctl(ip6fd, SIOCGLIFDSTADDR, &lifr) < 0) {
420 			warn("Couldn't get remote IPv6 address (%s): %m",
421 			    lifr.lifr_name);
422 			return (0);
423 		}
424 		eui64_copy(sin6->sin6_addr.s6_addr32[2],
425 		    ipv6cp_wantoptions[unit].hisid);
426 	}
427 	return (1);
428 }
429 #endif /* INET6 */
430 
431 /*
432  * Read information on existing interface(s) and configure ourselves
433  * to negotiate appropriately.
434  */
435 static void
436 read_interface(int unit)
437 {
438 	dbglog("reading existing interface data; %sip %sipv6",
439 	    IPCP_ENABLED ? "" : "!",
440 #ifdef INET6
441 	    IPV6CP_ENABLED ? "" :
442 #endif
443 	    "!");
444 	if (IPCP_ENABLED && !read_ip_interface(unit))
445 		IPCP_ENABLED = 0;
446 #ifdef INET6
447 	if (IPV6CP_ENABLED && !read_ipv6_interface(unit))
448 		IPV6CP_ENABLED = 0;
449 #endif
450 }
451 
452 /*
453  * sys_init()
454  *
455  * System-dependent initialization.
456  */
457 void
458 sys_init(bool open_as_user)
459 {
460 	uint32_t x;
461 	uint32_t typ;
462 
463 	if (pppfd != -1) {
464 		return;
465 	}
466 
467 	if (!direct_tty && devnam[0] != '\0') {
468 		/*
469 		 * Check for integrated driver-like devices (such as
470 		 * POS).  These identify themselves as "PPP
471 		 * multiplexor" drivers.
472 		 */
473 		if (open_as_user)
474 			(void) seteuid(getuid());
475 		pppfd = open(devnam, O_RDWR | O_NONBLOCK);
476 		if (open_as_user)
477 			(void) seteuid(0);
478 		if (pppfd >= 0 &&
479 		    strioctl(pppfd, PPPIO_GTYPE, &typ, 0, sizeof (typ)) >= 0 &&
480 		    typ == PPPTYP_MUX) {
481 			integrated_driver = 1;
482 			drvnam = devnam;
483 		} else if (demand) {
484 			(void) close(pppfd);
485 			pppfd = -1;
486 		} else {
487 			extra_dev_fd = pppfd;
488 			pppfd = -1;
489 		}
490 	}
491 
492 	/*
493 	 * Open Solaris PPP device driver.
494 	 */
495 	if (pppfd < 0)
496 		pppfd = open(drvnam, O_RDWR | O_NONBLOCK);
497 	if (pppfd < 0) {
498 		fatal("Can't open %s: %m", drvnam);
499 	}
500 	if (kdebugflag & 1) {
501 		x = PPPDBG_LOG + PPPDBG_DRIVER;
502 		if (strioctl(pppfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) {
503 			warn("PPPIO_DEBUG ioctl for mux failed: %m");
504 		}
505 	}
506 	/*
507 	 * Assign a new PPA and get its unit number.
508 	 */
509 	x = req_unit;
510 	if (strioctl(pppfd, PPPIO_NEWPPA, &x, sizeof (x), sizeof (x)) < 0) {
511 		if (errno == ENXIO && plumbed)
512 			fatal("No idle interfaces available for use");
513 		fatal("PPPIO_NEWPPA ioctl failed: %m");
514 	}
515 	ifunit = x;
516 	if (req_unit >= 0 && ifunit != req_unit) {
517 		if (plumbed)
518 			fatal("unable to get requested unit %d", req_unit);
519 		else
520 			warn("unable to get requested unit %d", req_unit);
521 	}
522 	/*
523 	 * Enable packet time-stamping when idle option is specified. Note
524 	 * that we need to only do this on the control stream. Subsequent
525 	 * streams attached to this control stream (ppa) will inherit
526 	 * the time-stamp bit.
527 	 */
528 	if (idle_time_limit > 0) {
529 		if (strioctl(pppfd, PPPIO_USETIMESTAMP, NULL, 0, 0) < 0) {
530 			warn("PPPIO_USETIMESTAMP ioctl failed: %m");
531 		}
532 	}
533 	if (plumbed) {
534 		sys_ifname();
535 		read_interface(0);
536 	}
537 }
538 
539 int
540 sys_extra_fd(void)
541 {
542 	int fd;
543 
544 	fd = extra_dev_fd;
545 	extra_dev_fd = -1;
546 	return (fd);
547 }
548 
549 static int
550 open_udpfd(void)
551 {
552 	int udpfd;
553 
554 	udpfd = open(UDP_DEV_NAME, O_RDWR | O_NONBLOCK, 0);
555 	if (udpfd < 0) {
556 		error("Couldn't open UDP device (%s): %m", UDP_DEV_NAME);
557 	}
558 	return (udpfd);
559 }
560 
561 /*
562  * plumb_ipif()
563  *
564  * Perform IP interface plumbing.
565  */
566 /*ARGSUSED*/
567 static int
568 plumb_ipif(int unit)
569 {
570 	int udpfd = -1, tmpfd;
571 	uint32_t x;
572 	struct ifreq ifr;
573 
574 	if (!IPCP_ENABLED || (ifunit == -1) || (pppfd == -1)) {
575 		return (0);
576 	}
577 	if (plumbed)
578 		return (1);
579 	if (ipfd == -1 && open_ipfd() == -1)
580 		return (0);
581 	if (use_plink && (udpfd = open_udpfd()) == -1)
582 		return (0);
583 	tmpfd = open(drvnam, O_RDWR | O_NONBLOCK, 0);
584 	if (tmpfd < 0) {
585 		error("Couldn't open PPP device (%s): %m", drvnam);
586 		if (udpfd != -1)
587 			(void) close(udpfd);
588 		return (0);
589 	}
590 	if (kdebugflag & 1) {
591 		x = PPPDBG_LOG + PPPDBG_DRIVER;
592 		if (strioctl(tmpfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) {
593 			warn("PPPIO_DEBUG ioctl for mux failed: %m");
594 		}
595 	}
596 	if (myioctl(tmpfd, I_PUSH, IP_MOD_NAME) < 0) {
597 		error("Couldn't push IP module (%s): %m", IP_MOD_NAME);
598 		goto err_ret;
599 	}
600 	/*
601 	 * Assign ppa according to the unit number returned by ppp device
602 	 * after plumbing is completed above.  Without setting the ppa, ip
603 	 * module will return EINVAL upon setting the interface UP
604 	 * (SIOCSxIFFLAGS).  This is because ip module in 2.8 expects two
605 	 * DLPI_INFO_REQ to be sent down to the driver (below ip) before
606 	 * IFF_UP bit can be set. Plumbing the device causes one DLPI_INFO_REQ
607 	 * to be sent down, and the second DLPI_INFO_REQ is sent upon receiving
608 	 * IF_UNITSEL (old) or SIOCSLIFNAME (new) ioctls. Such setting of the
609 	 * ppa is required because the ppp DLPI provider advertises itself as
610 	 * a DLPI style 2 type, which requires a point of attachment to be
611 	 * specified. The only way the user can specify a point of attachment
612 	 * is via SIOCSLIFNAME or IF_UNITSEL.  Such changes in the behavior of
613 	 * ip module was made to meet new or evolving standards requirements.
614 	 */
615 	if (myioctl(tmpfd, IF_UNITSEL, &ifunit) < 0) {
616 		error("Couldn't set ppa for unit %d: %m", ifunit);
617 		goto err_ret;
618 	}
619 	if (use_plink) {
620 		ipmuxid = myioctl(udpfd, I_PLINK, (void *)tmpfd);
621 		if (ipmuxid < 0) {
622 			error("Can't I_PLINK PPP device to IP: %m");
623 			goto err_ret;
624 		}
625 	} else {
626 		ipmuxid = myioctl(ipfd, I_LINK, (void *)tmpfd);
627 		if (ipmuxid < 0) {
628 			error("Can't I_LINK PPP device to IP: %m");
629 			goto err_ret;
630 		}
631 	}
632 	BZERO(&ifr, sizeof (ifr));
633 	(void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
634 	ifr.ifr_ip_muxid = ipmuxid;
635 	ifr.ifr_arp_muxid = -1;
636 	if (myioctl(ipfd, SIOCSIFMUXID, (caddr_t)&ifr) < 0) {
637 		error("Can't set mux ID SIOCSIFMUXID on %s: %m", ifname);
638 		goto err_ret;
639 	}
640 	if (udpfd != -1)
641 		(void) close(udpfd);
642 	(void) close(tmpfd);
643 	return (1);
644 err_ret:
645 	if (udpfd != -1)
646 		(void) close(udpfd);
647 	(void) close(tmpfd);
648 	return (0);
649 }
650 
651 /*
652  * unplumb_ipif()
653  *
654  * Perform IP interface unplumbing.  Possibly called from die(), so there
655  * shouldn't be any call to die() or fatal() here.
656  */
657 static int
658 unplumb_ipif(int unit)
659 {
660 	int udpfd = -1, fd = -1;
661 	int id;
662 	struct lifreq lifr;
663 
664 	if (!IPCP_ENABLED || (ifunit == -1)) {
665 		return (0);
666 	}
667 	if (!plumbed && (ipmuxid == -1 || (ipfd == -1 && !use_plink)))
668 		return (1);
669 	id = ipmuxid;
670 	if (!plumbed && use_plink) {
671 		if ((udpfd = open_udpfd()) == -1)
672 			return (0);
673 		/*
674 		 * Note: must re-get mux ID, since any intervening
675 		 * ifconfigs will change this.
676 		 */
677 		BZERO(&lifr, sizeof (lifr));
678 		(void) strlcpy(lifr.lifr_name, ifname,
679 		    sizeof (lifr.lifr_name));
680 		if (myioctl(ipfd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) {
681 			warn("Can't get mux fd: SIOCGLIFMUXID: %m");
682 		} else {
683 			id = lifr.lifr_ip_muxid;
684 			fd = myioctl(udpfd, _I_MUXID2FD, (void *)id);
685 			if (fd < 0) {
686 				warn("Can't get mux fd: _I_MUXID2FD: %m");
687 			}
688 		}
689 	}
690 	/*
691 	 * Mark down and unlink the ip interface.
692 	 */
693 	(void) sifdown(unit);
694 	if (default_route_gateway != 0) {
695 		(void) cifdefaultroute(0, default_route_gateway,
696 		    default_route_gateway);
697 	}
698 	if (proxy_arp_addr != 0) {
699 		(void) cifproxyarp(0, proxy_arp_addr);
700 	}
701 	ipmuxid = -1;
702 	if (plumbed)
703 		return (1);
704 	if (use_plink) {
705 		if (myioctl(udpfd, I_PUNLINK, (void *)id) < 0) {
706 			error("Can't I_PUNLINK PPP from IP: %m");
707 			if (fd != -1)
708 				(void) close(fd);
709 			(void) close(udpfd);
710 			return (0);
711 		}
712 		if (fd != -1)
713 			(void) close(fd);
714 		(void) close(udpfd);
715 	} else {
716 		if (myioctl(ipfd, I_UNLINK, (void *)id) < 0) {
717 			error("Can't I_UNLINK PPP from IP: %m");
718 			return (0);
719 		}
720 	}
721 	return (1);
722 }
723 
724 /*
725  * sys_cleanup()
726  *
727  * Restore any system state we modified before exiting: mark the
728  * interface down, delete default route and/or proxy arp entry. This
729  * should not call die() because it's called from die().
730  */
731 void
732 sys_cleanup()
733 {
734 	(void) unplumb_ipif(0);
735 #ifdef INET6
736 	(void) unplumb_ip6if(0);
737 #endif /* INET6 */
738 }
739 
740 /*
741  * get_first_hwaddr()
742  *
743  * Stores the first hardware interface address found in the system
744  * into addr and return 1 upon success, or 0 if none is found.  This
745  * is also called from the multilink code.
746  */
747 int
748 get_first_hwaddr(addr, msize)
749 	uchar_t *addr;
750 	int msize;
751 {
752 	struct ifconf ifc;
753 	register struct ifreq *pifreq;
754 	struct ifreq ifr;
755 	int fd, num_ifs, i;
756 	uint_t fl, req_size;
757 	char *req;
758 	boolean_t found;
759 
760 	if (addr == NULL) {
761 		return (0);
762 	}
763 	fd = socket(AF_INET, SOCK_DGRAM, 0);
764 	if (fd < 0) {
765 		error("get_first_hwaddr: error opening IP socket: %m");
766 		return (0);
767 	}
768 	/*
769 	 * Find out how many interfaces are running
770 	 */
771 	if (myioctl(fd, SIOCGIFNUM, (caddr_t)&num_ifs) < 0) {
772 		num_ifs = MAXIFS;
773 	}
774 	req_size = num_ifs * sizeof (struct ifreq);
775 	req = malloc(req_size);
776 	if (req == NULL) {
777 		novm("interface request structure.");
778 	}
779 	/*
780 	 * Get interface configuration info for all interfaces
781 	 */
782 	ifc.ifc_len = req_size;
783 	ifc.ifc_buf = req;
784 	if (myioctl(fd, SIOCGIFCONF, &ifc) < 0) {
785 		error("SIOCGIFCONF: %m");
786 		(void) close(fd);
787 		free(req);
788 		return (0);
789 	}
790 	/*
791 	 * And traverse each interface to look specifically for the first
792 	 * occurence of an Ethernet interface which has been marked up
793 	 */
794 	pifreq = ifc.ifc_req;
795 	found = 0;
796 	for (i = ifc.ifc_len / sizeof (struct ifreq); i > 0; i--, pifreq++) {
797 
798 		if (strchr(pifreq->ifr_name, ':') != NULL) {
799 			continue;
800 		}
801 		BZERO(&ifr, sizeof (ifr));
802 		(void) strncpy(ifr.ifr_name, pifreq->ifr_name,
803 		    sizeof (ifr.ifr_name));
804 		if (myioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
805 			continue;
806 		}
807 		fl = ifr.ifr_flags;
808 		if ((fl & (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK))
809 		    != (IFF_UP | IFF_BROADCAST)) {
810 			continue;
811 		}
812 		if (get_if_hwaddr(addr, msize, ifr.ifr_name) <= 0) {
813 			continue;
814 		}
815 		found = 1;
816 		break;
817 	}
818 	free(req);
819 	(void) close(fd);
820 
821 	return (found);
822 }
823 
824 /*
825  * get_if_hwaddr()
826  *
827  * Get the hardware address for the specified network interface device.
828  * Return the length of the MAC address (in bytes) or -1 if error.
829  */
830 int
831 get_if_hwaddr(addr, msize, if_name)
832 	uchar_t *addr;
833 	int msize;
834 	char *if_name;
835 {
836 	int unit, iffd, adrlen;
837 	bool dlpi_err = 0;
838 	char *adrp, *q;
839 	char ifdev[4+LIFNAMSIZ+1];	/* take "/dev/" into account */
840 	struct {
841 		union DL_primitives prim;
842 		char space[64];
843 	} reply;
844 
845 	if ((addr == NULL) || (if_name == NULL) || (if_name[0] == '\0')) {
846 		return (-1);
847 	}
848 	/*
849 	 * We have to open the device and ask it for its hardware address.
850 	 * First split apart the device name and unit.
851 	 */
852 	(void) slprintf(ifdev, sizeof (ifdev), "/dev/%s", if_name);
853 	for (q = ifdev + strlen(ifdev); --q >= ifdev; ) {
854 		if (!isdigit(*q)) {
855 			break;
856 		}
857 	}
858 	unit = atoi(q + 1);
859 	q[1] = '\0';
860 	/*
861 	 * Open the device and do a DLPI attach and phys_addr_req.
862 	 */
863 	iffd = open(ifdev, O_RDWR);
864 	if (iffd < 0) {
865 		error("Couldn't open %s: %m", ifdev);
866 		return (-1);
867 	}
868 
869 	if (dlpi_attach(iffd, unit) < 0) {
870 		error("DLPI attach to device %s failed", ifdev);
871 		dlpi_err = 1;
872 	} else if (dlpi_get_reply(iffd, &reply.prim, DL_OK_ACK,
873 	    sizeof (reply)) < 0) {
874 		error("DLPI get attach reply on device %s failed", ifdev);
875 		dlpi_err = 1;
876 	} else if (dlpi_info_req(iffd) < 0) {
877 		error("DLPI info request on device %s failed", ifdev);
878 		dlpi_err = 1;
879 	} else if (dlpi_get_reply(iffd, &reply.prim, DL_INFO_ACK,
880 	    sizeof (reply)) < 0) {
881 		error("DLPI get info request reply on device %s failed", ifdev);
882 		dlpi_err = 1;
883 	}
884 	(void) close(iffd);
885 	iffd = -1;
886 	if (dlpi_err) {
887 		return (-1);
888 	}
889 	adrlen = reply.prim.info_ack.dl_addr_length;
890 	adrp = (caddr_t)&reply + reply.prim.info_ack.dl_addr_offset;
891 
892 	if (reply.prim.info_ack.dl_sap_length < 0) {
893 		adrlen += reply.prim.info_ack.dl_sap_length;
894 	} else {
895 		adrp += reply.prim.info_ack.dl_sap_length;
896 	}
897 	/*
898 	 * Check if we have enough space to copy the address to.
899 	 */
900 	if (adrlen > msize) {
901 		return (-1);
902 	}
903 	(void) memcpy(addr, adrp, adrlen);
904 	return (adrlen);
905 }
906 
907 /*
908  * giflags()
909  */
910 static int
911 giflags(u_int32_t flag, bool *retval)
912 {
913 	struct ifreq ifr;
914 	int fd;
915 
916 	*retval = 0;
917 	fd = socket(AF_INET, SOCK_DGRAM, 0);
918 	if (fd < 0) {
919 		error("giflags: error opening IP socket: %m");
920 		return (errno);
921 	}
922 
923 	BZERO(&ifr, sizeof (ifr));
924 	(void) strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
925 	if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
926 		(void) close(fd);
927 		return (errno);
928 	}
929 
930 	*retval = ((ifr.ifr_flags & flag) != 0);
931 	(void) close(fd);
932 	return (errno);
933 }
934 
935 /*
936  * sys_close()
937  *
938  * Clean up in a child process before exec-ing.
939  */
940 void
941 sys_close()
942 {
943 	if (ipfd != -1) {
944 		(void) close(ipfd);
945 		ipfd = -1;
946 	}
947 #ifdef INET6
948 	if (ip6fd != -1) {
949 		(void) close(ip6fd);
950 		ip6fd = -1;
951 	}
952 #endif /* INET6 */
953 	if (pppfd != -1) {
954 		(void) close(pppfd);
955 		pppfd = -1;
956 	}
957 }
958 
959 /*
960  * any_compressions()
961  *
962  * Check if compression is enabled or not.  In the STREAMS implementation of
963  * kernel-portion pppd, the comp STREAMS module performs the ACFC, PFC, as
964  * well CCP and VJ compressions. However, if the user has explicitly declare
965  * to not enable them from the command line, there is no point of having the
966  * comp module be pushed on the stream.
967  */
968 static int
969 any_compressions(void)
970 {
971 	if ((!lcp_wantoptions[0].neg_accompression) &&
972 	    (!lcp_wantoptions[0].neg_pcompression) &&
973 	    (!ccp_protent.enabled_flag) &&
974 	    (!ipcp_wantoptions[0].neg_vj)) {
975 		return (0);
976 	}
977 	return (1);
978 }
979 
980 /*
981  * modpush()
982  *
983  * Push a module on the stream.
984  */
985 static int
986 modpush(int fd, const char *modname, const char *text)
987 {
988 	if (myioctl(fd, I_PUSH, (void *)modname) < 0) {
989 		error("Couldn't push %s module: %m", text);
990 		return (-1);
991 	}
992 	if (++tty_npushed == 1 && !already_ppp) {
993 		if (strioctl(fd, PPPIO_LASTMOD, NULL, 0, 0) < 0) {
994 			warn("unable to set LASTMOD on %s: %m", text);
995 		}
996 	}
997 	return (0);
998 }
999 
1000 /*
1001  * establish_ppp()
1002  *
1003  * Turn the serial port into a ppp interface.
1004  */
1005 int
1006 establish_ppp(fd)
1007 	int fd;
1008 {
1009 	int i;
1010 	uint32_t x;
1011 
1012 	if (default_device && !notty) {
1013 		tty_sid = getsid((pid_t)0);
1014 	}
1015 
1016 	if (integrated_driver)
1017 		return (pppfd);
1018 
1019 	/*
1020 	 * Pop any existing modules off the tty stream
1021 	 */
1022 	for (i = 0; ; ++i) {
1023 		if ((myioctl(fd, I_LOOK, tty_modules[i]) < 0) ||
1024 		    (strcmp(tty_modules[i], "ptem") == 0) ||
1025 		    (myioctl(fd, I_POP, (void *)0) < 0)) {
1026 			break;
1027 		}
1028 	}
1029 	tty_nmodules = i;
1030 	/*
1031 	 * Push the async hdlc module and the compressor module
1032 	 */
1033 	tty_npushed = 0;
1034 	if (!sync_serial && !already_ppp &&
1035 	    modpush(fd, AHDLC_MOD_NAME, "PPP async HDLC") < 0) {
1036 		return (-1);
1037 	}
1038 	/*
1039 	 * There's no need to push comp module if we don't intend
1040 	 * to compress anything
1041 	 */
1042 	if (any_compressions()) {
1043 		(void) modpush(fd, COMP_MOD_NAME, "PPP compression");
1044 	}
1045 
1046 	/*
1047 	 * Link the serial port under the PPP multiplexor
1048 	 */
1049 	if ((fdmuxid = myioctl(pppfd, I_LINK, (void *)fd)) < 0) {
1050 		error("Can't link tty to PPP mux: %m");
1051 		return (-1);
1052 	}
1053 	if (tty_npushed == 0 && !already_ppp) {
1054 		if (strioctl(pppfd, PPPIO_LASTMOD, NULL, 0, 0) < 0) {
1055 			warn("unable to set LASTMOD on PPP mux: %m");
1056 		}
1057 	}
1058 	/*
1059 	 * Debug configuration must occur *after* I_LINK.
1060 	 */
1061 	if (kdebugflag & 4) {
1062 		x = PPPDBG_LOG + PPPDBG_AHDLC;
1063 		if (strioctl(pppfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) {
1064 			warn("PPPIO_DEBUG ioctl for ahdlc module failed: %m");
1065 		}
1066 	}
1067 	if (any_compressions() && (kdebugflag & 2)) {
1068 		x = PPPDBG_LOG + PPPDBG_COMP;
1069 		if (strioctl(pppfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) {
1070 			warn("PPPIO_DEBUG ioctl for comp module failed: %m");
1071 		}
1072 	}
1073 	return (pppfd);
1074 }
1075 
1076 /*
1077  * restore_loop()
1078  *
1079  * Reattach the ppp unit to the loopback. This doesn't need to do anything
1080  * because disestablish_ppp does it
1081  */
1082 void
1083 restore_loop()
1084 {
1085 }
1086 
1087 /*
1088  * disestablish_ppp()
1089  *
1090  * Restore the serial port to normal operation.  It attempts to reconstruct
1091  * the stream with the previously popped modules.  This shouldn't call die()
1092  * because it's called from die().  Stream reconstruction is needed in case
1093  * pppd is used for dial-in on /dev/tty and there's an option error.
1094  */
1095 void
1096 disestablish_ppp(fd)
1097 	int fd;
1098 {
1099 	int i;
1100 
1101 	if (fdmuxid == -1 || integrated_driver) {
1102 		return;
1103 	}
1104 	if (myioctl(pppfd, I_UNLINK, (void *)fdmuxid) < 0) {
1105 		if (!hungup) {
1106 			error("Can't unlink tty from PPP mux: %m");
1107 		}
1108 	}
1109 	fdmuxid = -1;
1110 	if (!hungup) {
1111 		while (tty_npushed > 0 && myioctl(fd, I_POP, (void *)0) >= 0) {
1112 			--tty_npushed;
1113 		}
1114 		for (i = tty_nmodules - 1; i >= 0; --i) {
1115 			if (myioctl(fd, I_PUSH, tty_modules[i]) < 0) {
1116 				error("Couldn't restore tty module %s: %m",
1117 				    tty_modules[i]);
1118 			}
1119 		}
1120 	}
1121 	if (hungup && default_device && tty_sid > 0) {
1122 		/*
1123 		 * If we have received a hangup, we need to send a
1124 		 * SIGHUP to the terminal's controlling process.
1125 		 * The reason is that the original stream head for
1126 		 * the terminal hasn't seen the M_HANGUP message
1127 		 * (it went up through the ppp driver to the stream
1128 		 * head for our fd to /dev/ppp).
1129 		 */
1130 		(void) kill(tty_sid, SIGHUP);
1131 	}
1132 }
1133 
1134 /*
1135  * clean_check()
1136  *
1137  * Check whether the link seems not to be 8-bit clean
1138  */
1139 void
1140 clean_check()
1141 {
1142 	uint32_t x;
1143 	char *s = NULL;
1144 
1145 	/*
1146 	 * Skip this is synchronous link is used, since spppasyn won't
1147 	 * be anywhere in the stream below to handle the ioctl.
1148 	 */
1149 	if (sync_serial) {
1150 		return;
1151 	}
1152 
1153 	if (strioctl(pppfd, PPPIO_GCLEAN, &x, 0, sizeof (x)) < 0) {
1154 		warn("unable to obtain serial link status: %m");
1155 		return;
1156 	}
1157 	switch (~x) {
1158 	case RCV_B7_0:
1159 		s = "bit 7 set to 1";
1160 		break;
1161 	case RCV_B7_1:
1162 		s = "bit 7 set to 0";
1163 		break;
1164 	case RCV_EVNP:
1165 		s = "odd parity";
1166 		break;
1167 	case RCV_ODDP:
1168 		s = "even parity";
1169 		break;
1170 	}
1171 	if (s != NULL) {
1172 		warn("Serial link is not 8-bit clean:");
1173 		warn("All received characters had %s", s);
1174 	}
1175 }
1176 
1177 /*
1178  * List of valid speeds.
1179  */
1180 struct speed {
1181 	int speed_int;
1182 	int speed_val;
1183 } speeds [] = {
1184 #ifdef B50
1185 	{ 50, B50 },
1186 #endif
1187 #ifdef B75
1188 	{ 75, B75 },
1189 #endif
1190 #ifdef B110
1191 	{ 110, B110 },
1192 #endif
1193 #ifdef B134
1194 	{ 134, B134 },
1195 #endif
1196 #ifdef B150
1197 	{ 150, B150 },
1198 #endif
1199 #ifdef B200
1200 	{ 200, B200 },
1201 #endif
1202 #ifdef B300
1203 	{ 300, B300 },
1204 #endif
1205 #ifdef B600
1206 	{ 600, B600 },
1207 #endif
1208 #ifdef B1200
1209 	{ 1200, B1200 },
1210 #endif
1211 #ifdef B1800
1212 	{ 1800, B1800 },
1213 #endif
1214 #ifdef B2000
1215 	{ 2000, B2000 },
1216 #endif
1217 #ifdef B2400
1218 	{ 2400, B2400 },
1219 #endif
1220 #ifdef B3600
1221 	{ 3600, B3600 },
1222 #endif
1223 #ifdef B4800
1224 	{ 4800, B4800 },
1225 #endif
1226 #ifdef B7200
1227 	{ 7200, B7200 },
1228 #endif
1229 #ifdef B9600
1230 	{ 9600, B9600 },
1231 #endif
1232 #ifdef B19200
1233 	{ 19200, B19200 },
1234 #endif
1235 #ifdef B38400
1236 	{ 38400, B38400 },
1237 #endif
1238 #ifdef EXTA
1239 	{ 19200, EXTA },
1240 #endif
1241 #ifdef EXTB
1242 	{ 38400, EXTB },
1243 #endif
1244 #ifdef B57600
1245 	{ 57600, B57600 },
1246 #endif
1247 #ifdef B76800
1248 	{ 76800, B76800 },
1249 #endif
1250 #ifdef B115200
1251 	{ 115200, B115200 },
1252 #endif
1253 #ifdef B153600
1254 	{ 153600, B153600 },
1255 #endif
1256 #ifdef B230400
1257 	{ 230400, B230400 },
1258 #endif
1259 #ifdef B307200
1260 	{ 307200, B307200 },
1261 #endif
1262 #ifdef B460800
1263 	{ 460800, B460800 },
1264 #endif
1265 	{ 0, 0 }
1266 };
1267 
1268 /*
1269  * translate_speed()
1270  *
1271  * Translate from bits/second to a speed_t
1272  */
1273 static int
1274 translate_speed(int bps)
1275 {
1276 	struct speed *speedp;
1277 
1278 	if (bps == 0) {
1279 		return (0);
1280 	}
1281 	for (speedp = speeds; speedp->speed_int; speedp++) {
1282 		if (bps == speedp->speed_int) {
1283 			return (speedp->speed_val);
1284 		}
1285 	}
1286 	set_source(&speed_info);
1287 	option_error("speed %d not supported", bps);
1288 	return (0);
1289 }
1290 
1291 /*
1292  * baud_rate_of()
1293  *
1294  * Translate from a speed_t to bits/second
1295  */
1296 static int
1297 baud_rate_of(int speed)
1298 {
1299 	struct speed *speedp;
1300 
1301 	if (speed == 0) {
1302 		return (0);
1303 	}
1304 	for (speedp = speeds; speedp->speed_int; speedp++) {
1305 		if (speed == speedp->speed_val) {
1306 			return (speedp->speed_int);
1307 		}
1308 	}
1309 	return (0);
1310 }
1311 
1312 /*
1313  * set_up_tty()
1314  *
1315  * Set up the serial port on `fd' for 8 bits, no parity, at the requested
1316  * speed, etc.  If `local' is true, set CLOCAL regardless of whether the
1317  * modem option was specified.
1318  */
1319 void
1320 set_up_tty(fd, local)
1321 	int fd, local;
1322 {
1323 	int speed;
1324 	struct termios tios;
1325 	struct scc_mode sm;
1326 
1327 	if (already_ppp)
1328 		return;
1329 
1330 	if (sync_serial) {
1331 		restore_term = 0;
1332 		speed = B0;
1333 		baud_rate = 0;
1334 
1335 		if (strioctl(fd, S_IOCGETMODE, &sm, sizeof (sm),
1336 		    sizeof (sm)) < 0) {
1337 			return;
1338 		}
1339 
1340 		baud_rate = sm.sm_baudrate;
1341 		dbglog("synchronous speed appears to be %d bps", baud_rate);
1342 	} else {
1343 		if (tcgetattr(fd, &tios) < 0) {
1344 			fatal("tcgetattr: %m");
1345 		}
1346 		if (!restore_term) {
1347 			inittermios = tios;
1348 			if (myioctl(fd, TIOCGWINSZ, &wsinfo) < 0) {
1349 				if (errno == EINVAL) {
1350 					/*
1351 					 * ptem returns EINVAL if all zeroes.
1352 					 * Strange and unfixable code.
1353 					 */
1354 					bzero(&wsinfo, sizeof (wsinfo));
1355 				} else {
1356 					warn("unable to get TTY window "
1357 					    "size: %m");
1358 				}
1359 			}
1360 		}
1361 		tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
1362 		if (crtscts > 0) {
1363 			tios.c_cflag |= CRTSCTS | CRTSXOFF;
1364 		} else if (crtscts < 0) {
1365 			tios.c_cflag &= ~CRTSCTS & ~CRTSXOFF;
1366 		}
1367 		tios.c_cflag |= CS8 | CREAD | HUPCL;
1368 		if (local || !modem) {
1369 			tios.c_cflag |= CLOCAL;
1370 		}
1371 		tios.c_iflag = IGNBRK | IGNPAR;
1372 		tios.c_oflag = 0;
1373 		tios.c_lflag = 0;
1374 		tios.c_cc[VMIN] = 1;
1375 		tios.c_cc[VTIME] = 0;
1376 
1377 		if (crtscts == -2) {
1378 			tios.c_iflag |= IXON | IXOFF;
1379 			tios.c_cc[VSTOP] = 0x13;	/* DC3 = XOFF = ^S */
1380 			tios.c_cc[VSTART] = 0x11;	/* DC1 = XON  = ^Q */
1381 		}
1382 		speed = translate_speed(inspeed);
1383 		if (speed) {
1384 			(void) cfsetospeed(&tios, speed);
1385 			(void) cfsetispeed(&tios, speed);
1386 		} else {
1387 			speed = cfgetospeed(&tios);
1388 			/*
1389 			 * We can't proceed if the serial port speed is 0,
1390 			 * since that implies that the serial port is disabled.
1391 			 */
1392 			if (speed == B0) {
1393 				fatal("Baud rate for %s is 0; need explicit "
1394 				    "baud rate", devnam);
1395 			}
1396 		}
1397 		if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
1398 			fatal("tcsetattr: %m");
1399 		}
1400 		baud_rate = baud_rate_of(speed);
1401 		dbglog("%s speed set to %d bps",
1402 		    fd == pty_slave ? "pty" : "serial", baud_rate);
1403 		restore_term = 1;
1404 	}
1405 }
1406 
1407 /*
1408  * restore_tty()
1409  *
1410  * Restore the terminal to the saved settings.
1411  */
1412 void
1413 restore_tty(fd)
1414 	int fd;
1415 {
1416 	if (restore_term == 0) {
1417 		return;
1418 	}
1419 	if (!default_device) {
1420 		/*
1421 		 * Turn off echoing, because otherwise we can get into
1422 		 * a loop with the tty and the modem echoing to each
1423 		 * other. We presume we are the sole user of this tty
1424 		 * device, so when we close it, it will revert to its
1425 		 * defaults anyway.
1426 		 */
1427 		inittermios.c_lflag &= ~(ECHO | ECHONL);
1428 	}
1429 	if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) {
1430 		if (!hungup && errno != ENXIO) {
1431 			warn("tcsetattr: %m");
1432 		}
1433 	}
1434 	if (wsinfo.ws_row != 0 || wsinfo.ws_col != 0 ||
1435 	    wsinfo.ws_xpixel != 0 || wsinfo.ws_ypixel != 0) {
1436 		if (myioctl(fd, TIOCSWINSZ, &wsinfo) < 0) {
1437 			warn("unable to set TTY window size: %m");
1438 		}
1439 	}
1440 	restore_term = 0;
1441 }
1442 
1443 /*
1444  * setdtr()
1445  *
1446  * Control the DTR line on the serial port. This is called from die(), so it
1447  * shouldn't call die()
1448  */
1449 void
1450 setdtr(fd, on)
1451 	int fd, on;
1452 {
1453 	int modembits = TIOCM_DTR;
1454 	if (!already_ppp &&
1455 	    myioctl(fd, (on ? TIOCMBIS : TIOCMBIC), &modembits) < 0) {
1456 		warn("unable to set DTR line %s: %m", (on ? "ON" : "OFF"));
1457 	}
1458 }
1459 
1460 /*
1461  * open_loopback()
1462  *
1463  * Open the device we use for getting packets in demand mode. Under Solaris 2,
1464  * we use our existing fd to the ppp driver.
1465  */
1466 int
1467 open_ppp_loopback()
1468 {
1469 	/*
1470 	 * Plumb the interface.
1471 	 */
1472 	if (IPCP_ENABLED && (plumb_ipif(0) == 0)) {
1473 		fatal("Unable to initialize IP interface for demand dial.");
1474 	}
1475 #ifdef INET6
1476 	if (IPV6CP_ENABLED && (plumb_ip6if(0) == 0)) {
1477 		fatal("Unable to initialize IPv6 interface for demand dial.");
1478 	}
1479 #endif /* INET6 */
1480 
1481 	return (pppfd);
1482 }
1483 
1484 /*
1485  * output()
1486  *
1487  * Output PPP packet downstream
1488  */
1489 /*ARGSUSED*/
1490 void
1491 output(unit, p, len)
1492 	int unit;
1493 	uchar_t *p;
1494 	int len;
1495 {
1496 	struct strbuf data;
1497 	struct pollfd pfd;
1498 	int retries, n;
1499 	bool sent_ok = 1;
1500 
1501 	data.len = len;
1502 	data.buf = (caddr_t)p;
1503 	retries = 4;
1504 
1505 	while (putmsg(pppfd, NULL, &data, 0) < 0) {
1506 		if (errno == EINTR)
1507 			continue;
1508 		if (--retries < 0 ||
1509 		    (errno != EWOULDBLOCK && errno != EAGAIN)) {
1510 			if (errno != ENXIO) {
1511 				error("Couldn't send packet: %m");
1512 				sent_ok = 0;
1513 			}
1514 			break;
1515 		}
1516 		pfd.fd = pppfd;
1517 		pfd.events = POLLOUT;
1518 		do {
1519 			/* wait for up to 0.25 seconds */
1520 			n = poll(&pfd, 1, 250);
1521 		} while ((n == -1) && (errno == EINTR));
1522 	}
1523 	if (debug && sent_ok) {
1524 		dbglog("sent %P", p, len);
1525 	}
1526 }
1527 
1528 /*
1529  * wait_input()
1530  *
1531  * Wait until there is data available, for the length of time specified by
1532  * timo (indefinite if timo is NULL).
1533  */
1534 void
1535 wait_input(timo)
1536 	struct timeval *timo;
1537 {
1538 	int t;
1539 
1540 	t = (timo == NULL ? -1 : (timo->tv_sec * 1000 + timo->tv_usec / 1000));
1541 	if ((poll(pollfds, n_pollfds, t) < 0) && (errno != EINTR)) {
1542 		fatal("poll: %m");
1543 	}
1544 }
1545 
1546 /*
1547  * add_fd()
1548  *
1549  * Add an fd to the set that wait_input waits for.
1550  */
1551 void
1552 add_fd(fd)
1553 	int fd;
1554 {
1555 	int n;
1556 
1557 	if (fd < 0) {
1558 		return;
1559 	}
1560 	for (n = 0; n < n_pollfds; ++n) {
1561 		if (pollfds[n].fd == fd) {
1562 			return;
1563 		}
1564 	}
1565 	if (n_pollfds < MAX_POLLFDS) {
1566 		pollfds[n_pollfds].fd = fd;
1567 		pollfds[n_pollfds].events = POLLIN | POLLPRI | POLLHUP;
1568 		++n_pollfds;
1569 	} else {
1570 		fatal("add_fd: too many inputs!");
1571 	}
1572 }
1573 
1574 /*
1575  * remove_fd()
1576  *
1577  * Remove an fd from the set that wait_input waits for.
1578  */
1579 void
1580 remove_fd(fd)
1581 	int fd;
1582 {
1583 	int n;
1584 
1585 	for (n = 0; n < n_pollfds; ++n) {
1586 		if (pollfds[n].fd == fd) {
1587 			while (++n < n_pollfds) {
1588 				pollfds[n-1] = pollfds[n];
1589 			}
1590 			--n_pollfds;
1591 			break;
1592 		}
1593 	}
1594 }
1595 
1596 static void
1597 dump_packet(uchar_t *buf, int len)
1598 {
1599 	uchar_t *bp;
1600 	int proto, offs;
1601 	const char *cp;
1602 	char sbuf[32];
1603 	uint32_t src, dst;
1604 	struct protoent *pep;
1605 
1606 	if (len < 4) {
1607 		dbglog("strange link activity: %.*B", len, buf);
1608 		return;
1609 	}
1610 	bp = buf;
1611 	if (bp[0] == 0xFF && bp[1] == 0x03)
1612 		bp += 2;
1613 	proto = *bp++;
1614 	if (!(proto & 1))
1615 		proto = (proto << 8) + *bp++;
1616 	len -= bp-buf;
1617 	if (proto == PPP_IP) {
1618 		if (len < 20 || get_ipv(bp) != 4 || get_iphl(bp) < 5) {
1619 			dbglog("strange IP packet activity: %16.*B", len, buf);
1620 			return;
1621 		}
1622 		src = get_ipsrc(bp);
1623 		dst = get_ipdst(bp);
1624 		proto = get_ipproto(bp);
1625 		if ((pep = getprotobynumber(proto)) != NULL) {
1626 			cp = pep->p_name;
1627 		} else {
1628 			(void) slprintf(sbuf, sizeof (sbuf), "IP proto %d",
1629 			    proto);
1630 			cp = sbuf;
1631 		}
1632 		if ((get_ipoff(bp) & IP_OFFMASK) != 0) {
1633 			len -= get_iphl(bp) * 4;
1634 			bp += get_iphl(bp) * 4;
1635 			dbglog("%s fragment from %I->%I: %8.*B", cp, src, dst,
1636 			    len, bp);
1637 		} else {
1638 			if (len > get_iplen(bp))
1639 				len = get_iplen(bp);
1640 			len -= get_iphl(bp) * 4;
1641 			bp += get_iphl(bp) * 4;
1642 			offs = proto == IPPROTO_TCP ? (get_tcpoff(bp)*4) : 8;
1643 			if (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
1644 				dbglog("%s data:%d %I:%d->%I:%d: %8.*B", cp,
1645 				    len-offs, src, get_sport(bp), dst,
1646 				    get_dport(bp), len-offs, bp+offs);
1647 			else
1648 				dbglog("%s %d bytes %I->%I: %8.*B", cp, len,
1649 				    src, dst, len, bp);
1650 		}
1651 		return;
1652 	}
1653 	if ((cp = protocol_name(proto)) == NULL) {
1654 		(void) slprintf(sbuf, sizeof (sbuf), "0x#X", proto);
1655 		cp = (const char *)sbuf;
1656 	}
1657 	dbglog("link activity: %s %16.*B", cp, len, bp);
1658 }
1659 
1660 /*
1661  * handle_bind()
1662  */
1663 static void
1664 handle_bind(u_int32_t reason)
1665 {
1666 	/*
1667 	 * Here we might, in the future, handle DL_BIND_REQ notifications
1668 	 * in order to close and re-open a NCP when certain interface
1669 	 * parameters (addresses, etc.) are changed via external mechanisms
1670 	 * such as through the "ifconfig" program.
1671 	 */
1672 	switch (reason) {
1673 	case PPP_LINKSTAT_IPV4_BOUND:
1674 		break;
1675 #ifdef INET6
1676 	case PPP_LINKSTAT_IPV6_BOUND:
1677 		break;
1678 #endif
1679 	default:
1680 		error("handle_bind: unrecognized reason");
1681 		break;
1682 	}
1683 }
1684 
1685 /*
1686  * handle_unbind()
1687  */
1688 static void
1689 handle_unbind(u_int32_t reason)
1690 {
1691 	bool iff_up_isset;
1692 	int rc;
1693 	static const char *unplumb_str = "unplumbed";
1694 	static const char *down_str = "downed";
1695 
1696 	/*
1697 	 * Since the kernel driver (sppp) notifies this daemon of the
1698 	 * DLPI bind/unbind activities (for the purpose of bringing down
1699 	 * a NCP), we need to explicitly test the "actual" status of
1700 	 * the interface instance for which the notification is destined
1701 	 * from.  This is because /dev/ip performs multiple DLPI attach-
1702 	 * bind-unbind-detach during the early life of the interface,
1703 	 * and when certain interface parameters change.  A DL_UNBIND_REQ
1704 	 * coming down to the sppp driver from /dev/ip (which results in
1705 	 * our receiving of the PPP_LINKSTAT_*_UNBOUND link status message)
1706 	 * is not enough to conclude that the interface has been marked
1707 	 * DOWN (its IFF_UP bit is cleared) or is going away.  Therefore,
1708 	 * we should query /dev/ip directly, upon receiving such *_UNBOUND
1709 	 * notification, to determine whether the interface is DOWN
1710 	 * for real, and only take the necessary actions when IFF_UP
1711 	 * bit for the interface instance is actually cleared.
1712 	 */
1713 	switch (reason) {
1714 	case PPP_LINKSTAT_IPV4_UNBOUND:
1715 		(void) sleep(1);
1716 		rc = giflags(IFF_UP, &iff_up_isset);
1717 		if (!iff_up_isset) {
1718 			if_is_up = 0;
1719 			ipmuxid = -1;
1720 			info("IPv4 interface %s by administrator",
1721 			    ((rc < 0 && rc == ENXIO) ? unplumb_str : down_str));
1722 			fsm_close(&ipcp_fsm[0],
1723 			    "administratively disconnected");
1724 		}
1725 		break;
1726 #ifdef INET6
1727 	case PPP_LINKSTAT_IPV6_UNBOUND:
1728 		(void) sleep(1);
1729 		rc = giflags(IFF_UP, &iff_up_isset);
1730 		if (!iff_up_isset) {
1731 			if6_is_up = 0;
1732 			ip6muxid = -1;
1733 			info("IPv6 interface %s by administrator",
1734 			    ((rc < 0 && rc == ENXIO) ? unplumb_str : down_str));
1735 			fsm_close(&ipv6cp_fsm[0],
1736 			    "administratively disconnected");
1737 		}
1738 		break;
1739 #endif
1740 	default:
1741 		error("handle_unbind: unrecognized reason");
1742 		break;
1743 	}
1744 }
1745 
1746 /*
1747  * read_packet()
1748  *
1749  * Get a PPP packet from the serial device.
1750  */
1751 int
1752 read_packet(buf)
1753 	uchar_t *buf;
1754 {
1755 	struct strbuf ctrl;
1756 	struct strbuf data;
1757 	int flags;
1758 	int len;
1759 	int rc;
1760 	struct ppp_ls *plp;
1761 	uint32_t ctrlbuf[1536 / sizeof (uint32_t)];
1762 	bool flushmode;
1763 
1764 	flushmode = 0;
1765 	for (;;) {
1766 
1767 		data.maxlen = PPP_MRU + PPP_HDRLEN;
1768 		data.buf = (caddr_t)buf;
1769 
1770 		ctrl.maxlen = sizeof (ctrlbuf);
1771 		ctrl.buf = (caddr_t)ctrlbuf;
1772 
1773 		flags = 0;
1774 		rc = len = getmsg(pppfd, &ctrl, &data, &flags);
1775 		if (sys_read_packet_hook != NULL) {
1776 			rc = len = (*sys_read_packet_hook)(len, &ctrl, &data,
1777 			    flags);
1778 		}
1779 		if (len < 0) {
1780 			if (errno == EAGAIN || errno == EINTR) {
1781 				return (-1);
1782 			}
1783 			fatal("Error reading packet: %m");
1784 		}
1785 		if ((data.len > 0) && (ctrl.len < 0)) {
1786 			/*
1787 			 * If there's more data on stream head, keep reading
1788 			 * but discard, since the stream is now corrupt.
1789 			 */
1790 			if (rc & MOREDATA) {
1791 				dbglog("More data; input packet garbled");
1792 				flushmode = 1;
1793 				continue;
1794 			}
1795 			if (flushmode)
1796 				return (-1);
1797 			return (data.len);
1798 
1799 		} else if (ctrl.len > 0) {
1800 			/*
1801 			 * If there's more ctl on stream head, keep reading,
1802 			 * but start discarding.  We can't deal with fragmented
1803 			 * messages at all.
1804 			 */
1805 			if (rc & MORECTL) {
1806 				dbglog("More control; stream garbled");
1807 				flushmode = 1;
1808 				continue;
1809 			}
1810 			if (flushmode)
1811 				return (-1);
1812 			if (ctrl.len < sizeof (struct ppp_ls)) {
1813 				warn("read_packet: ctl.len %d < "
1814 				    "sizeof ppp_ls %d",
1815 				    ctrl.len, sizeof (struct ppp_ls));
1816 				return (-1);
1817 			}
1818 			plp = (struct ppp_ls *)ctrlbuf;
1819 			if (plp->magic != PPPLSMAGIC) {
1820 				/* Skip, as we don't understand it */
1821 				dbglog("read_packet: unrecognized control %lX",
1822 				    plp->magic);
1823 				return (-1);
1824 			}
1825 
1826 			lastlink_status = plp->ppp_message;
1827 
1828 			switch (plp->ppp_message) {
1829 			case PPP_LINKSTAT_HANGUP:
1830 				return (0);	/* Hangup */
1831 			/* For use by integrated drivers. */
1832 			case PPP_LINKSTAT_UP:
1833 				lcp_lowerdown(0);
1834 				lcp_lowerup(0);
1835 				return (0);
1836 			case PPP_LINKSTAT_NEEDUP:
1837 				if (data.len > 0 && debug)
1838 					dump_packet(buf, data.len);
1839 				return (-1);	/* Demand dial */
1840 			case PPP_LINKSTAT_IPV4_UNBOUND:
1841 				(void) handle_unbind(plp->ppp_message);
1842 				return (-1);
1843 			case PPP_LINKSTAT_IPV4_BOUND:
1844 				(void) handle_bind(plp->ppp_message);
1845 				return (-1);
1846 #ifdef INET6
1847 			case PPP_LINKSTAT_IPV6_UNBOUND:
1848 				(void) handle_unbind(plp->ppp_message);
1849 				return (-1);
1850 			case PPP_LINKSTAT_IPV6_BOUND:
1851 				(void) handle_bind(plp->ppp_message);
1852 				return (-1);
1853 #endif
1854 			default:
1855 				warn("read_packet: unknown link status type!");
1856 				return (-1);
1857 			}
1858 		} else {
1859 			/*
1860 			 * We get here on zero length data or control.
1861 			 */
1862 			return (-1);
1863 		}
1864 	}
1865 }
1866 
1867 /*
1868  * get_loop_output()
1869  *
1870  * Get outgoing packets from the ppp device, and detect when we want to bring
1871  * the real link up. Return value is 1 if we need to bring up the link, or 0
1872  * otherwise.
1873  */
1874 int
1875 get_loop_output()
1876 {
1877 	int loops;
1878 
1879 	/*
1880 	 * In the Solaris 2.x kernel-level portion implementation, packets
1881 	 * which are received on a demand-dial interface are immediately
1882 	 * discarded, and a notification message is sent up the control
1883 	 * stream to the pppd process.  Therefore, the call to read_packet()
1884 	 * below is merely there to wait for such message.
1885 	 */
1886 	lastlink_status = 0;
1887 	loops = 0;
1888 	while (read_packet(inpacket_buf) > 0) {
1889 		if (++loops > 10)
1890 			break;
1891 	}
1892 	return (lastlink_status == PPP_LINKSTAT_NEEDUP);
1893 }
1894 
1895 #ifdef MUX_FRAME
1896 /*ARGSUSED*/
1897 void
1898 ppp_send_muxoption(unit, muxflag)
1899 	int unit;
1900 	u_int32_t muxflag;
1901 {
1902 	uint32_t	cf[2];
1903 
1904 	/*
1905 	 * Since muxed frame feature is implemented in the async module,
1906 	 * don't send down the ioctl in the synchronous case.
1907 	 */
1908 	if (!sync_serial && fdmuxid >= 0 && pppfd != -1) {
1909 		cf[0] = muxflag;
1910 		cf[1] = X_MUXMASK;
1911 
1912 		if (strioctl(pppfd, PPPIO_MUX, cf, sizeof (cf), 0) < 0) {
1913 			error("Couldn't set mux option: %m");
1914 		}
1915 	}
1916 }
1917 
1918 /*ARGSUSED*/
1919 void
1920 ppp_recv_muxoption(unit, muxflag)
1921 	int unit;
1922 	u_int32_t muxflag;
1923 {
1924 	uint32_t	cf[2];
1925 
1926 	/*
1927 	 * Since muxed frame feature is implemented in the async module,
1928 	 * don't send down the ioctl in the synchronous case.
1929 	 */
1930 	if (!sync_serial && fdmuxid >= 0 && pppfd != -1) {
1931 		cf[0] = muxflag;
1932 		cf[1] = R_MUXMASK;
1933 
1934 		if (strioctl(pppfd, PPPIO_MUX, cf, sizeof (cf), 0) < 0) {
1935 			error("Couldn't set receive mux option: %m");
1936 		}
1937 	}
1938 }
1939 #endif
1940 
1941 /*
1942  * ppp_send_config()
1943  *
1944  * Configure the transmit characteristics of the ppp interface.
1945  */
1946 /*ARGSUSED*/
1947 void
1948 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
1949 	int unit;
1950 	int mtu;
1951 	u_int32_t asyncmap;
1952 	int pcomp;
1953 	int accomp;
1954 {
1955 	uint32_t cf[2];
1956 
1957 	if (pppfd == -1) {
1958 		error("ppp_send_config called with invalid device handle");
1959 		return;
1960 	}
1961 	cf[0] =	link_mtu = mtu;
1962 	if (strioctl(pppfd, PPPIO_MTU, cf, sizeof (cf[0]), 0) < 0) {
1963 		if (hungup && errno == ENXIO) {
1964 			return;
1965 		}
1966 		error("Couldn't set MTU: %m");
1967 	}
1968 	if (fdmuxid != -1) {
1969 		if (!sync_serial) {
1970 			if (strioctl(pppfd, PPPIO_XACCM, &asyncmap,
1971 			    sizeof (asyncmap), 0) < 0) {
1972 				error("Couldn't set transmit ACCM: %m");
1973 			}
1974 		}
1975 		cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0);
1976 		cf[1] = COMP_PROT | COMP_AC;
1977 
1978 		if (any_compressions() && strioctl(pppfd, PPPIO_CFLAGS, cf,
1979 		    sizeof (cf), sizeof (cf[0])) < 0) {
1980 			error("Couldn't set prot/AC compression: %m");
1981 		}
1982 	}
1983 }
1984 
1985 /*
1986  * ppp_set_xaccm()
1987  *
1988  * Set the extended transmit ACCM for the interface.
1989  */
1990 /*ARGSUSED*/
1991 void
1992 ppp_set_xaccm(unit, accm)
1993 	int unit;
1994 	ext_accm accm;
1995 {
1996 	if (sync_serial) {
1997 		return;
1998 	}
1999 	if (fdmuxid != -1 && strioctl(pppfd, PPPIO_XACCM, accm,
2000 	    sizeof (ext_accm), 0) < 0) {
2001 		if (!hungup || errno != ENXIO) {
2002 			warn("Couldn't set extended ACCM: %m");
2003 		}
2004 	}
2005 }
2006 
2007 /*
2008  * ppp_recv_config()
2009  *
2010  * Configure the receive-side characteristics of the ppp interface.
2011  */
2012 /*ARGSUSED*/
2013 void
2014 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
2015 	int unit;
2016 	int mru;
2017 	u_int32_t asyncmap;
2018 	int pcomp;
2019 	int accomp;
2020 {
2021 	uint32_t cf[2];
2022 
2023 	if (pppfd == -1) {
2024 		error("ppp_recv_config called with invalid device handle");
2025 		return;
2026 	}
2027 	cf[0] = mru;
2028 	if (strioctl(pppfd, PPPIO_MRU, cf, sizeof (cf[0]), 0) < 0) {
2029 		if (hungup && errno == ENXIO) {
2030 			return;
2031 		}
2032 		error("Couldn't set MRU: %m");
2033 	}
2034 	if (fdmuxid != -1) {
2035 		if (!sync_serial) {
2036 			if (strioctl(pppfd, PPPIO_RACCM, &asyncmap,
2037 			    sizeof (asyncmap), 0) < 0) {
2038 				error("Couldn't set receive ACCM: %m");
2039 			}
2040 		}
2041 		cf[0] = (pcomp ? DECOMP_PROT : 0) + (accomp ? DECOMP_AC : 0);
2042 		cf[1] = DECOMP_PROT | DECOMP_AC;
2043 
2044 		if (any_compressions() && strioctl(pppfd, PPPIO_CFLAGS, cf,
2045 		    sizeof (cf), sizeof (cf[0])) < 0) {
2046 			error("Couldn't set prot/AC decompression: %m");
2047 		}
2048 	}
2049 }
2050 
2051 #ifdef NEGOTIATE_FCS
2052 /*
2053  * ppp_send_fcs()
2054  *
2055  * Configure the sender-side FCS.
2056  */
2057 /*ARGSUSED*/
2058 void
2059 ppp_send_fcs(unit, fcstype)
2060 	int unit, fcstype;
2061 {
2062 	uint32_t fcs;
2063 
2064 	if (sync_serial) {
2065 		return;
2066 	}
2067 
2068 	if (fcstype & FCSALT_32) {
2069 		fcs = PPPFCS_32;
2070 	} else if (fcstype & FCSALT_NULL) {
2071 		fcs = PPPFCS_NONE;
2072 	} else {
2073 		fcs = PPPFCS_16;
2074 	}
2075 	if (strioctl(pppfd, PPPIO_XFCS, &fcs, sizeof (fcs), 0) < 0) {
2076 		warn("Couldn't set transmit FCS: %m");
2077 	}
2078 }
2079 
2080 /*
2081  * ppp_recv_fcs()
2082  *
2083  * Configure the receiver-side FCS.
2084  */
2085 /*ARGSUSED*/
2086 void
2087 ppp_recv_fcs(unit, fcstype)
2088 	int unit, fcstype;
2089 {
2090 	uint32_t fcs;
2091 
2092 	if (sync_serial) {
2093 		return;
2094 	}
2095 
2096 	if (fcstype & FCSALT_32) {
2097 		fcs = PPPFCS_32;
2098 	} else if (fcstype & FCSALT_NULL) {
2099 		fcs = PPPFCS_NONE;
2100 	} else {
2101 		fcs = PPPFCS_16;
2102 	}
2103 	if (strioctl(pppfd, PPPIO_RFCS, &fcs, sizeof (fcs), 0) < 0) {
2104 		warn("Couldn't set receive FCS: %m");
2105 	}
2106 }
2107 #endif
2108 
2109 /*
2110  * ccp_test()
2111  *
2112  * Ask kernel whether a given compression method is acceptable for use.
2113  */
2114 /*ARGSUSED*/
2115 int
2116 ccp_test(unit, opt_ptr, opt_len, for_transmit)
2117 	int unit;
2118 	uchar_t *opt_ptr;
2119 	int opt_len;
2120 	int for_transmit;
2121 {
2122 	if (strioctl(pppfd, (for_transmit ? PPPIO_XCOMP : PPPIO_RCOMP),
2123 	    opt_ptr, opt_len, 0) >= 0) {
2124 		return (1);
2125 	}
2126 	warn("Error in %s ioctl: %m",
2127 	    (for_transmit ? "PPPIO_XCOMP" : "PPPIO_RCOMP"));
2128 	return ((errno == ENOSR) ? 0 : -1);
2129 }
2130 
2131 #ifdef COMP_TUNE
2132 /*
2133  * ccp_tune()
2134  *
2135  * Tune compression effort level.
2136  */
2137 /*ARGSUSED*/
2138 void
2139 ccp_tune(unit, effort)
2140 	int unit, effort;
2141 {
2142 	uint32_t x;
2143 
2144 	x = effort;
2145 	if (strioctl(pppfd, PPPIO_COMPLEV, &x, sizeof (x), 0) < 0) {
2146 		warn("unable to set compression effort level: %m");
2147 	}
2148 }
2149 #endif
2150 
2151 /*
2152  * ccp_flags_set()
2153  *
2154  * Inform kernel about the current state of CCP.
2155  */
2156 /*ARGSUSED*/
2157 void
2158 ccp_flags_set(unit, isopen, isup)
2159 	int unit, isopen, isup;
2160 {
2161 	uint32_t cf[2];
2162 
2163 	cf[0] = (isopen ? CCP_ISOPEN : 0) + (isup ? CCP_ISUP : 0);
2164 	cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR;
2165 
2166 	if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0]))
2167 	    < 0) {
2168 		if (!hungup || errno != ENXIO) {
2169 			error("Couldn't set kernel CCP state: %m");
2170 		}
2171 	}
2172 }
2173 
2174 /*
2175  * get_idle_time()
2176  *
2177  * Return how long the link has been idle.
2178  */
2179 /*ARGSUSED*/
2180 int
2181 get_idle_time(u, pids)
2182 	int u;
2183 	struct ppp_idle *pids;
2184 {
2185 	int rc;
2186 
2187 	rc = strioctl(pppfd, PPPIO_GIDLE, pids, 0, sizeof (struct ppp_idle));
2188 	if (rc < 0) {
2189 		warn("unable to obtain idle time: %m");
2190 	}
2191 	return ((rc == 0) ? 1 : 0);
2192 }
2193 
2194 /*
2195  * get_ppp_stats()
2196  *
2197  * Return statistics for the link.
2198  */
2199 /*ARGSUSED*/
2200 int
2201 get_ppp_stats(u, stats)
2202 	int u;
2203 	struct pppd_stats *stats;
2204 {
2205 	struct ppp_stats64 s64;
2206 	struct ppp_stats s;
2207 
2208 	/* Try first to get these from the 64-bit interface */
2209 	if (strioctl(pppfd, PPPIO_GETSTAT64, &s64, 0, sizeof (s64)) >= 0) {
2210 		stats->bytes_in = s64.p.ppp_ibytes;
2211 		stats->bytes_out = s64.p.ppp_obytes;
2212 		stats->pkts_in = s64.p.ppp_ipackets;
2213 		stats->pkts_out = s64.p.ppp_opackets;
2214 		return (1);
2215 	}
2216 
2217 	if (strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof (s)) < 0) {
2218 		error("Couldn't get link statistics: %m");
2219 		return (0);
2220 	}
2221 	stats->bytes_in = s.p.ppp_ibytes;
2222 	stats->bytes_out = s.p.ppp_obytes;
2223 	stats->pkts_in = s.p.ppp_ipackets;
2224 	stats->pkts_out = s.p.ppp_opackets;
2225 	return (1);
2226 }
2227 
2228 #if defined(FILTER_PACKETS)
2229 /*
2230  * set_filters()
2231  *
2232  * Transfer the pass and active filters to the kernel.
2233  */
2234 int
2235 set_filters(pass, active)
2236 	struct bpf_program *pass;
2237 	struct bpf_program *active;
2238 {
2239 	int ret = 1;
2240 
2241 	if (pass->bf_len > 0) {
2242 		if (strioctl(pppfd, PPPIO_PASSFILT, pass,
2243 		    sizeof (struct bpf_program), 0) < 0) {
2244 			error("Couldn't set pass-filter in kernel: %m");
2245 			ret = 0;
2246 		}
2247 	}
2248 	if (active->bf_len > 0) {
2249 		if (strioctl(pppfd, PPPIO_ACTIVEFILT, active,
2250 		    sizeof (struct bpf_program), 0) < 0) {
2251 			error("Couldn't set active-filter in kernel: %m");
2252 			ret = 0;
2253 		}
2254 	}
2255 	return (ret);
2256 }
2257 #endif /* FILTER_PACKETS */
2258 
2259 /*
2260  * ccp_fatal_error()
2261  *
2262  * Returns 1 if decompression was disabled as a result of an error detected
2263  * after decompression of a packet, 0 otherwise.  This is necessary because
2264  * of patent nonsense.
2265  */
2266 /*ARGSUSED*/
2267 int
2268 ccp_fatal_error(unit)
2269 	int unit;
2270 {
2271 	uint32_t cf[2];
2272 
2273 	cf[0] = cf[1] = 0;
2274 	if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0]))
2275 	    < 0) {
2276 		if (errno != ENXIO && errno != EINVAL) {
2277 			error("Couldn't get compression flags: %m");
2278 		}
2279 		return (0);
2280 	}
2281 	return (cf[0] & CCP_FATALERROR);
2282 }
2283 
2284 /*
2285  * sifvjcomp()
2286  *
2287  * Config TCP header compression.
2288  */
2289 /*ARGSUSED*/
2290 int
2291 sifvjcomp(u, vjcomp, xcidcomp, xmaxcid)
2292 	int u, vjcomp, xcidcomp, xmaxcid;
2293 {
2294 	uint32_t cf[2];
2295 	uchar_t maxcid[2];
2296 
2297 	/*
2298 	 * Since VJ compression code is in the comp module, there's no
2299 	 * point of sending down any ioctls pertaining to VJ compression
2300 	 * when the module isn't pushed on the stream.
2301 	 */
2302 	if (!any_compressions()) {
2303 		return (1);
2304 	}
2305 
2306 	if (vjcomp) {
2307 		maxcid[0] = xcidcomp;
2308 		maxcid[1] = 15;		/* XXX should be rmaxcid */
2309 
2310 		if (strioctl(pppfd, PPPIO_VJINIT, maxcid,
2311 		    sizeof (maxcid), 0) < 0) {
2312 			error("Couldn't initialize VJ compression: %m");
2313 			return (0);
2314 		}
2315 	}
2316 
2317 	cf[0] = (vjcomp ? COMP_VJC + DECOMP_VJC : 0)	/* XXX this is wrong */
2318 		+ (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0);
2319 
2320 	cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID;
2321 
2322 	if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0]))
2323 	    < 0) {
2324 		if (vjcomp) {
2325 			error("Couldn't enable VJ compression: %m");
2326 		} else {
2327 			error("Couldn't disable VJ compression: %m");
2328 		}
2329 		return (0);
2330 	}
2331 	return (1);
2332 }
2333 
2334 /*
2335  * siflags()
2336  *
2337  * Set or clear the IP interface flags.
2338  */
2339 int
2340 siflags(f, set)
2341 	u_int32_t f;
2342 	int set;
2343 {
2344 	struct ifreq ifr;
2345 
2346 	if (!IPCP_ENABLED || (ipmuxid == -1)) {
2347 		return (0);
2348 	}
2349 	if (ipfd == -1 && open_ipfd() == -1)
2350 		return (0);
2351 	BZERO(&ifr, sizeof (ifr));
2352 	(void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2353 	if (myioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
2354 		error("Couldn't get IP interface flags: %m");
2355 		return (0);
2356 	}
2357 	if (set) {
2358 		ifr.ifr_flags |= f;
2359 	} else {
2360 		ifr.ifr_flags &= ~f;
2361 	}
2362 	if (myioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
2363 		error("Couldn't set IP interface flags: %m");
2364 		return (0);
2365 	}
2366 	return (1);
2367 }
2368 
2369 /*
2370  * sifup()
2371  *
2372  * Config the interface up and enable IP packets to pass.
2373  */
2374 /*ARGSUSED*/
2375 int
2376 sifup(u)
2377 	int u;
2378 {
2379 	if (if_is_up) {
2380 		return (1);
2381 	} else if (!IPCP_ENABLED) {
2382 		warn("sifup called when IPCP is disabled");
2383 		return (0);
2384 	} else if (ipmuxid == -1) {
2385 		warn("sifup called in wrong state");
2386 		return (0);
2387 	} else if (!siflags(IFF_UP, 1)) {
2388 		error("Unable to mark the IP interface UP");
2389 		return (0);
2390 	}
2391 	if_is_up = 1;
2392 	return (1);
2393 }
2394 
2395 /*
2396  * sifdown()
2397  *
2398  * Config the interface down and disable IP.  Possibly called from die(),
2399  * so there shouldn't be any call to die() here.
2400  */
2401 /*ARGSUSED*/
2402 int
2403 sifdown(u)
2404 	int u;
2405 {
2406 	if (!IPCP_ENABLED) {
2407 		warn("sifdown called when IPCP is disabled");
2408 		return (0);
2409 	} else if (!if_is_up || (ipmuxid == -1)) {
2410 		return (1);
2411 	} else if (!siflags(IFF_UP, 0)) {
2412 		error("Unable to mark the IP interface DOWN");
2413 		return (0);
2414 	}
2415 	if_is_up = 0;
2416 	return (1);
2417 }
2418 
2419 /*
2420  * sifnpmode()
2421  *
2422  * Set the mode for handling packets for a given NP.  Not worried
2423  * about performance here since this is done only rarely.
2424  */
2425 /*ARGSUSED*/
2426 int
2427 sifnpmode(u, proto, mode)
2428 	int u;
2429 	int proto;
2430 	enum NPmode mode;
2431 {
2432 	uint32_t npi[2];
2433 	const char *cp;
2434 	static const struct npi_entry {
2435 		enum NPmode ne_value;
2436 		const char *ne_name;
2437 	} npi_list[] = {
2438 		{ NPMODE_PASS, "pass" },
2439 		{ NPMODE_DROP, "drop" },
2440 		{ NPMODE_ERROR, "error" },
2441 		{ NPMODE_QUEUE, "queue" },
2442 	};
2443 	int i;
2444 	char pname[32], mname[32];
2445 
2446 	npi[0] = proto;
2447 	npi[1] = (uint32_t)mode;
2448 
2449 	cp = protocol_name(proto);
2450 	if (cp == NULL)
2451 		(void) slprintf(pname, sizeof (pname), "NP %04X", proto);
2452 	else
2453 		(void) strlcpy(pname, cp, sizeof (pname));
2454 	for (i = 0; i < Dim(npi_list); i++)
2455 		if (npi_list[i].ne_value == mode)
2456 			break;
2457 	if (i >= Dim(npi_list))
2458 		(void) slprintf(mname, sizeof (mname), "mode %d", (int)mode);
2459 	else
2460 		(void) strlcpy(mname, npi_list[i].ne_name, sizeof (mname));
2461 
2462 	if ((proto == PPP_IP && !if_is_up) ||
2463 	    (proto == PPP_IPV6 && !if6_is_up)) {
2464 		dbglog("ignoring request to set %s to %s", pname, mname);
2465 		return (1);
2466 	}
2467 	if (strioctl(pppfd, PPPIO_NPMODE, npi, sizeof (npi), 0) < 0) {
2468 		error("unable to set %s to %s: %m", pname, mname);
2469 		return (0);
2470 	}
2471 	return (1);
2472 }
2473 
2474 /*
2475  * sifmtu()
2476  *
2477  * Config the interface IP MTU.
2478  */
2479 int
2480 sifmtu(mtu)
2481 	int mtu;
2482 {
2483 	struct ifreq ifr;
2484 
2485 	if (!IPCP_ENABLED || (ipmuxid == -1)) {
2486 		return (0);
2487 	}
2488 	if (ipfd == -1 && open_ipfd() == -1)
2489 		return (0);
2490 	BZERO(&ifr, sizeof (ifr));
2491 	(void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2492 	ifr.ifr_metric = mtu;
2493 	if (myioctl(ipfd, SIOCSIFMTU, &ifr) < 0) {
2494 		error("Couldn't set IP MTU on %s to %d: %m", ifr.ifr_name,
2495 		    mtu);
2496 		return (0);
2497 	}
2498 	return (1);
2499 }
2500 
2501 /*
2502  * sifaddr()
2503  *
2504  * Config the interface IP addresses and netmask.
2505  */
2506 /*ARGSUSED*/
2507 int
2508 sifaddr(u, o, h, m)
2509 	int u;
2510 	u_int32_t o;
2511 	u_int32_t h;
2512 	u_int32_t m;
2513 {
2514 	struct ifreq ifr;
2515 	struct sockaddr_in sin;
2516 
2517 	if (!IPCP_ENABLED || (ipmuxid == -1 && plumb_ipif(u) == 0)) {
2518 		return (0);
2519 	}
2520 	if (ipfd == -1 && open_ipfd() == -1)
2521 		return (0);
2522 	/*
2523 	 * Set the IP interface MTU.
2524 	 */
2525 	if (!sifmtu(link_mtu)) {
2526 		return (0);
2527 	}
2528 	/*
2529 	 * Set the IP interface local point-to-point address.
2530 	 */
2531 	BZERO(&sin, sizeof (sin));
2532 	sin.sin_family = AF_INET;
2533 	sin.sin_addr.s_addr = o;
2534 
2535 	BZERO(&ifr, sizeof (ifr));
2536 	(void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2537 	ifr.ifr_addr = *(struct sockaddr *)&sin;
2538 	if (myioctl(ipfd, SIOCSIFADDR, &ifr) < 0) {
2539 		error("Couldn't set local IP address (%s): %m", ifr.ifr_name);
2540 		return (0);
2541 	}
2542 	/*
2543 	 * Set the IP interface remote point-to-point address.
2544 	 */
2545 	sin.sin_addr.s_addr = h;
2546 
2547 	ifr.ifr_dstaddr = *(struct sockaddr *)&sin;
2548 	if (myioctl(ipfd, SIOCSIFDSTADDR, &ifr) < 0) {
2549 		error("Couldn't set remote IP address (%s): %m", ifr.ifr_name);
2550 		return (0);
2551 	}
2552 	remote_addr = h;
2553 	return (1);
2554 }
2555 
2556 /*
2557  * cifaddr()
2558  *
2559  * Clear the interface IP addresses.
2560  */
2561 /*ARGSUSED*/
2562 int
2563 cifaddr(u, o, h)
2564 	int u;
2565 	u_int32_t o;
2566 	u_int32_t h;
2567 {
2568 	if (!IPCP_ENABLED) {
2569 		return (0);
2570 	}
2571 	/*
2572 	 * Most of the work is done in sifdown().
2573 	 */
2574 	remote_addr = 0;
2575 	return (1);
2576 }
2577 
2578 /*
2579  * sifroute()
2580  *
2581  * Add or delete a route.
2582  */
2583 /*ARGSUSED*/
2584 static int
2585 sifroute(int u, u_int32_t l, u_int32_t g, int add, const char *str)
2586 {
2587 	struct sockaddr_in sin_dst, sin_gtw;
2588 	struct rtentry rt;
2589 
2590 	if (!IPCP_ENABLED || (ipmuxid == -1)) {
2591 		error("Can't %s route: IP is not enabled", str);
2592 		return (0);
2593 	}
2594 	if (ipfd == -1 && open_ipfd() == -1)
2595 		return (0);
2596 
2597 	BZERO(&sin_dst, sizeof (sin_dst));
2598 	sin_dst.sin_family = AF_INET;
2599 	sin_dst.sin_addr.s_addr = l;
2600 
2601 	BZERO(&sin_gtw, sizeof (sin_gtw));
2602 	sin_gtw.sin_family = AF_INET;
2603 	sin_gtw.sin_addr.s_addr = g;
2604 
2605 	BZERO(&rt, sizeof (rt));
2606 	rt.rt_dst = *(struct sockaddr *)&sin_dst;
2607 	rt.rt_gateway = *(struct sockaddr *)&sin_gtw;
2608 	rt.rt_flags = (RTF_GATEWAY|RTF_STATIC);
2609 
2610 	if (myioctl(ipfd, (add ? SIOCADDRT : SIOCDELRT), &rt) < 0) {
2611 		error("Can't %s route: %m", str);
2612 		return (0);
2613 	}
2614 	return (1);
2615 }
2616 
2617 /*
2618  * sifdefaultroute()
2619  *
2620  * Assign a default route through the address given.
2621  */
2622 /*ARGSUSED*/
2623 int
2624 sifdefaultroute(u, l, g)
2625 	int u;
2626 	u_int32_t l;
2627 	u_int32_t g;
2628 {
2629 	if (!sifroute(u, 0, g, 1, "add default")) {
2630 		return (0);
2631 	}
2632 	default_route_gateway = g;
2633 	return (1);
2634 }
2635 
2636 /*
2637  * cifdefaultroute()
2638  *
2639  * Delete a default route through the address given.
2640  */
2641 /*ARGSUSED*/
2642 int
2643 cifdefaultroute(u, l, g)
2644 	int u;
2645 	u_int32_t l;
2646 	u_int32_t g;
2647 {
2648 	if (!sifroute(u, 0, g, 0, "delete default")) {
2649 		return (0);
2650 	}
2651 	default_route_gateway = 0;
2652 	return (1);
2653 }
2654 
2655 /*
2656  * sifproxyarp()
2657  *
2658  * Make a proxy ARP entry for the peer.
2659  */
2660 /*ARGSUSED*/
2661 int
2662 sifproxyarp(unit, hisaddr, quietflag)
2663 	int unit;
2664 	u_int32_t hisaddr;
2665 	int quietflag;
2666 {
2667 	struct sockaddr_in sin;
2668 	struct xarpreq arpreq;
2669 	const uchar_t *cp;
2670 	char *str = NULL;
2671 
2672 	if (!IPCP_ENABLED || (ipmuxid == -1)) {
2673 		return (0);
2674 	}
2675 	if (ipfd == -1 && open_ipfd() == -1)
2676 		return (0);
2677 
2678 	BZERO(&sin, sizeof (sin));
2679 	sin.sin_family = AF_INET;
2680 	sin.sin_addr.s_addr = hisaddr;
2681 
2682 	BZERO(&arpreq, sizeof (arpreq));
2683 	if (!get_ether_addr(hisaddr, &arpreq.xarp_ha, quietflag)) {
2684 		return (0);
2685 	}
2686 	BCOPY(&sin, &arpreq.xarp_pa, sizeof (sin));
2687 	arpreq.xarp_flags = ATF_PERM | ATF_PUBL;
2688 	arpreq.xarp_ha.sdl_family = AF_LINK;
2689 
2690 	if (myioctl(ipfd, SIOCSXARP, (caddr_t)&arpreq) < 0) {
2691 		if (!quietflag)
2692 			error("Couldn't set proxy ARP entry: %m");
2693 		return (0);
2694 	}
2695 	cp = (const uchar_t *)LLADDR(&arpreq.xarp_ha);
2696 	str = _link_ntoa(cp, str, arpreq.xarp_ha.sdl_alen, IFT_OTHER);
2697 	if (str != NULL) {
2698 		dbglog("established proxy ARP for %I using %s", hisaddr,
2699 		    str);
2700 		free(str);
2701 	}
2702 	proxy_arp_addr = hisaddr;
2703 	return (1);
2704 }
2705 
2706 /*
2707  * cifproxyarp()
2708  *
2709  * Delete the proxy ARP entry for the peer.
2710  */
2711 /*ARGSUSED*/
2712 int
2713 cifproxyarp(unit, hisaddr)
2714 	int unit;
2715 	u_int32_t hisaddr;
2716 {
2717 	struct sockaddr_in sin;
2718 	struct xarpreq arpreq;
2719 
2720 	if (!IPCP_ENABLED || (ipmuxid == -1)) {
2721 		return (0);
2722 	}
2723 	if (ipfd == -1 && open_ipfd() == -1)
2724 		return (0);
2725 
2726 	BZERO(&sin, sizeof (sin));
2727 	sin.sin_family = AF_INET;
2728 	sin.sin_addr.s_addr = hisaddr;
2729 
2730 	BZERO(&arpreq, sizeof (arpreq));
2731 	BCOPY(&sin, &arpreq.xarp_pa, sizeof (sin));
2732 	arpreq.xarp_ha.sdl_family = AF_LINK;
2733 
2734 	if (myioctl(ipfd, SIOCDXARP, (caddr_t)&arpreq) < 0) {
2735 		error("Couldn't delete proxy ARP entry: %m");
2736 		return (0);
2737 	}
2738 	proxy_arp_addr = 0;
2739 	return (1);
2740 }
2741 
2742 /*
2743  * get_ether_addr()
2744  *
2745  * Get the hardware address of an interface on the the same subnet as
2746  * ipaddr.  This routine uses old-style interfaces for intentional
2747  * backward compatibility -- SIOCGLIF* isn't in older Solaris
2748  * releases.
2749  */
2750 static int
2751 get_ether_addr(u_int32_t ipaddr, struct sockaddr_dl *hwaddr, int quietflag)
2752 {
2753 	struct ifreq *ifr, *ifend, ifreq;
2754 	int nif, s, retv;
2755 	struct ifconf ifc;
2756 	u_int32_t ina, mask;
2757 	struct xarpreq req;
2758 	struct sockaddr_in sin;
2759 
2760 	if (ipfd == -1 && open_ipfd() == -1)
2761 		return (0);
2762 
2763 	/*
2764 	 * Scan through the system's network interfaces.
2765 	 */
2766 	if (myioctl(ipfd, SIOCGIFNUM, &nif) < 0) {
2767 		nif = MAXIFS;
2768 	}
2769 	if (nif <= 0)
2770 		return (0);
2771 	ifc.ifc_len = nif * sizeof (struct ifreq);
2772 	ifc.ifc_buf = (caddr_t)malloc(ifc.ifc_len);
2773 	if (ifc.ifc_buf == NULL) {
2774 		return (0);
2775 	}
2776 	if (myioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
2777 		error("Couldn't get system interface list: %m");
2778 		free(ifc.ifc_buf);
2779 		return (0);
2780 	}
2781 	/* LINTED */
2782 	ifend = (struct ifreq *)(ifc.ifc_buf + ifc.ifc_len);
2783 	for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
2784 		if (ifr->ifr_addr.sa_family != AF_INET) {
2785 			continue;
2786 		}
2787 		/*
2788 		 * Check that the interface is up, and not
2789 		 * point-to-point or loopback.
2790 		 */
2791 		(void) strlcpy(ifreq.ifr_name, ifr->ifr_name,
2792 			sizeof (ifreq.ifr_name));
2793 		if (myioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0) {
2794 			continue;
2795 		}
2796 		if ((ifreq.ifr_flags & (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|
2797 		    IFF_LOOPBACK|IFF_NOARP)) != (IFF_UP|IFF_BROADCAST)) {
2798 			continue;
2799 		}
2800 		/*
2801 		 * Get its netmask and check that it's on the right subnet.
2802 		 */
2803 		if (myioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0) {
2804 			continue;
2805 		}
2806 		(void) memcpy(&sin, &ifr->ifr_addr, sizeof (sin));
2807 		ina = sin.sin_addr.s_addr;
2808 		(void) memcpy(&sin, &ifreq.ifr_addr, sizeof (sin));
2809 		mask = sin.sin_addr.s_addr;
2810 		if ((ipaddr & mask) == (ina & mask)) {
2811 			break;
2812 		}
2813 	}
2814 	if (ifr >= ifend) {
2815 		if (!quietflag)
2816 			warn("No suitable interface found for proxy ARP of %I",
2817 			    ipaddr);
2818 		free(ifc.ifc_buf);
2819 		return (0);
2820 	}
2821 	info("found interface %s for proxy ARP of %I", ifr->ifr_name, ipaddr);
2822 
2823 	/*
2824 	 * New way - get the address by doing an arp request.
2825 	 */
2826 	s = socket(AF_INET, SOCK_DGRAM, 0);
2827 	if (s < 0) {
2828 		error("get_ether_addr: error opening IP socket: %m");
2829 		free(ifc.ifc_buf);
2830 		return (0);
2831 	}
2832 	BZERO(&sin, sizeof (sin));
2833 	sin.sin_family = AF_INET;
2834 	sin.sin_addr.s_addr = ina;
2835 
2836 	BZERO(&req, sizeof (req));
2837 	BCOPY(&sin, &req.xarp_pa, sizeof (sin));
2838 	req.xarp_ha.sdl_family = AF_LINK;
2839 
2840 	if (myioctl(s, SIOCGXARP, &req) < 0) {
2841 		error("Couldn't get ARP entry for %I: %m", ina);
2842 		retv = 0;
2843 	} else {
2844 		(void) memcpy(hwaddr, &req.xarp_ha,
2845 		    sizeof (struct sockaddr_dl));
2846 		retv = 1;
2847 	}
2848 	(void) close(s);
2849 	free(ifc.ifc_buf);
2850 	return (retv);
2851 }
2852 
2853 /*
2854  * dlpi_attach()
2855  *
2856  * Send down DL_ATTACH_REQ to driver.
2857  */
2858 static int
2859 dlpi_attach(int fd, int ppa)
2860 {
2861 	dl_attach_req_t	req;
2862 	struct strbuf buf;
2863 
2864 	if (fd < 0) {
2865 		return (-1);
2866 	}
2867 	BZERO(&req, sizeof (req));
2868 	req.dl_primitive = DL_ATTACH_REQ;
2869 	req.dl_ppa = ppa;
2870 
2871 	buf.len = sizeof (req);
2872 	buf.buf = (void *) &req;
2873 
2874 	return (putmsg(fd, &buf, NULL, RS_HIPRI));
2875 }
2876 
2877 /*
2878  * dlpi_info_req()
2879  *
2880  * Send down DL_INFO_REQ to driver.
2881  */
2882 static int
2883 dlpi_info_req(int fd)
2884 {
2885 	dl_info_req_t req;
2886 	struct strbuf buf;
2887 
2888 	if (fd < 0) {
2889 		return (-1);
2890 	}
2891 	BZERO(&req, sizeof (req));
2892 	req.dl_primitive = DL_INFO_REQ;
2893 
2894 	buf.len = sizeof (req);
2895 	buf.buf = (void *) &req;
2896 
2897 	return (putmsg(fd, &buf, NULL, RS_HIPRI));
2898 }
2899 
2900 /*
2901  * dlpi_get_reply()
2902  *
2903  * Poll to get DLPI reply message from driver.
2904  */
2905 static int
2906 dlpi_get_reply(int fd, union DL_primitives *reply, int expected_prim,
2907     int maxlen)
2908 {
2909 	struct strbuf buf;
2910 	struct pollfd pfd;
2911 	int flags;
2912 	int n;
2913 
2914 	if (fd < 0) {
2915 		return (-1);
2916 	}
2917 	/*
2918 	 * Use poll to wait for a message with a timeout.
2919 	 */
2920 	pfd.fd = fd;
2921 	pfd.events = (POLLIN | POLLPRI);
2922 
2923 	do {
2924 		n = poll(&pfd, 1, 1000);
2925 	} while ((n == -1) && (errno == EINTR));
2926 
2927 	if (n <= 0) {
2928 		return (-1);
2929 	}
2930 	/*
2931 	 * Get the reply.
2932 	 */
2933 	buf.maxlen = maxlen;
2934 	buf.buf = (void *)reply;
2935 
2936 	flags = 0;
2937 
2938 	if (getmsg(fd, &buf, NULL, &flags) < 0) {
2939 		return (-1);
2940 	}
2941 	if (buf.len < sizeof (ulong_t)) {
2942 		if (debug) {
2943 			dbglog("dlpi response short (len=%d)\n", buf.len);
2944 		}
2945 		return (-1);
2946 	}
2947 	if (reply->dl_primitive == expected_prim) {
2948 		return (0);
2949 	}
2950 	if (debug) {
2951 		if (reply->dl_primitive == DL_ERROR_ACK) {
2952 			dbglog("dlpi error %d (unix errno %d) for prim %x\n",
2953 			    reply->error_ack.dl_errno,
2954 			    reply->error_ack.dl_unix_errno,
2955 			    reply->error_ack.dl_error_primitive);
2956 		} else {
2957 			dbglog("dlpi unexpected response prim %x\n",
2958 			    reply->dl_primitive);
2959 		}
2960 	}
2961 	return (-1);
2962 }
2963 
2964 /*
2965  * GetMask()
2966  *
2967  * Return mask (bogus, but needed for compatibility with other platforms).
2968  */
2969 /*ARGSUSED*/
2970 u_int32_t
2971 GetMask(addr)
2972 	u_int32_t addr;
2973 {
2974 	return (0xffffffffUL);
2975 }
2976 
2977 /*
2978  * logwtmp()
2979  *
2980  * Write an accounting record to the /var/adm/wtmp file.
2981  */
2982 /*ARGSUSED*/
2983 void
2984 logwtmp(line, name, host)
2985 	const char *line;
2986 	const char *name;
2987 	const char *host;
2988 {
2989 	static struct utmpx utmpx;
2990 
2991 	if (name[0] != '\0') {
2992 		/*
2993 		 * logging in
2994 		 */
2995 		(void) strncpy(utmpx.ut_user, name, sizeof (utmpx.ut_user));
2996 		(void) strncpy(utmpx.ut_id, ifname, sizeof (utmpx.ut_id));
2997 		(void) strncpy(utmpx.ut_line, line, sizeof (utmpx.ut_line));
2998 
2999 		utmpx.ut_pid = getpid();
3000 		utmpx.ut_type = USER_PROCESS;
3001 	} else {
3002 		utmpx.ut_type = DEAD_PROCESS;
3003 	}
3004 	(void) gettimeofday(&utmpx.ut_tv, NULL);
3005 	updwtmpx("/var/adm/wtmpx", &utmpx);
3006 }
3007 
3008 /*
3009  * get_host_seed()
3010  *
3011  * Return the serial number of this machine.
3012  */
3013 int
3014 get_host_seed()
3015 {
3016 	char buf[32];
3017 
3018 	if (sysinfo(SI_HW_SERIAL, buf, sizeof (buf)) < 0) {
3019 		error("sysinfo: %m");
3020 		return (0);
3021 	}
3022 	return ((int)strtoul(buf, NULL, 16));
3023 }
3024 
3025 /*
3026  * strioctl()
3027  *
3028  * Wrapper for STREAMS I_STR ioctl.  Masks out EINTR from caller.
3029  */
3030 static int
3031 strioctl(int fd, int cmd, void *ptr, int ilen, int olen)
3032 {
3033 	struct strioctl	str;
3034 
3035 	str.ic_cmd = cmd;
3036 	str.ic_timout = PPPSTRTIMOUT;
3037 	str.ic_len = ilen;
3038 	str.ic_dp = ptr;
3039 
3040 	if (myioctl(fd, I_STR, &str) == -1) {
3041 		return (-1);
3042 	}
3043 	if (str.ic_len != olen) {
3044 		dbglog("strioctl: expected %d bytes, got %d for cmd %x\n",
3045 		    olen, str.ic_len, cmd);
3046 	}
3047 	return (0);
3048 }
3049 
3050 /*
3051  * have_route_to()
3052  *
3053  * Determine if the system has a route to the specified IP address.
3054  * Returns 0 if not, 1 if so, -1 if we can't tell. `addr' is in network
3055  * byte order. For demand mode to work properly, we have to ignore routes
3056  * through our own interface. XXX Would be nice to use routing socket.
3057  */
3058 int
3059 have_route_to(addr)
3060 	u_int32_t addr;
3061 {
3062 	int r, flags, i;
3063 	struct {
3064 		struct T_optmgmt_req req;
3065 		struct opthdr hdr;
3066 	} req;
3067 	union {
3068 		struct T_optmgmt_ack ack;
3069 		unsigned char space[64];
3070 	} ack;
3071 	struct opthdr *rh;
3072 	struct strbuf cbuf, dbuf;
3073 	int nroutes;
3074 	mib2_ipRouteEntry_t routes[8];
3075 	mib2_ipRouteEntry_t *rp;
3076 
3077 	if (ipfd == -1 && open_ipfd() == -1)
3078 		return (0);
3079 
3080 	req.req.PRIM_type = T_OPTMGMT_REQ;
3081 	req.req.OPT_offset = (caddr_t)&req.hdr - (caddr_t)&req;
3082 	req.req.OPT_length = sizeof (req.hdr);
3083 #ifdef T_CURRENT
3084 	req.req.MGMT_flags = T_CURRENT;
3085 #else
3086 	/* Old-style */
3087 	req.req.MGMT_flags = T_CHECK;
3088 #endif
3089 
3090 	req.hdr.level = MIB2_IP;
3091 	req.hdr.name = 0;
3092 	req.hdr.len = 0;
3093 
3094 	cbuf.buf = (caddr_t)&req;
3095 	cbuf.len = sizeof (req);
3096 
3097 	if (putmsg(ipfd, &cbuf, NULL, 0) == -1) {
3098 		warn("have_route_to: putmsg: %m");
3099 		return (-1);
3100 	}
3101 
3102 	for (;;) {
3103 		cbuf.buf = (caddr_t)&ack;
3104 		cbuf.maxlen = sizeof (ack);
3105 		dbuf.buf = (caddr_t)routes;
3106 		dbuf.maxlen = sizeof (routes);
3107 		flags = 0;
3108 		r = getmsg(ipfd, &cbuf, &dbuf, &flags);
3109 		if (r == -1) {
3110 			warn("have_route_to: getmsg: %m");
3111 			return (-1);
3112 		}
3113 
3114 		if (cbuf.len < sizeof (struct T_optmgmt_ack) ||
3115 		    ack.ack.PRIM_type != T_OPTMGMT_ACK ||
3116 		    ack.ack.MGMT_flags != T_SUCCESS ||
3117 		    ack.ack.OPT_length < sizeof (struct opthdr)) {
3118 			dbglog("have_route_to: bad message len=%d prim=%d",
3119 			    cbuf.len, ack.ack.PRIM_type);
3120 			return (-1);
3121 		}
3122 		/* LINTED */
3123 		rh = (struct opthdr *)((caddr_t)&ack + ack.ack.OPT_offset);
3124 		if (rh->level == 0 && rh->name == 0) {
3125 			break;
3126 		}
3127 		if (rh->level != MIB2_IP || rh->name != MIB2_IP_21) {
3128 			while (r == MOREDATA) {
3129 				r = getmsg(ipfd, NULL, &dbuf, &flags);
3130 			}
3131 			continue;
3132 		}
3133 
3134 		/*
3135 		 * Note that we have to skip routes to our own
3136 		 * interface in order for demand dial to work.
3137 		 *
3138 		 * XXX awful hack here.  We don't know our own
3139 		 * ifIndex, so we can't check ipRouteIfIndex here.
3140 		 * Instead, we check the next hop address.
3141 		 */
3142 		for (;;) {
3143 			nroutes = dbuf.len / sizeof (mib2_ipRouteEntry_t);
3144 			for (rp = routes, i = 0; i < nroutes; ++i, ++rp) {
3145 				if (rp->ipRouteNextHop != remote_addr &&
3146 				    ((addr ^ rp->ipRouteDest) &
3147 					rp->ipRouteMask) == 0) {
3148 					dbglog("have route to %I/%I via %I",
3149 					    rp->ipRouteDest,
3150 					    rp->ipRouteMask,
3151 					    rp->ipRouteNextHop);
3152 					return (1);
3153 				}
3154 			}
3155 			if (r == 0) {
3156 				break;
3157 			}
3158 			r = getmsg(ipfd, NULL, &dbuf, &flags);
3159 		}
3160 	}
3161 	return (0);
3162 }
3163 
3164 /*
3165  * get_pty()
3166  *
3167  * Get a pty master/slave pair and chown the slave side to the uid given.
3168  * Assumes slave_name points to MAXPATHLEN bytes of space.
3169  */
3170 int
3171 get_pty(master_fdp, slave_fdp, slave_name, uid)
3172 	int *master_fdp;
3173 	int *slave_fdp;
3174 	char *slave_name;
3175 	int uid;
3176 {
3177 	int mfd;
3178 	int sfd;
3179 	char *pty_name;
3180 
3181 	mfd = open("/dev/ptmx", O_NOCTTY | O_RDWR);
3182 	if (mfd < 0) {
3183 		error("Couldn't open pty master: %m");
3184 		return (0);
3185 	}
3186 	pty_name = ptsname(mfd);
3187 	if (pty_name == NULL) {
3188 		dbglog("Didn't get pty slave name on first try; sleeping.");
3189 		/* In case "grow" operation is in progress; try again. */
3190 		(void) sleep(1);
3191 		pty_name = ptsname(mfd);
3192 	}
3193 	if (pty_name == NULL) {
3194 		error("Couldn't get name of pty slave");
3195 		(void) close(mfd);
3196 		return (0);
3197 	}
3198 	if (chown(pty_name, uid, -1) < 0) {
3199 		warn("Couldn't change owner of pty slave: %m");
3200 	}
3201 	if (chmod(pty_name, S_IRUSR | S_IWUSR) < 0) {
3202 		warn("Couldn't change permissions on pty slave: %m");
3203 	}
3204 	if (unlockpt(mfd) < 0) {
3205 		warn("Couldn't unlock pty slave: %m");
3206 	}
3207 	sfd = open(pty_name, O_RDWR);
3208 	if (sfd < 0) {
3209 		error("Couldn't open pty slave %s: %m", pty_name);
3210 		(void) close(mfd);
3211 		return (0);
3212 	}
3213 	if (myioctl(sfd, I_PUSH, "ptem") < 0) {
3214 		warn("Couldn't push ptem module on pty slave: %m");
3215 	}
3216 	dbglog("Using %s; master fd %d, slave fd %d", pty_name, mfd, sfd);
3217 
3218 	(void) strlcpy(slave_name, pty_name, MAXPATHLEN);
3219 
3220 	*master_fdp = mfd;
3221 	*slave_fdp = sfd;
3222 
3223 	return (1);
3224 }
3225 
3226 #ifdef INET6
3227 static int
3228 open_udp6fd(void)
3229 {
3230 	int udp6fd;
3231 
3232 	udp6fd = open(UDP6_DEV_NAME, O_RDWR | O_NONBLOCK, 0);
3233 	if (udp6fd < 0) {
3234 		error("Couldn't open UDPv6 device (%s): %m", UDP6_DEV_NAME);
3235 	}
3236 	return (udp6fd);
3237 }
3238 
3239 /*
3240  * plumb_ip6if()
3241  *
3242  * Perform IPv6 interface plumbing.
3243  */
3244 /*ARGSUSED*/
3245 static int
3246 plumb_ip6if(int unit)
3247 {
3248 	int udp6fd = -1, tmpfd;
3249 	uint32_t x;
3250 	struct lifreq lifr;
3251 
3252 	if (!IPV6CP_ENABLED || (ifunit == -1) || (pppfd == -1)) {
3253 		return (0);
3254 	}
3255 	if (plumbed)
3256 		return (1);
3257 	if (ip6fd == -1 && open_ip6fd() == -1)
3258 		return (0);
3259 	if (use_plink && (udp6fd = open_udp6fd()) == -1)
3260 		return (0);
3261 	tmpfd = open(drvnam, O_RDWR | O_NONBLOCK, 0);
3262 	if (tmpfd < 0) {
3263 		error("Couldn't open PPP device (%s): %m", drvnam);
3264 		if (udp6fd != -1)
3265 			(void) close(udp6fd);
3266 		return (0);
3267 	}
3268 	if (kdebugflag & 1) {
3269 		x = PPPDBG_LOG + PPPDBG_DRIVER;
3270 		if (strioctl(tmpfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) {
3271 			warn("PPPIO_DEBUG ioctl for mux failed: %m");
3272 		}
3273 	}
3274 	if (myioctl(tmpfd, I_PUSH, IP_MOD_NAME) < 0) {
3275 		error("Couldn't push IP module(%s): %m", IP_MOD_NAME);
3276 		goto err_ret;
3277 	}
3278 	/*
3279 	 * Sets interface ppa and flags (refer to comments in plumb_ipif for
3280 	 * the IF_UNITSEL ioctl). In addition, the IFF_IPV6 bit must be set in
3281 	 * order to declare this as an IPv6 interface.
3282 	 */
3283 	BZERO(&lifr, sizeof (lifr));
3284 	if (myioctl(tmpfd, SIOCGLIFFLAGS, &lifr) < 0) {
3285 		error("Couldn't get IPv6 interface flags: %m");
3286 		goto err_ret;
3287 	}
3288 	lifr.lifr_flags |= IFF_IPV6;
3289 	lifr.lifr_flags &= ~(IFF_BROADCAST | IFF_IPV4);
3290 	lifr.lifr_ppa = ifunit;
3291 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
3292 	if (myioctl(tmpfd, SIOCSLIFNAME, &lifr) < 0) {
3293 		error("Can't set ifname for unit %d: %m", ifunit);
3294 		goto err_ret;
3295 	}
3296 	if (use_plink) {
3297 		ip6muxid = myioctl(udp6fd, I_PLINK, (void *)tmpfd);
3298 		if (ip6muxid < 0) {
3299 			error("Can't I_PLINK PPP device to IPv6: %m");
3300 			goto err_ret;
3301 		}
3302 	} else {
3303 		ip6muxid = myioctl(ip6fd, I_LINK, (void *)tmpfd);
3304 		if (ip6muxid < 0) {
3305 			error("Can't I_LINK PPP device to IPv6: %m");
3306 			goto err_ret;
3307 		}
3308 	}
3309 	lifr.lifr_ip_muxid = ip6muxid;
3310 	lifr.lifr_arp_muxid = -1;
3311 	if (myioctl(ip6fd, SIOCSLIFMUXID, (caddr_t)&lifr) < 0) {
3312 		error("Can't set mux ID:  SIOCSLIFMUXID: %m");
3313 		goto err_ret;
3314 	}
3315 	(void) close(tmpfd);
3316 	if (udp6fd != -1)
3317 		(void) close(udp6fd);
3318 	return (1);
3319 
3320 err_ret:
3321 	(void) close(tmpfd);
3322 	if (udp6fd != -1)
3323 		(void) close(udp6fd);
3324 	return (0);
3325 }
3326 
3327 /*
3328  * unplumb_ip6if()
3329  *
3330  * Perform IPv6 interface unplumbing.  Possibly called from die(), so there
3331  * shouldn't be any call to die() here.
3332  */
3333 static int
3334 unplumb_ip6if(int unit)
3335 {
3336 	int udp6fd = -1, fd = -1;
3337 	int id;
3338 	struct lifreq lifr;
3339 
3340 	if (!IPV6CP_ENABLED || ifunit == -1) {
3341 		return (0);
3342 	}
3343 	if (!plumbed && (ip6muxid == -1 || (ip6fd == -1 && !use_plink))) {
3344 		return (1);
3345 	}
3346 	id = ip6muxid;
3347 	if (!plumbed && use_plink) {
3348 		if ((udp6fd = open_udp6fd()) == -1)
3349 			return (0);
3350 		/*
3351 		 * Note: must re-get mux ID, since any intervening
3352 		 * ifconfigs will change this.
3353 		 */
3354 		BZERO(&lifr, sizeof (lifr));
3355 		(void) strlcpy(lifr.lifr_name, ifname,
3356 		    sizeof (lifr.lifr_name));
3357 		if (myioctl(ip6fd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) {
3358 			warn("Can't get mux fd: SIOCGLIFMUXID: %m");
3359 		} else {
3360 			id = lifr.lifr_ip_muxid;
3361 			fd = myioctl(udp6fd, _I_MUXID2FD, (void *)id);
3362 			if (fd < 0) {
3363 				warn("Can't get mux fd: _I_MUXID2FD: %m");
3364 			}
3365 		}
3366 	}
3367 	/*
3368 	 * Mark down and unlink the IPv6 interface.
3369 	 */
3370 	(void) sif6down(unit);
3371 	if (plumbed)
3372 		return (1);
3373 	ip6muxid = -1;
3374 	if (use_plink) {
3375 		if ((fd = myioctl(udp6fd, _I_MUXID2FD, (void *)id)) < 0) {
3376 			error("Can't recapture mux fd: _I_MUXID2FD: %m");
3377 			(void) close(udp6fd);
3378 			return (0);
3379 		}
3380 		if (myioctl(udp6fd, I_PUNLINK, (void *)id) < 0) {
3381 			error("Can't I_PUNLINK PPP from IPv6: %m");
3382 			(void) close(fd);
3383 			(void) close(udp6fd);
3384 			return (0);
3385 		}
3386 		(void) close(fd);
3387 		(void) close(udp6fd);
3388 	} else {
3389 		if (myioctl(ip6fd, I_UNLINK, (void *)id) < 0) {
3390 			error("Can't I_UNLINK PPP from IPv6: %m");
3391 			return (0);
3392 		}
3393 	}
3394 	return (1);
3395 }
3396 
3397 /*
3398  * sif6flags()
3399  *
3400  * Set or clear the IPv6 interface flags.
3401  */
3402 int
3403 sif6flags(f, set)
3404 	u_int32_t f;
3405 	int set;
3406 {
3407 	struct lifreq lifr;
3408 	int fd;
3409 
3410 	if (!IPV6CP_ENABLED || (ip6muxid == -1)) {
3411 		return (0);
3412 	}
3413 	fd = socket(AF_INET6, SOCK_DGRAM, 0);
3414 	if (fd < 0) {
3415 		error("sif6flags: error opening IPv6 socket: %m");
3416 		return (0);
3417 	}
3418 	BZERO(&lifr, sizeof (lifr));
3419 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
3420 	if (myioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
3421 		error("Couldn't get IPv6 interface flags: %m");
3422 		(void) close(fd);
3423 		return (0);
3424 	}
3425 	if (set) {
3426 		lifr.lifr_flags |= f;
3427 	} else {
3428 		lifr.lifr_flags &= ~f;
3429 	}
3430 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
3431 	if (myioctl(fd, SIOCSLIFFLAGS, &lifr) < 0) {
3432 		error("Couldn't set IPv6 interface flags: %m");
3433 		(void) close(fd);
3434 		return (0);
3435 	}
3436 	(void) close(fd);
3437 	return (1);
3438 }
3439 
3440 /*
3441  * sif6up()
3442  *
3443  * Config the IPv6 interface up and enable IPv6 packets to pass.
3444  */
3445 /*ARGSUSED*/
3446 int
3447 sif6up(unit)
3448 	int unit;
3449 {
3450 	if (if6_is_up) {
3451 		return (1);
3452 	} else if (!IPV6CP_ENABLED) {
3453 		warn("sif6up called when IPV6CP is disabled");
3454 		return (0);
3455 	} else if (ip6muxid == -1) {
3456 		warn("sif6up called in wrong state");
3457 		return (0);
3458 	} else if (!sif6flags(IFF_UP, 1)) {
3459 		error("Unable to mark the IPv6 interface UP");
3460 		return (0);
3461 	}
3462 	if6_is_up = 1;
3463 	return (1);
3464 }
3465 
3466 /*
3467  * sif6down()
3468  *
3469  * Config the IPv6 interface down and disable IPv6.  Possibly called from
3470  * die(), so there shouldn't be any call to die() here.
3471  */
3472 /*ARGSUSED*/
3473 int
3474 sif6down(unit)
3475 	int unit;
3476 {
3477 	if (!IPV6CP_ENABLED) {
3478 		warn("sif6down called when IPV6CP is disabled");
3479 		return (0);
3480 	} else if (!if6_is_up || (ip6muxid == -1)) {
3481 		return (1);
3482 	} else if (!sif6flags(IFF_UP, 0)) {
3483 		error("Unable to mark the IPv6 interface DOWN");
3484 		return (0);
3485 	}
3486 	if6_is_up = 0;
3487 	return (1);
3488 }
3489 
3490 /*
3491  * sif6mtu()
3492  *
3493  * Config the IPv6 interface MTU.
3494  */
3495 int
3496 sif6mtu(mtu)
3497 	int mtu;
3498 {
3499 	struct lifreq lifr;
3500 	int s;
3501 
3502 	if (!IPV6CP_ENABLED || (ip6muxid == -1)) {
3503 		return (0);
3504 	}
3505 	s = socket(AF_INET6, SOCK_DGRAM, 0);
3506 	if (s < 0) {
3507 		error("sif6mtu: error opening IPv6 socket: %m");
3508 		return (0);
3509 	}
3510 	BZERO(&lifr, sizeof (lifr));
3511 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
3512 	lifr.lifr_mtu = mtu;
3513 	if (myioctl(s, SIOCSLIFMTU, &lifr) < 0) {
3514 		error("Couldn't set IPv6 MTU (%s): %m", lifr.lifr_name);
3515 		(void) close(s);
3516 		return (0);
3517 	}
3518 	(void) close(s);
3519 	return (1);
3520 }
3521 
3522 /*
3523  * sif6addr()
3524  *
3525  * Config the interface with an IPv6 link-local address.
3526  */
3527 /*ARGSUSED*/
3528 int
3529 sif6addr(unit, ourid, hisid)
3530 	int unit;
3531 	eui64_t ourid;
3532 	eui64_t hisid;
3533 {
3534 	struct lifreq lifr;
3535 	struct sockaddr_storage	laddr;
3536 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&laddr;
3537 	int fd;
3538 
3539 	if (!IPV6CP_ENABLED || (ip6muxid == -1 && plumb_ip6if(unit) == 0)) {
3540 		return (0);
3541 	}
3542 	fd = socket(AF_INET6, SOCK_DGRAM, 0);
3543 	if (fd < 0) {
3544 		error("sif6addr: error opening IPv6 socket: %m");
3545 		return (0);
3546 	}
3547 	/*
3548 	 * Set the IPv6 interface MTU.
3549 	 */
3550 	if (!sif6mtu(link_mtu)) {
3551 		(void) close(fd);
3552 		return (0);
3553 	}
3554 	/*
3555 	 * Set the interface address token.  Do this because /dev/ppp responds
3556 	 * to DL_PHYS_ADDR_REQ with zero values, hence the interface token
3557 	 * came to be zero too, and without this, in.ndpd will complain.
3558 	 */
3559 	BZERO(&lifr, sizeof (lifr));
3560 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
3561 	BZERO(sin6, sizeof (struct sockaddr_in6));
3562 	IN6_LLTOKEN_FROM_EUI64(lifr, sin6, ourid);
3563 	if (myioctl(fd, SIOCSLIFTOKEN, &lifr) < 0) {
3564 		error("Couldn't set IPv6 token (%s): %m", lifr.lifr_name);
3565 		(void) close(fd);
3566 		return (0);
3567 	}
3568 	/*
3569 	 * Set the IPv6 interface local point-to-point address.
3570 	 */
3571 	IN6_LLADDR_FROM_EUI64(lifr, sin6, ourid);
3572 	if (myioctl(fd, SIOCSLIFADDR, &lifr) < 0) {
3573 		error("Couldn't set local IPv6 address (%s): %m",
3574 		    lifr.lifr_name);
3575 		(void) close(fd);
3576 		return (0);
3577 	}
3578 	/*
3579 	 * Set the IPv6 interface local point-to-point address.
3580 	 */
3581 	BZERO(&lifr, sizeof (lifr));
3582 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
3583 	IN6_LLADDR_FROM_EUI64(lifr, sin6, hisid);
3584 	if (myioctl(fd, SIOCSLIFDSTADDR, &lifr) < 0) {
3585 		error("Couldn't set remote IPv6 address (%s): %m",
3586 		    lifr.lifr_name);
3587 		(void) close(fd);
3588 		return (0);
3589 	}
3590 	(void) close(fd);
3591 	return (1);
3592 }
3593 
3594 /*
3595  * cif6addr()
3596  */
3597 /*ARGSUSED*/
3598 int
3599 cif6addr(u, o, h)
3600 	int u;
3601 	eui64_t o;
3602 	eui64_t h;
3603 {
3604 	if (!IPV6CP_ENABLED) {
3605 		return (0);
3606 	}
3607 	/*
3608 	 * Do nothing here, as everything has been done in sif6down().
3609 	 */
3610 	return (1);
3611 }
3612 
3613 /*
3614  * ether_to_eui64()
3615  *
3616  * Convert 48-bit Ethernet address into 64-bit EUI. Walks the list of valid
3617  * ethernet interfaces, and convert the first found 48-bit MAC address into
3618  * EUI 64. caller also assumes that the system has a properly configured
3619  * Ethernet interface for this function to return non-zero.
3620  */
3621 int
3622 ether_to_eui64(p_eui64)
3623 	eui64_t *p_eui64;
3624 {
3625 	struct ether_addr eth_addr;
3626 
3627 	if (p_eui64 == NULL) {
3628 		return (0);
3629 	}
3630 	if (!get_first_hwaddr(eth_addr.ether_addr_octet,
3631 	    sizeof (eth_addr.ether_addr_octet))) {
3632 		return (0);
3633 	}
3634 	/*
3635 	 * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1]
3636 	 */
3637 	p_eui64->e8[0] = (eth_addr.ether_addr_octet[0] & 0xFF) | 0x02;
3638 	p_eui64->e8[1] = (eth_addr.ether_addr_octet[1] & 0xFF);
3639 	p_eui64->e8[2] = (eth_addr.ether_addr_octet[2] & 0xFF);
3640 	p_eui64->e8[3] = 0xFF;
3641 	p_eui64->e8[4] = 0xFE;
3642 	p_eui64->e8[5] = (eth_addr.ether_addr_octet[3] & 0xFF);
3643 	p_eui64->e8[6] = (eth_addr.ether_addr_octet[4] & 0xFF);
3644 	p_eui64->e8[7] = (eth_addr.ether_addr_octet[5] & 0xFF);
3645 	return (1);
3646 }
3647 #endif /* INET6 */
3648 
3649 struct bit_ent {
3650 	int val;
3651 	char *off, *on;
3652 };
3653 
3654 /* see sbuf[] below if you change this list */
3655 static struct bit_ent bit_list[] = {
3656 	{ TIOCM_DTR, "dtr", "DTR" },
3657 	{ TIOCM_RTS, "rts", "RTS" },
3658 	{ TIOCM_CTS, "cts", "CTS" },
3659 	{ TIOCM_CD, "dcd", "DCD" },
3660 	{ TIOCM_RI, "ri", "RI" },
3661 	{ TIOCM_DSR, "dsr", "DSR" },
3662 #if 0
3663 	{ TIOCM_LE, "disabled", "ENABLED" },
3664 	{ TIOCM_ST, NULL, "2nd-XMIT" },
3665 	{ TIOCM_SR, NULL, "2nd-RECV" },
3666 #endif
3667 	{ 0, NULL, NULL }
3668 };
3669 
3670 static void
3671 getbits(int fd, char *name, FILE *strptr)
3672 {
3673 	int nmods, i;
3674 	struct str_list strlist;
3675 	struct bit_ent *be;
3676 	int mstate;
3677 	char sbuf[50];		/* sum of string lengths in bit_list */
3678 	char *str;
3679 
3680 	nmods = ioctl(fd, I_LIST, NULL);
3681 	if (nmods < 0) {
3682 		error("unable to get module count: %m");
3683 	} else {
3684 		strlist.sl_nmods = nmods;
3685 		strlist.sl_modlist = malloc(sizeof (struct str_mlist) * nmods);
3686 		if (strlist.sl_modlist == NULL)
3687 			novm("module list");
3688 		if (ioctl(fd, I_LIST, (caddr_t)&strlist) < 0) {
3689 			error("unable to get module names: %m");
3690 		} else {
3691 			for (i = 0; i < strlist.sl_nmods; i++)
3692 				(void) flprintf(strptr, "%d: %s", i,
3693 				    strlist.sl_modlist[i].l_name);
3694 			free(strlist.sl_modlist);
3695 		}
3696 	}
3697 	if (ioctl(fd, TIOCMGET, &mstate) < 0) {
3698 		error("unable to get modem state: %m");
3699 	} else {
3700 		sbuf[0] = '\0';
3701 		for (be = bit_list; be->val != 0; be++) {
3702 			str = (be->val & mstate) ? be->on : be->off;
3703 			if (str != NULL) {
3704 				if (sbuf[0] != '\0')
3705 					(void) strcat(sbuf, " ");
3706 				(void) strcat(sbuf, str);
3707 			}
3708 		}
3709 		(void) flprintf(strptr, "%s: %s\n", name, sbuf);
3710 	}
3711 }
3712 
3713 /*
3714  * Print state of serial link.  The stream might be linked under the
3715  * /dev/sppp driver.  If it is, then it's necessary to unlink it first
3716  * and relink it when done.  Otherwise, it's not possible to use
3717  * ioctl() on the stream.
3718  */
3719 void
3720 sys_print_state(FILE *strptr)
3721 {
3722 	bool was_linked;
3723 
3724 	if (pppfd == -1)
3725 		return;
3726 	if (ttyfd == -1) {
3727 		(void) flprintf(strptr, "serial link is not active");
3728 		return;
3729 	}
3730 	was_linked = fdmuxid != -1;
3731 	if (was_linked && ioctl(pppfd, I_UNLINK, fdmuxid) == -1) {
3732 		error("I_UNLINK: %m");
3733 	} else {
3734 		fdmuxid = -1;
3735 		getbits(ttyfd, devnam, strptr);
3736 		if (was_linked &&
3737 		    (fdmuxid = ioctl(pppfd, I_LINK, (void *)ttyfd)) == -1)
3738 			fatal("I_LINK: %m");
3739 	}
3740 }
3741 
3742 /*
3743  * send ioctl to driver asking it to block packets with network protocol
3744  * proto in the control queue until the queue for proto is plumbed.
3745  */
3746 void
3747 sys_block_proto(uint16_t proto)
3748 {
3749 	if (proto > 0x7fff) {
3750 		warn("cannot block: not a network proto 0x%lx\n", proto);
3751 		return;
3752 	}
3753 	if (strioctl(pppfd, PPPIO_BLOCKNP, &proto, sizeof (proto), 0) < 0) {
3754 		warn("PPPIO_BLOCKNP ioctl failed %m");
3755 	}
3756 }
3757 /*
3758  * send ioctl to driver asking it to release packets with network protocol
3759  * proto from control queue to the protocol specific queue.
3760  */
3761 void
3762 sys_unblock_proto(uint16_t proto)
3763 {
3764 	if (proto > 0x7fff) {
3765 		warn("cannot unblock: not a network proto 0x%lx\n", proto);
3766 		return;
3767 	}
3768 	if (strioctl(pppfd, PPPIO_UNBLOCKNP, &proto, sizeof (proto), 0) < 0) {
3769 		warn("PPPIO_UNBLOCKNP ioctl failed %m");
3770 	}
3771 }
3772