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