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