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