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