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