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 #ifdef B50 1128 { 50, B50 }, 1129 #endif 1130 #ifdef B75 1131 { 75, B75 }, 1132 #endif 1133 #ifdef B110 1134 { 110, B110 }, 1135 #endif 1136 #ifdef B134 1137 { 134, B134 }, 1138 #endif 1139 #ifdef B150 1140 { 150, B150 }, 1141 #endif 1142 #ifdef B200 1143 { 200, B200 }, 1144 #endif 1145 #ifdef B300 1146 { 300, B300 }, 1147 #endif 1148 #ifdef B600 1149 { 600, B600 }, 1150 #endif 1151 #ifdef B1200 1152 { 1200, B1200 }, 1153 #endif 1154 #ifdef B1800 1155 { 1800, B1800 }, 1156 #endif 1157 #ifdef B2000 1158 { 2000, B2000 }, 1159 #endif 1160 #ifdef B2400 1161 { 2400, B2400 }, 1162 #endif 1163 #ifdef B3600 1164 { 3600, B3600 }, 1165 #endif 1166 #ifdef B4800 1167 { 4800, B4800 }, 1168 #endif 1169 #ifdef B7200 1170 { 7200, B7200 }, 1171 #endif 1172 #ifdef B9600 1173 { 9600, B9600 }, 1174 #endif 1175 #ifdef B19200 1176 { 19200, B19200 }, 1177 #endif 1178 #ifdef B38400 1179 { 38400, B38400 }, 1180 #endif 1181 #ifdef EXTA 1182 { 19200, EXTA }, 1183 #endif 1184 #ifdef EXTB 1185 { 38400, EXTB }, 1186 #endif 1187 #ifdef B57600 1188 { 57600, B57600 }, 1189 #endif 1190 #ifdef B76800 1191 { 76800, B76800 }, 1192 #endif 1193 #ifdef B115200 1194 { 115200, B115200 }, 1195 #endif 1196 #ifdef B153600 1197 { 153600, B153600 }, 1198 #endif 1199 #ifdef B230400 1200 { 230400, B230400 }, 1201 #endif 1202 #ifdef B307200 1203 { 307200, B307200 }, 1204 #endif 1205 #ifdef B460800 1206 { 460800, B460800 }, 1207 #endif 1208 #ifdef B921600 1209 { 921600, B921600 }, 1210 #endif 1211 { 0, 0 } 1212 }; 1213 1214 /* 1215 * translate_speed() 1216 * 1217 * Translate from bits/second to a speed_t 1218 */ 1219 static int 1220 translate_speed(int bps) 1221 { 1222 struct speed *speedp; 1223 1224 if (bps == 0) { 1225 return (0); 1226 } 1227 for (speedp = speeds; speedp->speed_int; speedp++) { 1228 if (bps == speedp->speed_int) { 1229 return (speedp->speed_val); 1230 } 1231 } 1232 set_source(&speed_info); 1233 option_error("speed %d not supported", bps); 1234 return (0); 1235 } 1236 1237 /* 1238 * baud_rate_of() 1239 * 1240 * Translate from a speed_t to bits/second 1241 */ 1242 static int 1243 baud_rate_of(int speed) 1244 { 1245 struct speed *speedp; 1246 1247 if (speed == 0) { 1248 return (0); 1249 } 1250 for (speedp = speeds; speedp->speed_int; speedp++) { 1251 if (speed == speedp->speed_val) { 1252 return (speedp->speed_int); 1253 } 1254 } 1255 return (0); 1256 } 1257 1258 /* 1259 * set_up_tty() 1260 * 1261 * Set up the serial port on `fd' for 8 bits, no parity, at the requested 1262 * speed, etc. If `local' is true, set CLOCAL regardless of whether the 1263 * modem option was specified. 1264 */ 1265 void 1266 set_up_tty(fd, local) 1267 int fd, local; 1268 { 1269 int speed; 1270 struct termios tios; 1271 struct scc_mode sm; 1272 1273 if (already_ppp) 1274 return; 1275 1276 if (sync_serial) { 1277 restore_term = 0; 1278 speed = B0; 1279 baud_rate = 0; 1280 1281 if (strioctl(fd, S_IOCGETMODE, &sm, sizeof (sm), 1282 sizeof (sm)) < 0) { 1283 return; 1284 } 1285 1286 baud_rate = sm.sm_baudrate; 1287 dbglog("synchronous speed appears to be %d bps", baud_rate); 1288 } else { 1289 if (tcgetattr(fd, &tios) < 0) { 1290 fatal("tcgetattr: %m"); 1291 } 1292 if (!restore_term) { 1293 inittermios = tios; 1294 if (myioctl(fd, TIOCGWINSZ, &wsinfo) < 0) { 1295 if (errno == EINVAL) { 1296 /* 1297 * ptem returns EINVAL if all zeroes. 1298 * Strange and unfixable code. 1299 */ 1300 bzero(&wsinfo, sizeof (wsinfo)); 1301 } else { 1302 warn("unable to get TTY window " 1303 "size: %m"); 1304 } 1305 } 1306 } 1307 tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL); 1308 if (crtscts > 0) { 1309 tios.c_cflag |= CRTSCTS | CRTSXOFF; 1310 } else if (crtscts < 0) { 1311 tios.c_cflag &= ~CRTSCTS & ~CRTSXOFF; 1312 } 1313 tios.c_cflag |= CS8 | CREAD | HUPCL; 1314 if (local || !modem) { 1315 tios.c_cflag |= CLOCAL; 1316 } 1317 tios.c_iflag = IGNBRK | IGNPAR; 1318 tios.c_oflag = 0; 1319 tios.c_lflag = 0; 1320 tios.c_cc[VMIN] = 1; 1321 tios.c_cc[VTIME] = 0; 1322 1323 if (crtscts == -2) { 1324 tios.c_iflag |= IXON | IXOFF; 1325 tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ 1326 tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ 1327 } 1328 speed = translate_speed(inspeed); 1329 if (speed) { 1330 (void) cfsetospeed(&tios, speed); 1331 (void) cfsetispeed(&tios, speed); 1332 } else { 1333 speed = cfgetospeed(&tios); 1334 /* 1335 * We can't proceed if the serial port speed is 0, 1336 * since that implies that the serial port is disabled. 1337 */ 1338 if (speed == B0) { 1339 fatal("Baud rate for %s is 0; need explicit " 1340 "baud rate", devnam); 1341 } 1342 } 1343 if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { 1344 fatal("tcsetattr: %m"); 1345 } 1346 baud_rate = baud_rate_of(speed); 1347 dbglog("%s speed set to %d bps", 1348 fd == pty_slave ? "pty" : "serial", baud_rate); 1349 restore_term = 1; 1350 } 1351 } 1352 1353 /* 1354 * restore_tty() 1355 * 1356 * Restore the terminal to the saved settings. 1357 */ 1358 void 1359 restore_tty(fd) 1360 int fd; 1361 { 1362 if (restore_term == 0) { 1363 return; 1364 } 1365 if (!default_device) { 1366 /* 1367 * Turn off echoing, because otherwise we can get into 1368 * a loop with the tty and the modem echoing to each 1369 * other. We presume we are the sole user of this tty 1370 * device, so when we close it, it will revert to its 1371 * defaults anyway. 1372 */ 1373 inittermios.c_lflag &= ~(ECHO | ECHONL); 1374 } 1375 if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) { 1376 if (!hungup && errno != ENXIO) { 1377 warn("tcsetattr: %m"); 1378 } 1379 } 1380 if (wsinfo.ws_row != 0 || wsinfo.ws_col != 0 || 1381 wsinfo.ws_xpixel != 0 || wsinfo.ws_ypixel != 0) { 1382 if (myioctl(fd, TIOCSWINSZ, &wsinfo) < 0) { 1383 warn("unable to set TTY window size: %m"); 1384 } 1385 } 1386 restore_term = 0; 1387 } 1388 1389 /* 1390 * setdtr() 1391 * 1392 * Control the DTR line on the serial port. This is called from die(), so it 1393 * shouldn't call die() 1394 */ 1395 void 1396 setdtr(fd, on) 1397 int fd, on; 1398 { 1399 int modembits = TIOCM_DTR; 1400 if (!already_ppp && 1401 myioctl(fd, (on ? TIOCMBIS : TIOCMBIC), &modembits) < 0) { 1402 warn("unable to set DTR line %s: %m", (on ? "ON" : "OFF")); 1403 } 1404 } 1405 1406 /* 1407 * open_loopback() 1408 * 1409 * Open the device we use for getting packets in demand mode. Under Solaris 2, 1410 * we use our existing fd to the ppp driver. 1411 */ 1412 int 1413 open_ppp_loopback() 1414 { 1415 /* 1416 * Plumb the interface. 1417 */ 1418 if (IPCP_ENABLED && (plumb_ipif(0) == 0)) { 1419 fatal("Unable to initialize IP interface for demand dial."); 1420 } 1421 #ifdef INET6 1422 if (IPV6CP_ENABLED && (plumb_ip6if(0) == 0)) { 1423 fatal("Unable to initialize IPv6 interface for demand dial."); 1424 } 1425 #endif /* INET6 */ 1426 1427 return (pppfd); 1428 } 1429 1430 /* 1431 * output() 1432 * 1433 * Output PPP packet downstream 1434 */ 1435 /*ARGSUSED*/ 1436 void 1437 output(unit, p, len) 1438 int unit; 1439 uchar_t *p; 1440 int len; 1441 { 1442 struct strbuf data; 1443 struct pollfd pfd; 1444 int retries, n; 1445 bool sent_ok = 1; 1446 1447 data.len = len; 1448 data.buf = (caddr_t)p; 1449 retries = 4; 1450 1451 while (putmsg(pppfd, NULL, &data, 0) < 0) { 1452 if (errno == EINTR) 1453 continue; 1454 if (--retries < 0 || 1455 (errno != EWOULDBLOCK && errno != EAGAIN)) { 1456 if (errno != ENXIO) { 1457 error("Couldn't send packet: %m"); 1458 sent_ok = 0; 1459 } 1460 break; 1461 } 1462 pfd.fd = pppfd; 1463 pfd.events = POLLOUT; 1464 do { 1465 /* wait for up to 0.25 seconds */ 1466 n = poll(&pfd, 1, 250); 1467 } while ((n == -1) && (errno == EINTR)); 1468 } 1469 if (debug && sent_ok) { 1470 dbglog("sent %P", p, len); 1471 } 1472 } 1473 1474 /* 1475 * wait_input() 1476 * 1477 * Wait until there is data available, for the length of time specified by 1478 * timo (indefinite if timo is NULL). 1479 */ 1480 void 1481 wait_input(timo) 1482 struct timeval *timo; 1483 { 1484 int t; 1485 1486 t = (timo == NULL ? -1 : (timo->tv_sec * 1000 + timo->tv_usec / 1000)); 1487 if ((poll(pollfds, n_pollfds, t) < 0) && (errno != EINTR)) { 1488 fatal("poll: %m"); 1489 } 1490 } 1491 1492 /* 1493 * add_fd() 1494 * 1495 * Add an fd to the set that wait_input waits for. 1496 */ 1497 void 1498 add_fd(fd) 1499 int fd; 1500 { 1501 int n; 1502 1503 if (fd < 0) { 1504 return; 1505 } 1506 for (n = 0; n < n_pollfds; ++n) { 1507 if (pollfds[n].fd == fd) { 1508 return; 1509 } 1510 } 1511 if (n_pollfds < MAX_POLLFDS) { 1512 pollfds[n_pollfds].fd = fd; 1513 pollfds[n_pollfds].events = POLLIN | POLLPRI | POLLHUP; 1514 ++n_pollfds; 1515 } else { 1516 fatal("add_fd: too many inputs!"); 1517 } 1518 } 1519 1520 /* 1521 * remove_fd() 1522 * 1523 * Remove an fd from the set that wait_input waits for. 1524 */ 1525 void 1526 remove_fd(fd) 1527 int fd; 1528 { 1529 int n; 1530 1531 for (n = 0; n < n_pollfds; ++n) { 1532 if (pollfds[n].fd == fd) { 1533 while (++n < n_pollfds) { 1534 pollfds[n-1] = pollfds[n]; 1535 } 1536 --n_pollfds; 1537 break; 1538 } 1539 } 1540 } 1541 1542 static void 1543 dump_packet(uchar_t *buf, int len) 1544 { 1545 uchar_t *bp; 1546 int proto, offs; 1547 const char *cp; 1548 char sbuf[32]; 1549 uint32_t src, dst; 1550 struct protoent *pep; 1551 struct in6_addr addr; 1552 char fromstr[INET6_ADDRSTRLEN]; 1553 char tostr[INET6_ADDRSTRLEN]; 1554 1555 if (len < 4) { 1556 notice("strange link activity: %.*B", len, buf); 1557 return; 1558 } 1559 bp = buf; 1560 if (bp[0] == 0xFF && bp[1] == 0x03) 1561 bp += 2; 1562 proto = *bp++; 1563 if (!(proto & 1)) 1564 proto = (proto << 8) + *bp++; 1565 len -= bp-buf; 1566 switch (proto) { 1567 case PPP_IP: 1568 if (len < IP_HDRLEN || get_ipv(bp) != 4 || get_iphl(bp) < 5) { 1569 notice("strange IP packet activity: %16.*B", len, buf); 1570 return; 1571 } 1572 src = get_ipsrc(bp); 1573 dst = get_ipdst(bp); 1574 proto = get_ipproto(bp); 1575 if ((pep = getprotobynumber(proto)) != NULL) { 1576 cp = pep->p_name; 1577 } else { 1578 (void) slprintf(sbuf, sizeof (sbuf), "IP proto %d", 1579 proto); 1580 cp = sbuf; 1581 } 1582 if ((get_ipoff(bp) & IP_OFFMASK) != 0) { 1583 len -= get_iphl(bp) * 4; 1584 bp += get_iphl(bp) * 4; 1585 notice("%s fragment from %I->%I: %8.*B", cp, src, dst, 1586 len, bp); 1587 } else { 1588 if (len > get_iplen(bp)) 1589 len = get_iplen(bp); 1590 len -= get_iphl(bp) * 4; 1591 bp += get_iphl(bp) * 4; 1592 offs = proto == IPPROTO_TCP ? (get_tcpoff(bp)*4) : 8; 1593 if (proto == IPPROTO_TCP || proto == IPPROTO_UDP) 1594 notice("%s data:%d %s%I:%d->%I:%d: %8.*B", cp, 1595 len-offs, 1596 proto == IPPROTO_TCP ? 1597 tcp_flag_decode(get_tcpflags(bp)) : "", 1598 src, get_sport(bp), dst, get_dport(bp), 1599 len-offs, bp+offs); 1600 else 1601 notice("%s %d bytes %I->%I: %8.*B", cp, len, 1602 src, dst, len, bp); 1603 } 1604 return; 1605 1606 case PPP_IPV6: 1607 if (len < IP6_HDRLEN) { 1608 notice("strange IPv6 activity: %16.*B", len, buf); 1609 return; 1610 } 1611 (void) BCOPY(get_ip6src(bp), &addr, sizeof (addr)); 1612 (void) inet_ntop(AF_INET6, &addr, fromstr, sizeof (fromstr)); 1613 (void) BCOPY(get_ip6dst(bp), &addr, sizeof (addr)); 1614 (void) inet_ntop(AF_INET6, &addr, tostr, sizeof (tostr)); 1615 proto = get_ip6nh(bp); 1616 if (proto == IPPROTO_FRAGMENT) { 1617 notice("IPv6 fragment from %s->%s", fromstr, 1618 tostr); 1619 return; 1620 } 1621 if ((pep = getprotobynumber(proto)) != NULL) { 1622 cp = pep->p_name; 1623 } else { 1624 (void) slprintf(sbuf, sizeof (sbuf), "IPv6 proto %d", 1625 proto); 1626 cp = sbuf; 1627 } 1628 len -= IP6_HDRLEN; 1629 bp += IP6_HDRLEN; 1630 offs = proto == IPPROTO_TCP ? (get_tcpoff(bp)*4) : 8; 1631 if (proto == IPPROTO_TCP || proto == IPPROTO_UDP) 1632 notice("%s data:%d %s[%s]%d->[%s]%d: %8.*B", cp, 1633 len-offs, 1634 proto == IPPROTO_TCP ? 1635 tcp_flag_decode(get_tcpflags(bp)) : "", 1636 fromstr, get_sport(bp), tostr, get_dport(bp), 1637 len-offs, bp+offs); 1638 else 1639 notice("%s %d bytes %s->%s: %8.*B", cp, len, 1640 fromstr, tostr, len, bp); 1641 return; 1642 } 1643 if ((cp = protocol_name(proto)) == NULL) { 1644 (void) slprintf(sbuf, sizeof (sbuf), "0x#X", proto); 1645 cp = (const char *)sbuf; 1646 } 1647 notice("link activity: %s %16.*B", cp, len, bp); 1648 } 1649 1650 /* 1651 * handle_bind() 1652 */ 1653 static void 1654 handle_bind(u_int32_t reason) 1655 { 1656 /* 1657 * Here we might, in the future, handle DL_BIND_REQ notifications 1658 * in order to close and re-open a NCP when certain interface 1659 * parameters (addresses, etc.) are changed via external mechanisms 1660 * such as through the "ifconfig" program. 1661 */ 1662 switch (reason) { 1663 case PPP_LINKSTAT_IPV4_BOUND: 1664 break; 1665 #ifdef INET6 1666 case PPP_LINKSTAT_IPV6_BOUND: 1667 break; 1668 #endif 1669 default: 1670 error("handle_bind: unrecognized reason"); 1671 break; 1672 } 1673 } 1674 1675 /* 1676 * handle_unbind() 1677 */ 1678 static void 1679 handle_unbind(u_int32_t reason) 1680 { 1681 bool iff_up_isset; 1682 int rc; 1683 static const char *unplumb_str = "unplumbed"; 1684 static const char *down_str = "downed"; 1685 1686 /* 1687 * Since the kernel driver (sppp) notifies this daemon of the 1688 * DLPI bind/unbind activities (for the purpose of bringing down 1689 * a NCP), we need to explicitly test the "actual" status of 1690 * the interface instance for which the notification is destined 1691 * from. This is because /dev/ip performs multiple DLPI attach- 1692 * bind-unbind-detach during the early life of the interface, 1693 * and when certain interface parameters change. A DL_UNBIND_REQ 1694 * coming down to the sppp driver from /dev/ip (which results in 1695 * our receiving of the PPP_LINKSTAT_*_UNBOUND link status message) 1696 * is not enough to conclude that the interface has been marked 1697 * DOWN (its IFF_UP bit is cleared) or is going away. Therefore, 1698 * we should query /dev/ip directly, upon receiving such *_UNBOUND 1699 * notification, to determine whether the interface is DOWN 1700 * for real, and only take the necessary actions when IFF_UP 1701 * bit for the interface instance is actually cleared. 1702 */ 1703 switch (reason) { 1704 case PPP_LINKSTAT_IPV4_UNBOUND: 1705 (void) sleep(1); 1706 rc = giflags(IFF_UP, &iff_up_isset); 1707 if (!iff_up_isset) { 1708 if_is_up = 0; 1709 ipmuxid = -1; 1710 info("IPv4 interface %s by administrator", 1711 ((rc < 0 && rc == ENXIO) ? unplumb_str : down_str)); 1712 fsm_close(&ipcp_fsm[0], 1713 "administratively disconnected"); 1714 } 1715 break; 1716 #ifdef INET6 1717 case PPP_LINKSTAT_IPV6_UNBOUND: 1718 (void) sleep(1); 1719 rc = giflags(IFF_UP, &iff_up_isset); 1720 if (!iff_up_isset) { 1721 if6_is_up = 0; 1722 ip6muxid = -1; 1723 info("IPv6 interface %s by administrator", 1724 ((rc < 0 && rc == ENXIO) ? unplumb_str : down_str)); 1725 fsm_close(&ipv6cp_fsm[0], 1726 "administratively disconnected"); 1727 } 1728 break; 1729 #endif 1730 default: 1731 error("handle_unbind: unrecognized reason"); 1732 break; 1733 } 1734 } 1735 1736 /* 1737 * read_packet() 1738 * 1739 * Get a PPP packet from the serial device. 1740 */ 1741 int 1742 read_packet(buf) 1743 uchar_t *buf; 1744 { 1745 struct strbuf ctrl; 1746 struct strbuf data; 1747 int flags; 1748 int len; 1749 int rc; 1750 struct ppp_ls *plp; 1751 uint32_t ctrlbuf[1536 / sizeof (uint32_t)]; 1752 bool flushmode; 1753 1754 flushmode = 0; 1755 for (;;) { 1756 1757 data.maxlen = PPP_MRU + PPP_HDRLEN; 1758 data.buf = (caddr_t)buf; 1759 1760 ctrl.maxlen = sizeof (ctrlbuf); 1761 ctrl.buf = (caddr_t)ctrlbuf; 1762 1763 flags = 0; 1764 rc = len = getmsg(pppfd, &ctrl, &data, &flags); 1765 if (sys_read_packet_hook != NULL) { 1766 rc = len = (*sys_read_packet_hook)(len, &ctrl, &data, 1767 flags); 1768 } 1769 if (len < 0) { 1770 if (errno == EAGAIN || errno == EINTR) { 1771 return (-1); 1772 } 1773 fatal("Error reading packet: %m"); 1774 } 1775 if ((data.len > 0) && (ctrl.len < 0)) { 1776 /* 1777 * If there's more data on stream head, keep reading 1778 * but discard, since the stream is now corrupt. 1779 */ 1780 if (rc & MOREDATA) { 1781 dbglog("More data; input packet garbled"); 1782 flushmode = 1; 1783 continue; 1784 } 1785 if (flushmode) 1786 return (-1); 1787 return (data.len); 1788 1789 } else if (ctrl.len > 0) { 1790 /* 1791 * If there's more ctl on stream head, keep reading, 1792 * but start discarding. We can't deal with fragmented 1793 * messages at all. 1794 */ 1795 if (rc & MORECTL) { 1796 dbglog("More control; stream garbled"); 1797 flushmode = 1; 1798 continue; 1799 } 1800 if (flushmode) 1801 return (-1); 1802 if (ctrl.len < sizeof (struct ppp_ls)) { 1803 warn("read_packet: ctl.len %d < " 1804 "sizeof ppp_ls %d", 1805 ctrl.len, sizeof (struct ppp_ls)); 1806 return (-1); 1807 } 1808 plp = (struct ppp_ls *)ctrlbuf; 1809 if (plp->magic != PPPLSMAGIC) { 1810 /* Skip, as we don't understand it */ 1811 dbglog("read_packet: unrecognized control %lX", 1812 plp->magic); 1813 return (-1); 1814 } 1815 1816 lastlink_status = plp->ppp_message; 1817 1818 switch (plp->ppp_message) { 1819 case PPP_LINKSTAT_HANGUP: 1820 return (0); /* Hangup */ 1821 /* For use by integrated drivers. */ 1822 case PPP_LINKSTAT_UP: 1823 lcp_lowerdown(0); 1824 lcp_lowerup(0); 1825 return (0); 1826 case PPP_LINKSTAT_NEEDUP: 1827 if (data.len > 0) 1828 dump_packet(buf, data.len); 1829 return (-1); /* Demand dial */ 1830 case PPP_LINKSTAT_IPV4_UNBOUND: 1831 (void) handle_unbind(plp->ppp_message); 1832 return (-1); 1833 case PPP_LINKSTAT_IPV4_BOUND: 1834 (void) handle_bind(plp->ppp_message); 1835 return (-1); 1836 #ifdef INET6 1837 case PPP_LINKSTAT_IPV6_UNBOUND: 1838 (void) handle_unbind(plp->ppp_message); 1839 return (-1); 1840 case PPP_LINKSTAT_IPV6_BOUND: 1841 (void) handle_bind(plp->ppp_message); 1842 return (-1); 1843 #endif 1844 default: 1845 warn("read_packet: unknown link status type!"); 1846 return (-1); 1847 } 1848 } else { 1849 /* 1850 * We get here on zero length data or control. 1851 */ 1852 return (-1); 1853 } 1854 } 1855 } 1856 1857 /* 1858 * get_loop_output() 1859 * 1860 * Get outgoing packets from the ppp device, and detect when we want to bring 1861 * the real link up. Return value is 1 if we need to bring up the link, or 0 1862 * otherwise. 1863 */ 1864 int 1865 get_loop_output() 1866 { 1867 int loops; 1868 1869 /* 1870 * In the Solaris 2.x kernel-level portion implementation, packets 1871 * which are received on a demand-dial interface are immediately 1872 * discarded, and a notification message is sent up the control 1873 * stream to the pppd process. Therefore, the call to read_packet() 1874 * below is merely there to wait for such message. 1875 */ 1876 lastlink_status = 0; 1877 loops = 0; 1878 while (read_packet(inpacket_buf) > 0) { 1879 if (++loops > 10) 1880 break; 1881 } 1882 return (lastlink_status == PPP_LINKSTAT_NEEDUP); 1883 } 1884 1885 #ifdef MUX_FRAME 1886 /*ARGSUSED*/ 1887 void 1888 ppp_send_muxoption(unit, muxflag) 1889 int unit; 1890 u_int32_t muxflag; 1891 { 1892 uint32_t cf[2]; 1893 1894 /* 1895 * Since muxed frame feature is implemented in the async module, 1896 * don't send down the ioctl in the synchronous case. 1897 */ 1898 if (!sync_serial && fdmuxid >= 0 && pppfd != -1) { 1899 cf[0] = muxflag; 1900 cf[1] = X_MUXMASK; 1901 1902 if (strioctl(pppfd, PPPIO_MUX, cf, sizeof (cf), 0) < 0) { 1903 error("Couldn't set mux option: %m"); 1904 } 1905 } 1906 } 1907 1908 /*ARGSUSED*/ 1909 void 1910 ppp_recv_muxoption(unit, muxflag) 1911 int unit; 1912 u_int32_t muxflag; 1913 { 1914 uint32_t cf[2]; 1915 1916 /* 1917 * Since muxed frame feature is implemented in the async module, 1918 * don't send down the ioctl in the synchronous case. 1919 */ 1920 if (!sync_serial && fdmuxid >= 0 && pppfd != -1) { 1921 cf[0] = muxflag; 1922 cf[1] = R_MUXMASK; 1923 1924 if (strioctl(pppfd, PPPIO_MUX, cf, sizeof (cf), 0) < 0) { 1925 error("Couldn't set receive mux option: %m"); 1926 } 1927 } 1928 } 1929 #endif 1930 1931 /* 1932 * ppp_send_config() 1933 * 1934 * Configure the transmit characteristics of the ppp interface. 1935 */ 1936 /*ARGSUSED*/ 1937 void 1938 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) 1939 int unit; 1940 int mtu; 1941 u_int32_t asyncmap; 1942 int pcomp; 1943 int accomp; 1944 { 1945 uint32_t cf[2]; 1946 1947 if (pppfd == -1) { 1948 error("ppp_send_config called with invalid device handle"); 1949 return; 1950 } 1951 cf[0] = link_mtu = mtu; 1952 if (strioctl(pppfd, PPPIO_MTU, cf, sizeof (cf[0]), 0) < 0) { 1953 if (hungup && errno == ENXIO) { 1954 return; 1955 } 1956 error("Couldn't set MTU: %m"); 1957 } 1958 if (fdmuxid != -1) { 1959 if (!sync_serial) { 1960 if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, 1961 sizeof (asyncmap), 0) < 0) { 1962 error("Couldn't set transmit ACCM: %m"); 1963 } 1964 } 1965 cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0); 1966 cf[1] = COMP_PROT | COMP_AC; 1967 1968 if (any_compressions() && strioctl(pppfd, PPPIO_CFLAGS, cf, 1969 sizeof (cf), sizeof (cf[0])) < 0) { 1970 error("Couldn't set prot/AC compression: %m"); 1971 } 1972 } 1973 } 1974 1975 /* 1976 * ppp_set_xaccm() 1977 * 1978 * Set the extended transmit ACCM for the interface. 1979 */ 1980 /*ARGSUSED*/ 1981 void 1982 ppp_set_xaccm(unit, accm) 1983 int unit; 1984 ext_accm accm; 1985 { 1986 if (sync_serial) { 1987 return; 1988 } 1989 if (fdmuxid != -1 && strioctl(pppfd, PPPIO_XACCM, accm, 1990 sizeof (ext_accm), 0) < 0) { 1991 if (!hungup || errno != ENXIO) { 1992 warn("Couldn't set extended ACCM: %m"); 1993 } 1994 } 1995 } 1996 1997 /* 1998 * ppp_recv_config() 1999 * 2000 * Configure the receive-side characteristics of the ppp interface. 2001 */ 2002 /*ARGSUSED*/ 2003 void 2004 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) 2005 int unit; 2006 int mru; 2007 u_int32_t asyncmap; 2008 int pcomp; 2009 int accomp; 2010 { 2011 uint32_t cf[2]; 2012 2013 if (pppfd == -1) { 2014 error("ppp_recv_config called with invalid device handle"); 2015 return; 2016 } 2017 cf[0] = mru; 2018 if (strioctl(pppfd, PPPIO_MRU, cf, sizeof (cf[0]), 0) < 0) { 2019 if (hungup && errno == ENXIO) { 2020 return; 2021 } 2022 error("Couldn't set MRU: %m"); 2023 } 2024 if (fdmuxid != -1) { 2025 if (!sync_serial) { 2026 if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, 2027 sizeof (asyncmap), 0) < 0) { 2028 error("Couldn't set receive ACCM: %m"); 2029 } 2030 } 2031 cf[0] = (pcomp ? DECOMP_PROT : 0) + (accomp ? DECOMP_AC : 0); 2032 cf[1] = DECOMP_PROT | DECOMP_AC; 2033 2034 if (any_compressions() && strioctl(pppfd, PPPIO_CFLAGS, cf, 2035 sizeof (cf), sizeof (cf[0])) < 0) { 2036 error("Couldn't set prot/AC decompression: %m"); 2037 } 2038 } 2039 } 2040 2041 #ifdef NEGOTIATE_FCS 2042 /* 2043 * ppp_send_fcs() 2044 * 2045 * Configure the sender-side FCS. 2046 */ 2047 /*ARGSUSED*/ 2048 void 2049 ppp_send_fcs(unit, fcstype) 2050 int unit, fcstype; 2051 { 2052 uint32_t fcs; 2053 2054 if (sync_serial) { 2055 return; 2056 } 2057 2058 if (fcstype & FCSALT_32) { 2059 fcs = PPPFCS_32; 2060 } else if (fcstype & FCSALT_NULL) { 2061 fcs = PPPFCS_NONE; 2062 } else { 2063 fcs = PPPFCS_16; 2064 } 2065 if (strioctl(pppfd, PPPIO_XFCS, &fcs, sizeof (fcs), 0) < 0) { 2066 warn("Couldn't set transmit FCS: %m"); 2067 } 2068 } 2069 2070 /* 2071 * ppp_recv_fcs() 2072 * 2073 * Configure the receiver-side FCS. 2074 */ 2075 /*ARGSUSED*/ 2076 void 2077 ppp_recv_fcs(unit, fcstype) 2078 int unit, fcstype; 2079 { 2080 uint32_t fcs; 2081 2082 if (sync_serial) { 2083 return; 2084 } 2085 2086 if (fcstype & FCSALT_32) { 2087 fcs = PPPFCS_32; 2088 } else if (fcstype & FCSALT_NULL) { 2089 fcs = PPPFCS_NONE; 2090 } else { 2091 fcs = PPPFCS_16; 2092 } 2093 if (strioctl(pppfd, PPPIO_RFCS, &fcs, sizeof (fcs), 0) < 0) { 2094 warn("Couldn't set receive FCS: %m"); 2095 } 2096 } 2097 #endif 2098 2099 /* 2100 * ccp_test() 2101 * 2102 * Ask kernel whether a given compression method is acceptable for use. 2103 */ 2104 /*ARGSUSED*/ 2105 int 2106 ccp_test(unit, opt_ptr, opt_len, for_transmit) 2107 int unit; 2108 uchar_t *opt_ptr; 2109 int opt_len; 2110 int for_transmit; 2111 { 2112 if (strioctl(pppfd, (for_transmit ? PPPIO_XCOMP : PPPIO_RCOMP), 2113 opt_ptr, opt_len, 0) >= 0) { 2114 return (1); 2115 } 2116 warn("Error in %s ioctl: %m", 2117 (for_transmit ? "PPPIO_XCOMP" : "PPPIO_RCOMP")); 2118 return ((errno == ENOSR) ? 0 : -1); 2119 } 2120 2121 #ifdef COMP_TUNE 2122 /* 2123 * ccp_tune() 2124 * 2125 * Tune compression effort level. 2126 */ 2127 /*ARGSUSED*/ 2128 void 2129 ccp_tune(unit, effort) 2130 int unit, effort; 2131 { 2132 uint32_t x; 2133 2134 x = effort; 2135 if (strioctl(pppfd, PPPIO_COMPLEV, &x, sizeof (x), 0) < 0) { 2136 warn("unable to set compression effort level: %m"); 2137 } 2138 } 2139 #endif 2140 2141 /* 2142 * ccp_flags_set() 2143 * 2144 * Inform kernel about the current state of CCP. 2145 */ 2146 /*ARGSUSED*/ 2147 void 2148 ccp_flags_set(unit, isopen, isup) 2149 int unit, isopen, isup; 2150 { 2151 uint32_t cf[2]; 2152 2153 cf[0] = (isopen ? CCP_ISOPEN : 0) + (isup ? CCP_ISUP : 0); 2154 cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR; 2155 2156 if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0])) 2157 < 0) { 2158 if (!hungup || errno != ENXIO) { 2159 error("Couldn't set kernel CCP state: %m"); 2160 } 2161 } 2162 } 2163 2164 /* 2165 * get_idle_time() 2166 * 2167 * Return how long the link has been idle. 2168 */ 2169 /*ARGSUSED*/ 2170 int 2171 get_idle_time(u, pids) 2172 int u; 2173 struct ppp_idle *pids; 2174 { 2175 int rc; 2176 2177 rc = strioctl(pppfd, PPPIO_GIDLE, pids, 0, sizeof (struct ppp_idle)); 2178 if (rc < 0) { 2179 warn("unable to obtain idle time: %m"); 2180 } 2181 return ((rc == 0) ? 1 : 0); 2182 } 2183 2184 /* 2185 * get_ppp_stats() 2186 * 2187 * Return statistics for the link. 2188 */ 2189 /*ARGSUSED*/ 2190 int 2191 get_ppp_stats(u, stats) 2192 int u; 2193 struct pppd_stats *stats; 2194 { 2195 struct ppp_stats64 s64; 2196 struct ppp_stats s; 2197 2198 /* Try first to get these from the 64-bit interface */ 2199 if (strioctl(pppfd, PPPIO_GETSTAT64, &s64, 0, sizeof (s64)) >= 0) { 2200 stats->bytes_in = s64.p.ppp_ibytes; 2201 stats->bytes_out = s64.p.ppp_obytes; 2202 stats->pkts_in = s64.p.ppp_ipackets; 2203 stats->pkts_out = s64.p.ppp_opackets; 2204 return (1); 2205 } 2206 2207 if (strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof (s)) < 0) { 2208 error("Couldn't get link statistics: %m"); 2209 return (0); 2210 } 2211 stats->bytes_in = s.p.ppp_ibytes; 2212 stats->bytes_out = s.p.ppp_obytes; 2213 stats->pkts_in = s.p.ppp_ipackets; 2214 stats->pkts_out = s.p.ppp_opackets; 2215 return (1); 2216 } 2217 2218 #if defined(FILTER_PACKETS) 2219 /* 2220 * set_filters() 2221 * 2222 * Transfer the pass and active filters to the kernel. 2223 */ 2224 int 2225 set_filters(pass, active) 2226 struct bpf_program *pass; 2227 struct bpf_program *active; 2228 { 2229 int ret = 1; 2230 2231 if (pass->bf_len > 0) { 2232 if (strioctl(pppfd, PPPIO_PASSFILT, pass, 2233 sizeof (struct bpf_program), 0) < 0) { 2234 error("Couldn't set pass-filter in kernel: %m"); 2235 ret = 0; 2236 } 2237 } 2238 if (active->bf_len > 0) { 2239 if (strioctl(pppfd, PPPIO_ACTIVEFILT, active, 2240 sizeof (struct bpf_program), 0) < 0) { 2241 error("Couldn't set active-filter in kernel: %m"); 2242 ret = 0; 2243 } 2244 } 2245 return (ret); 2246 } 2247 #endif /* FILTER_PACKETS */ 2248 2249 /* 2250 * ccp_fatal_error() 2251 * 2252 * Returns 1 if decompression was disabled as a result of an error detected 2253 * after decompression of a packet, 0 otherwise. This is necessary because 2254 * of patent nonsense. 2255 */ 2256 /*ARGSUSED*/ 2257 int 2258 ccp_fatal_error(unit) 2259 int unit; 2260 { 2261 uint32_t cf[2]; 2262 2263 cf[0] = cf[1] = 0; 2264 if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0])) 2265 < 0) { 2266 if (errno != ENXIO && errno != EINVAL) { 2267 error("Couldn't get compression flags: %m"); 2268 } 2269 return (0); 2270 } 2271 return (cf[0] & CCP_FATALERROR); 2272 } 2273 2274 /* 2275 * sifvjcomp() 2276 * 2277 * Config TCP header compression. 2278 */ 2279 /*ARGSUSED*/ 2280 int 2281 sifvjcomp(u, vjcomp, xcidcomp, xmaxcid) 2282 int u, vjcomp, xcidcomp, xmaxcid; 2283 { 2284 uint32_t cf[2]; 2285 uchar_t maxcid[2]; 2286 2287 /* 2288 * Since VJ compression code is in the comp module, there's no 2289 * point of sending down any ioctls pertaining to VJ compression 2290 * when the module isn't pushed on the stream. 2291 */ 2292 if (!any_compressions()) { 2293 return (1); 2294 } 2295 2296 if (vjcomp) { 2297 maxcid[0] = xcidcomp; 2298 maxcid[1] = 15; /* XXX should be rmaxcid */ 2299 2300 if (strioctl(pppfd, PPPIO_VJINIT, maxcid, 2301 sizeof (maxcid), 0) < 0) { 2302 error("Couldn't initialize VJ compression: %m"); 2303 return (0); 2304 } 2305 } 2306 2307 cf[0] = (vjcomp ? COMP_VJC + DECOMP_VJC : 0) /* XXX this is wrong */ 2308 + (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0); 2309 2310 cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID; 2311 2312 if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0])) 2313 < 0) { 2314 if (vjcomp) { 2315 error("Couldn't enable VJ compression: %m"); 2316 } else { 2317 error("Couldn't disable VJ compression: %m"); 2318 } 2319 return (0); 2320 } 2321 return (1); 2322 } 2323 2324 /* 2325 * siflags() 2326 * 2327 * Set or clear the IP interface flags. 2328 */ 2329 int 2330 siflags(f, set) 2331 u_int32_t f; 2332 int set; 2333 { 2334 struct ifreq ifr; 2335 2336 if (!IPCP_ENABLED || (ipmuxid == -1)) { 2337 return (0); 2338 } 2339 if (ipfd == -1 && open_ipfd() == -1) 2340 return (0); 2341 BZERO(&ifr, sizeof (ifr)); 2342 (void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 2343 if (myioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) { 2344 error("Couldn't get IP interface flags: %m"); 2345 return (0); 2346 } 2347 if (set) { 2348 ifr.ifr_flags |= f; 2349 } else { 2350 ifr.ifr_flags &= ~f; 2351 } 2352 if (myioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) { 2353 error("Couldn't set IP interface flags: %m"); 2354 return (0); 2355 } 2356 return (1); 2357 } 2358 2359 /* 2360 * sifup() 2361 * 2362 * Config the interface up and enable IP packets to pass. 2363 */ 2364 /*ARGSUSED*/ 2365 int 2366 sifup(u) 2367 int u; 2368 { 2369 if (if_is_up) { 2370 return (1); 2371 } else if (!IPCP_ENABLED) { 2372 warn("sifup called when IPCP is disabled"); 2373 return (0); 2374 } else if (ipmuxid == -1) { 2375 warn("sifup called in wrong state"); 2376 return (0); 2377 } else if (!siflags(IFF_UP, 1)) { 2378 error("Unable to mark the IP interface UP"); 2379 return (0); 2380 } 2381 if_is_up = 1; 2382 return (1); 2383 } 2384 2385 /* 2386 * sifdown() 2387 * 2388 * Config the interface down and disable IP. Possibly called from die(), 2389 * so there shouldn't be any call to die() here. 2390 */ 2391 /*ARGSUSED*/ 2392 int 2393 sifdown(u) 2394 int u; 2395 { 2396 if (!IPCP_ENABLED) { 2397 warn("sifdown called when IPCP is disabled"); 2398 return (0); 2399 } else if (!if_is_up || (ipmuxid == -1)) { 2400 return (1); 2401 } else if (!siflags(IFF_UP, 0)) { 2402 error("Unable to mark the IP interface DOWN"); 2403 return (0); 2404 } 2405 if_is_up = 0; 2406 return (1); 2407 } 2408 2409 /* 2410 * sifnpmode() 2411 * 2412 * Set the mode for handling packets for a given NP. Not worried 2413 * about performance here since this is done only rarely. 2414 */ 2415 /*ARGSUSED*/ 2416 int 2417 sifnpmode(u, proto, mode) 2418 int u; 2419 int proto; 2420 enum NPmode mode; 2421 { 2422 uint32_t npi[2]; 2423 const char *cp; 2424 static const struct npi_entry { 2425 enum NPmode ne_value; 2426 const char *ne_name; 2427 } npi_list[] = { 2428 { NPMODE_PASS, "pass" }, 2429 { NPMODE_DROP, "drop" }, 2430 { NPMODE_ERROR, "error" }, 2431 { NPMODE_QUEUE, "queue" }, 2432 }; 2433 int i; 2434 char pname[32], mname[32]; 2435 2436 npi[0] = proto; 2437 npi[1] = (uint32_t)mode; 2438 2439 cp = protocol_name(proto); 2440 if (cp == NULL) 2441 (void) slprintf(pname, sizeof (pname), "NP %04X", proto); 2442 else 2443 (void) strlcpy(pname, cp, sizeof (pname)); 2444 for (i = 0; i < Dim(npi_list); i++) 2445 if (npi_list[i].ne_value == mode) 2446 break; 2447 if (i >= Dim(npi_list)) 2448 (void) slprintf(mname, sizeof (mname), "mode %d", (int)mode); 2449 else 2450 (void) strlcpy(mname, npi_list[i].ne_name, sizeof (mname)); 2451 2452 if ((proto == PPP_IP && !if_is_up) || 2453 (proto == PPP_IPV6 && !if6_is_up)) { 2454 dbglog("ignoring request to set %s to %s", pname, mname); 2455 return (1); 2456 } 2457 if (strioctl(pppfd, PPPIO_NPMODE, npi, sizeof (npi), 0) < 0) { 2458 error("unable to set %s to %s: %m", pname, mname); 2459 return (0); 2460 } 2461 return (1); 2462 } 2463 2464 /* 2465 * sifmtu() 2466 * 2467 * Config the interface IP MTU. 2468 */ 2469 int 2470 sifmtu(mtu) 2471 int mtu; 2472 { 2473 struct ifreq ifr; 2474 2475 if (!IPCP_ENABLED || (ipmuxid == -1)) { 2476 return (0); 2477 } 2478 if (ipfd == -1 && open_ipfd() == -1) 2479 return (0); 2480 BZERO(&ifr, sizeof (ifr)); 2481 (void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 2482 ifr.ifr_metric = mtu; 2483 if (myioctl(ipfd, SIOCSIFMTU, &ifr) < 0) { 2484 error("Couldn't set IP MTU on %s to %d: %m", ifr.ifr_name, 2485 mtu); 2486 return (0); 2487 } 2488 return (1); 2489 } 2490 2491 /* 2492 * sifaddr() 2493 * 2494 * Config the interface IP addresses and netmask. 2495 */ 2496 /*ARGSUSED*/ 2497 int 2498 sifaddr(u, o, h, m) 2499 int u; 2500 u_int32_t o; 2501 u_int32_t h; 2502 u_int32_t m; 2503 { 2504 struct ifreq ifr; 2505 struct sockaddr_in sin; 2506 2507 if (!IPCP_ENABLED || (ipmuxid == -1 && plumb_ipif(u) == 0)) { 2508 return (0); 2509 } 2510 if (ipfd == -1 && open_ipfd() == -1) 2511 return (0); 2512 /* 2513 * Set the IP interface MTU. 2514 */ 2515 if (!sifmtu(link_mtu)) { 2516 return (0); 2517 } 2518 /* 2519 * Set the IP interface local point-to-point address. 2520 */ 2521 BZERO(&sin, sizeof (sin)); 2522 sin.sin_family = AF_INET; 2523 sin.sin_addr.s_addr = o; 2524 2525 BZERO(&ifr, sizeof (ifr)); 2526 (void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 2527 ifr.ifr_addr = *(struct sockaddr *)&sin; 2528 if (myioctl(ipfd, SIOCSIFADDR, &ifr) < 0) { 2529 error("Couldn't set local IP address (%s): %m", ifr.ifr_name); 2530 return (0); 2531 } 2532 /* 2533 * Set the IP interface remote point-to-point address. 2534 */ 2535 sin.sin_addr.s_addr = h; 2536 2537 ifr.ifr_dstaddr = *(struct sockaddr *)&sin; 2538 if (myioctl(ipfd, SIOCSIFDSTADDR, &ifr) < 0) { 2539 error("Couldn't set remote IP address (%s): %m", ifr.ifr_name); 2540 return (0); 2541 } 2542 remote_addr = h; 2543 return (1); 2544 } 2545 2546 /* 2547 * cifaddr() 2548 * 2549 * Clear the interface IP addresses. 2550 */ 2551 /*ARGSUSED*/ 2552 int 2553 cifaddr(u, o, h) 2554 int u; 2555 u_int32_t o; 2556 u_int32_t h; 2557 { 2558 if (!IPCP_ENABLED) { 2559 return (0); 2560 } 2561 /* 2562 * Most of the work is done in sifdown(). 2563 */ 2564 remote_addr = 0; 2565 return (1); 2566 } 2567 2568 /* 2569 * sifroute() 2570 * 2571 * Add or delete a route. 2572 */ 2573 /*ARGSUSED*/ 2574 static int 2575 sifroute(int u, u_int32_t l, u_int32_t g, int add, const char *str) 2576 { 2577 struct sockaddr_in sin_dst, sin_gtw; 2578 struct rtentry rt; 2579 2580 if (!IPCP_ENABLED || (ipmuxid == -1)) { 2581 error("Can't %s route: IP is not enabled", str); 2582 return (0); 2583 } 2584 if (ipfd == -1 && open_ipfd() == -1) 2585 return (0); 2586 2587 BZERO(&sin_dst, sizeof (sin_dst)); 2588 sin_dst.sin_family = AF_INET; 2589 sin_dst.sin_addr.s_addr = l; 2590 2591 BZERO(&sin_gtw, sizeof (sin_gtw)); 2592 sin_gtw.sin_family = AF_INET; 2593 sin_gtw.sin_addr.s_addr = g; 2594 2595 BZERO(&rt, sizeof (rt)); 2596 rt.rt_dst = *(struct sockaddr *)&sin_dst; 2597 rt.rt_gateway = *(struct sockaddr *)&sin_gtw; 2598 rt.rt_flags = (RTF_GATEWAY|RTF_STATIC); 2599 2600 if (myioctl(ipfd, (add ? SIOCADDRT : SIOCDELRT), &rt) < 0) { 2601 error("Can't %s route: %m", str); 2602 return (0); 2603 } 2604 return (1); 2605 } 2606 2607 /* 2608 * sifdefaultroute() 2609 * 2610 * Assign a default route through the address given. 2611 */ 2612 /*ARGSUSED*/ 2613 int 2614 sifdefaultroute(u, l, g) 2615 int u; 2616 u_int32_t l; 2617 u_int32_t g; 2618 { 2619 if (!sifroute(u, 0, g, 1, "add default")) { 2620 return (0); 2621 } 2622 default_route_gateway = g; 2623 return (1); 2624 } 2625 2626 /* 2627 * cifdefaultroute() 2628 * 2629 * Delete a default route through the address given. 2630 */ 2631 /*ARGSUSED*/ 2632 int 2633 cifdefaultroute(u, l, g) 2634 int u; 2635 u_int32_t l; 2636 u_int32_t g; 2637 { 2638 if (!sifroute(u, 0, g, 0, "delete default")) { 2639 return (0); 2640 } 2641 default_route_gateway = 0; 2642 return (1); 2643 } 2644 2645 /* 2646 * sifproxyarp() 2647 * 2648 * Make a proxy ARP entry for the peer. 2649 */ 2650 /*ARGSUSED*/ 2651 int 2652 sifproxyarp(unit, hisaddr, quietflag) 2653 int unit; 2654 u_int32_t hisaddr; 2655 int quietflag; 2656 { 2657 struct sockaddr_in sin; 2658 struct xarpreq arpreq; 2659 const uchar_t *cp; 2660 char *str = NULL; 2661 2662 if (!IPCP_ENABLED || (ipmuxid == -1)) { 2663 return (0); 2664 } 2665 if (ipfd == -1 && open_ipfd() == -1) 2666 return (0); 2667 2668 BZERO(&sin, sizeof (sin)); 2669 sin.sin_family = AF_INET; 2670 sin.sin_addr.s_addr = hisaddr; 2671 2672 BZERO(&arpreq, sizeof (arpreq)); 2673 if (!get_ether_addr(hisaddr, &arpreq.xarp_ha, quietflag)) { 2674 return (0); 2675 } 2676 BCOPY(&sin, &arpreq.xarp_pa, sizeof (sin)); 2677 arpreq.xarp_flags = ATF_PERM | ATF_PUBL; 2678 arpreq.xarp_ha.sdl_family = AF_LINK; 2679 2680 if (myioctl(ipfd, SIOCSXARP, (caddr_t)&arpreq) < 0) { 2681 if (!quietflag) 2682 error("Couldn't set proxy ARP entry: %m"); 2683 return (0); 2684 } 2685 cp = (const uchar_t *)LLADDR(&arpreq.xarp_ha); 2686 str = _link_ntoa(cp, str, arpreq.xarp_ha.sdl_alen, IFT_OTHER); 2687 if (str != NULL) { 2688 dbglog("established proxy ARP for %I using %s", hisaddr, 2689 str); 2690 free(str); 2691 } 2692 proxy_arp_addr = hisaddr; 2693 return (1); 2694 } 2695 2696 /* 2697 * cifproxyarp() 2698 * 2699 * Delete the proxy ARP entry for the peer. 2700 */ 2701 /*ARGSUSED*/ 2702 int 2703 cifproxyarp(unit, hisaddr) 2704 int unit; 2705 u_int32_t hisaddr; 2706 { 2707 struct sockaddr_in sin; 2708 struct xarpreq arpreq; 2709 2710 if (!IPCP_ENABLED || (ipmuxid == -1)) { 2711 return (0); 2712 } 2713 if (ipfd == -1 && open_ipfd() == -1) 2714 return (0); 2715 2716 BZERO(&sin, sizeof (sin)); 2717 sin.sin_family = AF_INET; 2718 sin.sin_addr.s_addr = hisaddr; 2719 2720 BZERO(&arpreq, sizeof (arpreq)); 2721 BCOPY(&sin, &arpreq.xarp_pa, sizeof (sin)); 2722 arpreq.xarp_ha.sdl_family = AF_LINK; 2723 2724 if (myioctl(ipfd, SIOCDXARP, (caddr_t)&arpreq) < 0) { 2725 error("Couldn't delete proxy ARP entry: %m"); 2726 return (0); 2727 } 2728 proxy_arp_addr = 0; 2729 return (1); 2730 } 2731 2732 /* 2733 * get_ether_addr() 2734 * 2735 * Get the hardware address of an interface on the the same subnet as 2736 * ipaddr. This routine uses old-style interfaces for intentional 2737 * backward compatibility -- SIOCGLIF* isn't in older Solaris 2738 * releases. 2739 */ 2740 static int 2741 get_ether_addr(u_int32_t ipaddr, struct sockaddr_dl *hwaddr, int quietflag) 2742 { 2743 struct ifreq *ifr, *ifend, ifreq; 2744 int nif, s, retv; 2745 struct ifconf ifc; 2746 u_int32_t ina, mask; 2747 struct xarpreq req; 2748 struct sockaddr_in sin; 2749 2750 if (ipfd == -1 && open_ipfd() == -1) 2751 return (0); 2752 2753 /* 2754 * Scan through the system's network interfaces. 2755 */ 2756 if (myioctl(ipfd, SIOCGIFNUM, &nif) < 0) { 2757 nif = MAXIFS; 2758 } 2759 if (nif <= 0) 2760 return (0); 2761 ifc.ifc_len = nif * sizeof (struct ifreq); 2762 ifc.ifc_buf = (caddr_t)malloc(ifc.ifc_len); 2763 if (ifc.ifc_buf == NULL) { 2764 return (0); 2765 } 2766 if (myioctl(ipfd, SIOCGIFCONF, &ifc) < 0) { 2767 error("Couldn't get system interface list: %m"); 2768 free(ifc.ifc_buf); 2769 return (0); 2770 } 2771 /* LINTED */ 2772 ifend = (struct ifreq *)(ifc.ifc_buf + ifc.ifc_len); 2773 for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) { 2774 if (ifr->ifr_addr.sa_family != AF_INET) { 2775 continue; 2776 } 2777 /* 2778 * Check that the interface is up, and not 2779 * point-to-point or loopback. 2780 */ 2781 (void) strlcpy(ifreq.ifr_name, ifr->ifr_name, 2782 sizeof (ifreq.ifr_name)); 2783 if (myioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0) { 2784 continue; 2785 } 2786 if ((ifreq.ifr_flags & (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT| 2787 IFF_LOOPBACK|IFF_NOARP)) != (IFF_UP|IFF_BROADCAST)) { 2788 continue; 2789 } 2790 /* 2791 * Get its netmask and check that it's on the right subnet. 2792 */ 2793 if (myioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0) { 2794 continue; 2795 } 2796 (void) memcpy(&sin, &ifr->ifr_addr, sizeof (sin)); 2797 ina = sin.sin_addr.s_addr; 2798 (void) memcpy(&sin, &ifreq.ifr_addr, sizeof (sin)); 2799 mask = sin.sin_addr.s_addr; 2800 if ((ipaddr & mask) == (ina & mask)) { 2801 break; 2802 } 2803 } 2804 if (ifr >= ifend) { 2805 if (!quietflag) 2806 warn("No suitable interface found for proxy ARP of %I", 2807 ipaddr); 2808 free(ifc.ifc_buf); 2809 return (0); 2810 } 2811 info("found interface %s for proxy ARP of %I", ifr->ifr_name, ipaddr); 2812 2813 /* 2814 * New way - get the address by doing an arp request. 2815 */ 2816 s = socket(AF_INET, SOCK_DGRAM, 0); 2817 if (s < 0) { 2818 error("get_ether_addr: error opening IP socket: %m"); 2819 free(ifc.ifc_buf); 2820 return (0); 2821 } 2822 BZERO(&sin, sizeof (sin)); 2823 sin.sin_family = AF_INET; 2824 sin.sin_addr.s_addr = ina; 2825 2826 BZERO(&req, sizeof (req)); 2827 BCOPY(&sin, &req.xarp_pa, sizeof (sin)); 2828 req.xarp_ha.sdl_family = AF_LINK; 2829 2830 if (myioctl(s, SIOCGXARP, &req) < 0) { 2831 error("Couldn't get ARP entry for %I: %m", ina); 2832 retv = 0; 2833 } else { 2834 (void) memcpy(hwaddr, &req.xarp_ha, 2835 sizeof (struct sockaddr_dl)); 2836 retv = 1; 2837 } 2838 (void) close(s); 2839 free(ifc.ifc_buf); 2840 return (retv); 2841 } 2842 2843 /* 2844 * GetMask() 2845 * 2846 * Return mask (bogus, but needed for compatibility with other platforms). 2847 */ 2848 /*ARGSUSED*/ 2849 u_int32_t 2850 GetMask(addr) 2851 u_int32_t addr; 2852 { 2853 return (0xffffffffUL); 2854 } 2855 2856 /* 2857 * logwtmp() 2858 * 2859 * Write an accounting record to the /var/adm/wtmp file. 2860 */ 2861 /*ARGSUSED*/ 2862 void 2863 logwtmp(line, name, host) 2864 const char *line; 2865 const char *name; 2866 const char *host; 2867 { 2868 static struct utmpx utmpx; 2869 2870 if (name[0] != '\0') { 2871 /* 2872 * logging in 2873 */ 2874 (void) strncpy(utmpx.ut_user, name, sizeof (utmpx.ut_user)); 2875 (void) strncpy(utmpx.ut_id, ifname, sizeof (utmpx.ut_id)); 2876 (void) strncpy(utmpx.ut_line, line, sizeof (utmpx.ut_line)); 2877 2878 utmpx.ut_pid = getpid(); 2879 utmpx.ut_type = USER_PROCESS; 2880 } else { 2881 utmpx.ut_type = DEAD_PROCESS; 2882 } 2883 (void) gettimeofday(&utmpx.ut_tv, NULL); 2884 updwtmpx("/var/adm/wtmpx", &utmpx); 2885 } 2886 2887 /* 2888 * get_host_seed() 2889 * 2890 * Return the serial number of this machine. 2891 */ 2892 int 2893 get_host_seed() 2894 { 2895 char buf[32]; 2896 2897 if (sysinfo(SI_HW_SERIAL, buf, sizeof (buf)) < 0) { 2898 error("sysinfo: %m"); 2899 return (0); 2900 } 2901 return ((int)strtoul(buf, NULL, 16)); 2902 } 2903 2904 /* 2905 * strioctl() 2906 * 2907 * Wrapper for STREAMS I_STR ioctl. Masks out EINTR from caller. 2908 */ 2909 static int 2910 strioctl(int fd, int cmd, void *ptr, int ilen, int olen) 2911 { 2912 struct strioctl str; 2913 2914 str.ic_cmd = cmd; 2915 str.ic_timout = PPPSTRTIMOUT; 2916 str.ic_len = ilen; 2917 str.ic_dp = ptr; 2918 2919 if (myioctl(fd, I_STR, &str) == -1) { 2920 return (-1); 2921 } 2922 if (str.ic_len != olen) { 2923 dbglog("strioctl: expected %d bytes, got %d for cmd %x\n", 2924 olen, str.ic_len, cmd); 2925 } 2926 return (0); 2927 } 2928 2929 /* 2930 * have_route_to() 2931 * 2932 * Determine if the system has a route to the specified IP address. 2933 * Returns 0 if not, 1 if so, -1 if we can't tell. `addr' is in network 2934 * byte order. For demand mode to work properly, we have to ignore routes 2935 * through our own interface. XXX Would be nice to use routing socket. 2936 */ 2937 int 2938 have_route_to(addr) 2939 u_int32_t addr; 2940 { 2941 int r, flags, i; 2942 struct { 2943 struct T_optmgmt_req req; 2944 struct opthdr hdr; 2945 } req; 2946 union { 2947 struct T_optmgmt_ack ack; 2948 unsigned char space[64]; 2949 } ack; 2950 struct opthdr *rh; 2951 struct strbuf cbuf, dbuf; 2952 int nroutes; 2953 mib2_ipRouteEntry_t routes[8]; 2954 mib2_ipRouteEntry_t *rp; 2955 2956 if (ipfd == -1 && open_ipfd() == -1) 2957 return (0); 2958 2959 req.req.PRIM_type = T_OPTMGMT_REQ; 2960 req.req.OPT_offset = (caddr_t)&req.hdr - (caddr_t)&req; 2961 req.req.OPT_length = sizeof (req.hdr); 2962 #ifdef T_CURRENT 2963 req.req.MGMT_flags = T_CURRENT; 2964 #else 2965 /* Old-style */ 2966 req.req.MGMT_flags = T_CHECK; 2967 #endif 2968 2969 req.hdr.level = MIB2_IP; 2970 req.hdr.name = 0; 2971 req.hdr.len = 0; 2972 2973 cbuf.buf = (caddr_t)&req; 2974 cbuf.len = sizeof (req); 2975 2976 if (putmsg(ipfd, &cbuf, NULL, 0) == -1) { 2977 warn("have_route_to: putmsg: %m"); 2978 return (-1); 2979 } 2980 2981 for (;;) { 2982 cbuf.buf = (caddr_t)&ack; 2983 cbuf.maxlen = sizeof (ack); 2984 dbuf.buf = (caddr_t)routes; 2985 dbuf.maxlen = sizeof (routes); 2986 flags = 0; 2987 r = getmsg(ipfd, &cbuf, &dbuf, &flags); 2988 if (r == -1) { 2989 warn("have_route_to: getmsg: %m"); 2990 return (-1); 2991 } 2992 2993 if (cbuf.len < sizeof (struct T_optmgmt_ack) || 2994 ack.ack.PRIM_type != T_OPTMGMT_ACK || 2995 ack.ack.MGMT_flags != T_SUCCESS || 2996 ack.ack.OPT_length < sizeof (struct opthdr)) { 2997 dbglog("have_route_to: bad message len=%d prim=%d", 2998 cbuf.len, ack.ack.PRIM_type); 2999 return (-1); 3000 } 3001 /* LINTED */ 3002 rh = (struct opthdr *)((caddr_t)&ack + ack.ack.OPT_offset); 3003 if (rh->level == 0 && rh->name == 0) { 3004 break; 3005 } 3006 if (rh->level != MIB2_IP || rh->name != MIB2_IP_21) { 3007 while (r == MOREDATA) { 3008 r = getmsg(ipfd, NULL, &dbuf, &flags); 3009 } 3010 continue; 3011 } 3012 3013 /* 3014 * Note that we have to skip routes to our own 3015 * interface in order for demand dial to work. 3016 * 3017 * XXX awful hack here. We don't know our own 3018 * ifIndex, so we can't check ipRouteIfIndex here. 3019 * Instead, we check the next hop address. 3020 */ 3021 for (;;) { 3022 nroutes = dbuf.len / sizeof (mib2_ipRouteEntry_t); 3023 for (rp = routes, i = 0; i < nroutes; ++i, ++rp) { 3024 if (rp->ipRouteNextHop != remote_addr && 3025 ((addr ^ rp->ipRouteDest) & 3026 rp->ipRouteMask) == 0) { 3027 dbglog("have route to %I/%I via %I", 3028 rp->ipRouteDest, 3029 rp->ipRouteMask, 3030 rp->ipRouteNextHop); 3031 return (1); 3032 } 3033 } 3034 if (r == 0) { 3035 break; 3036 } 3037 r = getmsg(ipfd, NULL, &dbuf, &flags); 3038 } 3039 } 3040 return (0); 3041 } 3042 3043 /* 3044 * get_pty() 3045 * 3046 * Get a pty master/slave pair and chown the slave side to the uid given. 3047 * Assumes slave_name points to MAXPATHLEN bytes of space. 3048 */ 3049 int 3050 get_pty(master_fdp, slave_fdp, slave_name, uid) 3051 int *master_fdp; 3052 int *slave_fdp; 3053 char *slave_name; 3054 int uid; 3055 { 3056 int mfd; 3057 int sfd; 3058 char *pty_name; 3059 3060 mfd = open("/dev/ptmx", O_NOCTTY | O_RDWR); 3061 if (mfd < 0) { 3062 error("Couldn't open pty master: %m"); 3063 return (0); 3064 } 3065 pty_name = ptsname(mfd); 3066 if (pty_name == NULL) { 3067 dbglog("Didn't get pty slave name on first try; sleeping."); 3068 /* In case "grow" operation is in progress; try again. */ 3069 (void) sleep(1); 3070 pty_name = ptsname(mfd); 3071 } 3072 if (pty_name == NULL) { 3073 error("Couldn't get name of pty slave"); 3074 (void) close(mfd); 3075 return (0); 3076 } 3077 if (chown(pty_name, uid, -1) < 0) { 3078 warn("Couldn't change owner of pty slave: %m"); 3079 } 3080 if (chmod(pty_name, S_IRUSR | S_IWUSR) < 0) { 3081 warn("Couldn't change permissions on pty slave: %m"); 3082 } 3083 if (unlockpt(mfd) < 0) { 3084 warn("Couldn't unlock pty slave: %m"); 3085 } 3086 sfd = open(pty_name, O_RDWR); 3087 if (sfd < 0) { 3088 error("Couldn't open pty slave %s: %m", pty_name); 3089 (void) close(mfd); 3090 return (0); 3091 } 3092 if (myioctl(sfd, I_PUSH, "ptem") < 0) { 3093 warn("Couldn't push ptem module on pty slave: %m"); 3094 } 3095 dbglog("Using %s; master fd %d, slave fd %d", pty_name, mfd, sfd); 3096 3097 (void) strlcpy(slave_name, pty_name, MAXPATHLEN); 3098 3099 *master_fdp = mfd; 3100 *slave_fdp = sfd; 3101 3102 return (1); 3103 } 3104 3105 #ifdef INET6 3106 static int 3107 open_udp6fd(void) 3108 { 3109 int udp6fd; 3110 3111 udp6fd = open(UDP6_DEV_NAME, O_RDWR | O_NONBLOCK, 0); 3112 if (udp6fd < 0) { 3113 error("Couldn't open UDPv6 device (%s): %m", UDP6_DEV_NAME); 3114 } 3115 return (udp6fd); 3116 } 3117 3118 /* 3119 * plumb_ip6if() 3120 * 3121 * Perform IPv6 interface plumbing. 3122 */ 3123 /*ARGSUSED*/ 3124 static int 3125 plumb_ip6if(int unit) 3126 { 3127 int udp6fd = -1, tmpfd; 3128 uint32_t x; 3129 struct lifreq lifr; 3130 3131 if (!IPV6CP_ENABLED || (ifunit == -1) || (pppfd == -1)) { 3132 return (0); 3133 } 3134 if (plumbed) 3135 return (1); 3136 if (ip6fd == -1 && open_ip6fd() == -1) 3137 return (0); 3138 if (use_plink && (udp6fd = open_udp6fd()) == -1) 3139 return (0); 3140 tmpfd = open(drvnam, O_RDWR | O_NONBLOCK, 0); 3141 if (tmpfd < 0) { 3142 error("Couldn't open PPP device (%s): %m", drvnam); 3143 if (udp6fd != -1) 3144 (void) close(udp6fd); 3145 return (0); 3146 } 3147 if (kdebugflag & 1) { 3148 x = PPPDBG_LOG + PPPDBG_DRIVER; 3149 if (strioctl(tmpfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) { 3150 warn("PPPIO_DEBUG ioctl for mux failed: %m"); 3151 } 3152 } 3153 if (myioctl(tmpfd, I_PUSH, IP_MOD_NAME) < 0) { 3154 error("Couldn't push IP module(%s): %m", IP_MOD_NAME); 3155 goto err_ret; 3156 } 3157 /* 3158 * Sets interface ppa and flags (refer to comments in plumb_ipif for 3159 * the IF_UNITSEL ioctl). In addition, the IFF_IPV6 bit must be set in 3160 * order to declare this as an IPv6 interface. 3161 */ 3162 BZERO(&lifr, sizeof (lifr)); 3163 if (myioctl(tmpfd, SIOCGLIFFLAGS, &lifr) < 0) { 3164 error("Couldn't get IPv6 interface flags: %m"); 3165 goto err_ret; 3166 } 3167 lifr.lifr_flags |= IFF_IPV6; 3168 lifr.lifr_flags &= ~(IFF_BROADCAST | IFF_IPV4); 3169 lifr.lifr_ppa = ifunit; 3170 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 3171 if (myioctl(tmpfd, SIOCSLIFNAME, &lifr) < 0) { 3172 error("Can't set ifname for unit %d: %m", ifunit); 3173 goto err_ret; 3174 } 3175 if (use_plink) { 3176 ip6muxid = myioctl(udp6fd, I_PLINK, (void *)tmpfd); 3177 if (ip6muxid < 0) { 3178 error("Can't I_PLINK PPP device to IPv6: %m"); 3179 goto err_ret; 3180 } 3181 } else { 3182 ip6muxid = myioctl(ip6fd, I_LINK, (void *)tmpfd); 3183 if (ip6muxid < 0) { 3184 error("Can't I_LINK PPP device to IPv6: %m"); 3185 goto err_ret; 3186 } 3187 } 3188 lifr.lifr_ip_muxid = ip6muxid; 3189 lifr.lifr_arp_muxid = -1; 3190 if (myioctl(ip6fd, SIOCSLIFMUXID, (caddr_t)&lifr) < 0) { 3191 error("Can't set mux ID: SIOCSLIFMUXID: %m"); 3192 goto err_ret; 3193 } 3194 (void) close(tmpfd); 3195 if (udp6fd != -1) 3196 (void) close(udp6fd); 3197 return (1); 3198 3199 err_ret: 3200 (void) close(tmpfd); 3201 if (udp6fd != -1) 3202 (void) close(udp6fd); 3203 return (0); 3204 } 3205 3206 /* 3207 * unplumb_ip6if() 3208 * 3209 * Perform IPv6 interface unplumbing. Possibly called from die(), so there 3210 * shouldn't be any call to die() here. 3211 */ 3212 static int 3213 unplumb_ip6if(int unit) 3214 { 3215 int udp6fd = -1, fd = -1; 3216 int id; 3217 struct lifreq lifr; 3218 3219 if (!IPV6CP_ENABLED || ifunit == -1) { 3220 return (0); 3221 } 3222 if (!plumbed && (ip6muxid == -1 || (ip6fd == -1 && !use_plink))) { 3223 return (1); 3224 } 3225 id = ip6muxid; 3226 if (!plumbed && use_plink) { 3227 if ((udp6fd = open_udp6fd()) == -1) 3228 return (0); 3229 /* 3230 * Note: must re-get mux ID, since any intervening 3231 * ifconfigs will change this. 3232 */ 3233 BZERO(&lifr, sizeof (lifr)); 3234 (void) strlcpy(lifr.lifr_name, ifname, 3235 sizeof (lifr.lifr_name)); 3236 if (myioctl(ip6fd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) { 3237 warn("Can't get mux fd: SIOCGLIFMUXID: %m"); 3238 } else { 3239 id = lifr.lifr_ip_muxid; 3240 fd = myioctl(udp6fd, _I_MUXID2FD, (void *)id); 3241 if (fd < 0) { 3242 warn("Can't get mux fd: _I_MUXID2FD: %m"); 3243 } 3244 } 3245 } 3246 /* 3247 * Mark down and unlink the IPv6 interface. 3248 */ 3249 (void) sif6down(unit); 3250 if (plumbed) 3251 return (1); 3252 ip6muxid = -1; 3253 if (use_plink) { 3254 if ((fd = myioctl(udp6fd, _I_MUXID2FD, (void *)id)) < 0) { 3255 error("Can't recapture mux fd: _I_MUXID2FD: %m"); 3256 (void) close(udp6fd); 3257 return (0); 3258 } 3259 if (myioctl(udp6fd, I_PUNLINK, (void *)id) < 0) { 3260 error("Can't I_PUNLINK PPP from IPv6: %m"); 3261 (void) close(fd); 3262 (void) close(udp6fd); 3263 return (0); 3264 } 3265 (void) close(fd); 3266 (void) close(udp6fd); 3267 } else { 3268 if (myioctl(ip6fd, I_UNLINK, (void *)id) < 0) { 3269 error("Can't I_UNLINK PPP from IPv6: %m"); 3270 return (0); 3271 } 3272 } 3273 return (1); 3274 } 3275 3276 /* 3277 * sif6flags() 3278 * 3279 * Set or clear the IPv6 interface flags. 3280 */ 3281 int 3282 sif6flags(f, set) 3283 u_int32_t f; 3284 int set; 3285 { 3286 struct lifreq lifr; 3287 int fd; 3288 3289 if (!IPV6CP_ENABLED || (ip6muxid == -1)) { 3290 return (0); 3291 } 3292 fd = socket(AF_INET6, SOCK_DGRAM, 0); 3293 if (fd < 0) { 3294 error("sif6flags: error opening IPv6 socket: %m"); 3295 return (0); 3296 } 3297 BZERO(&lifr, sizeof (lifr)); 3298 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 3299 if (myioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) { 3300 error("Couldn't get IPv6 interface flags: %m"); 3301 (void) close(fd); 3302 return (0); 3303 } 3304 if (set) { 3305 lifr.lifr_flags |= f; 3306 } else { 3307 lifr.lifr_flags &= ~f; 3308 } 3309 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 3310 if (myioctl(fd, SIOCSLIFFLAGS, &lifr) < 0) { 3311 error("Couldn't set IPv6 interface flags: %m"); 3312 (void) close(fd); 3313 return (0); 3314 } 3315 (void) close(fd); 3316 return (1); 3317 } 3318 3319 /* 3320 * sif6up() 3321 * 3322 * Config the IPv6 interface up and enable IPv6 packets to pass. 3323 */ 3324 /*ARGSUSED*/ 3325 int 3326 sif6up(unit) 3327 int unit; 3328 { 3329 if (if6_is_up) { 3330 return (1); 3331 } else if (!IPV6CP_ENABLED) { 3332 warn("sif6up called when IPV6CP is disabled"); 3333 return (0); 3334 } else if (ip6muxid == -1) { 3335 warn("sif6up called in wrong state"); 3336 return (0); 3337 } else if (!sif6flags(IFF_UP, 1)) { 3338 error("Unable to mark the IPv6 interface UP"); 3339 return (0); 3340 } 3341 if6_is_up = 1; 3342 return (1); 3343 } 3344 3345 /* 3346 * sif6down() 3347 * 3348 * Config the IPv6 interface down and disable IPv6. Possibly called from 3349 * die(), so there shouldn't be any call to die() here. 3350 */ 3351 /*ARGSUSED*/ 3352 int 3353 sif6down(unit) 3354 int unit; 3355 { 3356 if (!IPV6CP_ENABLED) { 3357 warn("sif6down called when IPV6CP is disabled"); 3358 return (0); 3359 } else if (!if6_is_up || (ip6muxid == -1)) { 3360 return (1); 3361 } else if (!sif6flags(IFF_UP, 0)) { 3362 error("Unable to mark the IPv6 interface DOWN"); 3363 return (0); 3364 } 3365 if6_is_up = 0; 3366 return (1); 3367 } 3368 3369 /* 3370 * sif6mtu() 3371 * 3372 * Config the IPv6 interface MTU. 3373 */ 3374 int 3375 sif6mtu(mtu) 3376 int mtu; 3377 { 3378 struct lifreq lifr; 3379 int s; 3380 3381 if (!IPV6CP_ENABLED || (ip6muxid == -1)) { 3382 return (0); 3383 } 3384 s = socket(AF_INET6, SOCK_DGRAM, 0); 3385 if (s < 0) { 3386 error("sif6mtu: error opening IPv6 socket: %m"); 3387 return (0); 3388 } 3389 BZERO(&lifr, sizeof (lifr)); 3390 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 3391 lifr.lifr_mtu = mtu; 3392 if (myioctl(s, SIOCSLIFMTU, &lifr) < 0) { 3393 error("Couldn't set IPv6 MTU (%s): %m", lifr.lifr_name); 3394 (void) close(s); 3395 return (0); 3396 } 3397 (void) close(s); 3398 return (1); 3399 } 3400 3401 /* 3402 * sif6addr() 3403 * 3404 * Config the interface with an IPv6 link-local address. 3405 */ 3406 /*ARGSUSED*/ 3407 int 3408 sif6addr(unit, ourid, hisid) 3409 int unit; 3410 eui64_t ourid; 3411 eui64_t hisid; 3412 { 3413 struct lifreq lifr; 3414 struct sockaddr_storage laddr; 3415 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&laddr; 3416 int fd; 3417 3418 if (!IPV6CP_ENABLED || (ip6muxid == -1 && plumb_ip6if(unit) == 0)) { 3419 return (0); 3420 } 3421 fd = socket(AF_INET6, SOCK_DGRAM, 0); 3422 if (fd < 0) { 3423 error("sif6addr: error opening IPv6 socket: %m"); 3424 return (0); 3425 } 3426 /* 3427 * Set the IPv6 interface MTU. 3428 */ 3429 if (!sif6mtu(link_mtu)) { 3430 (void) close(fd); 3431 return (0); 3432 } 3433 /* 3434 * Set the interface address token. Do this because /dev/ppp responds 3435 * to DL_PHYS_ADDR_REQ with zero values, hence the interface token 3436 * came to be zero too, and without this, in.ndpd will complain. 3437 */ 3438 BZERO(&lifr, sizeof (lifr)); 3439 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 3440 BZERO(sin6, sizeof (struct sockaddr_in6)); 3441 IN6_LLTOKEN_FROM_EUI64(lifr, sin6, ourid); 3442 if (myioctl(fd, SIOCSLIFTOKEN, &lifr) < 0) { 3443 error("Couldn't set IPv6 token (%s): %m", lifr.lifr_name); 3444 (void) close(fd); 3445 return (0); 3446 } 3447 /* 3448 * Set the IPv6 interface local point-to-point address. 3449 */ 3450 IN6_LLADDR_FROM_EUI64(lifr, sin6, ourid); 3451 if (myioctl(fd, SIOCSLIFADDR, &lifr) < 0) { 3452 error("Couldn't set local IPv6 address (%s): %m", 3453 lifr.lifr_name); 3454 (void) close(fd); 3455 return (0); 3456 } 3457 /* 3458 * Set the IPv6 interface local point-to-point address. 3459 */ 3460 BZERO(&lifr, sizeof (lifr)); 3461 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 3462 IN6_LLADDR_FROM_EUI64(lifr, sin6, hisid); 3463 if (myioctl(fd, SIOCSLIFDSTADDR, &lifr) < 0) { 3464 error("Couldn't set remote IPv6 address (%s): %m", 3465 lifr.lifr_name); 3466 (void) close(fd); 3467 return (0); 3468 } 3469 (void) close(fd); 3470 return (1); 3471 } 3472 3473 /* 3474 * cif6addr() 3475 */ 3476 /*ARGSUSED*/ 3477 int 3478 cif6addr(u, o, h) 3479 int u; 3480 eui64_t o; 3481 eui64_t h; 3482 { 3483 if (!IPV6CP_ENABLED) { 3484 return (0); 3485 } 3486 /* 3487 * Do nothing here, as everything has been done in sif6down(). 3488 */ 3489 return (1); 3490 } 3491 3492 /* 3493 * ether_to_eui64() 3494 * 3495 * Convert 48-bit Ethernet address into 64-bit EUI. Walks the list of valid 3496 * ethernet interfaces, and convert the first found 48-bit MAC address into 3497 * EUI 64. caller also assumes that the system has a properly configured 3498 * Ethernet interface for this function to return non-zero. 3499 */ 3500 int 3501 ether_to_eui64(p_eui64) 3502 eui64_t *p_eui64; 3503 { 3504 struct ether_addr eth_addr; 3505 3506 if (p_eui64 == NULL) { 3507 return (0); 3508 } 3509 if (!get_first_hwaddr(eth_addr.ether_addr_octet, 3510 sizeof (eth_addr.ether_addr_octet))) { 3511 return (0); 3512 } 3513 /* 3514 * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1] 3515 */ 3516 p_eui64->e8[0] = (eth_addr.ether_addr_octet[0] & 0xFF) | 0x02; 3517 p_eui64->e8[1] = (eth_addr.ether_addr_octet[1] & 0xFF); 3518 p_eui64->e8[2] = (eth_addr.ether_addr_octet[2] & 0xFF); 3519 p_eui64->e8[3] = 0xFF; 3520 p_eui64->e8[4] = 0xFE; 3521 p_eui64->e8[5] = (eth_addr.ether_addr_octet[3] & 0xFF); 3522 p_eui64->e8[6] = (eth_addr.ether_addr_octet[4] & 0xFF); 3523 p_eui64->e8[7] = (eth_addr.ether_addr_octet[5] & 0xFF); 3524 return (1); 3525 } 3526 #endif /* INET6 */ 3527 3528 struct bit_ent { 3529 int val; 3530 char *off, *on; 3531 }; 3532 3533 /* see sbuf[] below if you change this list */ 3534 static struct bit_ent bit_list[] = { 3535 { TIOCM_DTR, "dtr", "DTR" }, 3536 { TIOCM_RTS, "rts", "RTS" }, 3537 { TIOCM_CTS, "cts", "CTS" }, 3538 { TIOCM_CD, "dcd", "DCD" }, 3539 { TIOCM_RI, "ri", "RI" }, 3540 { TIOCM_DSR, "dsr", "DSR" }, 3541 #if 0 3542 { TIOCM_LE, "disabled", "ENABLED" }, 3543 { TIOCM_ST, NULL, "2nd-XMIT" }, 3544 { TIOCM_SR, NULL, "2nd-RECV" }, 3545 #endif 3546 { 0, NULL, NULL } 3547 }; 3548 3549 static void 3550 getbits(int fd, char *name, FILE *strptr) 3551 { 3552 int nmods, i; 3553 struct str_list strlist; 3554 struct bit_ent *be; 3555 int mstate; 3556 char sbuf[50]; /* sum of string lengths in bit_list */ 3557 char *str; 3558 3559 nmods = ioctl(fd, I_LIST, NULL); 3560 if (nmods < 0) { 3561 error("unable to get module count: %m"); 3562 } else { 3563 strlist.sl_nmods = nmods; 3564 strlist.sl_modlist = malloc(sizeof (struct str_mlist) * nmods); 3565 if (strlist.sl_modlist == NULL) 3566 novm("module list"); 3567 if (ioctl(fd, I_LIST, (caddr_t)&strlist) < 0) { 3568 error("unable to get module names: %m"); 3569 } else { 3570 for (i = 0; i < strlist.sl_nmods; i++) 3571 (void) flprintf(strptr, "%d: %s", i, 3572 strlist.sl_modlist[i].l_name); 3573 free(strlist.sl_modlist); 3574 } 3575 } 3576 if (ioctl(fd, TIOCMGET, &mstate) < 0) { 3577 error("unable to get modem state: %m"); 3578 } else { 3579 sbuf[0] = '\0'; 3580 for (be = bit_list; be->val != 0; be++) { 3581 str = (be->val & mstate) ? be->on : be->off; 3582 if (str != NULL) { 3583 if (sbuf[0] != '\0') 3584 (void) strcat(sbuf, " "); 3585 (void) strcat(sbuf, str); 3586 } 3587 } 3588 (void) flprintf(strptr, "%s: %s\n", name, sbuf); 3589 } 3590 } 3591 3592 /* 3593 * Print state of serial link. The stream might be linked under the 3594 * /dev/sppp driver. If it is, then it's necessary to unlink it first 3595 * and relink it when done. Otherwise, it's not possible to use 3596 * ioctl() on the stream. 3597 */ 3598 void 3599 sys_print_state(FILE *strptr) 3600 { 3601 bool was_linked; 3602 3603 if (pppfd == -1) 3604 return; 3605 if (ttyfd == -1) { 3606 (void) flprintf(strptr, "serial link is not active"); 3607 return; 3608 } 3609 was_linked = fdmuxid != -1; 3610 if (was_linked && ioctl(pppfd, I_UNLINK, fdmuxid) == -1) { 3611 error("I_UNLINK: %m"); 3612 } else { 3613 fdmuxid = -1; 3614 getbits(ttyfd, devnam, strptr); 3615 if (was_linked && 3616 (fdmuxid = ioctl(pppfd, I_LINK, (void *)ttyfd)) == -1) 3617 fatal("I_LINK: %m"); 3618 } 3619 } 3620 3621 /* 3622 * send ioctl to driver asking it to block packets with network protocol 3623 * proto in the control queue until the queue for proto is plumbed. 3624 */ 3625 void 3626 sys_block_proto(uint16_t proto) 3627 { 3628 if (proto > 0x7fff) { 3629 warn("cannot block: not a network proto 0x%lx\n", proto); 3630 return; 3631 } 3632 if (strioctl(pppfd, PPPIO_BLOCKNP, &proto, sizeof (proto), 0) < 0) { 3633 warn("PPPIO_BLOCKNP ioctl failed %m"); 3634 } 3635 } 3636 /* 3637 * send ioctl to driver asking it to release packets with network protocol 3638 * proto from control queue to the protocol specific queue. 3639 */ 3640 void 3641 sys_unblock_proto(uint16_t proto) 3642 { 3643 if (proto > 0x7fff) { 3644 warn("cannot unblock: not a network proto 0x%lx\n", proto); 3645 return; 3646 } 3647 if (strioctl(pppfd, PPPIO_UNBLOCKNP, &proto, sizeof (proto), 0) < 0) { 3648 warn("PPPIO_UNBLOCKNP ioctl failed %m"); 3649 } 3650 } 3651