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