xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.bin/pppd/sys-solaris.c (revision 74a8d72a557428e11e39b309193987d43fc7d66e)
1 /*
2  * System-dependent procedures for pppd under Solaris 2.x (SunOS 5.x).
3  *
4  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
5  * Use is subject to license terms.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation is hereby granted, provided that the above copyright
9  * notice appears in all copies.
10  *
11  * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
12  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
13  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT.  SUN SHALL NOT BE LIABLE FOR
15  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
16  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
17  *
18  * Copyright (c) 1994 The Australian National University.
19  * All rights reserved.
20  *
21  * Permission to use, copy, modify, and distribute this software and its
22  * documentation is hereby granted, provided that the above copyright
23  * notice appears in all copies.  This software is provided without any
24  * warranty, express or implied. The Australian National University
25  * makes no representations about the suitability of this software for
26  * any purpose.
27  *
28  * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
29  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
30  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
31  * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
32  * OF SUCH DAMAGE.
33  *
34  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
36  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
37  * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
38  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
39  * OR MODIFICATIONS.
40  */
41 
42 #pragma ident	"%Z%%M%	%I%	%E% SMI"
43 #define	RCSID	"$Id: sys-solaris.c,v 1.2 2000/04/21 01:27:57 masputra Exp $"
44 
45 #include <limits.h>
46 #include <stdio.h>
47 #include <stddef.h>
48 #include <stdlib.h>
49 #include <ctype.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <unistd.h>
53 #include <netdb.h>
54 #include <termios.h>
55 #include <signal.h>
56 #include <string.h>
57 #include <stropts.h>
58 #include <utmpx.h>
59 #include <sys/types.h>
60 #include <sys/ioccom.h>
61 #include <sys/stream.h>
62 #include <sys/stropts.h>
63 #include <sys/socket.h>
64 #include <sys/sockio.h>
65 #include <sys/sysmacros.h>
66 #include <sys/systeminfo.h>
67 #include <sys/stat.h>
68 #include <net/if.h>
69 #include <net/if_arp.h>
70 #include <net/route.h>
71 #include <net/ppp_defs.h>
72 #include <net/pppio.h>
73 #include <net/if_types.h>
74 #include <net/if_dl.h>
75 #include <netinet/in.h>
76 #include <sys/tihdr.h>
77 #include <inet/mib2.h>
78 #include <inet/ip.h>
79 #include <sys/ethernet.h>
80 #include <sys/ser_sync.h>
81 #include <libdlpi.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 	{ 0, 0 }
1215 };
1216 
1217 /*
1218  * translate_speed()
1219  *
1220  * Translate from bits/second to a speed_t
1221  */
1222 static int
1223 translate_speed(int bps)
1224 {
1225 	struct speed *speedp;
1226 
1227 	if (bps == 0) {
1228 		return (0);
1229 	}
1230 	for (speedp = speeds; speedp->speed_int; speedp++) {
1231 		if (bps == speedp->speed_int) {
1232 			return (speedp->speed_val);
1233 		}
1234 	}
1235 	set_source(&speed_info);
1236 	option_error("speed %d not supported", bps);
1237 	return (0);
1238 }
1239 
1240 /*
1241  * baud_rate_of()
1242  *
1243  * Translate from a speed_t to bits/second
1244  */
1245 static int
1246 baud_rate_of(int speed)
1247 {
1248 	struct speed *speedp;
1249 
1250 	if (speed == 0) {
1251 		return (0);
1252 	}
1253 	for (speedp = speeds; speedp->speed_int; speedp++) {
1254 		if (speed == speedp->speed_val) {
1255 			return (speedp->speed_int);
1256 		}
1257 	}
1258 	return (0);
1259 }
1260 
1261 /*
1262  * set_up_tty()
1263  *
1264  * Set up the serial port on `fd' for 8 bits, no parity, at the requested
1265  * speed, etc.  If `local' is true, set CLOCAL regardless of whether the
1266  * modem option was specified.
1267  */
1268 void
1269 set_up_tty(fd, local)
1270 	int fd, local;
1271 {
1272 	int speed;
1273 	struct termios tios;
1274 	struct scc_mode sm;
1275 
1276 	if (already_ppp)
1277 		return;
1278 
1279 	if (sync_serial) {
1280 		restore_term = 0;
1281 		speed = B0;
1282 		baud_rate = 0;
1283 
1284 		if (strioctl(fd, S_IOCGETMODE, &sm, sizeof (sm),
1285 		    sizeof (sm)) < 0) {
1286 			return;
1287 		}
1288 
1289 		baud_rate = sm.sm_baudrate;
1290 		dbglog("synchronous speed appears to be %d bps", baud_rate);
1291 	} else {
1292 		if (tcgetattr(fd, &tios) < 0) {
1293 			fatal("tcgetattr: %m");
1294 		}
1295 		if (!restore_term) {
1296 			inittermios = tios;
1297 			if (myioctl(fd, TIOCGWINSZ, &wsinfo) < 0) {
1298 				if (errno == EINVAL) {
1299 					/*
1300 					 * ptem returns EINVAL if all zeroes.
1301 					 * Strange and unfixable code.
1302 					 */
1303 					bzero(&wsinfo, sizeof (wsinfo));
1304 				} else {
1305 					warn("unable to get TTY window "
1306 					    "size: %m");
1307 				}
1308 			}
1309 		}
1310 		tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
1311 		if (crtscts > 0) {
1312 			tios.c_cflag |= CRTSCTS | CRTSXOFF;
1313 		} else if (crtscts < 0) {
1314 			tios.c_cflag &= ~CRTSCTS & ~CRTSXOFF;
1315 		}
1316 		tios.c_cflag |= CS8 | CREAD | HUPCL;
1317 		if (local || !modem) {
1318 			tios.c_cflag |= CLOCAL;
1319 		}
1320 		tios.c_iflag = IGNBRK | IGNPAR;
1321 		tios.c_oflag = 0;
1322 		tios.c_lflag = 0;
1323 		tios.c_cc[VMIN] = 1;
1324 		tios.c_cc[VTIME] = 0;
1325 
1326 		if (crtscts == -2) {
1327 			tios.c_iflag |= IXON | IXOFF;
1328 			tios.c_cc[VSTOP] = 0x13;	/* DC3 = XOFF = ^S */
1329 			tios.c_cc[VSTART] = 0x11;	/* DC1 = XON  = ^Q */
1330 		}
1331 		speed = translate_speed(inspeed);
1332 		if (speed) {
1333 			(void) cfsetospeed(&tios, speed);
1334 			(void) cfsetispeed(&tios, speed);
1335 		} else {
1336 			speed = cfgetospeed(&tios);
1337 			/*
1338 			 * We can't proceed if the serial port speed is 0,
1339 			 * since that implies that the serial port is disabled.
1340 			 */
1341 			if (speed == B0) {
1342 				fatal("Baud rate for %s is 0; need explicit "
1343 				    "baud rate", devnam);
1344 			}
1345 		}
1346 		if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
1347 			fatal("tcsetattr: %m");
1348 		}
1349 		baud_rate = baud_rate_of(speed);
1350 		dbglog("%s speed set to %d bps",
1351 		    fd == pty_slave ? "pty" : "serial", baud_rate);
1352 		restore_term = 1;
1353 	}
1354 }
1355 
1356 /*
1357  * restore_tty()
1358  *
1359  * Restore the terminal to the saved settings.
1360  */
1361 void
1362 restore_tty(fd)
1363 	int fd;
1364 {
1365 	if (restore_term == 0) {
1366 		return;
1367 	}
1368 	if (!default_device) {
1369 		/*
1370 		 * Turn off echoing, because otherwise we can get into
1371 		 * a loop with the tty and the modem echoing to each
1372 		 * other. We presume we are the sole user of this tty
1373 		 * device, so when we close it, it will revert to its
1374 		 * defaults anyway.
1375 		 */
1376 		inittermios.c_lflag &= ~(ECHO | ECHONL);
1377 	}
1378 	if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) {
1379 		if (!hungup && errno != ENXIO) {
1380 			warn("tcsetattr: %m");
1381 		}
1382 	}
1383 	if (wsinfo.ws_row != 0 || wsinfo.ws_col != 0 ||
1384 	    wsinfo.ws_xpixel != 0 || wsinfo.ws_ypixel != 0) {
1385 		if (myioctl(fd, TIOCSWINSZ, &wsinfo) < 0) {
1386 			warn("unable to set TTY window size: %m");
1387 		}
1388 	}
1389 	restore_term = 0;
1390 }
1391 
1392 /*
1393  * setdtr()
1394  *
1395  * Control the DTR line on the serial port. This is called from die(), so it
1396  * shouldn't call die()
1397  */
1398 void
1399 setdtr(fd, on)
1400 	int fd, on;
1401 {
1402 	int modembits = TIOCM_DTR;
1403 	if (!already_ppp &&
1404 	    myioctl(fd, (on ? TIOCMBIS : TIOCMBIC), &modembits) < 0) {
1405 		warn("unable to set DTR line %s: %m", (on ? "ON" : "OFF"));
1406 	}
1407 }
1408 
1409 /*
1410  * open_loopback()
1411  *
1412  * Open the device we use for getting packets in demand mode. Under Solaris 2,
1413  * we use our existing fd to the ppp driver.
1414  */
1415 int
1416 open_ppp_loopback()
1417 {
1418 	/*
1419 	 * Plumb the interface.
1420 	 */
1421 	if (IPCP_ENABLED && (plumb_ipif(0) == 0)) {
1422 		fatal("Unable to initialize IP interface for demand dial.");
1423 	}
1424 #ifdef INET6
1425 	if (IPV6CP_ENABLED && (plumb_ip6if(0) == 0)) {
1426 		fatal("Unable to initialize IPv6 interface for demand dial.");
1427 	}
1428 #endif /* INET6 */
1429 
1430 	return (pppfd);
1431 }
1432 
1433 /*
1434  * output()
1435  *
1436  * Output PPP packet downstream
1437  */
1438 /*ARGSUSED*/
1439 void
1440 output(unit, p, len)
1441 	int unit;
1442 	uchar_t *p;
1443 	int len;
1444 {
1445 	struct strbuf data;
1446 	struct pollfd pfd;
1447 	int retries, n;
1448 	bool sent_ok = 1;
1449 
1450 	data.len = len;
1451 	data.buf = (caddr_t)p;
1452 	retries = 4;
1453 
1454 	while (putmsg(pppfd, NULL, &data, 0) < 0) {
1455 		if (errno == EINTR)
1456 			continue;
1457 		if (--retries < 0 ||
1458 		    (errno != EWOULDBLOCK && errno != EAGAIN)) {
1459 			if (errno != ENXIO) {
1460 				error("Couldn't send packet: %m");
1461 				sent_ok = 0;
1462 			}
1463 			break;
1464 		}
1465 		pfd.fd = pppfd;
1466 		pfd.events = POLLOUT;
1467 		do {
1468 			/* wait for up to 0.25 seconds */
1469 			n = poll(&pfd, 1, 250);
1470 		} while ((n == -1) && (errno == EINTR));
1471 	}
1472 	if (debug && sent_ok) {
1473 		dbglog("sent %P", p, len);
1474 	}
1475 }
1476 
1477 /*
1478  * wait_input()
1479  *
1480  * Wait until there is data available, for the length of time specified by
1481  * timo (indefinite if timo is NULL).
1482  */
1483 void
1484 wait_input(timo)
1485 	struct timeval *timo;
1486 {
1487 	int t;
1488 
1489 	t = (timo == NULL ? -1 : (timo->tv_sec * 1000 + timo->tv_usec / 1000));
1490 	if ((poll(pollfds, n_pollfds, t) < 0) && (errno != EINTR)) {
1491 		fatal("poll: %m");
1492 	}
1493 }
1494 
1495 /*
1496  * add_fd()
1497  *
1498  * Add an fd to the set that wait_input waits for.
1499  */
1500 void
1501 add_fd(fd)
1502 	int fd;
1503 {
1504 	int n;
1505 
1506 	if (fd < 0) {
1507 		return;
1508 	}
1509 	for (n = 0; n < n_pollfds; ++n) {
1510 		if (pollfds[n].fd == fd) {
1511 			return;
1512 		}
1513 	}
1514 	if (n_pollfds < MAX_POLLFDS) {
1515 		pollfds[n_pollfds].fd = fd;
1516 		pollfds[n_pollfds].events = POLLIN | POLLPRI | POLLHUP;
1517 		++n_pollfds;
1518 	} else {
1519 		fatal("add_fd: too many inputs!");
1520 	}
1521 }
1522 
1523 /*
1524  * remove_fd()
1525  *
1526  * Remove an fd from the set that wait_input waits for.
1527  */
1528 void
1529 remove_fd(fd)
1530 	int fd;
1531 {
1532 	int n;
1533 
1534 	for (n = 0; n < n_pollfds; ++n) {
1535 		if (pollfds[n].fd == fd) {
1536 			while (++n < n_pollfds) {
1537 				pollfds[n-1] = pollfds[n];
1538 			}
1539 			--n_pollfds;
1540 			break;
1541 		}
1542 	}
1543 }
1544 
1545 static void
1546 dump_packet(uchar_t *buf, int len)
1547 {
1548 	uchar_t *bp;
1549 	int proto, offs;
1550 	const char *cp;
1551 	char sbuf[32];
1552 	uint32_t src, dst;
1553 	struct protoent *pep;
1554 
1555 	if (len < 4) {
1556 		dbglog("strange link activity: %.*B", len, buf);
1557 		return;
1558 	}
1559 	bp = buf;
1560 	if (bp[0] == 0xFF && bp[1] == 0x03)
1561 		bp += 2;
1562 	proto = *bp++;
1563 	if (!(proto & 1))
1564 		proto = (proto << 8) + *bp++;
1565 	len -= bp-buf;
1566 	if (proto == PPP_IP) {
1567 		if (len < 20 || get_ipv(bp) != 4 || get_iphl(bp) < 5) {
1568 			dbglog("strange IP packet activity: %16.*B", len, buf);
1569 			return;
1570 		}
1571 		src = get_ipsrc(bp);
1572 		dst = get_ipdst(bp);
1573 		proto = get_ipproto(bp);
1574 		if ((pep = getprotobynumber(proto)) != NULL) {
1575 			cp = pep->p_name;
1576 		} else {
1577 			(void) slprintf(sbuf, sizeof (sbuf), "IP proto %d",
1578 			    proto);
1579 			cp = sbuf;
1580 		}
1581 		if ((get_ipoff(bp) & IP_OFFMASK) != 0) {
1582 			len -= get_iphl(bp) * 4;
1583 			bp += get_iphl(bp) * 4;
1584 			dbglog("%s fragment from %I->%I: %8.*B", cp, src, dst,
1585 			    len, bp);
1586 		} else {
1587 			if (len > get_iplen(bp))
1588 				len = get_iplen(bp);
1589 			len -= get_iphl(bp) * 4;
1590 			bp += get_iphl(bp) * 4;
1591 			offs = proto == IPPROTO_TCP ? (get_tcpoff(bp)*4) : 8;
1592 			if (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
1593 				dbglog("%s data:%d %I:%d->%I:%d: %8.*B", cp,
1594 				    len-offs, src, get_sport(bp), dst,
1595 				    get_dport(bp), len-offs, bp+offs);
1596 			else
1597 				dbglog("%s %d bytes %I->%I: %8.*B", cp, len,
1598 				    src, dst, len, bp);
1599 		}
1600 		return;
1601 	}
1602 	if ((cp = protocol_name(proto)) == NULL) {
1603 		(void) slprintf(sbuf, sizeof (sbuf), "0x#X", proto);
1604 		cp = (const char *)sbuf;
1605 	}
1606 	dbglog("link activity: %s %16.*B", cp, len, bp);
1607 }
1608 
1609 /*
1610  * handle_bind()
1611  */
1612 static void
1613 handle_bind(u_int32_t reason)
1614 {
1615 	/*
1616 	 * Here we might, in the future, handle DL_BIND_REQ notifications
1617 	 * in order to close and re-open a NCP when certain interface
1618 	 * parameters (addresses, etc.) are changed via external mechanisms
1619 	 * such as through the "ifconfig" program.
1620 	 */
1621 	switch (reason) {
1622 	case PPP_LINKSTAT_IPV4_BOUND:
1623 		break;
1624 #ifdef INET6
1625 	case PPP_LINKSTAT_IPV6_BOUND:
1626 		break;
1627 #endif
1628 	default:
1629 		error("handle_bind: unrecognized reason");
1630 		break;
1631 	}
1632 }
1633 
1634 /*
1635  * handle_unbind()
1636  */
1637 static void
1638 handle_unbind(u_int32_t reason)
1639 {
1640 	bool iff_up_isset;
1641 	int rc;
1642 	static const char *unplumb_str = "unplumbed";
1643 	static const char *down_str = "downed";
1644 
1645 	/*
1646 	 * Since the kernel driver (sppp) notifies this daemon of the
1647 	 * DLPI bind/unbind activities (for the purpose of bringing down
1648 	 * a NCP), we need to explicitly test the "actual" status of
1649 	 * the interface instance for which the notification is destined
1650 	 * from.  This is because /dev/ip performs multiple DLPI attach-
1651 	 * bind-unbind-detach during the early life of the interface,
1652 	 * and when certain interface parameters change.  A DL_UNBIND_REQ
1653 	 * coming down to the sppp driver from /dev/ip (which results in
1654 	 * our receiving of the PPP_LINKSTAT_*_UNBOUND link status message)
1655 	 * is not enough to conclude that the interface has been marked
1656 	 * DOWN (its IFF_UP bit is cleared) or is going away.  Therefore,
1657 	 * we should query /dev/ip directly, upon receiving such *_UNBOUND
1658 	 * notification, to determine whether the interface is DOWN
1659 	 * for real, and only take the necessary actions when IFF_UP
1660 	 * bit for the interface instance is actually cleared.
1661 	 */
1662 	switch (reason) {
1663 	case PPP_LINKSTAT_IPV4_UNBOUND:
1664 		(void) sleep(1);
1665 		rc = giflags(IFF_UP, &iff_up_isset);
1666 		if (!iff_up_isset) {
1667 			if_is_up = 0;
1668 			ipmuxid = -1;
1669 			info("IPv4 interface %s by administrator",
1670 			    ((rc < 0 && rc == ENXIO) ? unplumb_str : down_str));
1671 			fsm_close(&ipcp_fsm[0],
1672 			    "administratively disconnected");
1673 		}
1674 		break;
1675 #ifdef INET6
1676 	case PPP_LINKSTAT_IPV6_UNBOUND:
1677 		(void) sleep(1);
1678 		rc = giflags(IFF_UP, &iff_up_isset);
1679 		if (!iff_up_isset) {
1680 			if6_is_up = 0;
1681 			ip6muxid = -1;
1682 			info("IPv6 interface %s by administrator",
1683 			    ((rc < 0 && rc == ENXIO) ? unplumb_str : down_str));
1684 			fsm_close(&ipv6cp_fsm[0],
1685 			    "administratively disconnected");
1686 		}
1687 		break;
1688 #endif
1689 	default:
1690 		error("handle_unbind: unrecognized reason");
1691 		break;
1692 	}
1693 }
1694 
1695 /*
1696  * read_packet()
1697  *
1698  * Get a PPP packet from the serial device.
1699  */
1700 int
1701 read_packet(buf)
1702 	uchar_t *buf;
1703 {
1704 	struct strbuf ctrl;
1705 	struct strbuf data;
1706 	int flags;
1707 	int len;
1708 	int rc;
1709 	struct ppp_ls *plp;
1710 	uint32_t ctrlbuf[1536 / sizeof (uint32_t)];
1711 	bool flushmode;
1712 
1713 	flushmode = 0;
1714 	for (;;) {
1715 
1716 		data.maxlen = PPP_MRU + PPP_HDRLEN;
1717 		data.buf = (caddr_t)buf;
1718 
1719 		ctrl.maxlen = sizeof (ctrlbuf);
1720 		ctrl.buf = (caddr_t)ctrlbuf;
1721 
1722 		flags = 0;
1723 		rc = len = getmsg(pppfd, &ctrl, &data, &flags);
1724 		if (sys_read_packet_hook != NULL) {
1725 			rc = len = (*sys_read_packet_hook)(len, &ctrl, &data,
1726 			    flags);
1727 		}
1728 		if (len < 0) {
1729 			if (errno == EAGAIN || errno == EINTR) {
1730 				return (-1);
1731 			}
1732 			fatal("Error reading packet: %m");
1733 		}
1734 		if ((data.len > 0) && (ctrl.len < 0)) {
1735 			/*
1736 			 * If there's more data on stream head, keep reading
1737 			 * but discard, since the stream is now corrupt.
1738 			 */
1739 			if (rc & MOREDATA) {
1740 				dbglog("More data; input packet garbled");
1741 				flushmode = 1;
1742 				continue;
1743 			}
1744 			if (flushmode)
1745 				return (-1);
1746 			return (data.len);
1747 
1748 		} else if (ctrl.len > 0) {
1749 			/*
1750 			 * If there's more ctl on stream head, keep reading,
1751 			 * but start discarding.  We can't deal with fragmented
1752 			 * messages at all.
1753 			 */
1754 			if (rc & MORECTL) {
1755 				dbglog("More control; stream garbled");
1756 				flushmode = 1;
1757 				continue;
1758 			}
1759 			if (flushmode)
1760 				return (-1);
1761 			if (ctrl.len < sizeof (struct ppp_ls)) {
1762 				warn("read_packet: ctl.len %d < "
1763 				    "sizeof ppp_ls %d",
1764 				    ctrl.len, sizeof (struct ppp_ls));
1765 				return (-1);
1766 			}
1767 			plp = (struct ppp_ls *)ctrlbuf;
1768 			if (plp->magic != PPPLSMAGIC) {
1769 				/* Skip, as we don't understand it */
1770 				dbglog("read_packet: unrecognized control %lX",
1771 				    plp->magic);
1772 				return (-1);
1773 			}
1774 
1775 			lastlink_status = plp->ppp_message;
1776 
1777 			switch (plp->ppp_message) {
1778 			case PPP_LINKSTAT_HANGUP:
1779 				return (0);	/* Hangup */
1780 			/* For use by integrated drivers. */
1781 			case PPP_LINKSTAT_UP:
1782 				lcp_lowerdown(0);
1783 				lcp_lowerup(0);
1784 				return (0);
1785 			case PPP_LINKSTAT_NEEDUP:
1786 				if (data.len > 0 && debug)
1787 					dump_packet(buf, data.len);
1788 				return (-1);	/* Demand dial */
1789 			case PPP_LINKSTAT_IPV4_UNBOUND:
1790 				(void) handle_unbind(plp->ppp_message);
1791 				return (-1);
1792 			case PPP_LINKSTAT_IPV4_BOUND:
1793 				(void) handle_bind(plp->ppp_message);
1794 				return (-1);
1795 #ifdef INET6
1796 			case PPP_LINKSTAT_IPV6_UNBOUND:
1797 				(void) handle_unbind(plp->ppp_message);
1798 				return (-1);
1799 			case PPP_LINKSTAT_IPV6_BOUND:
1800 				(void) handle_bind(plp->ppp_message);
1801 				return (-1);
1802 #endif
1803 			default:
1804 				warn("read_packet: unknown link status type!");
1805 				return (-1);
1806 			}
1807 		} else {
1808 			/*
1809 			 * We get here on zero length data or control.
1810 			 */
1811 			return (-1);
1812 		}
1813 	}
1814 }
1815 
1816 /*
1817  * get_loop_output()
1818  *
1819  * Get outgoing packets from the ppp device, and detect when we want to bring
1820  * the real link up. Return value is 1 if we need to bring up the link, or 0
1821  * otherwise.
1822  */
1823 int
1824 get_loop_output()
1825 {
1826 	int loops;
1827 
1828 	/*
1829 	 * In the Solaris 2.x kernel-level portion implementation, packets
1830 	 * which are received on a demand-dial interface are immediately
1831 	 * discarded, and a notification message is sent up the control
1832 	 * stream to the pppd process.  Therefore, the call to read_packet()
1833 	 * below is merely there to wait for such message.
1834 	 */
1835 	lastlink_status = 0;
1836 	loops = 0;
1837 	while (read_packet(inpacket_buf) > 0) {
1838 		if (++loops > 10)
1839 			break;
1840 	}
1841 	return (lastlink_status == PPP_LINKSTAT_NEEDUP);
1842 }
1843 
1844 #ifdef MUX_FRAME
1845 /*ARGSUSED*/
1846 void
1847 ppp_send_muxoption(unit, muxflag)
1848 	int unit;
1849 	u_int32_t muxflag;
1850 {
1851 	uint32_t	cf[2];
1852 
1853 	/*
1854 	 * Since muxed frame feature is implemented in the async module,
1855 	 * don't send down the ioctl in the synchronous case.
1856 	 */
1857 	if (!sync_serial && fdmuxid >= 0 && pppfd != -1) {
1858 		cf[0] = muxflag;
1859 		cf[1] = X_MUXMASK;
1860 
1861 		if (strioctl(pppfd, PPPIO_MUX, cf, sizeof (cf), 0) < 0) {
1862 			error("Couldn't set mux option: %m");
1863 		}
1864 	}
1865 }
1866 
1867 /*ARGSUSED*/
1868 void
1869 ppp_recv_muxoption(unit, muxflag)
1870 	int unit;
1871 	u_int32_t muxflag;
1872 {
1873 	uint32_t	cf[2];
1874 
1875 	/*
1876 	 * Since muxed frame feature is implemented in the async module,
1877 	 * don't send down the ioctl in the synchronous case.
1878 	 */
1879 	if (!sync_serial && fdmuxid >= 0 && pppfd != -1) {
1880 		cf[0] = muxflag;
1881 		cf[1] = R_MUXMASK;
1882 
1883 		if (strioctl(pppfd, PPPIO_MUX, cf, sizeof (cf), 0) < 0) {
1884 			error("Couldn't set receive mux option: %m");
1885 		}
1886 	}
1887 }
1888 #endif
1889 
1890 /*
1891  * ppp_send_config()
1892  *
1893  * Configure the transmit characteristics of the ppp interface.
1894  */
1895 /*ARGSUSED*/
1896 void
1897 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
1898 	int unit;
1899 	int mtu;
1900 	u_int32_t asyncmap;
1901 	int pcomp;
1902 	int accomp;
1903 {
1904 	uint32_t cf[2];
1905 
1906 	if (pppfd == -1) {
1907 		error("ppp_send_config called with invalid device handle");
1908 		return;
1909 	}
1910 	cf[0] =	link_mtu = mtu;
1911 	if (strioctl(pppfd, PPPIO_MTU, cf, sizeof (cf[0]), 0) < 0) {
1912 		if (hungup && errno == ENXIO) {
1913 			return;
1914 		}
1915 		error("Couldn't set MTU: %m");
1916 	}
1917 	if (fdmuxid != -1) {
1918 		if (!sync_serial) {
1919 			if (strioctl(pppfd, PPPIO_XACCM, &asyncmap,
1920 			    sizeof (asyncmap), 0) < 0) {
1921 				error("Couldn't set transmit ACCM: %m");
1922 			}
1923 		}
1924 		cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0);
1925 		cf[1] = COMP_PROT | COMP_AC;
1926 
1927 		if (any_compressions() && strioctl(pppfd, PPPIO_CFLAGS, cf,
1928 		    sizeof (cf), sizeof (cf[0])) < 0) {
1929 			error("Couldn't set prot/AC compression: %m");
1930 		}
1931 	}
1932 }
1933 
1934 /*
1935  * ppp_set_xaccm()
1936  *
1937  * Set the extended transmit ACCM for the interface.
1938  */
1939 /*ARGSUSED*/
1940 void
1941 ppp_set_xaccm(unit, accm)
1942 	int unit;
1943 	ext_accm accm;
1944 {
1945 	if (sync_serial) {
1946 		return;
1947 	}
1948 	if (fdmuxid != -1 && strioctl(pppfd, PPPIO_XACCM, accm,
1949 	    sizeof (ext_accm), 0) < 0) {
1950 		if (!hungup || errno != ENXIO) {
1951 			warn("Couldn't set extended ACCM: %m");
1952 		}
1953 	}
1954 }
1955 
1956 /*
1957  * ppp_recv_config()
1958  *
1959  * Configure the receive-side characteristics of the ppp interface.
1960  */
1961 /*ARGSUSED*/
1962 void
1963 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
1964 	int unit;
1965 	int mru;
1966 	u_int32_t asyncmap;
1967 	int pcomp;
1968 	int accomp;
1969 {
1970 	uint32_t cf[2];
1971 
1972 	if (pppfd == -1) {
1973 		error("ppp_recv_config called with invalid device handle");
1974 		return;
1975 	}
1976 	cf[0] = mru;
1977 	if (strioctl(pppfd, PPPIO_MRU, cf, sizeof (cf[0]), 0) < 0) {
1978 		if (hungup && errno == ENXIO) {
1979 			return;
1980 		}
1981 		error("Couldn't set MRU: %m");
1982 	}
1983 	if (fdmuxid != -1) {
1984 		if (!sync_serial) {
1985 			if (strioctl(pppfd, PPPIO_RACCM, &asyncmap,
1986 			    sizeof (asyncmap), 0) < 0) {
1987 				error("Couldn't set receive ACCM: %m");
1988 			}
1989 		}
1990 		cf[0] = (pcomp ? DECOMP_PROT : 0) + (accomp ? DECOMP_AC : 0);
1991 		cf[1] = DECOMP_PROT | DECOMP_AC;
1992 
1993 		if (any_compressions() && strioctl(pppfd, PPPIO_CFLAGS, cf,
1994 		    sizeof (cf), sizeof (cf[0])) < 0) {
1995 			error("Couldn't set prot/AC decompression: %m");
1996 		}
1997 	}
1998 }
1999 
2000 #ifdef NEGOTIATE_FCS
2001 /*
2002  * ppp_send_fcs()
2003  *
2004  * Configure the sender-side FCS.
2005  */
2006 /*ARGSUSED*/
2007 void
2008 ppp_send_fcs(unit, fcstype)
2009 	int unit, fcstype;
2010 {
2011 	uint32_t fcs;
2012 
2013 	if (sync_serial) {
2014 		return;
2015 	}
2016 
2017 	if (fcstype & FCSALT_32) {
2018 		fcs = PPPFCS_32;
2019 	} else if (fcstype & FCSALT_NULL) {
2020 		fcs = PPPFCS_NONE;
2021 	} else {
2022 		fcs = PPPFCS_16;
2023 	}
2024 	if (strioctl(pppfd, PPPIO_XFCS, &fcs, sizeof (fcs), 0) < 0) {
2025 		warn("Couldn't set transmit FCS: %m");
2026 	}
2027 }
2028 
2029 /*
2030  * ppp_recv_fcs()
2031  *
2032  * Configure the receiver-side FCS.
2033  */
2034 /*ARGSUSED*/
2035 void
2036 ppp_recv_fcs(unit, fcstype)
2037 	int unit, fcstype;
2038 {
2039 	uint32_t fcs;
2040 
2041 	if (sync_serial) {
2042 		return;
2043 	}
2044 
2045 	if (fcstype & FCSALT_32) {
2046 		fcs = PPPFCS_32;
2047 	} else if (fcstype & FCSALT_NULL) {
2048 		fcs = PPPFCS_NONE;
2049 	} else {
2050 		fcs = PPPFCS_16;
2051 	}
2052 	if (strioctl(pppfd, PPPIO_RFCS, &fcs, sizeof (fcs), 0) < 0) {
2053 		warn("Couldn't set receive FCS: %m");
2054 	}
2055 }
2056 #endif
2057 
2058 /*
2059  * ccp_test()
2060  *
2061  * Ask kernel whether a given compression method is acceptable for use.
2062  */
2063 /*ARGSUSED*/
2064 int
2065 ccp_test(unit, opt_ptr, opt_len, for_transmit)
2066 	int unit;
2067 	uchar_t *opt_ptr;
2068 	int opt_len;
2069 	int for_transmit;
2070 {
2071 	if (strioctl(pppfd, (for_transmit ? PPPIO_XCOMP : PPPIO_RCOMP),
2072 	    opt_ptr, opt_len, 0) >= 0) {
2073 		return (1);
2074 	}
2075 	warn("Error in %s ioctl: %m",
2076 	    (for_transmit ? "PPPIO_XCOMP" : "PPPIO_RCOMP"));
2077 	return ((errno == ENOSR) ? 0 : -1);
2078 }
2079 
2080 #ifdef COMP_TUNE
2081 /*
2082  * ccp_tune()
2083  *
2084  * Tune compression effort level.
2085  */
2086 /*ARGSUSED*/
2087 void
2088 ccp_tune(unit, effort)
2089 	int unit, effort;
2090 {
2091 	uint32_t x;
2092 
2093 	x = effort;
2094 	if (strioctl(pppfd, PPPIO_COMPLEV, &x, sizeof (x), 0) < 0) {
2095 		warn("unable to set compression effort level: %m");
2096 	}
2097 }
2098 #endif
2099 
2100 /*
2101  * ccp_flags_set()
2102  *
2103  * Inform kernel about the current state of CCP.
2104  */
2105 /*ARGSUSED*/
2106 void
2107 ccp_flags_set(unit, isopen, isup)
2108 	int unit, isopen, isup;
2109 {
2110 	uint32_t cf[2];
2111 
2112 	cf[0] = (isopen ? CCP_ISOPEN : 0) + (isup ? CCP_ISUP : 0);
2113 	cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR;
2114 
2115 	if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0]))
2116 	    < 0) {
2117 		if (!hungup || errno != ENXIO) {
2118 			error("Couldn't set kernel CCP state: %m");
2119 		}
2120 	}
2121 }
2122 
2123 /*
2124  * get_idle_time()
2125  *
2126  * Return how long the link has been idle.
2127  */
2128 /*ARGSUSED*/
2129 int
2130 get_idle_time(u, pids)
2131 	int u;
2132 	struct ppp_idle *pids;
2133 {
2134 	int rc;
2135 
2136 	rc = strioctl(pppfd, PPPIO_GIDLE, pids, 0, sizeof (struct ppp_idle));
2137 	if (rc < 0) {
2138 		warn("unable to obtain idle time: %m");
2139 	}
2140 	return ((rc == 0) ? 1 : 0);
2141 }
2142 
2143 /*
2144  * get_ppp_stats()
2145  *
2146  * Return statistics for the link.
2147  */
2148 /*ARGSUSED*/
2149 int
2150 get_ppp_stats(u, stats)
2151 	int u;
2152 	struct pppd_stats *stats;
2153 {
2154 	struct ppp_stats64 s64;
2155 	struct ppp_stats s;
2156 
2157 	/* Try first to get these from the 64-bit interface */
2158 	if (strioctl(pppfd, PPPIO_GETSTAT64, &s64, 0, sizeof (s64)) >= 0) {
2159 		stats->bytes_in = s64.p.ppp_ibytes;
2160 		stats->bytes_out = s64.p.ppp_obytes;
2161 		stats->pkts_in = s64.p.ppp_ipackets;
2162 		stats->pkts_out = s64.p.ppp_opackets;
2163 		return (1);
2164 	}
2165 
2166 	if (strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof (s)) < 0) {
2167 		error("Couldn't get link statistics: %m");
2168 		return (0);
2169 	}
2170 	stats->bytes_in = s.p.ppp_ibytes;
2171 	stats->bytes_out = s.p.ppp_obytes;
2172 	stats->pkts_in = s.p.ppp_ipackets;
2173 	stats->pkts_out = s.p.ppp_opackets;
2174 	return (1);
2175 }
2176 
2177 #if defined(FILTER_PACKETS)
2178 /*
2179  * set_filters()
2180  *
2181  * Transfer the pass and active filters to the kernel.
2182  */
2183 int
2184 set_filters(pass, active)
2185 	struct bpf_program *pass;
2186 	struct bpf_program *active;
2187 {
2188 	int ret = 1;
2189 
2190 	if (pass->bf_len > 0) {
2191 		if (strioctl(pppfd, PPPIO_PASSFILT, pass,
2192 		    sizeof (struct bpf_program), 0) < 0) {
2193 			error("Couldn't set pass-filter in kernel: %m");
2194 			ret = 0;
2195 		}
2196 	}
2197 	if (active->bf_len > 0) {
2198 		if (strioctl(pppfd, PPPIO_ACTIVEFILT, active,
2199 		    sizeof (struct bpf_program), 0) < 0) {
2200 			error("Couldn't set active-filter in kernel: %m");
2201 			ret = 0;
2202 		}
2203 	}
2204 	return (ret);
2205 }
2206 #endif /* FILTER_PACKETS */
2207 
2208 /*
2209  * ccp_fatal_error()
2210  *
2211  * Returns 1 if decompression was disabled as a result of an error detected
2212  * after decompression of a packet, 0 otherwise.  This is necessary because
2213  * of patent nonsense.
2214  */
2215 /*ARGSUSED*/
2216 int
2217 ccp_fatal_error(unit)
2218 	int unit;
2219 {
2220 	uint32_t cf[2];
2221 
2222 	cf[0] = cf[1] = 0;
2223 	if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0]))
2224 	    < 0) {
2225 		if (errno != ENXIO && errno != EINVAL) {
2226 			error("Couldn't get compression flags: %m");
2227 		}
2228 		return (0);
2229 	}
2230 	return (cf[0] & CCP_FATALERROR);
2231 }
2232 
2233 /*
2234  * sifvjcomp()
2235  *
2236  * Config TCP header compression.
2237  */
2238 /*ARGSUSED*/
2239 int
2240 sifvjcomp(u, vjcomp, xcidcomp, xmaxcid)
2241 	int u, vjcomp, xcidcomp, xmaxcid;
2242 {
2243 	uint32_t cf[2];
2244 	uchar_t maxcid[2];
2245 
2246 	/*
2247 	 * Since VJ compression code is in the comp module, there's no
2248 	 * point of sending down any ioctls pertaining to VJ compression
2249 	 * when the module isn't pushed on the stream.
2250 	 */
2251 	if (!any_compressions()) {
2252 		return (1);
2253 	}
2254 
2255 	if (vjcomp) {
2256 		maxcid[0] = xcidcomp;
2257 		maxcid[1] = 15;		/* XXX should be rmaxcid */
2258 
2259 		if (strioctl(pppfd, PPPIO_VJINIT, maxcid,
2260 		    sizeof (maxcid), 0) < 0) {
2261 			error("Couldn't initialize VJ compression: %m");
2262 			return (0);
2263 		}
2264 	}
2265 
2266 	cf[0] = (vjcomp ? COMP_VJC + DECOMP_VJC : 0)	/* XXX this is wrong */
2267 		+ (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0);
2268 
2269 	cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID;
2270 
2271 	if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0]))
2272 	    < 0) {
2273 		if (vjcomp) {
2274 			error("Couldn't enable VJ compression: %m");
2275 		} else {
2276 			error("Couldn't disable VJ compression: %m");
2277 		}
2278 		return (0);
2279 	}
2280 	return (1);
2281 }
2282 
2283 /*
2284  * siflags()
2285  *
2286  * Set or clear the IP interface flags.
2287  */
2288 int
2289 siflags(f, set)
2290 	u_int32_t f;
2291 	int set;
2292 {
2293 	struct ifreq ifr;
2294 
2295 	if (!IPCP_ENABLED || (ipmuxid == -1)) {
2296 		return (0);
2297 	}
2298 	if (ipfd == -1 && open_ipfd() == -1)
2299 		return (0);
2300 	BZERO(&ifr, sizeof (ifr));
2301 	(void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2302 	if (myioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
2303 		error("Couldn't get IP interface flags: %m");
2304 		return (0);
2305 	}
2306 	if (set) {
2307 		ifr.ifr_flags |= f;
2308 	} else {
2309 		ifr.ifr_flags &= ~f;
2310 	}
2311 	if (myioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
2312 		error("Couldn't set IP interface flags: %m");
2313 		return (0);
2314 	}
2315 	return (1);
2316 }
2317 
2318 /*
2319  * sifup()
2320  *
2321  * Config the interface up and enable IP packets to pass.
2322  */
2323 /*ARGSUSED*/
2324 int
2325 sifup(u)
2326 	int u;
2327 {
2328 	if (if_is_up) {
2329 		return (1);
2330 	} else if (!IPCP_ENABLED) {
2331 		warn("sifup called when IPCP is disabled");
2332 		return (0);
2333 	} else if (ipmuxid == -1) {
2334 		warn("sifup called in wrong state");
2335 		return (0);
2336 	} else if (!siflags(IFF_UP, 1)) {
2337 		error("Unable to mark the IP interface UP");
2338 		return (0);
2339 	}
2340 	if_is_up = 1;
2341 	return (1);
2342 }
2343 
2344 /*
2345  * sifdown()
2346  *
2347  * Config the interface down and disable IP.  Possibly called from die(),
2348  * so there shouldn't be any call to die() here.
2349  */
2350 /*ARGSUSED*/
2351 int
2352 sifdown(u)
2353 	int u;
2354 {
2355 	if (!IPCP_ENABLED) {
2356 		warn("sifdown called when IPCP is disabled");
2357 		return (0);
2358 	} else if (!if_is_up || (ipmuxid == -1)) {
2359 		return (1);
2360 	} else if (!siflags(IFF_UP, 0)) {
2361 		error("Unable to mark the IP interface DOWN");
2362 		return (0);
2363 	}
2364 	if_is_up = 0;
2365 	return (1);
2366 }
2367 
2368 /*
2369  * sifnpmode()
2370  *
2371  * Set the mode for handling packets for a given NP.  Not worried
2372  * about performance here since this is done only rarely.
2373  */
2374 /*ARGSUSED*/
2375 int
2376 sifnpmode(u, proto, mode)
2377 	int u;
2378 	int proto;
2379 	enum NPmode mode;
2380 {
2381 	uint32_t npi[2];
2382 	const char *cp;
2383 	static const struct npi_entry {
2384 		enum NPmode ne_value;
2385 		const char *ne_name;
2386 	} npi_list[] = {
2387 		{ NPMODE_PASS, "pass" },
2388 		{ NPMODE_DROP, "drop" },
2389 		{ NPMODE_ERROR, "error" },
2390 		{ NPMODE_QUEUE, "queue" },
2391 	};
2392 	int i;
2393 	char pname[32], mname[32];
2394 
2395 	npi[0] = proto;
2396 	npi[1] = (uint32_t)mode;
2397 
2398 	cp = protocol_name(proto);
2399 	if (cp == NULL)
2400 		(void) slprintf(pname, sizeof (pname), "NP %04X", proto);
2401 	else
2402 		(void) strlcpy(pname, cp, sizeof (pname));
2403 	for (i = 0; i < Dim(npi_list); i++)
2404 		if (npi_list[i].ne_value == mode)
2405 			break;
2406 	if (i >= Dim(npi_list))
2407 		(void) slprintf(mname, sizeof (mname), "mode %d", (int)mode);
2408 	else
2409 		(void) strlcpy(mname, npi_list[i].ne_name, sizeof (mname));
2410 
2411 	if ((proto == PPP_IP && !if_is_up) ||
2412 	    (proto == PPP_IPV6 && !if6_is_up)) {
2413 		dbglog("ignoring request to set %s to %s", pname, mname);
2414 		return (1);
2415 	}
2416 	if (strioctl(pppfd, PPPIO_NPMODE, npi, sizeof (npi), 0) < 0) {
2417 		error("unable to set %s to %s: %m", pname, mname);
2418 		return (0);
2419 	}
2420 	return (1);
2421 }
2422 
2423 /*
2424  * sifmtu()
2425  *
2426  * Config the interface IP MTU.
2427  */
2428 int
2429 sifmtu(mtu)
2430 	int mtu;
2431 {
2432 	struct ifreq ifr;
2433 
2434 	if (!IPCP_ENABLED || (ipmuxid == -1)) {
2435 		return (0);
2436 	}
2437 	if (ipfd == -1 && open_ipfd() == -1)
2438 		return (0);
2439 	BZERO(&ifr, sizeof (ifr));
2440 	(void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2441 	ifr.ifr_metric = mtu;
2442 	if (myioctl(ipfd, SIOCSIFMTU, &ifr) < 0) {
2443 		error("Couldn't set IP MTU on %s to %d: %m", ifr.ifr_name,
2444 		    mtu);
2445 		return (0);
2446 	}
2447 	return (1);
2448 }
2449 
2450 /*
2451  * sifaddr()
2452  *
2453  * Config the interface IP addresses and netmask.
2454  */
2455 /*ARGSUSED*/
2456 int
2457 sifaddr(u, o, h, m)
2458 	int u;
2459 	u_int32_t o;
2460 	u_int32_t h;
2461 	u_int32_t m;
2462 {
2463 	struct ifreq ifr;
2464 	struct sockaddr_in sin;
2465 
2466 	if (!IPCP_ENABLED || (ipmuxid == -1 && plumb_ipif(u) == 0)) {
2467 		return (0);
2468 	}
2469 	if (ipfd == -1 && open_ipfd() == -1)
2470 		return (0);
2471 	/*
2472 	 * Set the IP interface MTU.
2473 	 */
2474 	if (!sifmtu(link_mtu)) {
2475 		return (0);
2476 	}
2477 	/*
2478 	 * Set the IP interface local point-to-point address.
2479 	 */
2480 	BZERO(&sin, sizeof (sin));
2481 	sin.sin_family = AF_INET;
2482 	sin.sin_addr.s_addr = o;
2483 
2484 	BZERO(&ifr, sizeof (ifr));
2485 	(void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2486 	ifr.ifr_addr = *(struct sockaddr *)&sin;
2487 	if (myioctl(ipfd, SIOCSIFADDR, &ifr) < 0) {
2488 		error("Couldn't set local IP address (%s): %m", ifr.ifr_name);
2489 		return (0);
2490 	}
2491 	/*
2492 	 * Set the IP interface remote point-to-point address.
2493 	 */
2494 	sin.sin_addr.s_addr = h;
2495 
2496 	ifr.ifr_dstaddr = *(struct sockaddr *)&sin;
2497 	if (myioctl(ipfd, SIOCSIFDSTADDR, &ifr) < 0) {
2498 		error("Couldn't set remote IP address (%s): %m", ifr.ifr_name);
2499 		return (0);
2500 	}
2501 	remote_addr = h;
2502 	return (1);
2503 }
2504 
2505 /*
2506  * cifaddr()
2507  *
2508  * Clear the interface IP addresses.
2509  */
2510 /*ARGSUSED*/
2511 int
2512 cifaddr(u, o, h)
2513 	int u;
2514 	u_int32_t o;
2515 	u_int32_t h;
2516 {
2517 	if (!IPCP_ENABLED) {
2518 		return (0);
2519 	}
2520 	/*
2521 	 * Most of the work is done in sifdown().
2522 	 */
2523 	remote_addr = 0;
2524 	return (1);
2525 }
2526 
2527 /*
2528  * sifroute()
2529  *
2530  * Add or delete a route.
2531  */
2532 /*ARGSUSED*/
2533 static int
2534 sifroute(int u, u_int32_t l, u_int32_t g, int add, const char *str)
2535 {
2536 	struct sockaddr_in sin_dst, sin_gtw;
2537 	struct rtentry rt;
2538 
2539 	if (!IPCP_ENABLED || (ipmuxid == -1)) {
2540 		error("Can't %s route: IP is not enabled", str);
2541 		return (0);
2542 	}
2543 	if (ipfd == -1 && open_ipfd() == -1)
2544 		return (0);
2545 
2546 	BZERO(&sin_dst, sizeof (sin_dst));
2547 	sin_dst.sin_family = AF_INET;
2548 	sin_dst.sin_addr.s_addr = l;
2549 
2550 	BZERO(&sin_gtw, sizeof (sin_gtw));
2551 	sin_gtw.sin_family = AF_INET;
2552 	sin_gtw.sin_addr.s_addr = g;
2553 
2554 	BZERO(&rt, sizeof (rt));
2555 	rt.rt_dst = *(struct sockaddr *)&sin_dst;
2556 	rt.rt_gateway = *(struct sockaddr *)&sin_gtw;
2557 	rt.rt_flags = (RTF_GATEWAY|RTF_STATIC);
2558 
2559 	if (myioctl(ipfd, (add ? SIOCADDRT : SIOCDELRT), &rt) < 0) {
2560 		error("Can't %s route: %m", str);
2561 		return (0);
2562 	}
2563 	return (1);
2564 }
2565 
2566 /*
2567  * sifdefaultroute()
2568  *
2569  * Assign a default route through the address given.
2570  */
2571 /*ARGSUSED*/
2572 int
2573 sifdefaultroute(u, l, g)
2574 	int u;
2575 	u_int32_t l;
2576 	u_int32_t g;
2577 {
2578 	if (!sifroute(u, 0, g, 1, "add default")) {
2579 		return (0);
2580 	}
2581 	default_route_gateway = g;
2582 	return (1);
2583 }
2584 
2585 /*
2586  * cifdefaultroute()
2587  *
2588  * Delete a default route through the address given.
2589  */
2590 /*ARGSUSED*/
2591 int
2592 cifdefaultroute(u, l, g)
2593 	int u;
2594 	u_int32_t l;
2595 	u_int32_t g;
2596 {
2597 	if (!sifroute(u, 0, g, 0, "delete default")) {
2598 		return (0);
2599 	}
2600 	default_route_gateway = 0;
2601 	return (1);
2602 }
2603 
2604 /*
2605  * sifproxyarp()
2606  *
2607  * Make a proxy ARP entry for the peer.
2608  */
2609 /*ARGSUSED*/
2610 int
2611 sifproxyarp(unit, hisaddr, quietflag)
2612 	int unit;
2613 	u_int32_t hisaddr;
2614 	int quietflag;
2615 {
2616 	struct sockaddr_in sin;
2617 	struct xarpreq arpreq;
2618 	const uchar_t *cp;
2619 	char *str = NULL;
2620 
2621 	if (!IPCP_ENABLED || (ipmuxid == -1)) {
2622 		return (0);
2623 	}
2624 	if (ipfd == -1 && open_ipfd() == -1)
2625 		return (0);
2626 
2627 	BZERO(&sin, sizeof (sin));
2628 	sin.sin_family = AF_INET;
2629 	sin.sin_addr.s_addr = hisaddr;
2630 
2631 	BZERO(&arpreq, sizeof (arpreq));
2632 	if (!get_ether_addr(hisaddr, &arpreq.xarp_ha, quietflag)) {
2633 		return (0);
2634 	}
2635 	BCOPY(&sin, &arpreq.xarp_pa, sizeof (sin));
2636 	arpreq.xarp_flags = ATF_PERM | ATF_PUBL;
2637 	arpreq.xarp_ha.sdl_family = AF_LINK;
2638 
2639 	if (myioctl(ipfd, SIOCSXARP, (caddr_t)&arpreq) < 0) {
2640 		if (!quietflag)
2641 			error("Couldn't set proxy ARP entry: %m");
2642 		return (0);
2643 	}
2644 	cp = (const uchar_t *)LLADDR(&arpreq.xarp_ha);
2645 	str = _link_ntoa(cp, str, arpreq.xarp_ha.sdl_alen, IFT_OTHER);
2646 	if (str != NULL) {
2647 		dbglog("established proxy ARP for %I using %s", hisaddr,
2648 		    str);
2649 		free(str);
2650 	}
2651 	proxy_arp_addr = hisaddr;
2652 	return (1);
2653 }
2654 
2655 /*
2656  * cifproxyarp()
2657  *
2658  * Delete the proxy ARP entry for the peer.
2659  */
2660 /*ARGSUSED*/
2661 int
2662 cifproxyarp(unit, hisaddr)
2663 	int unit;
2664 	u_int32_t hisaddr;
2665 {
2666 	struct sockaddr_in sin;
2667 	struct xarpreq arpreq;
2668 
2669 	if (!IPCP_ENABLED || (ipmuxid == -1)) {
2670 		return (0);
2671 	}
2672 	if (ipfd == -1 && open_ipfd() == -1)
2673 		return (0);
2674 
2675 	BZERO(&sin, sizeof (sin));
2676 	sin.sin_family = AF_INET;
2677 	sin.sin_addr.s_addr = hisaddr;
2678 
2679 	BZERO(&arpreq, sizeof (arpreq));
2680 	BCOPY(&sin, &arpreq.xarp_pa, sizeof (sin));
2681 	arpreq.xarp_ha.sdl_family = AF_LINK;
2682 
2683 	if (myioctl(ipfd, SIOCDXARP, (caddr_t)&arpreq) < 0) {
2684 		error("Couldn't delete proxy ARP entry: %m");
2685 		return (0);
2686 	}
2687 	proxy_arp_addr = 0;
2688 	return (1);
2689 }
2690 
2691 /*
2692  * get_ether_addr()
2693  *
2694  * Get the hardware address of an interface on the the same subnet as
2695  * ipaddr.  This routine uses old-style interfaces for intentional
2696  * backward compatibility -- SIOCGLIF* isn't in older Solaris
2697  * releases.
2698  */
2699 static int
2700 get_ether_addr(u_int32_t ipaddr, struct sockaddr_dl *hwaddr, int quietflag)
2701 {
2702 	struct ifreq *ifr, *ifend, ifreq;
2703 	int nif, s, retv;
2704 	struct ifconf ifc;
2705 	u_int32_t ina, mask;
2706 	struct xarpreq req;
2707 	struct sockaddr_in sin;
2708 
2709 	if (ipfd == -1 && open_ipfd() == -1)
2710 		return (0);
2711 
2712 	/*
2713 	 * Scan through the system's network interfaces.
2714 	 */
2715 	if (myioctl(ipfd, SIOCGIFNUM, &nif) < 0) {
2716 		nif = MAXIFS;
2717 	}
2718 	if (nif <= 0)
2719 		return (0);
2720 	ifc.ifc_len = nif * sizeof (struct ifreq);
2721 	ifc.ifc_buf = (caddr_t)malloc(ifc.ifc_len);
2722 	if (ifc.ifc_buf == NULL) {
2723 		return (0);
2724 	}
2725 	if (myioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
2726 		error("Couldn't get system interface list: %m");
2727 		free(ifc.ifc_buf);
2728 		return (0);
2729 	}
2730 	/* LINTED */
2731 	ifend = (struct ifreq *)(ifc.ifc_buf + ifc.ifc_len);
2732 	for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
2733 		if (ifr->ifr_addr.sa_family != AF_INET) {
2734 			continue;
2735 		}
2736 		/*
2737 		 * Check that the interface is up, and not
2738 		 * point-to-point or loopback.
2739 		 */
2740 		(void) strlcpy(ifreq.ifr_name, ifr->ifr_name,
2741 		    sizeof (ifreq.ifr_name));
2742 		if (myioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0) {
2743 			continue;
2744 		}
2745 		if ((ifreq.ifr_flags & (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|
2746 		    IFF_LOOPBACK|IFF_NOARP)) != (IFF_UP|IFF_BROADCAST)) {
2747 			continue;
2748 		}
2749 		/*
2750 		 * Get its netmask and check that it's on the right subnet.
2751 		 */
2752 		if (myioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0) {
2753 			continue;
2754 		}
2755 		(void) memcpy(&sin, &ifr->ifr_addr, sizeof (sin));
2756 		ina = sin.sin_addr.s_addr;
2757 		(void) memcpy(&sin, &ifreq.ifr_addr, sizeof (sin));
2758 		mask = sin.sin_addr.s_addr;
2759 		if ((ipaddr & mask) == (ina & mask)) {
2760 			break;
2761 		}
2762 	}
2763 	if (ifr >= ifend) {
2764 		if (!quietflag)
2765 			warn("No suitable interface found for proxy ARP of %I",
2766 			    ipaddr);
2767 		free(ifc.ifc_buf);
2768 		return (0);
2769 	}
2770 	info("found interface %s for proxy ARP of %I", ifr->ifr_name, ipaddr);
2771 
2772 	/*
2773 	 * New way - get the address by doing an arp request.
2774 	 */
2775 	s = socket(AF_INET, SOCK_DGRAM, 0);
2776 	if (s < 0) {
2777 		error("get_ether_addr: error opening IP socket: %m");
2778 		free(ifc.ifc_buf);
2779 		return (0);
2780 	}
2781 	BZERO(&sin, sizeof (sin));
2782 	sin.sin_family = AF_INET;
2783 	sin.sin_addr.s_addr = ina;
2784 
2785 	BZERO(&req, sizeof (req));
2786 	BCOPY(&sin, &req.xarp_pa, sizeof (sin));
2787 	req.xarp_ha.sdl_family = AF_LINK;
2788 
2789 	if (myioctl(s, SIOCGXARP, &req) < 0) {
2790 		error("Couldn't get ARP entry for %I: %m", ina);
2791 		retv = 0;
2792 	} else {
2793 		(void) memcpy(hwaddr, &req.xarp_ha,
2794 		    sizeof (struct sockaddr_dl));
2795 		retv = 1;
2796 	}
2797 	(void) close(s);
2798 	free(ifc.ifc_buf);
2799 	return (retv);
2800 }
2801 
2802 /*
2803  * GetMask()
2804  *
2805  * Return mask (bogus, but needed for compatibility with other platforms).
2806  */
2807 /*ARGSUSED*/
2808 u_int32_t
2809 GetMask(addr)
2810 	u_int32_t addr;
2811 {
2812 	return (0xffffffffUL);
2813 }
2814 
2815 /*
2816  * logwtmp()
2817  *
2818  * Write an accounting record to the /var/adm/wtmp file.
2819  */
2820 /*ARGSUSED*/
2821 void
2822 logwtmp(line, name, host)
2823 	const char *line;
2824 	const char *name;
2825 	const char *host;
2826 {
2827 	static struct utmpx utmpx;
2828 
2829 	if (name[0] != '\0') {
2830 		/*
2831 		 * logging in
2832 		 */
2833 		(void) strncpy(utmpx.ut_user, name, sizeof (utmpx.ut_user));
2834 		(void) strncpy(utmpx.ut_id, ifname, sizeof (utmpx.ut_id));
2835 		(void) strncpy(utmpx.ut_line, line, sizeof (utmpx.ut_line));
2836 
2837 		utmpx.ut_pid = getpid();
2838 		utmpx.ut_type = USER_PROCESS;
2839 	} else {
2840 		utmpx.ut_type = DEAD_PROCESS;
2841 	}
2842 	(void) gettimeofday(&utmpx.ut_tv, NULL);
2843 	updwtmpx("/var/adm/wtmpx", &utmpx);
2844 }
2845 
2846 /*
2847  * get_host_seed()
2848  *
2849  * Return the serial number of this machine.
2850  */
2851 int
2852 get_host_seed()
2853 {
2854 	char buf[32];
2855 
2856 	if (sysinfo(SI_HW_SERIAL, buf, sizeof (buf)) < 0) {
2857 		error("sysinfo: %m");
2858 		return (0);
2859 	}
2860 	return ((int)strtoul(buf, NULL, 16));
2861 }
2862 
2863 /*
2864  * strioctl()
2865  *
2866  * Wrapper for STREAMS I_STR ioctl.  Masks out EINTR from caller.
2867  */
2868 static int
2869 strioctl(int fd, int cmd, void *ptr, int ilen, int olen)
2870 {
2871 	struct strioctl	str;
2872 
2873 	str.ic_cmd = cmd;
2874 	str.ic_timout = PPPSTRTIMOUT;
2875 	str.ic_len = ilen;
2876 	str.ic_dp = ptr;
2877 
2878 	if (myioctl(fd, I_STR, &str) == -1) {
2879 		return (-1);
2880 	}
2881 	if (str.ic_len != olen) {
2882 		dbglog("strioctl: expected %d bytes, got %d for cmd %x\n",
2883 		    olen, str.ic_len, cmd);
2884 	}
2885 	return (0);
2886 }
2887 
2888 /*
2889  * have_route_to()
2890  *
2891  * Determine if the system has a route to the specified IP address.
2892  * Returns 0 if not, 1 if so, -1 if we can't tell. `addr' is in network
2893  * byte order. For demand mode to work properly, we have to ignore routes
2894  * through our own interface. XXX Would be nice to use routing socket.
2895  */
2896 int
2897 have_route_to(addr)
2898 	u_int32_t addr;
2899 {
2900 	int r, flags, i;
2901 	struct {
2902 		struct T_optmgmt_req req;
2903 		struct opthdr hdr;
2904 	} req;
2905 	union {
2906 		struct T_optmgmt_ack ack;
2907 		unsigned char space[64];
2908 	} ack;
2909 	struct opthdr *rh;
2910 	struct strbuf cbuf, dbuf;
2911 	int nroutes;
2912 	mib2_ipRouteEntry_t routes[8];
2913 	mib2_ipRouteEntry_t *rp;
2914 
2915 	if (ipfd == -1 && open_ipfd() == -1)
2916 		return (0);
2917 
2918 	req.req.PRIM_type = T_OPTMGMT_REQ;
2919 	req.req.OPT_offset = (caddr_t)&req.hdr - (caddr_t)&req;
2920 	req.req.OPT_length = sizeof (req.hdr);
2921 #ifdef T_CURRENT
2922 	req.req.MGMT_flags = T_CURRENT;
2923 #else
2924 	/* Old-style */
2925 	req.req.MGMT_flags = T_CHECK;
2926 #endif
2927 
2928 	req.hdr.level = MIB2_IP;
2929 	req.hdr.name = 0;
2930 	req.hdr.len = 0;
2931 
2932 	cbuf.buf = (caddr_t)&req;
2933 	cbuf.len = sizeof (req);
2934 
2935 	if (putmsg(ipfd, &cbuf, NULL, 0) == -1) {
2936 		warn("have_route_to: putmsg: %m");
2937 		return (-1);
2938 	}
2939 
2940 	for (;;) {
2941 		cbuf.buf = (caddr_t)&ack;
2942 		cbuf.maxlen = sizeof (ack);
2943 		dbuf.buf = (caddr_t)routes;
2944 		dbuf.maxlen = sizeof (routes);
2945 		flags = 0;
2946 		r = getmsg(ipfd, &cbuf, &dbuf, &flags);
2947 		if (r == -1) {
2948 			warn("have_route_to: getmsg: %m");
2949 			return (-1);
2950 		}
2951 
2952 		if (cbuf.len < sizeof (struct T_optmgmt_ack) ||
2953 		    ack.ack.PRIM_type != T_OPTMGMT_ACK ||
2954 		    ack.ack.MGMT_flags != T_SUCCESS ||
2955 		    ack.ack.OPT_length < sizeof (struct opthdr)) {
2956 			dbglog("have_route_to: bad message len=%d prim=%d",
2957 			    cbuf.len, ack.ack.PRIM_type);
2958 			return (-1);
2959 		}
2960 		/* LINTED */
2961 		rh = (struct opthdr *)((caddr_t)&ack + ack.ack.OPT_offset);
2962 		if (rh->level == 0 && rh->name == 0) {
2963 			break;
2964 		}
2965 		if (rh->level != MIB2_IP || rh->name != MIB2_IP_21) {
2966 			while (r == MOREDATA) {
2967 				r = getmsg(ipfd, NULL, &dbuf, &flags);
2968 			}
2969 			continue;
2970 		}
2971 
2972 		/*
2973 		 * Note that we have to skip routes to our own
2974 		 * interface in order for demand dial to work.
2975 		 *
2976 		 * XXX awful hack here.  We don't know our own
2977 		 * ifIndex, so we can't check ipRouteIfIndex here.
2978 		 * Instead, we check the next hop address.
2979 		 */
2980 		for (;;) {
2981 			nroutes = dbuf.len / sizeof (mib2_ipRouteEntry_t);
2982 			for (rp = routes, i = 0; i < nroutes; ++i, ++rp) {
2983 				if (rp->ipRouteNextHop != remote_addr &&
2984 				    ((addr ^ rp->ipRouteDest) &
2985 					rp->ipRouteMask) == 0) {
2986 					dbglog("have route to %I/%I via %I",
2987 					    rp->ipRouteDest,
2988 					    rp->ipRouteMask,
2989 					    rp->ipRouteNextHop);
2990 					return (1);
2991 				}
2992 			}
2993 			if (r == 0) {
2994 				break;
2995 			}
2996 			r = getmsg(ipfd, NULL, &dbuf, &flags);
2997 		}
2998 	}
2999 	return (0);
3000 }
3001 
3002 /*
3003  * get_pty()
3004  *
3005  * Get a pty master/slave pair and chown the slave side to the uid given.
3006  * Assumes slave_name points to MAXPATHLEN bytes of space.
3007  */
3008 int
3009 get_pty(master_fdp, slave_fdp, slave_name, uid)
3010 	int *master_fdp;
3011 	int *slave_fdp;
3012 	char *slave_name;
3013 	int uid;
3014 {
3015 	int mfd;
3016 	int sfd;
3017 	char *pty_name;
3018 
3019 	mfd = open("/dev/ptmx", O_NOCTTY | O_RDWR);
3020 	if (mfd < 0) {
3021 		error("Couldn't open pty master: %m");
3022 		return (0);
3023 	}
3024 	pty_name = ptsname(mfd);
3025 	if (pty_name == NULL) {
3026 		dbglog("Didn't get pty slave name on first try; sleeping.");
3027 		/* In case "grow" operation is in progress; try again. */
3028 		(void) sleep(1);
3029 		pty_name = ptsname(mfd);
3030 	}
3031 	if (pty_name == NULL) {
3032 		error("Couldn't get name of pty slave");
3033 		(void) close(mfd);
3034 		return (0);
3035 	}
3036 	if (chown(pty_name, uid, -1) < 0) {
3037 		warn("Couldn't change owner of pty slave: %m");
3038 	}
3039 	if (chmod(pty_name, S_IRUSR | S_IWUSR) < 0) {
3040 		warn("Couldn't change permissions on pty slave: %m");
3041 	}
3042 	if (unlockpt(mfd) < 0) {
3043 		warn("Couldn't unlock pty slave: %m");
3044 	}
3045 	sfd = open(pty_name, O_RDWR);
3046 	if (sfd < 0) {
3047 		error("Couldn't open pty slave %s: %m", pty_name);
3048 		(void) close(mfd);
3049 		return (0);
3050 	}
3051 	if (myioctl(sfd, I_PUSH, "ptem") < 0) {
3052 		warn("Couldn't push ptem module on pty slave: %m");
3053 	}
3054 	dbglog("Using %s; master fd %d, slave fd %d", pty_name, mfd, sfd);
3055 
3056 	(void) strlcpy(slave_name, pty_name, MAXPATHLEN);
3057 
3058 	*master_fdp = mfd;
3059 	*slave_fdp = sfd;
3060 
3061 	return (1);
3062 }
3063 
3064 #ifdef INET6
3065 static int
3066 open_udp6fd(void)
3067 {
3068 	int udp6fd;
3069 
3070 	udp6fd = open(UDP6_DEV_NAME, O_RDWR | O_NONBLOCK, 0);
3071 	if (udp6fd < 0) {
3072 		error("Couldn't open UDPv6 device (%s): %m", UDP6_DEV_NAME);
3073 	}
3074 	return (udp6fd);
3075 }
3076 
3077 /*
3078  * plumb_ip6if()
3079  *
3080  * Perform IPv6 interface plumbing.
3081  */
3082 /*ARGSUSED*/
3083 static int
3084 plumb_ip6if(int unit)
3085 {
3086 	int udp6fd = -1, tmpfd;
3087 	uint32_t x;
3088 	struct lifreq lifr;
3089 
3090 	if (!IPV6CP_ENABLED || (ifunit == -1) || (pppfd == -1)) {
3091 		return (0);
3092 	}
3093 	if (plumbed)
3094 		return (1);
3095 	if (ip6fd == -1 && open_ip6fd() == -1)
3096 		return (0);
3097 	if (use_plink && (udp6fd = open_udp6fd()) == -1)
3098 		return (0);
3099 	tmpfd = open(drvnam, O_RDWR | O_NONBLOCK, 0);
3100 	if (tmpfd < 0) {
3101 		error("Couldn't open PPP device (%s): %m", drvnam);
3102 		if (udp6fd != -1)
3103 			(void) close(udp6fd);
3104 		return (0);
3105 	}
3106 	if (kdebugflag & 1) {
3107 		x = PPPDBG_LOG + PPPDBG_DRIVER;
3108 		if (strioctl(tmpfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) {
3109 			warn("PPPIO_DEBUG ioctl for mux failed: %m");
3110 		}
3111 	}
3112 	if (myioctl(tmpfd, I_PUSH, IP_MOD_NAME) < 0) {
3113 		error("Couldn't push IP module(%s): %m", IP_MOD_NAME);
3114 		goto err_ret;
3115 	}
3116 	/*
3117 	 * Sets interface ppa and flags (refer to comments in plumb_ipif for
3118 	 * the IF_UNITSEL ioctl). In addition, the IFF_IPV6 bit must be set in
3119 	 * order to declare this as an IPv6 interface.
3120 	 */
3121 	BZERO(&lifr, sizeof (lifr));
3122 	if (myioctl(tmpfd, SIOCGLIFFLAGS, &lifr) < 0) {
3123 		error("Couldn't get IPv6 interface flags: %m");
3124 		goto err_ret;
3125 	}
3126 	lifr.lifr_flags |= IFF_IPV6;
3127 	lifr.lifr_flags &= ~(IFF_BROADCAST | IFF_IPV4);
3128 	lifr.lifr_ppa = ifunit;
3129 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
3130 	if (myioctl(tmpfd, SIOCSLIFNAME, &lifr) < 0) {
3131 		error("Can't set ifname for unit %d: %m", ifunit);
3132 		goto err_ret;
3133 	}
3134 	if (use_plink) {
3135 		ip6muxid = myioctl(udp6fd, I_PLINK, (void *)tmpfd);
3136 		if (ip6muxid < 0) {
3137 			error("Can't I_PLINK PPP device to IPv6: %m");
3138 			goto err_ret;
3139 		}
3140 	} else {
3141 		ip6muxid = myioctl(ip6fd, I_LINK, (void *)tmpfd);
3142 		if (ip6muxid < 0) {
3143 			error("Can't I_LINK PPP device to IPv6: %m");
3144 			goto err_ret;
3145 		}
3146 	}
3147 	lifr.lifr_ip_muxid = ip6muxid;
3148 	lifr.lifr_arp_muxid = -1;
3149 	if (myioctl(ip6fd, SIOCSLIFMUXID, (caddr_t)&lifr) < 0) {
3150 		error("Can't set mux ID:  SIOCSLIFMUXID: %m");
3151 		goto err_ret;
3152 	}
3153 	(void) close(tmpfd);
3154 	if (udp6fd != -1)
3155 		(void) close(udp6fd);
3156 	return (1);
3157 
3158 err_ret:
3159 	(void) close(tmpfd);
3160 	if (udp6fd != -1)
3161 		(void) close(udp6fd);
3162 	return (0);
3163 }
3164 
3165 /*
3166  * unplumb_ip6if()
3167  *
3168  * Perform IPv6 interface unplumbing.  Possibly called from die(), so there
3169  * shouldn't be any call to die() here.
3170  */
3171 static int
3172 unplumb_ip6if(int unit)
3173 {
3174 	int udp6fd = -1, fd = -1;
3175 	int id;
3176 	struct lifreq lifr;
3177 
3178 	if (!IPV6CP_ENABLED || ifunit == -1) {
3179 		return (0);
3180 	}
3181 	if (!plumbed && (ip6muxid == -1 || (ip6fd == -1 && !use_plink))) {
3182 		return (1);
3183 	}
3184 	id = ip6muxid;
3185 	if (!plumbed && use_plink) {
3186 		if ((udp6fd = open_udp6fd()) == -1)
3187 			return (0);
3188 		/*
3189 		 * Note: must re-get mux ID, since any intervening
3190 		 * ifconfigs will change this.
3191 		 */
3192 		BZERO(&lifr, sizeof (lifr));
3193 		(void) strlcpy(lifr.lifr_name, ifname,
3194 		    sizeof (lifr.lifr_name));
3195 		if (myioctl(ip6fd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) {
3196 			warn("Can't get mux fd: SIOCGLIFMUXID: %m");
3197 		} else {
3198 			id = lifr.lifr_ip_muxid;
3199 			fd = myioctl(udp6fd, _I_MUXID2FD, (void *)id);
3200 			if (fd < 0) {
3201 				warn("Can't get mux fd: _I_MUXID2FD: %m");
3202 			}
3203 		}
3204 	}
3205 	/*
3206 	 * Mark down and unlink the IPv6 interface.
3207 	 */
3208 	(void) sif6down(unit);
3209 	if (plumbed)
3210 		return (1);
3211 	ip6muxid = -1;
3212 	if (use_plink) {
3213 		if ((fd = myioctl(udp6fd, _I_MUXID2FD, (void *)id)) < 0) {
3214 			error("Can't recapture mux fd: _I_MUXID2FD: %m");
3215 			(void) close(udp6fd);
3216 			return (0);
3217 		}
3218 		if (myioctl(udp6fd, I_PUNLINK, (void *)id) < 0) {
3219 			error("Can't I_PUNLINK PPP from IPv6: %m");
3220 			(void) close(fd);
3221 			(void) close(udp6fd);
3222 			return (0);
3223 		}
3224 		(void) close(fd);
3225 		(void) close(udp6fd);
3226 	} else {
3227 		if (myioctl(ip6fd, I_UNLINK, (void *)id) < 0) {
3228 			error("Can't I_UNLINK PPP from IPv6: %m");
3229 			return (0);
3230 		}
3231 	}
3232 	return (1);
3233 }
3234 
3235 /*
3236  * sif6flags()
3237  *
3238  * Set or clear the IPv6 interface flags.
3239  */
3240 int
3241 sif6flags(f, set)
3242 	u_int32_t f;
3243 	int set;
3244 {
3245 	struct lifreq lifr;
3246 	int fd;
3247 
3248 	if (!IPV6CP_ENABLED || (ip6muxid == -1)) {
3249 		return (0);
3250 	}
3251 	fd = socket(AF_INET6, SOCK_DGRAM, 0);
3252 	if (fd < 0) {
3253 		error("sif6flags: error opening IPv6 socket: %m");
3254 		return (0);
3255 	}
3256 	BZERO(&lifr, sizeof (lifr));
3257 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
3258 	if (myioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
3259 		error("Couldn't get IPv6 interface flags: %m");
3260 		(void) close(fd);
3261 		return (0);
3262 	}
3263 	if (set) {
3264 		lifr.lifr_flags |= f;
3265 	} else {
3266 		lifr.lifr_flags &= ~f;
3267 	}
3268 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
3269 	if (myioctl(fd, SIOCSLIFFLAGS, &lifr) < 0) {
3270 		error("Couldn't set IPv6 interface flags: %m");
3271 		(void) close(fd);
3272 		return (0);
3273 	}
3274 	(void) close(fd);
3275 	return (1);
3276 }
3277 
3278 /*
3279  * sif6up()
3280  *
3281  * Config the IPv6 interface up and enable IPv6 packets to pass.
3282  */
3283 /*ARGSUSED*/
3284 int
3285 sif6up(unit)
3286 	int unit;
3287 {
3288 	if (if6_is_up) {
3289 		return (1);
3290 	} else if (!IPV6CP_ENABLED) {
3291 		warn("sif6up called when IPV6CP is disabled");
3292 		return (0);
3293 	} else if (ip6muxid == -1) {
3294 		warn("sif6up called in wrong state");
3295 		return (0);
3296 	} else if (!sif6flags(IFF_UP, 1)) {
3297 		error("Unable to mark the IPv6 interface UP");
3298 		return (0);
3299 	}
3300 	if6_is_up = 1;
3301 	return (1);
3302 }
3303 
3304 /*
3305  * sif6down()
3306  *
3307  * Config the IPv6 interface down and disable IPv6.  Possibly called from
3308  * die(), so there shouldn't be any call to die() here.
3309  */
3310 /*ARGSUSED*/
3311 int
3312 sif6down(unit)
3313 	int unit;
3314 {
3315 	if (!IPV6CP_ENABLED) {
3316 		warn("sif6down called when IPV6CP is disabled");
3317 		return (0);
3318 	} else if (!if6_is_up || (ip6muxid == -1)) {
3319 		return (1);
3320 	} else if (!sif6flags(IFF_UP, 0)) {
3321 		error("Unable to mark the IPv6 interface DOWN");
3322 		return (0);
3323 	}
3324 	if6_is_up = 0;
3325 	return (1);
3326 }
3327 
3328 /*
3329  * sif6mtu()
3330  *
3331  * Config the IPv6 interface MTU.
3332  */
3333 int
3334 sif6mtu(mtu)
3335 	int mtu;
3336 {
3337 	struct lifreq lifr;
3338 	int s;
3339 
3340 	if (!IPV6CP_ENABLED || (ip6muxid == -1)) {
3341 		return (0);
3342 	}
3343 	s = socket(AF_INET6, SOCK_DGRAM, 0);
3344 	if (s < 0) {
3345 		error("sif6mtu: error opening IPv6 socket: %m");
3346 		return (0);
3347 	}
3348 	BZERO(&lifr, sizeof (lifr));
3349 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
3350 	lifr.lifr_mtu = mtu;
3351 	if (myioctl(s, SIOCSLIFMTU, &lifr) < 0) {
3352 		error("Couldn't set IPv6 MTU (%s): %m", lifr.lifr_name);
3353 		(void) close(s);
3354 		return (0);
3355 	}
3356 	(void) close(s);
3357 	return (1);
3358 }
3359 
3360 /*
3361  * sif6addr()
3362  *
3363  * Config the interface with an IPv6 link-local address.
3364  */
3365 /*ARGSUSED*/
3366 int
3367 sif6addr(unit, ourid, hisid)
3368 	int unit;
3369 	eui64_t ourid;
3370 	eui64_t hisid;
3371 {
3372 	struct lifreq lifr;
3373 	struct sockaddr_storage	laddr;
3374 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&laddr;
3375 	int fd;
3376 
3377 	if (!IPV6CP_ENABLED || (ip6muxid == -1 && plumb_ip6if(unit) == 0)) {
3378 		return (0);
3379 	}
3380 	fd = socket(AF_INET6, SOCK_DGRAM, 0);
3381 	if (fd < 0) {
3382 		error("sif6addr: error opening IPv6 socket: %m");
3383 		return (0);
3384 	}
3385 	/*
3386 	 * Set the IPv6 interface MTU.
3387 	 */
3388 	if (!sif6mtu(link_mtu)) {
3389 		(void) close(fd);
3390 		return (0);
3391 	}
3392 	/*
3393 	 * Set the interface address token.  Do this because /dev/ppp responds
3394 	 * to DL_PHYS_ADDR_REQ with zero values, hence the interface token
3395 	 * came to be zero too, and without this, in.ndpd will complain.
3396 	 */
3397 	BZERO(&lifr, sizeof (lifr));
3398 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
3399 	BZERO(sin6, sizeof (struct sockaddr_in6));
3400 	IN6_LLTOKEN_FROM_EUI64(lifr, sin6, ourid);
3401 	if (myioctl(fd, SIOCSLIFTOKEN, &lifr) < 0) {
3402 		error("Couldn't set IPv6 token (%s): %m", lifr.lifr_name);
3403 		(void) close(fd);
3404 		return (0);
3405 	}
3406 	/*
3407 	 * Set the IPv6 interface local point-to-point address.
3408 	 */
3409 	IN6_LLADDR_FROM_EUI64(lifr, sin6, ourid);
3410 	if (myioctl(fd, SIOCSLIFADDR, &lifr) < 0) {
3411 		error("Couldn't set local IPv6 address (%s): %m",
3412 		    lifr.lifr_name);
3413 		(void) close(fd);
3414 		return (0);
3415 	}
3416 	/*
3417 	 * Set the IPv6 interface local point-to-point address.
3418 	 */
3419 	BZERO(&lifr, sizeof (lifr));
3420 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
3421 	IN6_LLADDR_FROM_EUI64(lifr, sin6, hisid);
3422 	if (myioctl(fd, SIOCSLIFDSTADDR, &lifr) < 0) {
3423 		error("Couldn't set remote IPv6 address (%s): %m",
3424 		    lifr.lifr_name);
3425 		(void) close(fd);
3426 		return (0);
3427 	}
3428 	(void) close(fd);
3429 	return (1);
3430 }
3431 
3432 /*
3433  * cif6addr()
3434  */
3435 /*ARGSUSED*/
3436 int
3437 cif6addr(u, o, h)
3438 	int u;
3439 	eui64_t o;
3440 	eui64_t h;
3441 {
3442 	if (!IPV6CP_ENABLED) {
3443 		return (0);
3444 	}
3445 	/*
3446 	 * Do nothing here, as everything has been done in sif6down().
3447 	 */
3448 	return (1);
3449 }
3450 
3451 /*
3452  * ether_to_eui64()
3453  *
3454  * Convert 48-bit Ethernet address into 64-bit EUI. Walks the list of valid
3455  * ethernet interfaces, and convert the first found 48-bit MAC address into
3456  * EUI 64. caller also assumes that the system has a properly configured
3457  * Ethernet interface for this function to return non-zero.
3458  */
3459 int
3460 ether_to_eui64(p_eui64)
3461 	eui64_t *p_eui64;
3462 {
3463 	struct ether_addr eth_addr;
3464 
3465 	if (p_eui64 == NULL) {
3466 		return (0);
3467 	}
3468 	if (!get_first_hwaddr(eth_addr.ether_addr_octet,
3469 	    sizeof (eth_addr.ether_addr_octet))) {
3470 		return (0);
3471 	}
3472 	/*
3473 	 * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1]
3474 	 */
3475 	p_eui64->e8[0] = (eth_addr.ether_addr_octet[0] & 0xFF) | 0x02;
3476 	p_eui64->e8[1] = (eth_addr.ether_addr_octet[1] & 0xFF);
3477 	p_eui64->e8[2] = (eth_addr.ether_addr_octet[2] & 0xFF);
3478 	p_eui64->e8[3] = 0xFF;
3479 	p_eui64->e8[4] = 0xFE;
3480 	p_eui64->e8[5] = (eth_addr.ether_addr_octet[3] & 0xFF);
3481 	p_eui64->e8[6] = (eth_addr.ether_addr_octet[4] & 0xFF);
3482 	p_eui64->e8[7] = (eth_addr.ether_addr_octet[5] & 0xFF);
3483 	return (1);
3484 }
3485 #endif /* INET6 */
3486 
3487 struct bit_ent {
3488 	int val;
3489 	char *off, *on;
3490 };
3491 
3492 /* see sbuf[] below if you change this list */
3493 static struct bit_ent bit_list[] = {
3494 	{ TIOCM_DTR, "dtr", "DTR" },
3495 	{ TIOCM_RTS, "rts", "RTS" },
3496 	{ TIOCM_CTS, "cts", "CTS" },
3497 	{ TIOCM_CD, "dcd", "DCD" },
3498 	{ TIOCM_RI, "ri", "RI" },
3499 	{ TIOCM_DSR, "dsr", "DSR" },
3500 #if 0
3501 	{ TIOCM_LE, "disabled", "ENABLED" },
3502 	{ TIOCM_ST, NULL, "2nd-XMIT" },
3503 	{ TIOCM_SR, NULL, "2nd-RECV" },
3504 #endif
3505 	{ 0, NULL, NULL }
3506 };
3507 
3508 static void
3509 getbits(int fd, char *name, FILE *strptr)
3510 {
3511 	int nmods, i;
3512 	struct str_list strlist;
3513 	struct bit_ent *be;
3514 	int mstate;
3515 	char sbuf[50];		/* sum of string lengths in bit_list */
3516 	char *str;
3517 
3518 	nmods = ioctl(fd, I_LIST, NULL);
3519 	if (nmods < 0) {
3520 		error("unable to get module count: %m");
3521 	} else {
3522 		strlist.sl_nmods = nmods;
3523 		strlist.sl_modlist = malloc(sizeof (struct str_mlist) * nmods);
3524 		if (strlist.sl_modlist == NULL)
3525 			novm("module list");
3526 		if (ioctl(fd, I_LIST, (caddr_t)&strlist) < 0) {
3527 			error("unable to get module names: %m");
3528 		} else {
3529 			for (i = 0; i < strlist.sl_nmods; i++)
3530 				(void) flprintf(strptr, "%d: %s", i,
3531 				    strlist.sl_modlist[i].l_name);
3532 			free(strlist.sl_modlist);
3533 		}
3534 	}
3535 	if (ioctl(fd, TIOCMGET, &mstate) < 0) {
3536 		error("unable to get modem state: %m");
3537 	} else {
3538 		sbuf[0] = '\0';
3539 		for (be = bit_list; be->val != 0; be++) {
3540 			str = (be->val & mstate) ? be->on : be->off;
3541 			if (str != NULL) {
3542 				if (sbuf[0] != '\0')
3543 					(void) strcat(sbuf, " ");
3544 				(void) strcat(sbuf, str);
3545 			}
3546 		}
3547 		(void) flprintf(strptr, "%s: %s\n", name, sbuf);
3548 	}
3549 }
3550 
3551 /*
3552  * Print state of serial link.  The stream might be linked under the
3553  * /dev/sppp driver.  If it is, then it's necessary to unlink it first
3554  * and relink it when done.  Otherwise, it's not possible to use
3555  * ioctl() on the stream.
3556  */
3557 void
3558 sys_print_state(FILE *strptr)
3559 {
3560 	bool was_linked;
3561 
3562 	if (pppfd == -1)
3563 		return;
3564 	if (ttyfd == -1) {
3565 		(void) flprintf(strptr, "serial link is not active");
3566 		return;
3567 	}
3568 	was_linked = fdmuxid != -1;
3569 	if (was_linked && ioctl(pppfd, I_UNLINK, fdmuxid) == -1) {
3570 		error("I_UNLINK: %m");
3571 	} else {
3572 		fdmuxid = -1;
3573 		getbits(ttyfd, devnam, strptr);
3574 		if (was_linked &&
3575 		    (fdmuxid = ioctl(pppfd, I_LINK, (void *)ttyfd)) == -1)
3576 			fatal("I_LINK: %m");
3577 	}
3578 }
3579 
3580 /*
3581  * send ioctl to driver asking it to block packets with network protocol
3582  * proto in the control queue until the queue for proto is plumbed.
3583  */
3584 void
3585 sys_block_proto(uint16_t proto)
3586 {
3587 	if (proto > 0x7fff) {
3588 		warn("cannot block: not a network proto 0x%lx\n", proto);
3589 		return;
3590 	}
3591 	if (strioctl(pppfd, PPPIO_BLOCKNP, &proto, sizeof (proto), 0) < 0) {
3592 		warn("PPPIO_BLOCKNP ioctl failed %m");
3593 	}
3594 }
3595 /*
3596  * send ioctl to driver asking it to release packets with network protocol
3597  * proto from control queue to the protocol specific queue.
3598  */
3599 void
3600 sys_unblock_proto(uint16_t proto)
3601 {
3602 	if (proto > 0x7fff) {
3603 		warn("cannot unblock: not a network proto 0x%lx\n", proto);
3604 		return;
3605 	}
3606 	if (strioctl(pppfd, PPPIO_UNBLOCKNP, &proto, sizeof (proto), 0) < 0) {
3607 		warn("PPPIO_UNBLOCKNP ioctl failed %m");
3608 	}
3609 }
3610