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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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