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