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