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