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