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