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