17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * System-dependent procedures for pppd under Solaris 2.x (SunOS 5.x). 37c478bd9Sstevel@tonic-gate * 4de81e71eSTim Marsland * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 57c478bd9Sstevel@tonic-gate * Use is subject to license terms. 67c478bd9Sstevel@tonic-gate * 77c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software and its 87c478bd9Sstevel@tonic-gate * documentation is hereby granted, provided that the above copyright 97c478bd9Sstevel@tonic-gate * notice appears in all copies. 107c478bd9Sstevel@tonic-gate * 117c478bd9Sstevel@tonic-gate * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF 127c478bd9Sstevel@tonic-gate * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 137c478bd9Sstevel@tonic-gate * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 147c478bd9Sstevel@tonic-gate * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR 157c478bd9Sstevel@tonic-gate * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR 167c478bd9Sstevel@tonic-gate * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES 177c478bd9Sstevel@tonic-gate * 187c478bd9Sstevel@tonic-gate * Copyright (c) 1994 The Australian National University. 197c478bd9Sstevel@tonic-gate * All rights reserved. 207c478bd9Sstevel@tonic-gate * 217c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software and its 227c478bd9Sstevel@tonic-gate * documentation is hereby granted, provided that the above copyright 237c478bd9Sstevel@tonic-gate * notice appears in all copies. This software is provided without any 247c478bd9Sstevel@tonic-gate * warranty, express or implied. The Australian National University 257c478bd9Sstevel@tonic-gate * makes no representations about the suitability of this software for 267c478bd9Sstevel@tonic-gate * any purpose. 277c478bd9Sstevel@tonic-gate * 287c478bd9Sstevel@tonic-gate * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY 297c478bd9Sstevel@tonic-gate * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 307c478bd9Sstevel@tonic-gate * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 317c478bd9Sstevel@tonic-gate * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY 327c478bd9Sstevel@tonic-gate * OF SUCH DAMAGE. 337c478bd9Sstevel@tonic-gate * 347c478bd9Sstevel@tonic-gate * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, 357c478bd9Sstevel@tonic-gate * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 367c478bd9Sstevel@tonic-gate * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 377c478bd9Sstevel@tonic-gate * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO 387c478bd9Sstevel@tonic-gate * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 397c478bd9Sstevel@tonic-gate * OR MODIFICATIONS. 407c478bd9Sstevel@tonic-gate */ 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #define RCSID "$Id: sys-solaris.c,v 1.2 2000/04/21 01:27:57 masputra Exp $" 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate #include <limits.h> 457c478bd9Sstevel@tonic-gate #include <stdio.h> 467c478bd9Sstevel@tonic-gate #include <stddef.h> 477c478bd9Sstevel@tonic-gate #include <stdlib.h> 487c478bd9Sstevel@tonic-gate #include <ctype.h> 497c478bd9Sstevel@tonic-gate #include <errno.h> 507c478bd9Sstevel@tonic-gate #include <fcntl.h> 517c478bd9Sstevel@tonic-gate #include <unistd.h> 527c478bd9Sstevel@tonic-gate #include <netdb.h> 537c478bd9Sstevel@tonic-gate #include <termios.h> 547c478bd9Sstevel@tonic-gate #include <signal.h> 557c478bd9Sstevel@tonic-gate #include <string.h> 567c478bd9Sstevel@tonic-gate #include <stropts.h> 577c478bd9Sstevel@tonic-gate #include <utmpx.h> 587c478bd9Sstevel@tonic-gate #include <sys/types.h> 597c478bd9Sstevel@tonic-gate #include <sys/ioccom.h> 607c478bd9Sstevel@tonic-gate #include <sys/stream.h> 617c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 627c478bd9Sstevel@tonic-gate #include <sys/socket.h> 637c478bd9Sstevel@tonic-gate #include <sys/sockio.h> 647c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 657c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 667c478bd9Sstevel@tonic-gate #include <sys/stat.h> 677c478bd9Sstevel@tonic-gate #include <net/if.h> 687c478bd9Sstevel@tonic-gate #include <net/if_arp.h> 697c478bd9Sstevel@tonic-gate #include <net/route.h> 707c478bd9Sstevel@tonic-gate #include <net/ppp_defs.h> 717c478bd9Sstevel@tonic-gate #include <net/pppio.h> 727c478bd9Sstevel@tonic-gate #include <net/if_types.h> 737c478bd9Sstevel@tonic-gate #include <net/if_dl.h> 747c478bd9Sstevel@tonic-gate #include <netinet/in.h> 757c478bd9Sstevel@tonic-gate #include <sys/tihdr.h> 767c478bd9Sstevel@tonic-gate #include <inet/mib2.h> 77ff550d0eSmasputra #include <inet/ip.h> 787c478bd9Sstevel@tonic-gate #include <sys/ethernet.h> 797c478bd9Sstevel@tonic-gate #include <sys/ser_sync.h> 80fb60e41dSss #include <libdlpi.h> 81*f53eecf5SJames Carlson #include <arpa/inet.h> 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate #include "pppd.h" 847c478bd9Sstevel@tonic-gate #include "fsm.h" 857c478bd9Sstevel@tonic-gate #include "lcp.h" 867c478bd9Sstevel@tonic-gate #include "ipcp.h" 877c478bd9Sstevel@tonic-gate #ifdef INET6 887c478bd9Sstevel@tonic-gate #include "ipv6cp.h" 897c478bd9Sstevel@tonic-gate #endif /* INET6 */ 907c478bd9Sstevel@tonic-gate #include "ccp.h" 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate #if !defined(lint) && !defined(_lint) 937c478bd9Sstevel@tonic-gate static const char rcsid[] = RCSID; 947c478bd9Sstevel@tonic-gate #endif 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate #define PPPSTRTIMOUT 1 /* Timeout in seconds for ioctl */ 977c478bd9Sstevel@tonic-gate #define MAX_POLLFDS 32 987c478bd9Sstevel@tonic-gate #define NMODULES 32 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate #ifndef MAXIFS 1017c478bd9Sstevel@tonic-gate #define MAXIFS 256 1027c478bd9Sstevel@tonic-gate #endif /* MAXIFS */ 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate #ifdef INET6 1057c478bd9Sstevel@tonic-gate #define _IN6_LLX_FROM_EUI64(l, s, eui64, as, len) \ 1067c478bd9Sstevel@tonic-gate (s->sin6_addr.s6_addr32[0] = htonl(as), \ 1077c478bd9Sstevel@tonic-gate eui64_copy(eui64, s->sin6_addr.s6_addr32[2]), \ 1087c478bd9Sstevel@tonic-gate s->sin6_family = AF_INET6, \ 1097c478bd9Sstevel@tonic-gate l.lifr_addr.ss_family = AF_INET6, \ 1107c478bd9Sstevel@tonic-gate l.lifr_addrlen = len, \ 1117c478bd9Sstevel@tonic-gate l.lifr_addr = laddr) 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* 1147c478bd9Sstevel@tonic-gate * Generate a link-local address with an interface-id based on the given 1157c478bd9Sstevel@tonic-gate * EUI64 identifier. Note that the len field is unused by SIOCSLIFADDR. 1167c478bd9Sstevel@tonic-gate */ 1177c478bd9Sstevel@tonic-gate #define IN6_LLADDR_FROM_EUI64(l, s, eui64) \ 1187c478bd9Sstevel@tonic-gate _IN6_LLX_FROM_EUI64(l, s, eui64, 0xfe800000, 0) 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* 1217c478bd9Sstevel@tonic-gate * Generate an EUI64 based interface-id for use by stateless address 1227c478bd9Sstevel@tonic-gate * autoconfiguration. These are required to be 64 bits long as defined in 1237c478bd9Sstevel@tonic-gate * the "Interface Identifiers" section of the IPv6 Addressing Architecture 1247c478bd9Sstevel@tonic-gate * (RFC3513). 1257c478bd9Sstevel@tonic-gate */ 1267c478bd9Sstevel@tonic-gate #define IN6_LLTOKEN_FROM_EUI64(l, s, eui64) \ 1277c478bd9Sstevel@tonic-gate _IN6_LLX_FROM_EUI64(l, s, eui64, 0, 64) 1287c478bd9Sstevel@tonic-gate #endif /* INET6 */ 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate #define IPCP_ENABLED ipcp_protent.enabled_flag 1317c478bd9Sstevel@tonic-gate #ifdef INET6 1327c478bd9Sstevel@tonic-gate #define IPV6CP_ENABLED ipv6cp_protent.enabled_flag 1337c478bd9Sstevel@tonic-gate #endif /* INET6 */ 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /* For plug-in usage. */ 1367c478bd9Sstevel@tonic-gate int (*sys_read_packet_hook) __P((int retv, struct strbuf *ctrl, 1377c478bd9Sstevel@tonic-gate struct strbuf *data, int flags)) = NULL; 1387c478bd9Sstevel@tonic-gate bool already_ppp = 0; /* Already in PPP mode */ 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate static int pppfd = -1; /* ppp driver fd */ 1417c478bd9Sstevel@tonic-gate static int fdmuxid = -1; /* driver mux fd */ 1427c478bd9Sstevel@tonic-gate static int ipfd = -1; /* IPv4 fd */ 1437c478bd9Sstevel@tonic-gate static int ipmuxid = -1; /* IPv4 mux fd */ 1447c478bd9Sstevel@tonic-gate static int ip6fd = -1; /* IPv6 fd */ 1457c478bd9Sstevel@tonic-gate static int ip6muxid = -1; /* IPv6 mux fd */ 1467c478bd9Sstevel@tonic-gate static bool if6_is_up = 0; /* IPv6 if marked as up */ 1477c478bd9Sstevel@tonic-gate static bool if_is_up = 0; /* IPv4 if marked as up */ 1487c478bd9Sstevel@tonic-gate static bool restore_term = 0; /* Restore TTY after closing link */ 1497c478bd9Sstevel@tonic-gate static struct termios inittermios; /* TTY settings */ 1507c478bd9Sstevel@tonic-gate static struct winsize wsinfo; /* Initial window size info */ 1517c478bd9Sstevel@tonic-gate static pid_t tty_sid; /* original sess ID for term */ 1527c478bd9Sstevel@tonic-gate static struct pollfd pollfds[MAX_POLLFDS]; /* array of polled fd */ 1537c478bd9Sstevel@tonic-gate static int n_pollfds = 0; /* total count of polled fd */ 1547c478bd9Sstevel@tonic-gate static int link_mtu; /* link Maximum Transmit Unit */ 1557c478bd9Sstevel@tonic-gate static int tty_nmodules; /* total count of TTY modules used */ 1567c478bd9Sstevel@tonic-gate static char tty_modules[NMODULES][FMNAMESZ+1]; 1577c478bd9Sstevel@tonic-gate /* array of TTY modules used */ 1587c478bd9Sstevel@tonic-gate static int tty_npushed; /* total count of pushed PPP modules */ 1597c478bd9Sstevel@tonic-gate static u_int32_t remote_addr; /* IP address of peer */ 1607c478bd9Sstevel@tonic-gate static u_int32_t default_route_gateway; /* Gateway for default route */ 1617c478bd9Sstevel@tonic-gate static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry */ 1627c478bd9Sstevel@tonic-gate static u_int32_t lastlink_status; /* Last link status info */ 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate static bool use_plink = 0; /* Use I_LINK by default */ 1657c478bd9Sstevel@tonic-gate static bool plumbed = 0; /* Use existing interface */ 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate /* Default is to use /dev/sppp as driver. */ 1687c478bd9Sstevel@tonic-gate static const char *drvnam = PPP_DEV_NAME; 1697c478bd9Sstevel@tonic-gate static bool integrated_driver = 0; 1707c478bd9Sstevel@tonic-gate static int extra_dev_fd = -1; /* keep open until ready */ 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate static option_t solaris_option_list[] = { 1737c478bd9Sstevel@tonic-gate { "plink", o_bool, &use_plink, "Use I_PLINK instead of I_LINK", 1747c478bd9Sstevel@tonic-gate OPT_PRIV|1 }, 1757c478bd9Sstevel@tonic-gate { "noplink", o_bool, &use_plink, "Use I_LINK instead of I_PLINK", 1767c478bd9Sstevel@tonic-gate OPT_PRIV|0 }, 1777c478bd9Sstevel@tonic-gate { "plumbed", o_bool, &plumbed, "Use pre-plumbed interface", 1787c478bd9Sstevel@tonic-gate OPT_PRIV|1 }, 1797c478bd9Sstevel@tonic-gate { NULL } 1807c478bd9Sstevel@tonic-gate }; 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * Prototypes for procedures local to this file. 1847c478bd9Sstevel@tonic-gate */ 1857c478bd9Sstevel@tonic-gate static int translate_speed __P((int)); 1867c478bd9Sstevel@tonic-gate static int baud_rate_of __P((int)); 1877c478bd9Sstevel@tonic-gate static int get_ether_addr __P((u_int32_t, struct sockaddr_dl *, int)); 1887c478bd9Sstevel@tonic-gate static int strioctl __P((int, int, void *, int, int)); 1897c478bd9Sstevel@tonic-gate static int plumb_ipif __P((int)); 1907c478bd9Sstevel@tonic-gate static int unplumb_ipif __P((int)); 1917c478bd9Sstevel@tonic-gate #ifdef INET6 1927c478bd9Sstevel@tonic-gate static int plumb_ip6if __P((int)); 1937c478bd9Sstevel@tonic-gate static int unplumb_ip6if __P((int)); 1947c478bd9Sstevel@tonic-gate static int open_ip6fd(void); 1957c478bd9Sstevel@tonic-gate #endif /* INET6 */ 1967c478bd9Sstevel@tonic-gate static int open_ipfd(void); 1977c478bd9Sstevel@tonic-gate static int sifroute __P((int, u_int32_t, u_int32_t, int, const char *)); 1987c478bd9Sstevel@tonic-gate static int giflags __P((u_int32_t, bool *)); 1997c478bd9Sstevel@tonic-gate static void handle_unbind __P((u_int32_t)); 2007c478bd9Sstevel@tonic-gate static void handle_bind __P((u_int32_t)); 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* 2037c478bd9Sstevel@tonic-gate * Wrapper for regular ioctl; masks out EINTR. 2047c478bd9Sstevel@tonic-gate */ 2057c478bd9Sstevel@tonic-gate static int 2067c478bd9Sstevel@tonic-gate myioctl(int fd, int cmd, void *arg) 2077c478bd9Sstevel@tonic-gate { 2087c478bd9Sstevel@tonic-gate int retv; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate errno = 0; 2117c478bd9Sstevel@tonic-gate while ((retv = ioctl(fd, cmd, arg)) == -1) { 2127c478bd9Sstevel@tonic-gate if (errno != EINTR) 2137c478bd9Sstevel@tonic-gate break; 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate return (retv); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* 2197c478bd9Sstevel@tonic-gate * sys_check_options() 2207c478bd9Sstevel@tonic-gate * 2217c478bd9Sstevel@tonic-gate * Check the options that the user specified. 2227c478bd9Sstevel@tonic-gate */ 2237c478bd9Sstevel@tonic-gate int 2247c478bd9Sstevel@tonic-gate sys_check_options(void) 2257c478bd9Sstevel@tonic-gate { 2267c478bd9Sstevel@tonic-gate if (plumbed) { 2277c478bd9Sstevel@tonic-gate if (req_unit == -1) 2287c478bd9Sstevel@tonic-gate req_unit = -2; 2297c478bd9Sstevel@tonic-gate ipmuxid = 0; 2307c478bd9Sstevel@tonic-gate ip6muxid = 0; 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate return (1); 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate /* 2367c478bd9Sstevel@tonic-gate * sys_options() 2377c478bd9Sstevel@tonic-gate * 2387c478bd9Sstevel@tonic-gate * Add or remove system-specific options. 2397c478bd9Sstevel@tonic-gate */ 2407c478bd9Sstevel@tonic-gate void 2417c478bd9Sstevel@tonic-gate sys_options(void) 2427c478bd9Sstevel@tonic-gate { 2437c478bd9Sstevel@tonic-gate (void) remove_option("ktune"); 2447c478bd9Sstevel@tonic-gate (void) remove_option("noktune"); 2457c478bd9Sstevel@tonic-gate add_options(solaris_option_list); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * sys_ifname() 2507c478bd9Sstevel@tonic-gate * 2517c478bd9Sstevel@tonic-gate * Set ifname[] to contain name of IP interface for this unit. 2527c478bd9Sstevel@tonic-gate */ 2537c478bd9Sstevel@tonic-gate void 2547c478bd9Sstevel@tonic-gate sys_ifname(void) 2557c478bd9Sstevel@tonic-gate { 2567c478bd9Sstevel@tonic-gate const char *cp; 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate if ((cp = strrchr(drvnam, '/')) == NULL) 2597c478bd9Sstevel@tonic-gate cp = drvnam; 2607c478bd9Sstevel@tonic-gate else 2617c478bd9Sstevel@tonic-gate cp++; 2627c478bd9Sstevel@tonic-gate (void) slprintf(ifname, sizeof (ifname), "%s%d", cp, ifunit); 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate /* 2667c478bd9Sstevel@tonic-gate * ppp_available() 2677c478bd9Sstevel@tonic-gate * 2687c478bd9Sstevel@tonic-gate * Check whether the system has any ppp interfaces. 2697c478bd9Sstevel@tonic-gate */ 2707c478bd9Sstevel@tonic-gate int 2717c478bd9Sstevel@tonic-gate ppp_available(void) 2727c478bd9Sstevel@tonic-gate { 2737c478bd9Sstevel@tonic-gate struct stat buf; 2747c478bd9Sstevel@tonic-gate int fd; 2757c478bd9Sstevel@tonic-gate uint32_t typ; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate if (stat(PPP_DEV_NAME, &buf) >= 0) 2787c478bd9Sstevel@tonic-gate return (1); 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate /* 2817c478bd9Sstevel@tonic-gate * Simple check for system using Apollo POS without SUNWpppd 2827c478bd9Sstevel@tonic-gate * (/dev/sppp) installed. This is intentionally not kept open 2837c478bd9Sstevel@tonic-gate * here, since the user may not have the same privileges (as 2847c478bd9Sstevel@tonic-gate * determined later). If Apollo were just shipped with the 2857c478bd9Sstevel@tonic-gate * full complement of packages, this wouldn't be an issue. 2867c478bd9Sstevel@tonic-gate */ 2877c478bd9Sstevel@tonic-gate if (devnam[0] == '\0' && 2887c478bd9Sstevel@tonic-gate (fd = open(devnam, O_RDWR | O_NONBLOCK | O_NOCTTY)) >= 0) { 2897c478bd9Sstevel@tonic-gate if (strioctl(fd, PPPIO_GTYPE, &typ, 0, sizeof (typ)) >= 0 && 2907c478bd9Sstevel@tonic-gate typ == PPPTYP_MUX) { 2917c478bd9Sstevel@tonic-gate (void) close(fd); 2927c478bd9Sstevel@tonic-gate return (1); 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate (void) close(fd); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate return (0); 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate static int 3007c478bd9Sstevel@tonic-gate open_ipfd(void) 3017c478bd9Sstevel@tonic-gate { 3027c478bd9Sstevel@tonic-gate ipfd = open(IP_DEV_NAME, O_RDWR | O_NONBLOCK, 0); 3037c478bd9Sstevel@tonic-gate if (ipfd < 0) { 3047c478bd9Sstevel@tonic-gate error("Couldn't open IP device (%s): %m", IP_DEV_NAME); 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate return (ipfd); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate static int 3107c478bd9Sstevel@tonic-gate read_ip_interface(int unit) 3117c478bd9Sstevel@tonic-gate { 3127c478bd9Sstevel@tonic-gate struct ifreq ifr; 3137c478bd9Sstevel@tonic-gate struct sockaddr_in sin; 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate if (ipfd == -1 && open_ipfd() == -1) 3167c478bd9Sstevel@tonic-gate return (0); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate BZERO(&ifr, sizeof (ifr)); 3197c478bd9Sstevel@tonic-gate (void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate /* Get the existing MTU */ 3227c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCGIFMTU, &ifr) < 0) { 3237c478bd9Sstevel@tonic-gate warn("Couldn't get IP MTU on %s: %m", ifr.ifr_name); 3247c478bd9Sstevel@tonic-gate return (0); 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate dbglog("got MTU %d from interface", ifr.ifr_metric); 3277c478bd9Sstevel@tonic-gate if (ifr.ifr_metric != 0 && 3287c478bd9Sstevel@tonic-gate (lcp_allowoptions[unit].mru == 0 || 329fb60e41dSss lcp_allowoptions[unit].mru > ifr.ifr_metric)) 3307c478bd9Sstevel@tonic-gate lcp_allowoptions[unit].mru = ifr.ifr_metric; 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate /* Get the local IP address */ 3337c478bd9Sstevel@tonic-gate if (ipcp_wantoptions[unit].ouraddr == 0 || 3347c478bd9Sstevel@tonic-gate ipcp_from_hostname) { 3357c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCGIFADDR, &ifr) < 0) { 3367c478bd9Sstevel@tonic-gate warn("Couldn't get local IP address (%s): %m", 3377c478bd9Sstevel@tonic-gate ifr.ifr_name); 3387c478bd9Sstevel@tonic-gate return (0); 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate BCOPY(&ifr.ifr_addr, &sin, sizeof (struct sockaddr_in)); 3417c478bd9Sstevel@tonic-gate ipcp_wantoptions[unit].ouraddr = sin.sin_addr.s_addr; 3427c478bd9Sstevel@tonic-gate dbglog("got local address %I from interface", 3437c478bd9Sstevel@tonic-gate ipcp_wantoptions[unit].ouraddr); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate /* Get the remote IP address */ 3477c478bd9Sstevel@tonic-gate if (ipcp_wantoptions[unit].hisaddr == 0) { 3487c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCGIFDSTADDR, &ifr) < 0) { 3497c478bd9Sstevel@tonic-gate warn("Couldn't get remote IP address (%s): %m", 3507c478bd9Sstevel@tonic-gate ifr.ifr_name); 3517c478bd9Sstevel@tonic-gate return (0); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate BCOPY(&ifr.ifr_dstaddr, &sin, sizeof (struct sockaddr_in)); 3547c478bd9Sstevel@tonic-gate ipcp_wantoptions[unit].hisaddr = sin.sin_addr.s_addr; 3557c478bd9Sstevel@tonic-gate dbglog("got remote address %I from interface", 3567c478bd9Sstevel@tonic-gate ipcp_wantoptions[unit].hisaddr); 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate return (1); 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate #ifdef INET6 3627c478bd9Sstevel@tonic-gate static int 3637c478bd9Sstevel@tonic-gate open_ip6fd(void) 3647c478bd9Sstevel@tonic-gate { 3657c478bd9Sstevel@tonic-gate ip6fd = open(IP6_DEV_NAME, O_RDWR | O_NONBLOCK, 0); 3667c478bd9Sstevel@tonic-gate if (ip6fd < 0) { 3677c478bd9Sstevel@tonic-gate error("Couldn't open IPv6 device (%s): %m", IP6_DEV_NAME); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate return (ip6fd); 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate static int 3737c478bd9Sstevel@tonic-gate read_ipv6_interface(int unit) 3747c478bd9Sstevel@tonic-gate { 3757c478bd9Sstevel@tonic-gate struct lifreq lifr; 3767c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate if (ip6fd == -1 && open_ip6fd() == -1) 3797c478bd9Sstevel@tonic-gate return (0); 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate BZERO(&lifr, sizeof (lifr)); 3827c478bd9Sstevel@tonic-gate (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate /* Get the existing MTU */ 3857c478bd9Sstevel@tonic-gate if (myioctl(ip6fd, SIOCGLIFMTU, &lifr) < 0) { 3867c478bd9Sstevel@tonic-gate warn("Couldn't get IPv6 MTU on %s: %m", lifr.lifr_name); 3877c478bd9Sstevel@tonic-gate return (0); 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate if (lifr.lifr_mtu != 0 && 3907c478bd9Sstevel@tonic-gate (lcp_allowoptions[unit].mru == 0 || 391fb60e41dSss lcp_allowoptions[unit].mru > lifr.lifr_mtu)) 3927c478bd9Sstevel@tonic-gate lcp_allowoptions[unit].mru = lifr.lifr_mtu; 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate /* Get the local IPv6 address */ 3957c478bd9Sstevel@tonic-gate if (eui64_iszero(ipv6cp_wantoptions[unit].ourid) || 3967c478bd9Sstevel@tonic-gate (ipcp_from_hostname && ipv6cp_wantoptions[unit].use_ip)) { 3977c478bd9Sstevel@tonic-gate if (myioctl(ip6fd, SIOCGLIFADDR, &lifr) < 0) { 3987c478bd9Sstevel@tonic-gate warn("Couldn't get local IPv6 address (%s): %m", 3997c478bd9Sstevel@tonic-gate lifr.lifr_name); 4007c478bd9Sstevel@tonic-gate return (0); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate eui64_copy(sin6->sin6_addr.s6_addr32[2], 4037c478bd9Sstevel@tonic-gate ipv6cp_wantoptions[unit].ourid); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate /* Get the remote IP address */ 4077c478bd9Sstevel@tonic-gate if (eui64_iszero(ipv6cp_wantoptions[unit].hisid)) { 4087c478bd9Sstevel@tonic-gate if (myioctl(ip6fd, SIOCGLIFDSTADDR, &lifr) < 0) { 4097c478bd9Sstevel@tonic-gate warn("Couldn't get remote IPv6 address (%s): %m", 4107c478bd9Sstevel@tonic-gate lifr.lifr_name); 4117c478bd9Sstevel@tonic-gate return (0); 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate eui64_copy(sin6->sin6_addr.s6_addr32[2], 4147c478bd9Sstevel@tonic-gate ipv6cp_wantoptions[unit].hisid); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate return (1); 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate #endif /* INET6 */ 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate /* 4217c478bd9Sstevel@tonic-gate * Read information on existing interface(s) and configure ourselves 4227c478bd9Sstevel@tonic-gate * to negotiate appropriately. 4237c478bd9Sstevel@tonic-gate */ 4247c478bd9Sstevel@tonic-gate static void 4257c478bd9Sstevel@tonic-gate read_interface(int unit) 4267c478bd9Sstevel@tonic-gate { 4277c478bd9Sstevel@tonic-gate dbglog("reading existing interface data; %sip %sipv6", 4287c478bd9Sstevel@tonic-gate IPCP_ENABLED ? "" : "!", 4297c478bd9Sstevel@tonic-gate #ifdef INET6 4307c478bd9Sstevel@tonic-gate IPV6CP_ENABLED ? "" : 4317c478bd9Sstevel@tonic-gate #endif 4327c478bd9Sstevel@tonic-gate "!"); 4337c478bd9Sstevel@tonic-gate if (IPCP_ENABLED && !read_ip_interface(unit)) 4347c478bd9Sstevel@tonic-gate IPCP_ENABLED = 0; 4357c478bd9Sstevel@tonic-gate #ifdef INET6 4367c478bd9Sstevel@tonic-gate if (IPV6CP_ENABLED && !read_ipv6_interface(unit)) 4377c478bd9Sstevel@tonic-gate IPV6CP_ENABLED = 0; 4387c478bd9Sstevel@tonic-gate #endif 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate /* 4427c478bd9Sstevel@tonic-gate * sys_init() 4437c478bd9Sstevel@tonic-gate * 4447c478bd9Sstevel@tonic-gate * System-dependent initialization. 4457c478bd9Sstevel@tonic-gate */ 4467c478bd9Sstevel@tonic-gate void 4477c478bd9Sstevel@tonic-gate sys_init(bool open_as_user) 4487c478bd9Sstevel@tonic-gate { 4497c478bd9Sstevel@tonic-gate uint32_t x; 4507c478bd9Sstevel@tonic-gate uint32_t typ; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate if (pppfd != -1) { 4537c478bd9Sstevel@tonic-gate return; 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate if (!direct_tty && devnam[0] != '\0') { 4577c478bd9Sstevel@tonic-gate /* 4587c478bd9Sstevel@tonic-gate * Check for integrated driver-like devices (such as 4597c478bd9Sstevel@tonic-gate * POS). These identify themselves as "PPP 4607c478bd9Sstevel@tonic-gate * multiplexor" drivers. 4617c478bd9Sstevel@tonic-gate */ 4627c478bd9Sstevel@tonic-gate if (open_as_user) 4637c478bd9Sstevel@tonic-gate (void) seteuid(getuid()); 4647c478bd9Sstevel@tonic-gate pppfd = open(devnam, O_RDWR | O_NONBLOCK); 4657c478bd9Sstevel@tonic-gate if (open_as_user) 4667c478bd9Sstevel@tonic-gate (void) seteuid(0); 4677c478bd9Sstevel@tonic-gate if (pppfd >= 0 && 4687c478bd9Sstevel@tonic-gate strioctl(pppfd, PPPIO_GTYPE, &typ, 0, sizeof (typ)) >= 0 && 4697c478bd9Sstevel@tonic-gate typ == PPPTYP_MUX) { 4707c478bd9Sstevel@tonic-gate integrated_driver = 1; 4717c478bd9Sstevel@tonic-gate drvnam = devnam; 4727c478bd9Sstevel@tonic-gate } else if (demand) { 4737c478bd9Sstevel@tonic-gate (void) close(pppfd); 4747c478bd9Sstevel@tonic-gate pppfd = -1; 4757c478bd9Sstevel@tonic-gate } else { 4767c478bd9Sstevel@tonic-gate extra_dev_fd = pppfd; 4777c478bd9Sstevel@tonic-gate pppfd = -1; 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate /* 4827c478bd9Sstevel@tonic-gate * Open Solaris PPP device driver. 4837c478bd9Sstevel@tonic-gate */ 4847c478bd9Sstevel@tonic-gate if (pppfd < 0) 4857c478bd9Sstevel@tonic-gate pppfd = open(drvnam, O_RDWR | O_NONBLOCK); 4867c478bd9Sstevel@tonic-gate if (pppfd < 0) { 4877c478bd9Sstevel@tonic-gate fatal("Can't open %s: %m", drvnam); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate if (kdebugflag & 1) { 4907c478bd9Sstevel@tonic-gate x = PPPDBG_LOG + PPPDBG_DRIVER; 4917c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) { 4927c478bd9Sstevel@tonic-gate warn("PPPIO_DEBUG ioctl for mux failed: %m"); 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate /* 4967c478bd9Sstevel@tonic-gate * Assign a new PPA and get its unit number. 4977c478bd9Sstevel@tonic-gate */ 4987c478bd9Sstevel@tonic-gate x = req_unit; 4997c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_NEWPPA, &x, sizeof (x), sizeof (x)) < 0) { 5007c478bd9Sstevel@tonic-gate if (errno == ENXIO && plumbed) 5017c478bd9Sstevel@tonic-gate fatal("No idle interfaces available for use"); 5027c478bd9Sstevel@tonic-gate fatal("PPPIO_NEWPPA ioctl failed: %m"); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate ifunit = x; 5057c478bd9Sstevel@tonic-gate if (req_unit >= 0 && ifunit != req_unit) { 5067c478bd9Sstevel@tonic-gate if (plumbed) 5077c478bd9Sstevel@tonic-gate fatal("unable to get requested unit %d", req_unit); 5087c478bd9Sstevel@tonic-gate else 5097c478bd9Sstevel@tonic-gate warn("unable to get requested unit %d", req_unit); 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate /* 5127c478bd9Sstevel@tonic-gate * Enable packet time-stamping when idle option is specified. Note 5137c478bd9Sstevel@tonic-gate * that we need to only do this on the control stream. Subsequent 5147c478bd9Sstevel@tonic-gate * streams attached to this control stream (ppa) will inherit 5157c478bd9Sstevel@tonic-gate * the time-stamp bit. 5167c478bd9Sstevel@tonic-gate */ 5177c478bd9Sstevel@tonic-gate if (idle_time_limit > 0) { 5187c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_USETIMESTAMP, NULL, 0, 0) < 0) { 5197c478bd9Sstevel@tonic-gate warn("PPPIO_USETIMESTAMP ioctl failed: %m"); 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate if (plumbed) { 5237c478bd9Sstevel@tonic-gate sys_ifname(); 5247c478bd9Sstevel@tonic-gate read_interface(0); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate int 5297c478bd9Sstevel@tonic-gate sys_extra_fd(void) 5307c478bd9Sstevel@tonic-gate { 5317c478bd9Sstevel@tonic-gate int fd; 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate fd = extra_dev_fd; 5347c478bd9Sstevel@tonic-gate extra_dev_fd = -1; 5357c478bd9Sstevel@tonic-gate return (fd); 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate static int 5397c478bd9Sstevel@tonic-gate open_udpfd(void) 5407c478bd9Sstevel@tonic-gate { 5417c478bd9Sstevel@tonic-gate int udpfd; 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate udpfd = open(UDP_DEV_NAME, O_RDWR | O_NONBLOCK, 0); 5447c478bd9Sstevel@tonic-gate if (udpfd < 0) { 5457c478bd9Sstevel@tonic-gate error("Couldn't open UDP device (%s): %m", UDP_DEV_NAME); 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate return (udpfd); 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate /* 5517c478bd9Sstevel@tonic-gate * plumb_ipif() 5527c478bd9Sstevel@tonic-gate * 5537c478bd9Sstevel@tonic-gate * Perform IP interface plumbing. 5547c478bd9Sstevel@tonic-gate */ 5557c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 5567c478bd9Sstevel@tonic-gate static int 5577c478bd9Sstevel@tonic-gate plumb_ipif(int unit) 5587c478bd9Sstevel@tonic-gate { 5597c478bd9Sstevel@tonic-gate int udpfd = -1, tmpfd; 5607c478bd9Sstevel@tonic-gate uint32_t x; 5617c478bd9Sstevel@tonic-gate struct ifreq ifr; 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate if (!IPCP_ENABLED || (ifunit == -1) || (pppfd == -1)) { 5647c478bd9Sstevel@tonic-gate return (0); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate if (plumbed) 5677c478bd9Sstevel@tonic-gate return (1); 5687c478bd9Sstevel@tonic-gate if (ipfd == -1 && open_ipfd() == -1) 5697c478bd9Sstevel@tonic-gate return (0); 5707c478bd9Sstevel@tonic-gate if (use_plink && (udpfd = open_udpfd()) == -1) 5717c478bd9Sstevel@tonic-gate return (0); 5727c478bd9Sstevel@tonic-gate tmpfd = open(drvnam, O_RDWR | O_NONBLOCK, 0); 5737c478bd9Sstevel@tonic-gate if (tmpfd < 0) { 5747c478bd9Sstevel@tonic-gate error("Couldn't open PPP device (%s): %m", drvnam); 5757c478bd9Sstevel@tonic-gate if (udpfd != -1) 5767c478bd9Sstevel@tonic-gate (void) close(udpfd); 5777c478bd9Sstevel@tonic-gate return (0); 5787c478bd9Sstevel@tonic-gate } 5797c478bd9Sstevel@tonic-gate if (kdebugflag & 1) { 5807c478bd9Sstevel@tonic-gate x = PPPDBG_LOG + PPPDBG_DRIVER; 5817c478bd9Sstevel@tonic-gate if (strioctl(tmpfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) { 5827c478bd9Sstevel@tonic-gate warn("PPPIO_DEBUG ioctl for mux failed: %m"); 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate if (myioctl(tmpfd, I_PUSH, IP_MOD_NAME) < 0) { 5867c478bd9Sstevel@tonic-gate error("Couldn't push IP module (%s): %m", IP_MOD_NAME); 5877c478bd9Sstevel@tonic-gate goto err_ret; 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate /* 5907c478bd9Sstevel@tonic-gate * Assign ppa according to the unit number returned by ppp device 5917c478bd9Sstevel@tonic-gate * after plumbing is completed above. Without setting the ppa, ip 5927c478bd9Sstevel@tonic-gate * module will return EINVAL upon setting the interface UP 5937c478bd9Sstevel@tonic-gate * (SIOCSxIFFLAGS). This is because ip module in 2.8 expects two 5947c478bd9Sstevel@tonic-gate * DLPI_INFO_REQ to be sent down to the driver (below ip) before 5957c478bd9Sstevel@tonic-gate * IFF_UP bit can be set. Plumbing the device causes one DLPI_INFO_REQ 5967c478bd9Sstevel@tonic-gate * to be sent down, and the second DLPI_INFO_REQ is sent upon receiving 5977c478bd9Sstevel@tonic-gate * IF_UNITSEL (old) or SIOCSLIFNAME (new) ioctls. Such setting of the 5987c478bd9Sstevel@tonic-gate * ppa is required because the ppp DLPI provider advertises itself as 5997c478bd9Sstevel@tonic-gate * a DLPI style 2 type, which requires a point of attachment to be 6007c478bd9Sstevel@tonic-gate * specified. The only way the user can specify a point of attachment 6017c478bd9Sstevel@tonic-gate * is via SIOCSLIFNAME or IF_UNITSEL. Such changes in the behavior of 6027c478bd9Sstevel@tonic-gate * ip module was made to meet new or evolving standards requirements. 6037c478bd9Sstevel@tonic-gate */ 6047c478bd9Sstevel@tonic-gate if (myioctl(tmpfd, IF_UNITSEL, &ifunit) < 0) { 6057c478bd9Sstevel@tonic-gate error("Couldn't set ppa for unit %d: %m", ifunit); 6067c478bd9Sstevel@tonic-gate goto err_ret; 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate if (use_plink) { 6097c478bd9Sstevel@tonic-gate ipmuxid = myioctl(udpfd, I_PLINK, (void *)tmpfd); 6107c478bd9Sstevel@tonic-gate if (ipmuxid < 0) { 6117c478bd9Sstevel@tonic-gate error("Can't I_PLINK PPP device to IP: %m"); 6127c478bd9Sstevel@tonic-gate goto err_ret; 6137c478bd9Sstevel@tonic-gate } 6147c478bd9Sstevel@tonic-gate } else { 6157c478bd9Sstevel@tonic-gate ipmuxid = myioctl(ipfd, I_LINK, (void *)tmpfd); 6167c478bd9Sstevel@tonic-gate if (ipmuxid < 0) { 6177c478bd9Sstevel@tonic-gate error("Can't I_LINK PPP device to IP: %m"); 6187c478bd9Sstevel@tonic-gate goto err_ret; 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate BZERO(&ifr, sizeof (ifr)); 6227c478bd9Sstevel@tonic-gate (void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 6237c478bd9Sstevel@tonic-gate ifr.ifr_ip_muxid = ipmuxid; 6247c478bd9Sstevel@tonic-gate ifr.ifr_arp_muxid = -1; 6257c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCSIFMUXID, (caddr_t)&ifr) < 0) { 6267c478bd9Sstevel@tonic-gate error("Can't set mux ID SIOCSIFMUXID on %s: %m", ifname); 6277c478bd9Sstevel@tonic-gate goto err_ret; 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate if (udpfd != -1) 6307c478bd9Sstevel@tonic-gate (void) close(udpfd); 6317c478bd9Sstevel@tonic-gate (void) close(tmpfd); 6327c478bd9Sstevel@tonic-gate return (1); 6337c478bd9Sstevel@tonic-gate err_ret: 6347c478bd9Sstevel@tonic-gate if (udpfd != -1) 6357c478bd9Sstevel@tonic-gate (void) close(udpfd); 6367c478bd9Sstevel@tonic-gate (void) close(tmpfd); 6377c478bd9Sstevel@tonic-gate return (0); 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate /* 6417c478bd9Sstevel@tonic-gate * unplumb_ipif() 6427c478bd9Sstevel@tonic-gate * 6437c478bd9Sstevel@tonic-gate * Perform IP interface unplumbing. Possibly called from die(), so there 6447c478bd9Sstevel@tonic-gate * shouldn't be any call to die() or fatal() here. 6457c478bd9Sstevel@tonic-gate */ 6467c478bd9Sstevel@tonic-gate static int 6477c478bd9Sstevel@tonic-gate unplumb_ipif(int unit) 6487c478bd9Sstevel@tonic-gate { 6497c478bd9Sstevel@tonic-gate int udpfd = -1, fd = -1; 6507c478bd9Sstevel@tonic-gate int id; 6517c478bd9Sstevel@tonic-gate struct lifreq lifr; 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate if (!IPCP_ENABLED || (ifunit == -1)) { 6547c478bd9Sstevel@tonic-gate return (0); 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate if (!plumbed && (ipmuxid == -1 || (ipfd == -1 && !use_plink))) 6577c478bd9Sstevel@tonic-gate return (1); 6587c478bd9Sstevel@tonic-gate id = ipmuxid; 6597c478bd9Sstevel@tonic-gate if (!plumbed && use_plink) { 6607c478bd9Sstevel@tonic-gate if ((udpfd = open_udpfd()) == -1) 6617c478bd9Sstevel@tonic-gate return (0); 6627c478bd9Sstevel@tonic-gate /* 6637c478bd9Sstevel@tonic-gate * Note: must re-get mux ID, since any intervening 6647c478bd9Sstevel@tonic-gate * ifconfigs will change this. 6657c478bd9Sstevel@tonic-gate */ 6667c478bd9Sstevel@tonic-gate BZERO(&lifr, sizeof (lifr)); 6677c478bd9Sstevel@tonic-gate (void) strlcpy(lifr.lifr_name, ifname, 6687c478bd9Sstevel@tonic-gate sizeof (lifr.lifr_name)); 6697c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) { 6707c478bd9Sstevel@tonic-gate warn("Can't get mux fd: SIOCGLIFMUXID: %m"); 6717c478bd9Sstevel@tonic-gate } else { 6727c478bd9Sstevel@tonic-gate id = lifr.lifr_ip_muxid; 6737c478bd9Sstevel@tonic-gate fd = myioctl(udpfd, _I_MUXID2FD, (void *)id); 6747c478bd9Sstevel@tonic-gate if (fd < 0) { 6757c478bd9Sstevel@tonic-gate warn("Can't get mux fd: _I_MUXID2FD: %m"); 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate } 6797c478bd9Sstevel@tonic-gate /* 6807c478bd9Sstevel@tonic-gate * Mark down and unlink the ip interface. 6817c478bd9Sstevel@tonic-gate */ 6827c478bd9Sstevel@tonic-gate (void) sifdown(unit); 6837c478bd9Sstevel@tonic-gate if (default_route_gateway != 0) { 6847c478bd9Sstevel@tonic-gate (void) cifdefaultroute(0, default_route_gateway, 6857c478bd9Sstevel@tonic-gate default_route_gateway); 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate if (proxy_arp_addr != 0) { 6887c478bd9Sstevel@tonic-gate (void) cifproxyarp(0, proxy_arp_addr); 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate ipmuxid = -1; 6917c478bd9Sstevel@tonic-gate if (plumbed) 6927c478bd9Sstevel@tonic-gate return (1); 6937c478bd9Sstevel@tonic-gate if (use_plink) { 6947c478bd9Sstevel@tonic-gate if (myioctl(udpfd, I_PUNLINK, (void *)id) < 0) { 6957c478bd9Sstevel@tonic-gate error("Can't I_PUNLINK PPP from IP: %m"); 6967c478bd9Sstevel@tonic-gate if (fd != -1) 6977c478bd9Sstevel@tonic-gate (void) close(fd); 6987c478bd9Sstevel@tonic-gate (void) close(udpfd); 6997c478bd9Sstevel@tonic-gate return (0); 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate if (fd != -1) 7027c478bd9Sstevel@tonic-gate (void) close(fd); 7037c478bd9Sstevel@tonic-gate (void) close(udpfd); 7047c478bd9Sstevel@tonic-gate } else { 7057c478bd9Sstevel@tonic-gate if (myioctl(ipfd, I_UNLINK, (void *)id) < 0) { 7067c478bd9Sstevel@tonic-gate error("Can't I_UNLINK PPP from IP: %m"); 7077c478bd9Sstevel@tonic-gate return (0); 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate return (1); 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate /* 7147c478bd9Sstevel@tonic-gate * sys_cleanup() 7157c478bd9Sstevel@tonic-gate * 7167c478bd9Sstevel@tonic-gate * Restore any system state we modified before exiting: mark the 7177c478bd9Sstevel@tonic-gate * interface down, delete default route and/or proxy arp entry. This 7187c478bd9Sstevel@tonic-gate * should not call die() because it's called from die(). 7197c478bd9Sstevel@tonic-gate */ 7207c478bd9Sstevel@tonic-gate void 7217c478bd9Sstevel@tonic-gate sys_cleanup() 7227c478bd9Sstevel@tonic-gate { 7237c478bd9Sstevel@tonic-gate (void) unplumb_ipif(0); 7247c478bd9Sstevel@tonic-gate #ifdef INET6 7257c478bd9Sstevel@tonic-gate (void) unplumb_ip6if(0); 7267c478bd9Sstevel@tonic-gate #endif /* INET6 */ 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate /* 7307c478bd9Sstevel@tonic-gate * get_first_hwaddr() 7317c478bd9Sstevel@tonic-gate * 7327c478bd9Sstevel@tonic-gate * Stores the first hardware interface address found in the system 7337c478bd9Sstevel@tonic-gate * into addr and return 1 upon success, or 0 if none is found. This 7347c478bd9Sstevel@tonic-gate * is also called from the multilink code. 7357c478bd9Sstevel@tonic-gate */ 7367c478bd9Sstevel@tonic-gate int 7377c478bd9Sstevel@tonic-gate get_first_hwaddr(addr, msize) 7387c478bd9Sstevel@tonic-gate uchar_t *addr; 7397c478bd9Sstevel@tonic-gate int msize; 7407c478bd9Sstevel@tonic-gate { 7417c478bd9Sstevel@tonic-gate struct ifconf ifc; 7427c478bd9Sstevel@tonic-gate register struct ifreq *pifreq; 7437c478bd9Sstevel@tonic-gate struct ifreq ifr; 7447c478bd9Sstevel@tonic-gate int fd, num_ifs, i; 7457c478bd9Sstevel@tonic-gate uint_t fl, req_size; 7467c478bd9Sstevel@tonic-gate char *req; 7477c478bd9Sstevel@tonic-gate boolean_t found; 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate if (addr == NULL) { 7507c478bd9Sstevel@tonic-gate return (0); 7517c478bd9Sstevel@tonic-gate } 7527c478bd9Sstevel@tonic-gate fd = socket(AF_INET, SOCK_DGRAM, 0); 7537c478bd9Sstevel@tonic-gate if (fd < 0) { 7547c478bd9Sstevel@tonic-gate error("get_first_hwaddr: error opening IP socket: %m"); 7557c478bd9Sstevel@tonic-gate return (0); 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate /* 7587c478bd9Sstevel@tonic-gate * Find out how many interfaces are running 7597c478bd9Sstevel@tonic-gate */ 7607c478bd9Sstevel@tonic-gate if (myioctl(fd, SIOCGIFNUM, (caddr_t)&num_ifs) < 0) { 7617c478bd9Sstevel@tonic-gate num_ifs = MAXIFS; 7627c478bd9Sstevel@tonic-gate } 7637c478bd9Sstevel@tonic-gate req_size = num_ifs * sizeof (struct ifreq); 7647c478bd9Sstevel@tonic-gate req = malloc(req_size); 7657c478bd9Sstevel@tonic-gate if (req == NULL) { 7667c478bd9Sstevel@tonic-gate novm("interface request structure."); 7677c478bd9Sstevel@tonic-gate } 7687c478bd9Sstevel@tonic-gate /* 7697c478bd9Sstevel@tonic-gate * Get interface configuration info for all interfaces 7707c478bd9Sstevel@tonic-gate */ 7717c478bd9Sstevel@tonic-gate ifc.ifc_len = req_size; 7727c478bd9Sstevel@tonic-gate ifc.ifc_buf = req; 7737c478bd9Sstevel@tonic-gate if (myioctl(fd, SIOCGIFCONF, &ifc) < 0) { 7747c478bd9Sstevel@tonic-gate error("SIOCGIFCONF: %m"); 7757c478bd9Sstevel@tonic-gate (void) close(fd); 7767c478bd9Sstevel@tonic-gate free(req); 7777c478bd9Sstevel@tonic-gate return (0); 7787c478bd9Sstevel@tonic-gate } 7797c478bd9Sstevel@tonic-gate /* 7807c478bd9Sstevel@tonic-gate * And traverse each interface to look specifically for the first 7817c478bd9Sstevel@tonic-gate * occurence of an Ethernet interface which has been marked up 7827c478bd9Sstevel@tonic-gate */ 7837c478bd9Sstevel@tonic-gate pifreq = ifc.ifc_req; 7847c478bd9Sstevel@tonic-gate found = 0; 7857c478bd9Sstevel@tonic-gate for (i = ifc.ifc_len / sizeof (struct ifreq); i > 0; i--, pifreq++) { 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate if (strchr(pifreq->ifr_name, ':') != NULL) { 7887c478bd9Sstevel@tonic-gate continue; 7897c478bd9Sstevel@tonic-gate } 7907c478bd9Sstevel@tonic-gate BZERO(&ifr, sizeof (ifr)); 7917c478bd9Sstevel@tonic-gate (void) strncpy(ifr.ifr_name, pifreq->ifr_name, 7927c478bd9Sstevel@tonic-gate sizeof (ifr.ifr_name)); 7937c478bd9Sstevel@tonic-gate if (myioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { 7947c478bd9Sstevel@tonic-gate continue; 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate fl = ifr.ifr_flags; 7977c478bd9Sstevel@tonic-gate if ((fl & (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK)) 7987c478bd9Sstevel@tonic-gate != (IFF_UP | IFF_BROADCAST)) { 7997c478bd9Sstevel@tonic-gate continue; 8007c478bd9Sstevel@tonic-gate } 8017c478bd9Sstevel@tonic-gate if (get_if_hwaddr(addr, msize, ifr.ifr_name) <= 0) { 8027c478bd9Sstevel@tonic-gate continue; 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate found = 1; 8057c478bd9Sstevel@tonic-gate break; 8067c478bd9Sstevel@tonic-gate } 8077c478bd9Sstevel@tonic-gate free(req); 8087c478bd9Sstevel@tonic-gate (void) close(fd); 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate return (found); 8117c478bd9Sstevel@tonic-gate } 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate /* 8147c478bd9Sstevel@tonic-gate * get_if_hwaddr() 8157c478bd9Sstevel@tonic-gate * 8167c478bd9Sstevel@tonic-gate * Get the hardware address for the specified network interface device. 8177c478bd9Sstevel@tonic-gate * Return the length of the MAC address (in bytes) or -1 if error. 8187c478bd9Sstevel@tonic-gate */ 8197c478bd9Sstevel@tonic-gate int 820fb60e41dSss get_if_hwaddr(uchar_t *addrp, int msize, char *linkname) 821fb60e41dSss { 822fb60e41dSss dlpi_handle_t dh; 823fb60e41dSss uchar_t physaddr[DLPI_PHYSADDR_MAX]; 824fb60e41dSss size_t physaddrlen = sizeof (physaddr); 825fb60e41dSss int retv; 826fb60e41dSss 827fb60e41dSss if ((addrp == NULL) || (linkname == NULL)) 8287c478bd9Sstevel@tonic-gate return (-1); 829fb60e41dSss 8307c478bd9Sstevel@tonic-gate /* 831fb60e41dSss * Open the link and ask for hardware address. 8327c478bd9Sstevel@tonic-gate */ 833fb60e41dSss if ((retv = dlpi_open(linkname, &dh, 0)) != DLPI_SUCCESS) { 834fb60e41dSss error("Could not open %s: %s", linkname, dlpi_strerror(retv)); 8357c478bd9Sstevel@tonic-gate return (-1); 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate 838fb60e41dSss retv = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, 839fb60e41dSss physaddr, &physaddrlen); 840fb60e41dSss dlpi_close(dh); 841fb60e41dSss if (retv != DLPI_SUCCESS) { 842fb60e41dSss error("Could not get physical address on %s: %s", linkname, 843fb60e41dSss dlpi_strerror(retv)); 8447c478bd9Sstevel@tonic-gate return (-1); 8457c478bd9Sstevel@tonic-gate } 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate /* 8487c478bd9Sstevel@tonic-gate * Check if we have enough space to copy the address to. 8497c478bd9Sstevel@tonic-gate */ 850fb60e41dSss if (physaddrlen > msize) 8517c478bd9Sstevel@tonic-gate return (-1); 852fb60e41dSss (void) memcpy(addrp, physaddr, physaddrlen); 853fb60e41dSss return (physaddrlen); 8547c478bd9Sstevel@tonic-gate } 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate /* 8577c478bd9Sstevel@tonic-gate * giflags() 8587c478bd9Sstevel@tonic-gate */ 8597c478bd9Sstevel@tonic-gate static int 8607c478bd9Sstevel@tonic-gate giflags(u_int32_t flag, bool *retval) 8617c478bd9Sstevel@tonic-gate { 8627c478bd9Sstevel@tonic-gate struct ifreq ifr; 8637c478bd9Sstevel@tonic-gate int fd; 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate *retval = 0; 8667c478bd9Sstevel@tonic-gate fd = socket(AF_INET, SOCK_DGRAM, 0); 8677c478bd9Sstevel@tonic-gate if (fd < 0) { 8687c478bd9Sstevel@tonic-gate error("giflags: error opening IP socket: %m"); 8697c478bd9Sstevel@tonic-gate return (errno); 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate BZERO(&ifr, sizeof (ifr)); 8737c478bd9Sstevel@tonic-gate (void) strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 8747c478bd9Sstevel@tonic-gate if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { 8757c478bd9Sstevel@tonic-gate (void) close(fd); 8767c478bd9Sstevel@tonic-gate return (errno); 8777c478bd9Sstevel@tonic-gate } 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate *retval = ((ifr.ifr_flags & flag) != 0); 8807c478bd9Sstevel@tonic-gate (void) close(fd); 8817c478bd9Sstevel@tonic-gate return (errno); 8827c478bd9Sstevel@tonic-gate } 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate /* 8857c478bd9Sstevel@tonic-gate * sys_close() 8867c478bd9Sstevel@tonic-gate * 8877c478bd9Sstevel@tonic-gate * Clean up in a child process before exec-ing. 8887c478bd9Sstevel@tonic-gate */ 8897c478bd9Sstevel@tonic-gate void 8907c478bd9Sstevel@tonic-gate sys_close() 8917c478bd9Sstevel@tonic-gate { 8927c478bd9Sstevel@tonic-gate if (ipfd != -1) { 8937c478bd9Sstevel@tonic-gate (void) close(ipfd); 8947c478bd9Sstevel@tonic-gate ipfd = -1; 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate #ifdef INET6 8977c478bd9Sstevel@tonic-gate if (ip6fd != -1) { 8987c478bd9Sstevel@tonic-gate (void) close(ip6fd); 8997c478bd9Sstevel@tonic-gate ip6fd = -1; 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate #endif /* INET6 */ 9027c478bd9Sstevel@tonic-gate if (pppfd != -1) { 9037c478bd9Sstevel@tonic-gate (void) close(pppfd); 9047c478bd9Sstevel@tonic-gate pppfd = -1; 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate } 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate /* 9097c478bd9Sstevel@tonic-gate * any_compressions() 9107c478bd9Sstevel@tonic-gate * 9117c478bd9Sstevel@tonic-gate * Check if compression is enabled or not. In the STREAMS implementation of 9127c478bd9Sstevel@tonic-gate * kernel-portion pppd, the comp STREAMS module performs the ACFC, PFC, as 9137c478bd9Sstevel@tonic-gate * well CCP and VJ compressions. However, if the user has explicitly declare 9147c478bd9Sstevel@tonic-gate * to not enable them from the command line, there is no point of having the 9157c478bd9Sstevel@tonic-gate * comp module be pushed on the stream. 9167c478bd9Sstevel@tonic-gate */ 9177c478bd9Sstevel@tonic-gate static int 9187c478bd9Sstevel@tonic-gate any_compressions(void) 9197c478bd9Sstevel@tonic-gate { 9207c478bd9Sstevel@tonic-gate if ((!lcp_wantoptions[0].neg_accompression) && 9217c478bd9Sstevel@tonic-gate (!lcp_wantoptions[0].neg_pcompression) && 9227c478bd9Sstevel@tonic-gate (!ccp_protent.enabled_flag) && 9237c478bd9Sstevel@tonic-gate (!ipcp_wantoptions[0].neg_vj)) { 9247c478bd9Sstevel@tonic-gate return (0); 9257c478bd9Sstevel@tonic-gate } 9267c478bd9Sstevel@tonic-gate return (1); 9277c478bd9Sstevel@tonic-gate } 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate /* 9307c478bd9Sstevel@tonic-gate * modpush() 9317c478bd9Sstevel@tonic-gate * 9327c478bd9Sstevel@tonic-gate * Push a module on the stream. 9337c478bd9Sstevel@tonic-gate */ 9347c478bd9Sstevel@tonic-gate static int 9357c478bd9Sstevel@tonic-gate modpush(int fd, const char *modname, const char *text) 9367c478bd9Sstevel@tonic-gate { 9377c478bd9Sstevel@tonic-gate if (myioctl(fd, I_PUSH, (void *)modname) < 0) { 9387c478bd9Sstevel@tonic-gate error("Couldn't push %s module: %m", text); 9397c478bd9Sstevel@tonic-gate return (-1); 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate if (++tty_npushed == 1 && !already_ppp) { 9427c478bd9Sstevel@tonic-gate if (strioctl(fd, PPPIO_LASTMOD, NULL, 0, 0) < 0) { 9437c478bd9Sstevel@tonic-gate warn("unable to set LASTMOD on %s: %m", text); 9447c478bd9Sstevel@tonic-gate } 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate return (0); 9477c478bd9Sstevel@tonic-gate } 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate /* 9507c478bd9Sstevel@tonic-gate * establish_ppp() 9517c478bd9Sstevel@tonic-gate * 9527c478bd9Sstevel@tonic-gate * Turn the serial port into a ppp interface. 9537c478bd9Sstevel@tonic-gate */ 9547c478bd9Sstevel@tonic-gate int 9557c478bd9Sstevel@tonic-gate establish_ppp(fd) 9567c478bd9Sstevel@tonic-gate int fd; 9577c478bd9Sstevel@tonic-gate { 9587c478bd9Sstevel@tonic-gate int i; 9597c478bd9Sstevel@tonic-gate uint32_t x; 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate if (default_device && !notty) { 9627c478bd9Sstevel@tonic-gate tty_sid = getsid((pid_t)0); 9637c478bd9Sstevel@tonic-gate } 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate if (integrated_driver) 9667c478bd9Sstevel@tonic-gate return (pppfd); 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate /* 9697c478bd9Sstevel@tonic-gate * Pop any existing modules off the tty stream 9707c478bd9Sstevel@tonic-gate */ 9717c478bd9Sstevel@tonic-gate for (i = 0; ; ++i) { 9727c478bd9Sstevel@tonic-gate if ((myioctl(fd, I_LOOK, tty_modules[i]) < 0) || 9737c478bd9Sstevel@tonic-gate (strcmp(tty_modules[i], "ptem") == 0) || 9747c478bd9Sstevel@tonic-gate (myioctl(fd, I_POP, (void *)0) < 0)) { 9757c478bd9Sstevel@tonic-gate break; 9767c478bd9Sstevel@tonic-gate } 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate tty_nmodules = i; 9797c478bd9Sstevel@tonic-gate /* 9807c478bd9Sstevel@tonic-gate * Push the async hdlc module and the compressor module 9817c478bd9Sstevel@tonic-gate */ 9827c478bd9Sstevel@tonic-gate tty_npushed = 0; 9837c478bd9Sstevel@tonic-gate if (!sync_serial && !already_ppp && 9847c478bd9Sstevel@tonic-gate modpush(fd, AHDLC_MOD_NAME, "PPP async HDLC") < 0) { 9857c478bd9Sstevel@tonic-gate return (-1); 9867c478bd9Sstevel@tonic-gate } 9877c478bd9Sstevel@tonic-gate /* 9887c478bd9Sstevel@tonic-gate * There's no need to push comp module if we don't intend 9897c478bd9Sstevel@tonic-gate * to compress anything 9907c478bd9Sstevel@tonic-gate */ 9917c478bd9Sstevel@tonic-gate if (any_compressions()) { 9927c478bd9Sstevel@tonic-gate (void) modpush(fd, COMP_MOD_NAME, "PPP compression"); 9937c478bd9Sstevel@tonic-gate } 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate /* 9967c478bd9Sstevel@tonic-gate * Link the serial port under the PPP multiplexor 9977c478bd9Sstevel@tonic-gate */ 9987c478bd9Sstevel@tonic-gate if ((fdmuxid = myioctl(pppfd, I_LINK, (void *)fd)) < 0) { 9997c478bd9Sstevel@tonic-gate error("Can't link tty to PPP mux: %m"); 10007c478bd9Sstevel@tonic-gate return (-1); 10017c478bd9Sstevel@tonic-gate } 10027c478bd9Sstevel@tonic-gate if (tty_npushed == 0 && !already_ppp) { 10037c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_LASTMOD, NULL, 0, 0) < 0) { 10047c478bd9Sstevel@tonic-gate warn("unable to set LASTMOD on PPP mux: %m"); 10057c478bd9Sstevel@tonic-gate } 10067c478bd9Sstevel@tonic-gate } 10077c478bd9Sstevel@tonic-gate /* 10087c478bd9Sstevel@tonic-gate * Debug configuration must occur *after* I_LINK. 10097c478bd9Sstevel@tonic-gate */ 10107c478bd9Sstevel@tonic-gate if (kdebugflag & 4) { 10117c478bd9Sstevel@tonic-gate x = PPPDBG_LOG + PPPDBG_AHDLC; 10127c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) { 10137c478bd9Sstevel@tonic-gate warn("PPPIO_DEBUG ioctl for ahdlc module failed: %m"); 10147c478bd9Sstevel@tonic-gate } 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate if (any_compressions() && (kdebugflag & 2)) { 10177c478bd9Sstevel@tonic-gate x = PPPDBG_LOG + PPPDBG_COMP; 10187c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) { 10197c478bd9Sstevel@tonic-gate warn("PPPIO_DEBUG ioctl for comp module failed: %m"); 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate return (pppfd); 10237c478bd9Sstevel@tonic-gate } 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate /* 10267c478bd9Sstevel@tonic-gate * restore_loop() 10277c478bd9Sstevel@tonic-gate * 10287c478bd9Sstevel@tonic-gate * Reattach the ppp unit to the loopback. This doesn't need to do anything 10297c478bd9Sstevel@tonic-gate * because disestablish_ppp does it 10307c478bd9Sstevel@tonic-gate */ 10317c478bd9Sstevel@tonic-gate void 10327c478bd9Sstevel@tonic-gate restore_loop() 10337c478bd9Sstevel@tonic-gate { 10347c478bd9Sstevel@tonic-gate } 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate /* 10377c478bd9Sstevel@tonic-gate * disestablish_ppp() 10387c478bd9Sstevel@tonic-gate * 10397c478bd9Sstevel@tonic-gate * Restore the serial port to normal operation. It attempts to reconstruct 10407c478bd9Sstevel@tonic-gate * the stream with the previously popped modules. This shouldn't call die() 10417c478bd9Sstevel@tonic-gate * because it's called from die(). Stream reconstruction is needed in case 10427c478bd9Sstevel@tonic-gate * pppd is used for dial-in on /dev/tty and there's an option error. 10437c478bd9Sstevel@tonic-gate */ 10447c478bd9Sstevel@tonic-gate void 10457c478bd9Sstevel@tonic-gate disestablish_ppp(fd) 10467c478bd9Sstevel@tonic-gate int fd; 10477c478bd9Sstevel@tonic-gate { 10487c478bd9Sstevel@tonic-gate int i; 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate if (fdmuxid == -1 || integrated_driver) { 10517c478bd9Sstevel@tonic-gate return; 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate if (myioctl(pppfd, I_UNLINK, (void *)fdmuxid) < 0) { 10547c478bd9Sstevel@tonic-gate if (!hungup) { 10557c478bd9Sstevel@tonic-gate error("Can't unlink tty from PPP mux: %m"); 10567c478bd9Sstevel@tonic-gate } 10577c478bd9Sstevel@tonic-gate } 10587c478bd9Sstevel@tonic-gate fdmuxid = -1; 10597c478bd9Sstevel@tonic-gate if (!hungup) { 10607c478bd9Sstevel@tonic-gate while (tty_npushed > 0 && myioctl(fd, I_POP, (void *)0) >= 0) { 10617c478bd9Sstevel@tonic-gate --tty_npushed; 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate for (i = tty_nmodules - 1; i >= 0; --i) { 10647c478bd9Sstevel@tonic-gate if (myioctl(fd, I_PUSH, tty_modules[i]) < 0) { 10657c478bd9Sstevel@tonic-gate error("Couldn't restore tty module %s: %m", 10667c478bd9Sstevel@tonic-gate tty_modules[i]); 10677c478bd9Sstevel@tonic-gate } 10687c478bd9Sstevel@tonic-gate } 10697c478bd9Sstevel@tonic-gate } 10707c478bd9Sstevel@tonic-gate if (hungup && default_device && tty_sid > 0) { 10717c478bd9Sstevel@tonic-gate /* 10727c478bd9Sstevel@tonic-gate * If we have received a hangup, we need to send a 10737c478bd9Sstevel@tonic-gate * SIGHUP to the terminal's controlling process. 10747c478bd9Sstevel@tonic-gate * The reason is that the original stream head for 10757c478bd9Sstevel@tonic-gate * the terminal hasn't seen the M_HANGUP message 10767c478bd9Sstevel@tonic-gate * (it went up through the ppp driver to the stream 10777c478bd9Sstevel@tonic-gate * head for our fd to /dev/ppp). 10787c478bd9Sstevel@tonic-gate */ 10797c478bd9Sstevel@tonic-gate (void) kill(tty_sid, SIGHUP); 10807c478bd9Sstevel@tonic-gate } 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate /* 10847c478bd9Sstevel@tonic-gate * clean_check() 10857c478bd9Sstevel@tonic-gate * 10867c478bd9Sstevel@tonic-gate * Check whether the link seems not to be 8-bit clean 10877c478bd9Sstevel@tonic-gate */ 10887c478bd9Sstevel@tonic-gate void 10897c478bd9Sstevel@tonic-gate clean_check() 10907c478bd9Sstevel@tonic-gate { 10917c478bd9Sstevel@tonic-gate uint32_t x; 10927c478bd9Sstevel@tonic-gate char *s = NULL; 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate /* 10957c478bd9Sstevel@tonic-gate * Skip this is synchronous link is used, since spppasyn won't 10967c478bd9Sstevel@tonic-gate * be anywhere in the stream below to handle the ioctl. 10977c478bd9Sstevel@tonic-gate */ 10987c478bd9Sstevel@tonic-gate if (sync_serial) { 10997c478bd9Sstevel@tonic-gate return; 11007c478bd9Sstevel@tonic-gate } 11017c478bd9Sstevel@tonic-gate 11027c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_GCLEAN, &x, 0, sizeof (x)) < 0) { 11037c478bd9Sstevel@tonic-gate warn("unable to obtain serial link status: %m"); 11047c478bd9Sstevel@tonic-gate return; 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate switch (~x) { 11077c478bd9Sstevel@tonic-gate case RCV_B7_0: 11087c478bd9Sstevel@tonic-gate s = "bit 7 set to 1"; 11097c478bd9Sstevel@tonic-gate break; 11107c478bd9Sstevel@tonic-gate case RCV_B7_1: 11117c478bd9Sstevel@tonic-gate s = "bit 7 set to 0"; 11127c478bd9Sstevel@tonic-gate break; 11137c478bd9Sstevel@tonic-gate case RCV_EVNP: 11147c478bd9Sstevel@tonic-gate s = "odd parity"; 11157c478bd9Sstevel@tonic-gate break; 11167c478bd9Sstevel@tonic-gate case RCV_ODDP: 11177c478bd9Sstevel@tonic-gate s = "even parity"; 11187c478bd9Sstevel@tonic-gate break; 11197c478bd9Sstevel@tonic-gate } 11207c478bd9Sstevel@tonic-gate if (s != NULL) { 11217c478bd9Sstevel@tonic-gate warn("Serial link is not 8-bit clean:"); 11227c478bd9Sstevel@tonic-gate warn("All received characters had %s", s); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate } 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate /* 11277c478bd9Sstevel@tonic-gate * List of valid speeds. 11287c478bd9Sstevel@tonic-gate */ 11297c478bd9Sstevel@tonic-gate struct speed { 11307c478bd9Sstevel@tonic-gate int speed_int; 11317c478bd9Sstevel@tonic-gate int speed_val; 11327c478bd9Sstevel@tonic-gate } speeds [] = { 11337c478bd9Sstevel@tonic-gate #ifdef B50 11347c478bd9Sstevel@tonic-gate { 50, B50 }, 11357c478bd9Sstevel@tonic-gate #endif 11367c478bd9Sstevel@tonic-gate #ifdef B75 11377c478bd9Sstevel@tonic-gate { 75, B75 }, 11387c478bd9Sstevel@tonic-gate #endif 11397c478bd9Sstevel@tonic-gate #ifdef B110 11407c478bd9Sstevel@tonic-gate { 110, B110 }, 11417c478bd9Sstevel@tonic-gate #endif 11427c478bd9Sstevel@tonic-gate #ifdef B134 11437c478bd9Sstevel@tonic-gate { 134, B134 }, 11447c478bd9Sstevel@tonic-gate #endif 11457c478bd9Sstevel@tonic-gate #ifdef B150 11467c478bd9Sstevel@tonic-gate { 150, B150 }, 11477c478bd9Sstevel@tonic-gate #endif 11487c478bd9Sstevel@tonic-gate #ifdef B200 11497c478bd9Sstevel@tonic-gate { 200, B200 }, 11507c478bd9Sstevel@tonic-gate #endif 11517c478bd9Sstevel@tonic-gate #ifdef B300 11527c478bd9Sstevel@tonic-gate { 300, B300 }, 11537c478bd9Sstevel@tonic-gate #endif 11547c478bd9Sstevel@tonic-gate #ifdef B600 11557c478bd9Sstevel@tonic-gate { 600, B600 }, 11567c478bd9Sstevel@tonic-gate #endif 11577c478bd9Sstevel@tonic-gate #ifdef B1200 11587c478bd9Sstevel@tonic-gate { 1200, B1200 }, 11597c478bd9Sstevel@tonic-gate #endif 11607c478bd9Sstevel@tonic-gate #ifdef B1800 11617c478bd9Sstevel@tonic-gate { 1800, B1800 }, 11627c478bd9Sstevel@tonic-gate #endif 11637c478bd9Sstevel@tonic-gate #ifdef B2000 11647c478bd9Sstevel@tonic-gate { 2000, B2000 }, 11657c478bd9Sstevel@tonic-gate #endif 11667c478bd9Sstevel@tonic-gate #ifdef B2400 11677c478bd9Sstevel@tonic-gate { 2400, B2400 }, 11687c478bd9Sstevel@tonic-gate #endif 11697c478bd9Sstevel@tonic-gate #ifdef B3600 11707c478bd9Sstevel@tonic-gate { 3600, B3600 }, 11717c478bd9Sstevel@tonic-gate #endif 11727c478bd9Sstevel@tonic-gate #ifdef B4800 11737c478bd9Sstevel@tonic-gate { 4800, B4800 }, 11747c478bd9Sstevel@tonic-gate #endif 11757c478bd9Sstevel@tonic-gate #ifdef B7200 11767c478bd9Sstevel@tonic-gate { 7200, B7200 }, 11777c478bd9Sstevel@tonic-gate #endif 11787c478bd9Sstevel@tonic-gate #ifdef B9600 11797c478bd9Sstevel@tonic-gate { 9600, B9600 }, 11807c478bd9Sstevel@tonic-gate #endif 11817c478bd9Sstevel@tonic-gate #ifdef B19200 11827c478bd9Sstevel@tonic-gate { 19200, B19200 }, 11837c478bd9Sstevel@tonic-gate #endif 11847c478bd9Sstevel@tonic-gate #ifdef B38400 11857c478bd9Sstevel@tonic-gate { 38400, B38400 }, 11867c478bd9Sstevel@tonic-gate #endif 11877c478bd9Sstevel@tonic-gate #ifdef EXTA 11887c478bd9Sstevel@tonic-gate { 19200, EXTA }, 11897c478bd9Sstevel@tonic-gate #endif 11907c478bd9Sstevel@tonic-gate #ifdef EXTB 11917c478bd9Sstevel@tonic-gate { 38400, EXTB }, 11927c478bd9Sstevel@tonic-gate #endif 11937c478bd9Sstevel@tonic-gate #ifdef B57600 11947c478bd9Sstevel@tonic-gate { 57600, B57600 }, 11957c478bd9Sstevel@tonic-gate #endif 11967c478bd9Sstevel@tonic-gate #ifdef B76800 11977c478bd9Sstevel@tonic-gate { 76800, B76800 }, 11987c478bd9Sstevel@tonic-gate #endif 11997c478bd9Sstevel@tonic-gate #ifdef B115200 12007c478bd9Sstevel@tonic-gate { 115200, B115200 }, 12017c478bd9Sstevel@tonic-gate #endif 12027c478bd9Sstevel@tonic-gate #ifdef B153600 12037c478bd9Sstevel@tonic-gate { 153600, B153600 }, 12047c478bd9Sstevel@tonic-gate #endif 12057c478bd9Sstevel@tonic-gate #ifdef B230400 12067c478bd9Sstevel@tonic-gate { 230400, B230400 }, 12077c478bd9Sstevel@tonic-gate #endif 12087c478bd9Sstevel@tonic-gate #ifdef B307200 12097c478bd9Sstevel@tonic-gate { 307200, B307200 }, 12107c478bd9Sstevel@tonic-gate #endif 12117c478bd9Sstevel@tonic-gate #ifdef B460800 12127c478bd9Sstevel@tonic-gate { 460800, B460800 }, 1213de81e71eSTim Marsland #endif 1214de81e71eSTim Marsland #ifdef B921600 1215de81e71eSTim Marsland { 921600, B921600 }, 12167c478bd9Sstevel@tonic-gate #endif 12177c478bd9Sstevel@tonic-gate { 0, 0 } 12187c478bd9Sstevel@tonic-gate }; 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate /* 12217c478bd9Sstevel@tonic-gate * translate_speed() 12227c478bd9Sstevel@tonic-gate * 12237c478bd9Sstevel@tonic-gate * Translate from bits/second to a speed_t 12247c478bd9Sstevel@tonic-gate */ 12257c478bd9Sstevel@tonic-gate static int 12267c478bd9Sstevel@tonic-gate translate_speed(int bps) 12277c478bd9Sstevel@tonic-gate { 12287c478bd9Sstevel@tonic-gate struct speed *speedp; 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate if (bps == 0) { 12317c478bd9Sstevel@tonic-gate return (0); 12327c478bd9Sstevel@tonic-gate } 12337c478bd9Sstevel@tonic-gate for (speedp = speeds; speedp->speed_int; speedp++) { 12347c478bd9Sstevel@tonic-gate if (bps == speedp->speed_int) { 12357c478bd9Sstevel@tonic-gate return (speedp->speed_val); 12367c478bd9Sstevel@tonic-gate } 12377c478bd9Sstevel@tonic-gate } 12387c478bd9Sstevel@tonic-gate set_source(&speed_info); 12397c478bd9Sstevel@tonic-gate option_error("speed %d not supported", bps); 12407c478bd9Sstevel@tonic-gate return (0); 12417c478bd9Sstevel@tonic-gate } 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate /* 12447c478bd9Sstevel@tonic-gate * baud_rate_of() 12457c478bd9Sstevel@tonic-gate * 12467c478bd9Sstevel@tonic-gate * Translate from a speed_t to bits/second 12477c478bd9Sstevel@tonic-gate */ 12487c478bd9Sstevel@tonic-gate static int 12497c478bd9Sstevel@tonic-gate baud_rate_of(int speed) 12507c478bd9Sstevel@tonic-gate { 12517c478bd9Sstevel@tonic-gate struct speed *speedp; 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate if (speed == 0) { 12547c478bd9Sstevel@tonic-gate return (0); 12557c478bd9Sstevel@tonic-gate } 12567c478bd9Sstevel@tonic-gate for (speedp = speeds; speedp->speed_int; speedp++) { 12577c478bd9Sstevel@tonic-gate if (speed == speedp->speed_val) { 12587c478bd9Sstevel@tonic-gate return (speedp->speed_int); 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate } 12617c478bd9Sstevel@tonic-gate return (0); 12627c478bd9Sstevel@tonic-gate } 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate /* 12657c478bd9Sstevel@tonic-gate * set_up_tty() 12667c478bd9Sstevel@tonic-gate * 12677c478bd9Sstevel@tonic-gate * Set up the serial port on `fd' for 8 bits, no parity, at the requested 12687c478bd9Sstevel@tonic-gate * speed, etc. If `local' is true, set CLOCAL regardless of whether the 12697c478bd9Sstevel@tonic-gate * modem option was specified. 12707c478bd9Sstevel@tonic-gate */ 12717c478bd9Sstevel@tonic-gate void 12727c478bd9Sstevel@tonic-gate set_up_tty(fd, local) 12737c478bd9Sstevel@tonic-gate int fd, local; 12747c478bd9Sstevel@tonic-gate { 12757c478bd9Sstevel@tonic-gate int speed; 12767c478bd9Sstevel@tonic-gate struct termios tios; 12777c478bd9Sstevel@tonic-gate struct scc_mode sm; 12787c478bd9Sstevel@tonic-gate 12797c478bd9Sstevel@tonic-gate if (already_ppp) 12807c478bd9Sstevel@tonic-gate return; 12817c478bd9Sstevel@tonic-gate 12827c478bd9Sstevel@tonic-gate if (sync_serial) { 12837c478bd9Sstevel@tonic-gate restore_term = 0; 12847c478bd9Sstevel@tonic-gate speed = B0; 12857c478bd9Sstevel@tonic-gate baud_rate = 0; 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate if (strioctl(fd, S_IOCGETMODE, &sm, sizeof (sm), 12887c478bd9Sstevel@tonic-gate sizeof (sm)) < 0) { 12897c478bd9Sstevel@tonic-gate return; 12907c478bd9Sstevel@tonic-gate } 12917c478bd9Sstevel@tonic-gate 12927c478bd9Sstevel@tonic-gate baud_rate = sm.sm_baudrate; 12937c478bd9Sstevel@tonic-gate dbglog("synchronous speed appears to be %d bps", baud_rate); 12947c478bd9Sstevel@tonic-gate } else { 12957c478bd9Sstevel@tonic-gate if (tcgetattr(fd, &tios) < 0) { 12967c478bd9Sstevel@tonic-gate fatal("tcgetattr: %m"); 12977c478bd9Sstevel@tonic-gate } 12987c478bd9Sstevel@tonic-gate if (!restore_term) { 12997c478bd9Sstevel@tonic-gate inittermios = tios; 13007c478bd9Sstevel@tonic-gate if (myioctl(fd, TIOCGWINSZ, &wsinfo) < 0) { 13017c478bd9Sstevel@tonic-gate if (errno == EINVAL) { 13027c478bd9Sstevel@tonic-gate /* 13037c478bd9Sstevel@tonic-gate * ptem returns EINVAL if all zeroes. 13047c478bd9Sstevel@tonic-gate * Strange and unfixable code. 13057c478bd9Sstevel@tonic-gate */ 13067c478bd9Sstevel@tonic-gate bzero(&wsinfo, sizeof (wsinfo)); 13077c478bd9Sstevel@tonic-gate } else { 13087c478bd9Sstevel@tonic-gate warn("unable to get TTY window " 13097c478bd9Sstevel@tonic-gate "size: %m"); 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate } 13127c478bd9Sstevel@tonic-gate } 13137c478bd9Sstevel@tonic-gate tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL); 13147c478bd9Sstevel@tonic-gate if (crtscts > 0) { 13157c478bd9Sstevel@tonic-gate tios.c_cflag |= CRTSCTS | CRTSXOFF; 13167c478bd9Sstevel@tonic-gate } else if (crtscts < 0) { 13177c478bd9Sstevel@tonic-gate tios.c_cflag &= ~CRTSCTS & ~CRTSXOFF; 13187c478bd9Sstevel@tonic-gate } 13197c478bd9Sstevel@tonic-gate tios.c_cflag |= CS8 | CREAD | HUPCL; 13207c478bd9Sstevel@tonic-gate if (local || !modem) { 13217c478bd9Sstevel@tonic-gate tios.c_cflag |= CLOCAL; 13227c478bd9Sstevel@tonic-gate } 13237c478bd9Sstevel@tonic-gate tios.c_iflag = IGNBRK | IGNPAR; 13247c478bd9Sstevel@tonic-gate tios.c_oflag = 0; 13257c478bd9Sstevel@tonic-gate tios.c_lflag = 0; 13267c478bd9Sstevel@tonic-gate tios.c_cc[VMIN] = 1; 13277c478bd9Sstevel@tonic-gate tios.c_cc[VTIME] = 0; 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate if (crtscts == -2) { 13307c478bd9Sstevel@tonic-gate tios.c_iflag |= IXON | IXOFF; 13317c478bd9Sstevel@tonic-gate tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ 13327c478bd9Sstevel@tonic-gate tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ 13337c478bd9Sstevel@tonic-gate } 13347c478bd9Sstevel@tonic-gate speed = translate_speed(inspeed); 13357c478bd9Sstevel@tonic-gate if (speed) { 13367c478bd9Sstevel@tonic-gate (void) cfsetospeed(&tios, speed); 13377c478bd9Sstevel@tonic-gate (void) cfsetispeed(&tios, speed); 13387c478bd9Sstevel@tonic-gate } else { 13397c478bd9Sstevel@tonic-gate speed = cfgetospeed(&tios); 13407c478bd9Sstevel@tonic-gate /* 13417c478bd9Sstevel@tonic-gate * We can't proceed if the serial port speed is 0, 13427c478bd9Sstevel@tonic-gate * since that implies that the serial port is disabled. 13437c478bd9Sstevel@tonic-gate */ 13447c478bd9Sstevel@tonic-gate if (speed == B0) { 13457c478bd9Sstevel@tonic-gate fatal("Baud rate for %s is 0; need explicit " 13467c478bd9Sstevel@tonic-gate "baud rate", devnam); 13477c478bd9Sstevel@tonic-gate } 13487c478bd9Sstevel@tonic-gate } 13497c478bd9Sstevel@tonic-gate if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { 13507c478bd9Sstevel@tonic-gate fatal("tcsetattr: %m"); 13517c478bd9Sstevel@tonic-gate } 13527c478bd9Sstevel@tonic-gate baud_rate = baud_rate_of(speed); 13537c478bd9Sstevel@tonic-gate dbglog("%s speed set to %d bps", 13547c478bd9Sstevel@tonic-gate fd == pty_slave ? "pty" : "serial", baud_rate); 13557c478bd9Sstevel@tonic-gate restore_term = 1; 13567c478bd9Sstevel@tonic-gate } 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate /* 13607c478bd9Sstevel@tonic-gate * restore_tty() 13617c478bd9Sstevel@tonic-gate * 13627c478bd9Sstevel@tonic-gate * Restore the terminal to the saved settings. 13637c478bd9Sstevel@tonic-gate */ 13647c478bd9Sstevel@tonic-gate void 13657c478bd9Sstevel@tonic-gate restore_tty(fd) 13667c478bd9Sstevel@tonic-gate int fd; 13677c478bd9Sstevel@tonic-gate { 13687c478bd9Sstevel@tonic-gate if (restore_term == 0) { 13697c478bd9Sstevel@tonic-gate return; 13707c478bd9Sstevel@tonic-gate } 13717c478bd9Sstevel@tonic-gate if (!default_device) { 13727c478bd9Sstevel@tonic-gate /* 13737c478bd9Sstevel@tonic-gate * Turn off echoing, because otherwise we can get into 13747c478bd9Sstevel@tonic-gate * a loop with the tty and the modem echoing to each 13757c478bd9Sstevel@tonic-gate * other. We presume we are the sole user of this tty 13767c478bd9Sstevel@tonic-gate * device, so when we close it, it will revert to its 13777c478bd9Sstevel@tonic-gate * defaults anyway. 13787c478bd9Sstevel@tonic-gate */ 13797c478bd9Sstevel@tonic-gate inittermios.c_lflag &= ~(ECHO | ECHONL); 13807c478bd9Sstevel@tonic-gate } 13817c478bd9Sstevel@tonic-gate if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) { 13827c478bd9Sstevel@tonic-gate if (!hungup && errno != ENXIO) { 13837c478bd9Sstevel@tonic-gate warn("tcsetattr: %m"); 13847c478bd9Sstevel@tonic-gate } 13857c478bd9Sstevel@tonic-gate } 13867c478bd9Sstevel@tonic-gate if (wsinfo.ws_row != 0 || wsinfo.ws_col != 0 || 13877c478bd9Sstevel@tonic-gate wsinfo.ws_xpixel != 0 || wsinfo.ws_ypixel != 0) { 13887c478bd9Sstevel@tonic-gate if (myioctl(fd, TIOCSWINSZ, &wsinfo) < 0) { 13897c478bd9Sstevel@tonic-gate warn("unable to set TTY window size: %m"); 13907c478bd9Sstevel@tonic-gate } 13917c478bd9Sstevel@tonic-gate } 13927c478bd9Sstevel@tonic-gate restore_term = 0; 13937c478bd9Sstevel@tonic-gate } 13947c478bd9Sstevel@tonic-gate 13957c478bd9Sstevel@tonic-gate /* 13967c478bd9Sstevel@tonic-gate * setdtr() 13977c478bd9Sstevel@tonic-gate * 13987c478bd9Sstevel@tonic-gate * Control the DTR line on the serial port. This is called from die(), so it 13997c478bd9Sstevel@tonic-gate * shouldn't call die() 14007c478bd9Sstevel@tonic-gate */ 14017c478bd9Sstevel@tonic-gate void 14027c478bd9Sstevel@tonic-gate setdtr(fd, on) 14037c478bd9Sstevel@tonic-gate int fd, on; 14047c478bd9Sstevel@tonic-gate { 14057c478bd9Sstevel@tonic-gate int modembits = TIOCM_DTR; 14067c478bd9Sstevel@tonic-gate if (!already_ppp && 14077c478bd9Sstevel@tonic-gate myioctl(fd, (on ? TIOCMBIS : TIOCMBIC), &modembits) < 0) { 14087c478bd9Sstevel@tonic-gate warn("unable to set DTR line %s: %m", (on ? "ON" : "OFF")); 14097c478bd9Sstevel@tonic-gate } 14107c478bd9Sstevel@tonic-gate } 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate /* 14137c478bd9Sstevel@tonic-gate * open_loopback() 14147c478bd9Sstevel@tonic-gate * 14157c478bd9Sstevel@tonic-gate * Open the device we use for getting packets in demand mode. Under Solaris 2, 14167c478bd9Sstevel@tonic-gate * we use our existing fd to the ppp driver. 14177c478bd9Sstevel@tonic-gate */ 14187c478bd9Sstevel@tonic-gate int 14197c478bd9Sstevel@tonic-gate open_ppp_loopback() 14207c478bd9Sstevel@tonic-gate { 14217c478bd9Sstevel@tonic-gate /* 14227c478bd9Sstevel@tonic-gate * Plumb the interface. 14237c478bd9Sstevel@tonic-gate */ 14247c478bd9Sstevel@tonic-gate if (IPCP_ENABLED && (plumb_ipif(0) == 0)) { 14257c478bd9Sstevel@tonic-gate fatal("Unable to initialize IP interface for demand dial."); 14267c478bd9Sstevel@tonic-gate } 14277c478bd9Sstevel@tonic-gate #ifdef INET6 14287c478bd9Sstevel@tonic-gate if (IPV6CP_ENABLED && (plumb_ip6if(0) == 0)) { 14297c478bd9Sstevel@tonic-gate fatal("Unable to initialize IPv6 interface for demand dial."); 14307c478bd9Sstevel@tonic-gate } 14317c478bd9Sstevel@tonic-gate #endif /* INET6 */ 14327c478bd9Sstevel@tonic-gate 14337c478bd9Sstevel@tonic-gate return (pppfd); 14347c478bd9Sstevel@tonic-gate } 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate /* 14377c478bd9Sstevel@tonic-gate * output() 14387c478bd9Sstevel@tonic-gate * 14397c478bd9Sstevel@tonic-gate * Output PPP packet downstream 14407c478bd9Sstevel@tonic-gate */ 14417c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 14427c478bd9Sstevel@tonic-gate void 14437c478bd9Sstevel@tonic-gate output(unit, p, len) 14447c478bd9Sstevel@tonic-gate int unit; 14457c478bd9Sstevel@tonic-gate uchar_t *p; 14467c478bd9Sstevel@tonic-gate int len; 14477c478bd9Sstevel@tonic-gate { 14487c478bd9Sstevel@tonic-gate struct strbuf data; 14497c478bd9Sstevel@tonic-gate struct pollfd pfd; 14507c478bd9Sstevel@tonic-gate int retries, n; 14517c478bd9Sstevel@tonic-gate bool sent_ok = 1; 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate data.len = len; 14547c478bd9Sstevel@tonic-gate data.buf = (caddr_t)p; 14557c478bd9Sstevel@tonic-gate retries = 4; 14567c478bd9Sstevel@tonic-gate 14577c478bd9Sstevel@tonic-gate while (putmsg(pppfd, NULL, &data, 0) < 0) { 14587c478bd9Sstevel@tonic-gate if (errno == EINTR) 14597c478bd9Sstevel@tonic-gate continue; 14607c478bd9Sstevel@tonic-gate if (--retries < 0 || 14617c478bd9Sstevel@tonic-gate (errno != EWOULDBLOCK && errno != EAGAIN)) { 14627c478bd9Sstevel@tonic-gate if (errno != ENXIO) { 14637c478bd9Sstevel@tonic-gate error("Couldn't send packet: %m"); 14647c478bd9Sstevel@tonic-gate sent_ok = 0; 14657c478bd9Sstevel@tonic-gate } 14667c478bd9Sstevel@tonic-gate break; 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate pfd.fd = pppfd; 14697c478bd9Sstevel@tonic-gate pfd.events = POLLOUT; 14707c478bd9Sstevel@tonic-gate do { 14717c478bd9Sstevel@tonic-gate /* wait for up to 0.25 seconds */ 14727c478bd9Sstevel@tonic-gate n = poll(&pfd, 1, 250); 14737c478bd9Sstevel@tonic-gate } while ((n == -1) && (errno == EINTR)); 14747c478bd9Sstevel@tonic-gate } 14757c478bd9Sstevel@tonic-gate if (debug && sent_ok) { 14767c478bd9Sstevel@tonic-gate dbglog("sent %P", p, len); 14777c478bd9Sstevel@tonic-gate } 14787c478bd9Sstevel@tonic-gate } 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate /* 14817c478bd9Sstevel@tonic-gate * wait_input() 14827c478bd9Sstevel@tonic-gate * 14837c478bd9Sstevel@tonic-gate * Wait until there is data available, for the length of time specified by 14847c478bd9Sstevel@tonic-gate * timo (indefinite if timo is NULL). 14857c478bd9Sstevel@tonic-gate */ 14867c478bd9Sstevel@tonic-gate void 14877c478bd9Sstevel@tonic-gate wait_input(timo) 14887c478bd9Sstevel@tonic-gate struct timeval *timo; 14897c478bd9Sstevel@tonic-gate { 14907c478bd9Sstevel@tonic-gate int t; 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate t = (timo == NULL ? -1 : (timo->tv_sec * 1000 + timo->tv_usec / 1000)); 14937c478bd9Sstevel@tonic-gate if ((poll(pollfds, n_pollfds, t) < 0) && (errno != EINTR)) { 14947c478bd9Sstevel@tonic-gate fatal("poll: %m"); 14957c478bd9Sstevel@tonic-gate } 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate /* 14997c478bd9Sstevel@tonic-gate * add_fd() 15007c478bd9Sstevel@tonic-gate * 15017c478bd9Sstevel@tonic-gate * Add an fd to the set that wait_input waits for. 15027c478bd9Sstevel@tonic-gate */ 15037c478bd9Sstevel@tonic-gate void 15047c478bd9Sstevel@tonic-gate add_fd(fd) 15057c478bd9Sstevel@tonic-gate int fd; 15067c478bd9Sstevel@tonic-gate { 15077c478bd9Sstevel@tonic-gate int n; 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate if (fd < 0) { 15107c478bd9Sstevel@tonic-gate return; 15117c478bd9Sstevel@tonic-gate } 15127c478bd9Sstevel@tonic-gate for (n = 0; n < n_pollfds; ++n) { 15137c478bd9Sstevel@tonic-gate if (pollfds[n].fd == fd) { 15147c478bd9Sstevel@tonic-gate return; 15157c478bd9Sstevel@tonic-gate } 15167c478bd9Sstevel@tonic-gate } 15177c478bd9Sstevel@tonic-gate if (n_pollfds < MAX_POLLFDS) { 15187c478bd9Sstevel@tonic-gate pollfds[n_pollfds].fd = fd; 15197c478bd9Sstevel@tonic-gate pollfds[n_pollfds].events = POLLIN | POLLPRI | POLLHUP; 15207c478bd9Sstevel@tonic-gate ++n_pollfds; 15217c478bd9Sstevel@tonic-gate } else { 15227c478bd9Sstevel@tonic-gate fatal("add_fd: too many inputs!"); 15237c478bd9Sstevel@tonic-gate } 15247c478bd9Sstevel@tonic-gate } 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate /* 15277c478bd9Sstevel@tonic-gate * remove_fd() 15287c478bd9Sstevel@tonic-gate * 15297c478bd9Sstevel@tonic-gate * Remove an fd from the set that wait_input waits for. 15307c478bd9Sstevel@tonic-gate */ 15317c478bd9Sstevel@tonic-gate void 15327c478bd9Sstevel@tonic-gate remove_fd(fd) 15337c478bd9Sstevel@tonic-gate int fd; 15347c478bd9Sstevel@tonic-gate { 15357c478bd9Sstevel@tonic-gate int n; 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate for (n = 0; n < n_pollfds; ++n) { 15387c478bd9Sstevel@tonic-gate if (pollfds[n].fd == fd) { 15397c478bd9Sstevel@tonic-gate while (++n < n_pollfds) { 15407c478bd9Sstevel@tonic-gate pollfds[n-1] = pollfds[n]; 15417c478bd9Sstevel@tonic-gate } 15427c478bd9Sstevel@tonic-gate --n_pollfds; 15437c478bd9Sstevel@tonic-gate break; 15447c478bd9Sstevel@tonic-gate } 15457c478bd9Sstevel@tonic-gate } 15467c478bd9Sstevel@tonic-gate } 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate static void 15497c478bd9Sstevel@tonic-gate dump_packet(uchar_t *buf, int len) 15507c478bd9Sstevel@tonic-gate { 15517c478bd9Sstevel@tonic-gate uchar_t *bp; 15527c478bd9Sstevel@tonic-gate int proto, offs; 15537c478bd9Sstevel@tonic-gate const char *cp; 15547c478bd9Sstevel@tonic-gate char sbuf[32]; 15557c478bd9Sstevel@tonic-gate uint32_t src, dst; 15567c478bd9Sstevel@tonic-gate struct protoent *pep; 1557*f53eecf5SJames Carlson struct in6_addr addr; 1558*f53eecf5SJames Carlson char fromstr[INET6_ADDRSTRLEN]; 1559*f53eecf5SJames Carlson char tostr[INET6_ADDRSTRLEN]; 15607c478bd9Sstevel@tonic-gate 15617c478bd9Sstevel@tonic-gate if (len < 4) { 1562*f53eecf5SJames Carlson notice("strange link activity: %.*B", len, buf); 15637c478bd9Sstevel@tonic-gate return; 15647c478bd9Sstevel@tonic-gate } 15657c478bd9Sstevel@tonic-gate bp = buf; 15667c478bd9Sstevel@tonic-gate if (bp[0] == 0xFF && bp[1] == 0x03) 15677c478bd9Sstevel@tonic-gate bp += 2; 15687c478bd9Sstevel@tonic-gate proto = *bp++; 15697c478bd9Sstevel@tonic-gate if (!(proto & 1)) 15707c478bd9Sstevel@tonic-gate proto = (proto << 8) + *bp++; 15717c478bd9Sstevel@tonic-gate len -= bp-buf; 1572*f53eecf5SJames Carlson switch (proto) { 1573*f53eecf5SJames Carlson case PPP_IP: 1574*f53eecf5SJames Carlson if (len < IP_HDRLEN || get_ipv(bp) != 4 || get_iphl(bp) < 5) { 1575*f53eecf5SJames Carlson notice("strange IP packet activity: %16.*B", len, buf); 15767c478bd9Sstevel@tonic-gate return; 15777c478bd9Sstevel@tonic-gate } 15787c478bd9Sstevel@tonic-gate src = get_ipsrc(bp); 15797c478bd9Sstevel@tonic-gate dst = get_ipdst(bp); 15807c478bd9Sstevel@tonic-gate proto = get_ipproto(bp); 15817c478bd9Sstevel@tonic-gate if ((pep = getprotobynumber(proto)) != NULL) { 15827c478bd9Sstevel@tonic-gate cp = pep->p_name; 15837c478bd9Sstevel@tonic-gate } else { 15847c478bd9Sstevel@tonic-gate (void) slprintf(sbuf, sizeof (sbuf), "IP proto %d", 15857c478bd9Sstevel@tonic-gate proto); 15867c478bd9Sstevel@tonic-gate cp = sbuf; 15877c478bd9Sstevel@tonic-gate } 15887c478bd9Sstevel@tonic-gate if ((get_ipoff(bp) & IP_OFFMASK) != 0) { 15897c478bd9Sstevel@tonic-gate len -= get_iphl(bp) * 4; 15907c478bd9Sstevel@tonic-gate bp += get_iphl(bp) * 4; 1591*f53eecf5SJames Carlson notice("%s fragment from %I->%I: %8.*B", cp, src, dst, 15927c478bd9Sstevel@tonic-gate len, bp); 15937c478bd9Sstevel@tonic-gate } else { 15947c478bd9Sstevel@tonic-gate if (len > get_iplen(bp)) 15957c478bd9Sstevel@tonic-gate len = get_iplen(bp); 15967c478bd9Sstevel@tonic-gate len -= get_iphl(bp) * 4; 15977c478bd9Sstevel@tonic-gate bp += get_iphl(bp) * 4; 15987c478bd9Sstevel@tonic-gate offs = proto == IPPROTO_TCP ? (get_tcpoff(bp)*4) : 8; 15997c478bd9Sstevel@tonic-gate if (proto == IPPROTO_TCP || proto == IPPROTO_UDP) 1600*f53eecf5SJames Carlson notice("%s data:%d %s%I:%d->%I:%d: %8.*B", cp, 1601*f53eecf5SJames Carlson len-offs, 1602*f53eecf5SJames Carlson proto == IPPROTO_TCP ? 1603*f53eecf5SJames Carlson tcp_flag_decode(get_tcpflags(bp)) : "", 1604*f53eecf5SJames Carlson src, get_sport(bp), dst, get_dport(bp), 1605*f53eecf5SJames Carlson len-offs, bp+offs); 16067c478bd9Sstevel@tonic-gate else 1607*f53eecf5SJames Carlson notice("%s %d bytes %I->%I: %8.*B", cp, len, 16087c478bd9Sstevel@tonic-gate src, dst, len, bp); 16097c478bd9Sstevel@tonic-gate } 16107c478bd9Sstevel@tonic-gate return; 1611*f53eecf5SJames Carlson 1612*f53eecf5SJames Carlson case PPP_IPV6: 1613*f53eecf5SJames Carlson if (len < IP6_HDRLEN) { 1614*f53eecf5SJames Carlson notice("strange IPv6 activity: %16.*B", len, buf); 1615*f53eecf5SJames Carlson return; 1616*f53eecf5SJames Carlson } 1617*f53eecf5SJames Carlson (void) BCOPY(get_ip6src(bp), &addr, sizeof (addr)); 1618*f53eecf5SJames Carlson (void) inet_ntop(AF_INET6, &addr, fromstr, sizeof (fromstr)); 1619*f53eecf5SJames Carlson (void) BCOPY(get_ip6dst(bp), &addr, sizeof (addr)); 1620*f53eecf5SJames Carlson (void) inet_ntop(AF_INET6, &addr, tostr, sizeof (tostr)); 1621*f53eecf5SJames Carlson proto = get_ip6nh(bp); 1622*f53eecf5SJames Carlson if (proto == IPPROTO_FRAGMENT) { 1623*f53eecf5SJames Carlson notice("IPv6 fragment from %s->%s", fromstr, 1624*f53eecf5SJames Carlson tostr); 1625*f53eecf5SJames Carlson return; 1626*f53eecf5SJames Carlson } 1627*f53eecf5SJames Carlson if ((pep = getprotobynumber(proto)) != NULL) { 1628*f53eecf5SJames Carlson cp = pep->p_name; 1629*f53eecf5SJames Carlson } else { 1630*f53eecf5SJames Carlson (void) slprintf(sbuf, sizeof (sbuf), "IPv6 proto %d", 1631*f53eecf5SJames Carlson proto); 1632*f53eecf5SJames Carlson cp = sbuf; 1633*f53eecf5SJames Carlson } 1634*f53eecf5SJames Carlson len -= IP6_HDRLEN; 1635*f53eecf5SJames Carlson bp += IP6_HDRLEN; 1636*f53eecf5SJames Carlson offs = proto == IPPROTO_TCP ? (get_tcpoff(bp)*4) : 8; 1637*f53eecf5SJames Carlson if (proto == IPPROTO_TCP || proto == IPPROTO_UDP) 1638*f53eecf5SJames Carlson notice("%s data:%d %s[%s]%d->[%s]%d: %8.*B", cp, 1639*f53eecf5SJames Carlson len-offs, 1640*f53eecf5SJames Carlson proto == IPPROTO_TCP ? 1641*f53eecf5SJames Carlson tcp_flag_decode(get_tcpflags(bp)) : "", 1642*f53eecf5SJames Carlson fromstr, get_sport(bp), tostr, get_dport(bp), 1643*f53eecf5SJames Carlson len-offs, bp+offs); 1644*f53eecf5SJames Carlson else 1645*f53eecf5SJames Carlson notice("%s %d bytes %s->%s: %8.*B", cp, len, 1646*f53eecf5SJames Carlson fromstr, tostr, len, bp); 1647*f53eecf5SJames Carlson return; 16487c478bd9Sstevel@tonic-gate } 16497c478bd9Sstevel@tonic-gate if ((cp = protocol_name(proto)) == NULL) { 16507c478bd9Sstevel@tonic-gate (void) slprintf(sbuf, sizeof (sbuf), "0x#X", proto); 16517c478bd9Sstevel@tonic-gate cp = (const char *)sbuf; 16527c478bd9Sstevel@tonic-gate } 1653*f53eecf5SJames Carlson notice("link activity: %s %16.*B", cp, len, bp); 16547c478bd9Sstevel@tonic-gate } 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate /* 16577c478bd9Sstevel@tonic-gate * handle_bind() 16587c478bd9Sstevel@tonic-gate */ 16597c478bd9Sstevel@tonic-gate static void 16607c478bd9Sstevel@tonic-gate handle_bind(u_int32_t reason) 16617c478bd9Sstevel@tonic-gate { 16627c478bd9Sstevel@tonic-gate /* 16637c478bd9Sstevel@tonic-gate * Here we might, in the future, handle DL_BIND_REQ notifications 16647c478bd9Sstevel@tonic-gate * in order to close and re-open a NCP when certain interface 16657c478bd9Sstevel@tonic-gate * parameters (addresses, etc.) are changed via external mechanisms 16667c478bd9Sstevel@tonic-gate * such as through the "ifconfig" program. 16677c478bd9Sstevel@tonic-gate */ 16687c478bd9Sstevel@tonic-gate switch (reason) { 16697c478bd9Sstevel@tonic-gate case PPP_LINKSTAT_IPV4_BOUND: 16707c478bd9Sstevel@tonic-gate break; 16717c478bd9Sstevel@tonic-gate #ifdef INET6 16727c478bd9Sstevel@tonic-gate case PPP_LINKSTAT_IPV6_BOUND: 16737c478bd9Sstevel@tonic-gate break; 16747c478bd9Sstevel@tonic-gate #endif 16757c478bd9Sstevel@tonic-gate default: 16767c478bd9Sstevel@tonic-gate error("handle_bind: unrecognized reason"); 16777c478bd9Sstevel@tonic-gate break; 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate } 16807c478bd9Sstevel@tonic-gate 16817c478bd9Sstevel@tonic-gate /* 16827c478bd9Sstevel@tonic-gate * handle_unbind() 16837c478bd9Sstevel@tonic-gate */ 16847c478bd9Sstevel@tonic-gate static void 16857c478bd9Sstevel@tonic-gate handle_unbind(u_int32_t reason) 16867c478bd9Sstevel@tonic-gate { 16877c478bd9Sstevel@tonic-gate bool iff_up_isset; 16887c478bd9Sstevel@tonic-gate int rc; 16897c478bd9Sstevel@tonic-gate static const char *unplumb_str = "unplumbed"; 16907c478bd9Sstevel@tonic-gate static const char *down_str = "downed"; 16917c478bd9Sstevel@tonic-gate 16927c478bd9Sstevel@tonic-gate /* 16937c478bd9Sstevel@tonic-gate * Since the kernel driver (sppp) notifies this daemon of the 16947c478bd9Sstevel@tonic-gate * DLPI bind/unbind activities (for the purpose of bringing down 16957c478bd9Sstevel@tonic-gate * a NCP), we need to explicitly test the "actual" status of 16967c478bd9Sstevel@tonic-gate * the interface instance for which the notification is destined 16977c478bd9Sstevel@tonic-gate * from. This is because /dev/ip performs multiple DLPI attach- 16987c478bd9Sstevel@tonic-gate * bind-unbind-detach during the early life of the interface, 16997c478bd9Sstevel@tonic-gate * and when certain interface parameters change. A DL_UNBIND_REQ 17007c478bd9Sstevel@tonic-gate * coming down to the sppp driver from /dev/ip (which results in 17017c478bd9Sstevel@tonic-gate * our receiving of the PPP_LINKSTAT_*_UNBOUND link status message) 17027c478bd9Sstevel@tonic-gate * is not enough to conclude that the interface has been marked 17037c478bd9Sstevel@tonic-gate * DOWN (its IFF_UP bit is cleared) or is going away. Therefore, 17047c478bd9Sstevel@tonic-gate * we should query /dev/ip directly, upon receiving such *_UNBOUND 17057c478bd9Sstevel@tonic-gate * notification, to determine whether the interface is DOWN 17067c478bd9Sstevel@tonic-gate * for real, and only take the necessary actions when IFF_UP 17077c478bd9Sstevel@tonic-gate * bit for the interface instance is actually cleared. 17087c478bd9Sstevel@tonic-gate */ 17097c478bd9Sstevel@tonic-gate switch (reason) { 17107c478bd9Sstevel@tonic-gate case PPP_LINKSTAT_IPV4_UNBOUND: 17117c478bd9Sstevel@tonic-gate (void) sleep(1); 17127c478bd9Sstevel@tonic-gate rc = giflags(IFF_UP, &iff_up_isset); 17137c478bd9Sstevel@tonic-gate if (!iff_up_isset) { 17147c478bd9Sstevel@tonic-gate if_is_up = 0; 17157c478bd9Sstevel@tonic-gate ipmuxid = -1; 17167c478bd9Sstevel@tonic-gate info("IPv4 interface %s by administrator", 17177c478bd9Sstevel@tonic-gate ((rc < 0 && rc == ENXIO) ? unplumb_str : down_str)); 17187c478bd9Sstevel@tonic-gate fsm_close(&ipcp_fsm[0], 17197c478bd9Sstevel@tonic-gate "administratively disconnected"); 17207c478bd9Sstevel@tonic-gate } 17217c478bd9Sstevel@tonic-gate break; 17227c478bd9Sstevel@tonic-gate #ifdef INET6 17237c478bd9Sstevel@tonic-gate case PPP_LINKSTAT_IPV6_UNBOUND: 17247c478bd9Sstevel@tonic-gate (void) sleep(1); 17257c478bd9Sstevel@tonic-gate rc = giflags(IFF_UP, &iff_up_isset); 17267c478bd9Sstevel@tonic-gate if (!iff_up_isset) { 17277c478bd9Sstevel@tonic-gate if6_is_up = 0; 17287c478bd9Sstevel@tonic-gate ip6muxid = -1; 17297c478bd9Sstevel@tonic-gate info("IPv6 interface %s by administrator", 17307c478bd9Sstevel@tonic-gate ((rc < 0 && rc == ENXIO) ? unplumb_str : down_str)); 17317c478bd9Sstevel@tonic-gate fsm_close(&ipv6cp_fsm[0], 17327c478bd9Sstevel@tonic-gate "administratively disconnected"); 17337c478bd9Sstevel@tonic-gate } 17347c478bd9Sstevel@tonic-gate break; 17357c478bd9Sstevel@tonic-gate #endif 17367c478bd9Sstevel@tonic-gate default: 17377c478bd9Sstevel@tonic-gate error("handle_unbind: unrecognized reason"); 17387c478bd9Sstevel@tonic-gate break; 17397c478bd9Sstevel@tonic-gate } 17407c478bd9Sstevel@tonic-gate } 17417c478bd9Sstevel@tonic-gate 17427c478bd9Sstevel@tonic-gate /* 17437c478bd9Sstevel@tonic-gate * read_packet() 17447c478bd9Sstevel@tonic-gate * 17457c478bd9Sstevel@tonic-gate * Get a PPP packet from the serial device. 17467c478bd9Sstevel@tonic-gate */ 17477c478bd9Sstevel@tonic-gate int 17487c478bd9Sstevel@tonic-gate read_packet(buf) 17497c478bd9Sstevel@tonic-gate uchar_t *buf; 17507c478bd9Sstevel@tonic-gate { 17517c478bd9Sstevel@tonic-gate struct strbuf ctrl; 17527c478bd9Sstevel@tonic-gate struct strbuf data; 17537c478bd9Sstevel@tonic-gate int flags; 17547c478bd9Sstevel@tonic-gate int len; 17557c478bd9Sstevel@tonic-gate int rc; 17567c478bd9Sstevel@tonic-gate struct ppp_ls *plp; 17577c478bd9Sstevel@tonic-gate uint32_t ctrlbuf[1536 / sizeof (uint32_t)]; 17587c478bd9Sstevel@tonic-gate bool flushmode; 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate flushmode = 0; 17617c478bd9Sstevel@tonic-gate for (;;) { 17627c478bd9Sstevel@tonic-gate 17637c478bd9Sstevel@tonic-gate data.maxlen = PPP_MRU + PPP_HDRLEN; 17647c478bd9Sstevel@tonic-gate data.buf = (caddr_t)buf; 17657c478bd9Sstevel@tonic-gate 17667c478bd9Sstevel@tonic-gate ctrl.maxlen = sizeof (ctrlbuf); 17677c478bd9Sstevel@tonic-gate ctrl.buf = (caddr_t)ctrlbuf; 17687c478bd9Sstevel@tonic-gate 17697c478bd9Sstevel@tonic-gate flags = 0; 17707c478bd9Sstevel@tonic-gate rc = len = getmsg(pppfd, &ctrl, &data, &flags); 17717c478bd9Sstevel@tonic-gate if (sys_read_packet_hook != NULL) { 17727c478bd9Sstevel@tonic-gate rc = len = (*sys_read_packet_hook)(len, &ctrl, &data, 17737c478bd9Sstevel@tonic-gate flags); 17747c478bd9Sstevel@tonic-gate } 17757c478bd9Sstevel@tonic-gate if (len < 0) { 17767c478bd9Sstevel@tonic-gate if (errno == EAGAIN || errno == EINTR) { 17777c478bd9Sstevel@tonic-gate return (-1); 17787c478bd9Sstevel@tonic-gate } 17797c478bd9Sstevel@tonic-gate fatal("Error reading packet: %m"); 17807c478bd9Sstevel@tonic-gate } 17817c478bd9Sstevel@tonic-gate if ((data.len > 0) && (ctrl.len < 0)) { 17827c478bd9Sstevel@tonic-gate /* 17837c478bd9Sstevel@tonic-gate * If there's more data on stream head, keep reading 17847c478bd9Sstevel@tonic-gate * but discard, since the stream is now corrupt. 17857c478bd9Sstevel@tonic-gate */ 17867c478bd9Sstevel@tonic-gate if (rc & MOREDATA) { 17877c478bd9Sstevel@tonic-gate dbglog("More data; input packet garbled"); 17887c478bd9Sstevel@tonic-gate flushmode = 1; 17897c478bd9Sstevel@tonic-gate continue; 17907c478bd9Sstevel@tonic-gate } 17917c478bd9Sstevel@tonic-gate if (flushmode) 17927c478bd9Sstevel@tonic-gate return (-1); 17937c478bd9Sstevel@tonic-gate return (data.len); 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate } else if (ctrl.len > 0) { 17967c478bd9Sstevel@tonic-gate /* 17977c478bd9Sstevel@tonic-gate * If there's more ctl on stream head, keep reading, 17987c478bd9Sstevel@tonic-gate * but start discarding. We can't deal with fragmented 17997c478bd9Sstevel@tonic-gate * messages at all. 18007c478bd9Sstevel@tonic-gate */ 18017c478bd9Sstevel@tonic-gate if (rc & MORECTL) { 18027c478bd9Sstevel@tonic-gate dbglog("More control; stream garbled"); 18037c478bd9Sstevel@tonic-gate flushmode = 1; 18047c478bd9Sstevel@tonic-gate continue; 18057c478bd9Sstevel@tonic-gate } 18067c478bd9Sstevel@tonic-gate if (flushmode) 18077c478bd9Sstevel@tonic-gate return (-1); 18087c478bd9Sstevel@tonic-gate if (ctrl.len < sizeof (struct ppp_ls)) { 18097c478bd9Sstevel@tonic-gate warn("read_packet: ctl.len %d < " 18107c478bd9Sstevel@tonic-gate "sizeof ppp_ls %d", 18117c478bd9Sstevel@tonic-gate ctrl.len, sizeof (struct ppp_ls)); 18127c478bd9Sstevel@tonic-gate return (-1); 18137c478bd9Sstevel@tonic-gate } 18147c478bd9Sstevel@tonic-gate plp = (struct ppp_ls *)ctrlbuf; 18157c478bd9Sstevel@tonic-gate if (plp->magic != PPPLSMAGIC) { 18167c478bd9Sstevel@tonic-gate /* Skip, as we don't understand it */ 18177c478bd9Sstevel@tonic-gate dbglog("read_packet: unrecognized control %lX", 18187c478bd9Sstevel@tonic-gate plp->magic); 18197c478bd9Sstevel@tonic-gate return (-1); 18207c478bd9Sstevel@tonic-gate } 18217c478bd9Sstevel@tonic-gate 18227c478bd9Sstevel@tonic-gate lastlink_status = plp->ppp_message; 18237c478bd9Sstevel@tonic-gate 18247c478bd9Sstevel@tonic-gate switch (plp->ppp_message) { 18257c478bd9Sstevel@tonic-gate case PPP_LINKSTAT_HANGUP: 18267c478bd9Sstevel@tonic-gate return (0); /* Hangup */ 18277c478bd9Sstevel@tonic-gate /* For use by integrated drivers. */ 18287c478bd9Sstevel@tonic-gate case PPP_LINKSTAT_UP: 18297c478bd9Sstevel@tonic-gate lcp_lowerdown(0); 18307c478bd9Sstevel@tonic-gate lcp_lowerup(0); 18317c478bd9Sstevel@tonic-gate return (0); 18327c478bd9Sstevel@tonic-gate case PPP_LINKSTAT_NEEDUP: 1833*f53eecf5SJames Carlson if (data.len > 0) 18347c478bd9Sstevel@tonic-gate dump_packet(buf, data.len); 18357c478bd9Sstevel@tonic-gate return (-1); /* Demand dial */ 18367c478bd9Sstevel@tonic-gate case PPP_LINKSTAT_IPV4_UNBOUND: 18377c478bd9Sstevel@tonic-gate (void) handle_unbind(plp->ppp_message); 18387c478bd9Sstevel@tonic-gate return (-1); 18397c478bd9Sstevel@tonic-gate case PPP_LINKSTAT_IPV4_BOUND: 18407c478bd9Sstevel@tonic-gate (void) handle_bind(plp->ppp_message); 18417c478bd9Sstevel@tonic-gate return (-1); 18427c478bd9Sstevel@tonic-gate #ifdef INET6 18437c478bd9Sstevel@tonic-gate case PPP_LINKSTAT_IPV6_UNBOUND: 18447c478bd9Sstevel@tonic-gate (void) handle_unbind(plp->ppp_message); 18457c478bd9Sstevel@tonic-gate return (-1); 18467c478bd9Sstevel@tonic-gate case PPP_LINKSTAT_IPV6_BOUND: 18477c478bd9Sstevel@tonic-gate (void) handle_bind(plp->ppp_message); 18487c478bd9Sstevel@tonic-gate return (-1); 18497c478bd9Sstevel@tonic-gate #endif 18507c478bd9Sstevel@tonic-gate default: 18517c478bd9Sstevel@tonic-gate warn("read_packet: unknown link status type!"); 18527c478bd9Sstevel@tonic-gate return (-1); 18537c478bd9Sstevel@tonic-gate } 18547c478bd9Sstevel@tonic-gate } else { 18557c478bd9Sstevel@tonic-gate /* 18567c478bd9Sstevel@tonic-gate * We get here on zero length data or control. 18577c478bd9Sstevel@tonic-gate */ 18587c478bd9Sstevel@tonic-gate return (-1); 18597c478bd9Sstevel@tonic-gate } 18607c478bd9Sstevel@tonic-gate } 18617c478bd9Sstevel@tonic-gate } 18627c478bd9Sstevel@tonic-gate 18637c478bd9Sstevel@tonic-gate /* 18647c478bd9Sstevel@tonic-gate * get_loop_output() 18657c478bd9Sstevel@tonic-gate * 18667c478bd9Sstevel@tonic-gate * Get outgoing packets from the ppp device, and detect when we want to bring 18677c478bd9Sstevel@tonic-gate * the real link up. Return value is 1 if we need to bring up the link, or 0 18687c478bd9Sstevel@tonic-gate * otherwise. 18697c478bd9Sstevel@tonic-gate */ 18707c478bd9Sstevel@tonic-gate int 18717c478bd9Sstevel@tonic-gate get_loop_output() 18727c478bd9Sstevel@tonic-gate { 18737c478bd9Sstevel@tonic-gate int loops; 18747c478bd9Sstevel@tonic-gate 18757c478bd9Sstevel@tonic-gate /* 18767c478bd9Sstevel@tonic-gate * In the Solaris 2.x kernel-level portion implementation, packets 18777c478bd9Sstevel@tonic-gate * which are received on a demand-dial interface are immediately 18787c478bd9Sstevel@tonic-gate * discarded, and a notification message is sent up the control 18797c478bd9Sstevel@tonic-gate * stream to the pppd process. Therefore, the call to read_packet() 18807c478bd9Sstevel@tonic-gate * below is merely there to wait for such message. 18817c478bd9Sstevel@tonic-gate */ 18827c478bd9Sstevel@tonic-gate lastlink_status = 0; 18837c478bd9Sstevel@tonic-gate loops = 0; 18847c478bd9Sstevel@tonic-gate while (read_packet(inpacket_buf) > 0) { 18857c478bd9Sstevel@tonic-gate if (++loops > 10) 18867c478bd9Sstevel@tonic-gate break; 18877c478bd9Sstevel@tonic-gate } 18887c478bd9Sstevel@tonic-gate return (lastlink_status == PPP_LINKSTAT_NEEDUP); 18897c478bd9Sstevel@tonic-gate } 18907c478bd9Sstevel@tonic-gate 18917c478bd9Sstevel@tonic-gate #ifdef MUX_FRAME 18927c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 18937c478bd9Sstevel@tonic-gate void 18947c478bd9Sstevel@tonic-gate ppp_send_muxoption(unit, muxflag) 18957c478bd9Sstevel@tonic-gate int unit; 18967c478bd9Sstevel@tonic-gate u_int32_t muxflag; 18977c478bd9Sstevel@tonic-gate { 18987c478bd9Sstevel@tonic-gate uint32_t cf[2]; 18997c478bd9Sstevel@tonic-gate 19007c478bd9Sstevel@tonic-gate /* 19017c478bd9Sstevel@tonic-gate * Since muxed frame feature is implemented in the async module, 19027c478bd9Sstevel@tonic-gate * don't send down the ioctl in the synchronous case. 19037c478bd9Sstevel@tonic-gate */ 19047c478bd9Sstevel@tonic-gate if (!sync_serial && fdmuxid >= 0 && pppfd != -1) { 19057c478bd9Sstevel@tonic-gate cf[0] = muxflag; 19067c478bd9Sstevel@tonic-gate cf[1] = X_MUXMASK; 19077c478bd9Sstevel@tonic-gate 19087c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_MUX, cf, sizeof (cf), 0) < 0) { 19097c478bd9Sstevel@tonic-gate error("Couldn't set mux option: %m"); 19107c478bd9Sstevel@tonic-gate } 19117c478bd9Sstevel@tonic-gate } 19127c478bd9Sstevel@tonic-gate } 19137c478bd9Sstevel@tonic-gate 19147c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 19157c478bd9Sstevel@tonic-gate void 19167c478bd9Sstevel@tonic-gate ppp_recv_muxoption(unit, muxflag) 19177c478bd9Sstevel@tonic-gate int unit; 19187c478bd9Sstevel@tonic-gate u_int32_t muxflag; 19197c478bd9Sstevel@tonic-gate { 19207c478bd9Sstevel@tonic-gate uint32_t cf[2]; 19217c478bd9Sstevel@tonic-gate 19227c478bd9Sstevel@tonic-gate /* 19237c478bd9Sstevel@tonic-gate * Since muxed frame feature is implemented in the async module, 19247c478bd9Sstevel@tonic-gate * don't send down the ioctl in the synchronous case. 19257c478bd9Sstevel@tonic-gate */ 19267c478bd9Sstevel@tonic-gate if (!sync_serial && fdmuxid >= 0 && pppfd != -1) { 19277c478bd9Sstevel@tonic-gate cf[0] = muxflag; 19287c478bd9Sstevel@tonic-gate cf[1] = R_MUXMASK; 19297c478bd9Sstevel@tonic-gate 19307c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_MUX, cf, sizeof (cf), 0) < 0) { 19317c478bd9Sstevel@tonic-gate error("Couldn't set receive mux option: %m"); 19327c478bd9Sstevel@tonic-gate } 19337c478bd9Sstevel@tonic-gate } 19347c478bd9Sstevel@tonic-gate } 19357c478bd9Sstevel@tonic-gate #endif 19367c478bd9Sstevel@tonic-gate 19377c478bd9Sstevel@tonic-gate /* 19387c478bd9Sstevel@tonic-gate * ppp_send_config() 19397c478bd9Sstevel@tonic-gate * 19407c478bd9Sstevel@tonic-gate * Configure the transmit characteristics of the ppp interface. 19417c478bd9Sstevel@tonic-gate */ 19427c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 19437c478bd9Sstevel@tonic-gate void 19447c478bd9Sstevel@tonic-gate ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) 19457c478bd9Sstevel@tonic-gate int unit; 19467c478bd9Sstevel@tonic-gate int mtu; 19477c478bd9Sstevel@tonic-gate u_int32_t asyncmap; 19487c478bd9Sstevel@tonic-gate int pcomp; 19497c478bd9Sstevel@tonic-gate int accomp; 19507c478bd9Sstevel@tonic-gate { 19517c478bd9Sstevel@tonic-gate uint32_t cf[2]; 19527c478bd9Sstevel@tonic-gate 19537c478bd9Sstevel@tonic-gate if (pppfd == -1) { 19547c478bd9Sstevel@tonic-gate error("ppp_send_config called with invalid device handle"); 19557c478bd9Sstevel@tonic-gate return; 19567c478bd9Sstevel@tonic-gate } 19577c478bd9Sstevel@tonic-gate cf[0] = link_mtu = mtu; 19587c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_MTU, cf, sizeof (cf[0]), 0) < 0) { 19597c478bd9Sstevel@tonic-gate if (hungup && errno == ENXIO) { 19607c478bd9Sstevel@tonic-gate return; 19617c478bd9Sstevel@tonic-gate } 19627c478bd9Sstevel@tonic-gate error("Couldn't set MTU: %m"); 19637c478bd9Sstevel@tonic-gate } 19647c478bd9Sstevel@tonic-gate if (fdmuxid != -1) { 19657c478bd9Sstevel@tonic-gate if (!sync_serial) { 19667c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, 19677c478bd9Sstevel@tonic-gate sizeof (asyncmap), 0) < 0) { 19687c478bd9Sstevel@tonic-gate error("Couldn't set transmit ACCM: %m"); 19697c478bd9Sstevel@tonic-gate } 19707c478bd9Sstevel@tonic-gate } 19717c478bd9Sstevel@tonic-gate cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0); 19727c478bd9Sstevel@tonic-gate cf[1] = COMP_PROT | COMP_AC; 19737c478bd9Sstevel@tonic-gate 19747c478bd9Sstevel@tonic-gate if (any_compressions() && strioctl(pppfd, PPPIO_CFLAGS, cf, 19757c478bd9Sstevel@tonic-gate sizeof (cf), sizeof (cf[0])) < 0) { 19767c478bd9Sstevel@tonic-gate error("Couldn't set prot/AC compression: %m"); 19777c478bd9Sstevel@tonic-gate } 19787c478bd9Sstevel@tonic-gate } 19797c478bd9Sstevel@tonic-gate } 19807c478bd9Sstevel@tonic-gate 19817c478bd9Sstevel@tonic-gate /* 19827c478bd9Sstevel@tonic-gate * ppp_set_xaccm() 19837c478bd9Sstevel@tonic-gate * 19847c478bd9Sstevel@tonic-gate * Set the extended transmit ACCM for the interface. 19857c478bd9Sstevel@tonic-gate */ 19867c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 19877c478bd9Sstevel@tonic-gate void 19887c478bd9Sstevel@tonic-gate ppp_set_xaccm(unit, accm) 19897c478bd9Sstevel@tonic-gate int unit; 19907c478bd9Sstevel@tonic-gate ext_accm accm; 19917c478bd9Sstevel@tonic-gate { 19927c478bd9Sstevel@tonic-gate if (sync_serial) { 19937c478bd9Sstevel@tonic-gate return; 19947c478bd9Sstevel@tonic-gate } 19957c478bd9Sstevel@tonic-gate if (fdmuxid != -1 && strioctl(pppfd, PPPIO_XACCM, accm, 19967c478bd9Sstevel@tonic-gate sizeof (ext_accm), 0) < 0) { 19977c478bd9Sstevel@tonic-gate if (!hungup || errno != ENXIO) { 19987c478bd9Sstevel@tonic-gate warn("Couldn't set extended ACCM: %m"); 19997c478bd9Sstevel@tonic-gate } 20007c478bd9Sstevel@tonic-gate } 20017c478bd9Sstevel@tonic-gate } 20027c478bd9Sstevel@tonic-gate 20037c478bd9Sstevel@tonic-gate /* 20047c478bd9Sstevel@tonic-gate * ppp_recv_config() 20057c478bd9Sstevel@tonic-gate * 20067c478bd9Sstevel@tonic-gate * Configure the receive-side characteristics of the ppp interface. 20077c478bd9Sstevel@tonic-gate */ 20087c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 20097c478bd9Sstevel@tonic-gate void 20107c478bd9Sstevel@tonic-gate ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) 20117c478bd9Sstevel@tonic-gate int unit; 20127c478bd9Sstevel@tonic-gate int mru; 20137c478bd9Sstevel@tonic-gate u_int32_t asyncmap; 20147c478bd9Sstevel@tonic-gate int pcomp; 20157c478bd9Sstevel@tonic-gate int accomp; 20167c478bd9Sstevel@tonic-gate { 20177c478bd9Sstevel@tonic-gate uint32_t cf[2]; 20187c478bd9Sstevel@tonic-gate 20197c478bd9Sstevel@tonic-gate if (pppfd == -1) { 20207c478bd9Sstevel@tonic-gate error("ppp_recv_config called with invalid device handle"); 20217c478bd9Sstevel@tonic-gate return; 20227c478bd9Sstevel@tonic-gate } 20237c478bd9Sstevel@tonic-gate cf[0] = mru; 20247c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_MRU, cf, sizeof (cf[0]), 0) < 0) { 20257c478bd9Sstevel@tonic-gate if (hungup && errno == ENXIO) { 20267c478bd9Sstevel@tonic-gate return; 20277c478bd9Sstevel@tonic-gate } 20287c478bd9Sstevel@tonic-gate error("Couldn't set MRU: %m"); 20297c478bd9Sstevel@tonic-gate } 20307c478bd9Sstevel@tonic-gate if (fdmuxid != -1) { 20317c478bd9Sstevel@tonic-gate if (!sync_serial) { 20327c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, 20337c478bd9Sstevel@tonic-gate sizeof (asyncmap), 0) < 0) { 20347c478bd9Sstevel@tonic-gate error("Couldn't set receive ACCM: %m"); 20357c478bd9Sstevel@tonic-gate } 20367c478bd9Sstevel@tonic-gate } 20377c478bd9Sstevel@tonic-gate cf[0] = (pcomp ? DECOMP_PROT : 0) + (accomp ? DECOMP_AC : 0); 20387c478bd9Sstevel@tonic-gate cf[1] = DECOMP_PROT | DECOMP_AC; 20397c478bd9Sstevel@tonic-gate 20407c478bd9Sstevel@tonic-gate if (any_compressions() && strioctl(pppfd, PPPIO_CFLAGS, cf, 20417c478bd9Sstevel@tonic-gate sizeof (cf), sizeof (cf[0])) < 0) { 20427c478bd9Sstevel@tonic-gate error("Couldn't set prot/AC decompression: %m"); 20437c478bd9Sstevel@tonic-gate } 20447c478bd9Sstevel@tonic-gate } 20457c478bd9Sstevel@tonic-gate } 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate #ifdef NEGOTIATE_FCS 20487c478bd9Sstevel@tonic-gate /* 20497c478bd9Sstevel@tonic-gate * ppp_send_fcs() 20507c478bd9Sstevel@tonic-gate * 20517c478bd9Sstevel@tonic-gate * Configure the sender-side FCS. 20527c478bd9Sstevel@tonic-gate */ 20537c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 20547c478bd9Sstevel@tonic-gate void 20557c478bd9Sstevel@tonic-gate ppp_send_fcs(unit, fcstype) 20567c478bd9Sstevel@tonic-gate int unit, fcstype; 20577c478bd9Sstevel@tonic-gate { 20587c478bd9Sstevel@tonic-gate uint32_t fcs; 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate if (sync_serial) { 20617c478bd9Sstevel@tonic-gate return; 20627c478bd9Sstevel@tonic-gate } 20637c478bd9Sstevel@tonic-gate 20647c478bd9Sstevel@tonic-gate if (fcstype & FCSALT_32) { 20657c478bd9Sstevel@tonic-gate fcs = PPPFCS_32; 20667c478bd9Sstevel@tonic-gate } else if (fcstype & FCSALT_NULL) { 20677c478bd9Sstevel@tonic-gate fcs = PPPFCS_NONE; 20687c478bd9Sstevel@tonic-gate } else { 20697c478bd9Sstevel@tonic-gate fcs = PPPFCS_16; 20707c478bd9Sstevel@tonic-gate } 20717c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_XFCS, &fcs, sizeof (fcs), 0) < 0) { 20727c478bd9Sstevel@tonic-gate warn("Couldn't set transmit FCS: %m"); 20737c478bd9Sstevel@tonic-gate } 20747c478bd9Sstevel@tonic-gate } 20757c478bd9Sstevel@tonic-gate 20767c478bd9Sstevel@tonic-gate /* 20777c478bd9Sstevel@tonic-gate * ppp_recv_fcs() 20787c478bd9Sstevel@tonic-gate * 20797c478bd9Sstevel@tonic-gate * Configure the receiver-side FCS. 20807c478bd9Sstevel@tonic-gate */ 20817c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 20827c478bd9Sstevel@tonic-gate void 20837c478bd9Sstevel@tonic-gate ppp_recv_fcs(unit, fcstype) 20847c478bd9Sstevel@tonic-gate int unit, fcstype; 20857c478bd9Sstevel@tonic-gate { 20867c478bd9Sstevel@tonic-gate uint32_t fcs; 20877c478bd9Sstevel@tonic-gate 20887c478bd9Sstevel@tonic-gate if (sync_serial) { 20897c478bd9Sstevel@tonic-gate return; 20907c478bd9Sstevel@tonic-gate } 20917c478bd9Sstevel@tonic-gate 20927c478bd9Sstevel@tonic-gate if (fcstype & FCSALT_32) { 20937c478bd9Sstevel@tonic-gate fcs = PPPFCS_32; 20947c478bd9Sstevel@tonic-gate } else if (fcstype & FCSALT_NULL) { 20957c478bd9Sstevel@tonic-gate fcs = PPPFCS_NONE; 20967c478bd9Sstevel@tonic-gate } else { 20977c478bd9Sstevel@tonic-gate fcs = PPPFCS_16; 20987c478bd9Sstevel@tonic-gate } 20997c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_RFCS, &fcs, sizeof (fcs), 0) < 0) { 21007c478bd9Sstevel@tonic-gate warn("Couldn't set receive FCS: %m"); 21017c478bd9Sstevel@tonic-gate } 21027c478bd9Sstevel@tonic-gate } 21037c478bd9Sstevel@tonic-gate #endif 21047c478bd9Sstevel@tonic-gate 21057c478bd9Sstevel@tonic-gate /* 21067c478bd9Sstevel@tonic-gate * ccp_test() 21077c478bd9Sstevel@tonic-gate * 21087c478bd9Sstevel@tonic-gate * Ask kernel whether a given compression method is acceptable for use. 21097c478bd9Sstevel@tonic-gate */ 21107c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 21117c478bd9Sstevel@tonic-gate int 21127c478bd9Sstevel@tonic-gate ccp_test(unit, opt_ptr, opt_len, for_transmit) 21137c478bd9Sstevel@tonic-gate int unit; 21147c478bd9Sstevel@tonic-gate uchar_t *opt_ptr; 21157c478bd9Sstevel@tonic-gate int opt_len; 21167c478bd9Sstevel@tonic-gate int for_transmit; 21177c478bd9Sstevel@tonic-gate { 21187c478bd9Sstevel@tonic-gate if (strioctl(pppfd, (for_transmit ? PPPIO_XCOMP : PPPIO_RCOMP), 21197c478bd9Sstevel@tonic-gate opt_ptr, opt_len, 0) >= 0) { 21207c478bd9Sstevel@tonic-gate return (1); 21217c478bd9Sstevel@tonic-gate } 21227c478bd9Sstevel@tonic-gate warn("Error in %s ioctl: %m", 21237c478bd9Sstevel@tonic-gate (for_transmit ? "PPPIO_XCOMP" : "PPPIO_RCOMP")); 21247c478bd9Sstevel@tonic-gate return ((errno == ENOSR) ? 0 : -1); 21257c478bd9Sstevel@tonic-gate } 21267c478bd9Sstevel@tonic-gate 21277c478bd9Sstevel@tonic-gate #ifdef COMP_TUNE 21287c478bd9Sstevel@tonic-gate /* 21297c478bd9Sstevel@tonic-gate * ccp_tune() 21307c478bd9Sstevel@tonic-gate * 21317c478bd9Sstevel@tonic-gate * Tune compression effort level. 21327c478bd9Sstevel@tonic-gate */ 21337c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 21347c478bd9Sstevel@tonic-gate void 21357c478bd9Sstevel@tonic-gate ccp_tune(unit, effort) 21367c478bd9Sstevel@tonic-gate int unit, effort; 21377c478bd9Sstevel@tonic-gate { 21387c478bd9Sstevel@tonic-gate uint32_t x; 21397c478bd9Sstevel@tonic-gate 21407c478bd9Sstevel@tonic-gate x = effort; 21417c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_COMPLEV, &x, sizeof (x), 0) < 0) { 21427c478bd9Sstevel@tonic-gate warn("unable to set compression effort level: %m"); 21437c478bd9Sstevel@tonic-gate } 21447c478bd9Sstevel@tonic-gate } 21457c478bd9Sstevel@tonic-gate #endif 21467c478bd9Sstevel@tonic-gate 21477c478bd9Sstevel@tonic-gate /* 21487c478bd9Sstevel@tonic-gate * ccp_flags_set() 21497c478bd9Sstevel@tonic-gate * 21507c478bd9Sstevel@tonic-gate * Inform kernel about the current state of CCP. 21517c478bd9Sstevel@tonic-gate */ 21527c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 21537c478bd9Sstevel@tonic-gate void 21547c478bd9Sstevel@tonic-gate ccp_flags_set(unit, isopen, isup) 21557c478bd9Sstevel@tonic-gate int unit, isopen, isup; 21567c478bd9Sstevel@tonic-gate { 21577c478bd9Sstevel@tonic-gate uint32_t cf[2]; 21587c478bd9Sstevel@tonic-gate 21597c478bd9Sstevel@tonic-gate cf[0] = (isopen ? CCP_ISOPEN : 0) + (isup ? CCP_ISUP : 0); 21607c478bd9Sstevel@tonic-gate cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR; 21617c478bd9Sstevel@tonic-gate 21627c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0])) 21637c478bd9Sstevel@tonic-gate < 0) { 21647c478bd9Sstevel@tonic-gate if (!hungup || errno != ENXIO) { 21657c478bd9Sstevel@tonic-gate error("Couldn't set kernel CCP state: %m"); 21667c478bd9Sstevel@tonic-gate } 21677c478bd9Sstevel@tonic-gate } 21687c478bd9Sstevel@tonic-gate } 21697c478bd9Sstevel@tonic-gate 21707c478bd9Sstevel@tonic-gate /* 21717c478bd9Sstevel@tonic-gate * get_idle_time() 21727c478bd9Sstevel@tonic-gate * 21737c478bd9Sstevel@tonic-gate * Return how long the link has been idle. 21747c478bd9Sstevel@tonic-gate */ 21757c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 21767c478bd9Sstevel@tonic-gate int 21777c478bd9Sstevel@tonic-gate get_idle_time(u, pids) 21787c478bd9Sstevel@tonic-gate int u; 21797c478bd9Sstevel@tonic-gate struct ppp_idle *pids; 21807c478bd9Sstevel@tonic-gate { 21817c478bd9Sstevel@tonic-gate int rc; 21827c478bd9Sstevel@tonic-gate 21837c478bd9Sstevel@tonic-gate rc = strioctl(pppfd, PPPIO_GIDLE, pids, 0, sizeof (struct ppp_idle)); 21847c478bd9Sstevel@tonic-gate if (rc < 0) { 21857c478bd9Sstevel@tonic-gate warn("unable to obtain idle time: %m"); 21867c478bd9Sstevel@tonic-gate } 21877c478bd9Sstevel@tonic-gate return ((rc == 0) ? 1 : 0); 21887c478bd9Sstevel@tonic-gate } 21897c478bd9Sstevel@tonic-gate 21907c478bd9Sstevel@tonic-gate /* 21917c478bd9Sstevel@tonic-gate * get_ppp_stats() 21927c478bd9Sstevel@tonic-gate * 21937c478bd9Sstevel@tonic-gate * Return statistics for the link. 21947c478bd9Sstevel@tonic-gate */ 21957c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 21967c478bd9Sstevel@tonic-gate int 21977c478bd9Sstevel@tonic-gate get_ppp_stats(u, stats) 21987c478bd9Sstevel@tonic-gate int u; 21997c478bd9Sstevel@tonic-gate struct pppd_stats *stats; 22007c478bd9Sstevel@tonic-gate { 22017c478bd9Sstevel@tonic-gate struct ppp_stats64 s64; 22027c478bd9Sstevel@tonic-gate struct ppp_stats s; 22037c478bd9Sstevel@tonic-gate 22047c478bd9Sstevel@tonic-gate /* Try first to get these from the 64-bit interface */ 22057c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_GETSTAT64, &s64, 0, sizeof (s64)) >= 0) { 22067c478bd9Sstevel@tonic-gate stats->bytes_in = s64.p.ppp_ibytes; 22077c478bd9Sstevel@tonic-gate stats->bytes_out = s64.p.ppp_obytes; 22087c478bd9Sstevel@tonic-gate stats->pkts_in = s64.p.ppp_ipackets; 22097c478bd9Sstevel@tonic-gate stats->pkts_out = s64.p.ppp_opackets; 22107c478bd9Sstevel@tonic-gate return (1); 22117c478bd9Sstevel@tonic-gate } 22127c478bd9Sstevel@tonic-gate 22137c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof (s)) < 0) { 22147c478bd9Sstevel@tonic-gate error("Couldn't get link statistics: %m"); 22157c478bd9Sstevel@tonic-gate return (0); 22167c478bd9Sstevel@tonic-gate } 22177c478bd9Sstevel@tonic-gate stats->bytes_in = s.p.ppp_ibytes; 22187c478bd9Sstevel@tonic-gate stats->bytes_out = s.p.ppp_obytes; 22197c478bd9Sstevel@tonic-gate stats->pkts_in = s.p.ppp_ipackets; 22207c478bd9Sstevel@tonic-gate stats->pkts_out = s.p.ppp_opackets; 22217c478bd9Sstevel@tonic-gate return (1); 22227c478bd9Sstevel@tonic-gate } 22237c478bd9Sstevel@tonic-gate 22247c478bd9Sstevel@tonic-gate #if defined(FILTER_PACKETS) 22257c478bd9Sstevel@tonic-gate /* 22267c478bd9Sstevel@tonic-gate * set_filters() 22277c478bd9Sstevel@tonic-gate * 22287c478bd9Sstevel@tonic-gate * Transfer the pass and active filters to the kernel. 22297c478bd9Sstevel@tonic-gate */ 22307c478bd9Sstevel@tonic-gate int 22317c478bd9Sstevel@tonic-gate set_filters(pass, active) 22327c478bd9Sstevel@tonic-gate struct bpf_program *pass; 22337c478bd9Sstevel@tonic-gate struct bpf_program *active; 22347c478bd9Sstevel@tonic-gate { 22357c478bd9Sstevel@tonic-gate int ret = 1; 22367c478bd9Sstevel@tonic-gate 22377c478bd9Sstevel@tonic-gate if (pass->bf_len > 0) { 22387c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_PASSFILT, pass, 22397c478bd9Sstevel@tonic-gate sizeof (struct bpf_program), 0) < 0) { 22407c478bd9Sstevel@tonic-gate error("Couldn't set pass-filter in kernel: %m"); 22417c478bd9Sstevel@tonic-gate ret = 0; 22427c478bd9Sstevel@tonic-gate } 22437c478bd9Sstevel@tonic-gate } 22447c478bd9Sstevel@tonic-gate if (active->bf_len > 0) { 22457c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_ACTIVEFILT, active, 22467c478bd9Sstevel@tonic-gate sizeof (struct bpf_program), 0) < 0) { 22477c478bd9Sstevel@tonic-gate error("Couldn't set active-filter in kernel: %m"); 22487c478bd9Sstevel@tonic-gate ret = 0; 22497c478bd9Sstevel@tonic-gate } 22507c478bd9Sstevel@tonic-gate } 22517c478bd9Sstevel@tonic-gate return (ret); 22527c478bd9Sstevel@tonic-gate } 22537c478bd9Sstevel@tonic-gate #endif /* FILTER_PACKETS */ 22547c478bd9Sstevel@tonic-gate 22557c478bd9Sstevel@tonic-gate /* 22567c478bd9Sstevel@tonic-gate * ccp_fatal_error() 22577c478bd9Sstevel@tonic-gate * 22587c478bd9Sstevel@tonic-gate * Returns 1 if decompression was disabled as a result of an error detected 22597c478bd9Sstevel@tonic-gate * after decompression of a packet, 0 otherwise. This is necessary because 22607c478bd9Sstevel@tonic-gate * of patent nonsense. 22617c478bd9Sstevel@tonic-gate */ 22627c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 22637c478bd9Sstevel@tonic-gate int 22647c478bd9Sstevel@tonic-gate ccp_fatal_error(unit) 22657c478bd9Sstevel@tonic-gate int unit; 22667c478bd9Sstevel@tonic-gate { 22677c478bd9Sstevel@tonic-gate uint32_t cf[2]; 22687c478bd9Sstevel@tonic-gate 22697c478bd9Sstevel@tonic-gate cf[0] = cf[1] = 0; 22707c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0])) 22717c478bd9Sstevel@tonic-gate < 0) { 22727c478bd9Sstevel@tonic-gate if (errno != ENXIO && errno != EINVAL) { 22737c478bd9Sstevel@tonic-gate error("Couldn't get compression flags: %m"); 22747c478bd9Sstevel@tonic-gate } 22757c478bd9Sstevel@tonic-gate return (0); 22767c478bd9Sstevel@tonic-gate } 22777c478bd9Sstevel@tonic-gate return (cf[0] & CCP_FATALERROR); 22787c478bd9Sstevel@tonic-gate } 22797c478bd9Sstevel@tonic-gate 22807c478bd9Sstevel@tonic-gate /* 22817c478bd9Sstevel@tonic-gate * sifvjcomp() 22827c478bd9Sstevel@tonic-gate * 22837c478bd9Sstevel@tonic-gate * Config TCP header compression. 22847c478bd9Sstevel@tonic-gate */ 22857c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 22867c478bd9Sstevel@tonic-gate int 22877c478bd9Sstevel@tonic-gate sifvjcomp(u, vjcomp, xcidcomp, xmaxcid) 22887c478bd9Sstevel@tonic-gate int u, vjcomp, xcidcomp, xmaxcid; 22897c478bd9Sstevel@tonic-gate { 22907c478bd9Sstevel@tonic-gate uint32_t cf[2]; 22917c478bd9Sstevel@tonic-gate uchar_t maxcid[2]; 22927c478bd9Sstevel@tonic-gate 22937c478bd9Sstevel@tonic-gate /* 22947c478bd9Sstevel@tonic-gate * Since VJ compression code is in the comp module, there's no 22957c478bd9Sstevel@tonic-gate * point of sending down any ioctls pertaining to VJ compression 22967c478bd9Sstevel@tonic-gate * when the module isn't pushed on the stream. 22977c478bd9Sstevel@tonic-gate */ 22987c478bd9Sstevel@tonic-gate if (!any_compressions()) { 22997c478bd9Sstevel@tonic-gate return (1); 23007c478bd9Sstevel@tonic-gate } 23017c478bd9Sstevel@tonic-gate 23027c478bd9Sstevel@tonic-gate if (vjcomp) { 23037c478bd9Sstevel@tonic-gate maxcid[0] = xcidcomp; 23047c478bd9Sstevel@tonic-gate maxcid[1] = 15; /* XXX should be rmaxcid */ 23057c478bd9Sstevel@tonic-gate 23067c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_VJINIT, maxcid, 23077c478bd9Sstevel@tonic-gate sizeof (maxcid), 0) < 0) { 23087c478bd9Sstevel@tonic-gate error("Couldn't initialize VJ compression: %m"); 23097c478bd9Sstevel@tonic-gate return (0); 23107c478bd9Sstevel@tonic-gate } 23117c478bd9Sstevel@tonic-gate } 23127c478bd9Sstevel@tonic-gate 23137c478bd9Sstevel@tonic-gate cf[0] = (vjcomp ? COMP_VJC + DECOMP_VJC : 0) /* XXX this is wrong */ 23147c478bd9Sstevel@tonic-gate + (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0); 23157c478bd9Sstevel@tonic-gate 23167c478bd9Sstevel@tonic-gate cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID; 23177c478bd9Sstevel@tonic-gate 23187c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0])) 23197c478bd9Sstevel@tonic-gate < 0) { 23207c478bd9Sstevel@tonic-gate if (vjcomp) { 23217c478bd9Sstevel@tonic-gate error("Couldn't enable VJ compression: %m"); 23227c478bd9Sstevel@tonic-gate } else { 23237c478bd9Sstevel@tonic-gate error("Couldn't disable VJ compression: %m"); 23247c478bd9Sstevel@tonic-gate } 23257c478bd9Sstevel@tonic-gate return (0); 23267c478bd9Sstevel@tonic-gate } 23277c478bd9Sstevel@tonic-gate return (1); 23287c478bd9Sstevel@tonic-gate } 23297c478bd9Sstevel@tonic-gate 23307c478bd9Sstevel@tonic-gate /* 23317c478bd9Sstevel@tonic-gate * siflags() 23327c478bd9Sstevel@tonic-gate * 23337c478bd9Sstevel@tonic-gate * Set or clear the IP interface flags. 23347c478bd9Sstevel@tonic-gate */ 23357c478bd9Sstevel@tonic-gate int 23367c478bd9Sstevel@tonic-gate siflags(f, set) 23377c478bd9Sstevel@tonic-gate u_int32_t f; 23387c478bd9Sstevel@tonic-gate int set; 23397c478bd9Sstevel@tonic-gate { 23407c478bd9Sstevel@tonic-gate struct ifreq ifr; 23417c478bd9Sstevel@tonic-gate 23427c478bd9Sstevel@tonic-gate if (!IPCP_ENABLED || (ipmuxid == -1)) { 23437c478bd9Sstevel@tonic-gate return (0); 23447c478bd9Sstevel@tonic-gate } 23457c478bd9Sstevel@tonic-gate if (ipfd == -1 && open_ipfd() == -1) 23467c478bd9Sstevel@tonic-gate return (0); 23477c478bd9Sstevel@tonic-gate BZERO(&ifr, sizeof (ifr)); 23487c478bd9Sstevel@tonic-gate (void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 23497c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) { 23507c478bd9Sstevel@tonic-gate error("Couldn't get IP interface flags: %m"); 23517c478bd9Sstevel@tonic-gate return (0); 23527c478bd9Sstevel@tonic-gate } 23537c478bd9Sstevel@tonic-gate if (set) { 23547c478bd9Sstevel@tonic-gate ifr.ifr_flags |= f; 23557c478bd9Sstevel@tonic-gate } else { 23567c478bd9Sstevel@tonic-gate ifr.ifr_flags &= ~f; 23577c478bd9Sstevel@tonic-gate } 23587c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) { 23597c478bd9Sstevel@tonic-gate error("Couldn't set IP interface flags: %m"); 23607c478bd9Sstevel@tonic-gate return (0); 23617c478bd9Sstevel@tonic-gate } 23627c478bd9Sstevel@tonic-gate return (1); 23637c478bd9Sstevel@tonic-gate } 23647c478bd9Sstevel@tonic-gate 23657c478bd9Sstevel@tonic-gate /* 23667c478bd9Sstevel@tonic-gate * sifup() 23677c478bd9Sstevel@tonic-gate * 23687c478bd9Sstevel@tonic-gate * Config the interface up and enable IP packets to pass. 23697c478bd9Sstevel@tonic-gate */ 23707c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 23717c478bd9Sstevel@tonic-gate int 23727c478bd9Sstevel@tonic-gate sifup(u) 23737c478bd9Sstevel@tonic-gate int u; 23747c478bd9Sstevel@tonic-gate { 23757c478bd9Sstevel@tonic-gate if (if_is_up) { 23767c478bd9Sstevel@tonic-gate return (1); 23777c478bd9Sstevel@tonic-gate } else if (!IPCP_ENABLED) { 23787c478bd9Sstevel@tonic-gate warn("sifup called when IPCP is disabled"); 23797c478bd9Sstevel@tonic-gate return (0); 23807c478bd9Sstevel@tonic-gate } else if (ipmuxid == -1) { 23817c478bd9Sstevel@tonic-gate warn("sifup called in wrong state"); 23827c478bd9Sstevel@tonic-gate return (0); 23837c478bd9Sstevel@tonic-gate } else if (!siflags(IFF_UP, 1)) { 23847c478bd9Sstevel@tonic-gate error("Unable to mark the IP interface UP"); 23857c478bd9Sstevel@tonic-gate return (0); 23867c478bd9Sstevel@tonic-gate } 23877c478bd9Sstevel@tonic-gate if_is_up = 1; 23887c478bd9Sstevel@tonic-gate return (1); 23897c478bd9Sstevel@tonic-gate } 23907c478bd9Sstevel@tonic-gate 23917c478bd9Sstevel@tonic-gate /* 23927c478bd9Sstevel@tonic-gate * sifdown() 23937c478bd9Sstevel@tonic-gate * 23947c478bd9Sstevel@tonic-gate * Config the interface down and disable IP. Possibly called from die(), 23957c478bd9Sstevel@tonic-gate * so there shouldn't be any call to die() here. 23967c478bd9Sstevel@tonic-gate */ 23977c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 23987c478bd9Sstevel@tonic-gate int 23997c478bd9Sstevel@tonic-gate sifdown(u) 24007c478bd9Sstevel@tonic-gate int u; 24017c478bd9Sstevel@tonic-gate { 24027c478bd9Sstevel@tonic-gate if (!IPCP_ENABLED) { 24037c478bd9Sstevel@tonic-gate warn("sifdown called when IPCP is disabled"); 24047c478bd9Sstevel@tonic-gate return (0); 24057c478bd9Sstevel@tonic-gate } else if (!if_is_up || (ipmuxid == -1)) { 24067c478bd9Sstevel@tonic-gate return (1); 24077c478bd9Sstevel@tonic-gate } else if (!siflags(IFF_UP, 0)) { 24087c478bd9Sstevel@tonic-gate error("Unable to mark the IP interface DOWN"); 24097c478bd9Sstevel@tonic-gate return (0); 24107c478bd9Sstevel@tonic-gate } 24117c478bd9Sstevel@tonic-gate if_is_up = 0; 24127c478bd9Sstevel@tonic-gate return (1); 24137c478bd9Sstevel@tonic-gate } 24147c478bd9Sstevel@tonic-gate 24157c478bd9Sstevel@tonic-gate /* 24167c478bd9Sstevel@tonic-gate * sifnpmode() 24177c478bd9Sstevel@tonic-gate * 24187c478bd9Sstevel@tonic-gate * Set the mode for handling packets for a given NP. Not worried 24197c478bd9Sstevel@tonic-gate * about performance here since this is done only rarely. 24207c478bd9Sstevel@tonic-gate */ 24217c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 24227c478bd9Sstevel@tonic-gate int 24237c478bd9Sstevel@tonic-gate sifnpmode(u, proto, mode) 24247c478bd9Sstevel@tonic-gate int u; 24257c478bd9Sstevel@tonic-gate int proto; 24267c478bd9Sstevel@tonic-gate enum NPmode mode; 24277c478bd9Sstevel@tonic-gate { 24287c478bd9Sstevel@tonic-gate uint32_t npi[2]; 24297c478bd9Sstevel@tonic-gate const char *cp; 24307c478bd9Sstevel@tonic-gate static const struct npi_entry { 24317c478bd9Sstevel@tonic-gate enum NPmode ne_value; 24327c478bd9Sstevel@tonic-gate const char *ne_name; 24337c478bd9Sstevel@tonic-gate } npi_list[] = { 24347c478bd9Sstevel@tonic-gate { NPMODE_PASS, "pass" }, 24357c478bd9Sstevel@tonic-gate { NPMODE_DROP, "drop" }, 24367c478bd9Sstevel@tonic-gate { NPMODE_ERROR, "error" }, 24377c478bd9Sstevel@tonic-gate { NPMODE_QUEUE, "queue" }, 24387c478bd9Sstevel@tonic-gate }; 24397c478bd9Sstevel@tonic-gate int i; 24407c478bd9Sstevel@tonic-gate char pname[32], mname[32]; 24417c478bd9Sstevel@tonic-gate 24427c478bd9Sstevel@tonic-gate npi[0] = proto; 24437c478bd9Sstevel@tonic-gate npi[1] = (uint32_t)mode; 24447c478bd9Sstevel@tonic-gate 24457c478bd9Sstevel@tonic-gate cp = protocol_name(proto); 24467c478bd9Sstevel@tonic-gate if (cp == NULL) 24477c478bd9Sstevel@tonic-gate (void) slprintf(pname, sizeof (pname), "NP %04X", proto); 24487c478bd9Sstevel@tonic-gate else 24497c478bd9Sstevel@tonic-gate (void) strlcpy(pname, cp, sizeof (pname)); 24507c478bd9Sstevel@tonic-gate for (i = 0; i < Dim(npi_list); i++) 24517c478bd9Sstevel@tonic-gate if (npi_list[i].ne_value == mode) 24527c478bd9Sstevel@tonic-gate break; 24537c478bd9Sstevel@tonic-gate if (i >= Dim(npi_list)) 24547c478bd9Sstevel@tonic-gate (void) slprintf(mname, sizeof (mname), "mode %d", (int)mode); 24557c478bd9Sstevel@tonic-gate else 24567c478bd9Sstevel@tonic-gate (void) strlcpy(mname, npi_list[i].ne_name, sizeof (mname)); 24577c478bd9Sstevel@tonic-gate 24587c478bd9Sstevel@tonic-gate if ((proto == PPP_IP && !if_is_up) || 24597c478bd9Sstevel@tonic-gate (proto == PPP_IPV6 && !if6_is_up)) { 24607c478bd9Sstevel@tonic-gate dbglog("ignoring request to set %s to %s", pname, mname); 24617c478bd9Sstevel@tonic-gate return (1); 24627c478bd9Sstevel@tonic-gate } 24637c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_NPMODE, npi, sizeof (npi), 0) < 0) { 24647c478bd9Sstevel@tonic-gate error("unable to set %s to %s: %m", pname, mname); 24657c478bd9Sstevel@tonic-gate return (0); 24667c478bd9Sstevel@tonic-gate } 24677c478bd9Sstevel@tonic-gate return (1); 24687c478bd9Sstevel@tonic-gate } 24697c478bd9Sstevel@tonic-gate 24707c478bd9Sstevel@tonic-gate /* 24717c478bd9Sstevel@tonic-gate * sifmtu() 24727c478bd9Sstevel@tonic-gate * 24737c478bd9Sstevel@tonic-gate * Config the interface IP MTU. 24747c478bd9Sstevel@tonic-gate */ 24757c478bd9Sstevel@tonic-gate int 24767c478bd9Sstevel@tonic-gate sifmtu(mtu) 24777c478bd9Sstevel@tonic-gate int mtu; 24787c478bd9Sstevel@tonic-gate { 24797c478bd9Sstevel@tonic-gate struct ifreq ifr; 24807c478bd9Sstevel@tonic-gate 24817c478bd9Sstevel@tonic-gate if (!IPCP_ENABLED || (ipmuxid == -1)) { 24827c478bd9Sstevel@tonic-gate return (0); 24837c478bd9Sstevel@tonic-gate } 24847c478bd9Sstevel@tonic-gate if (ipfd == -1 && open_ipfd() == -1) 24857c478bd9Sstevel@tonic-gate return (0); 24867c478bd9Sstevel@tonic-gate BZERO(&ifr, sizeof (ifr)); 24877c478bd9Sstevel@tonic-gate (void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 24887c478bd9Sstevel@tonic-gate ifr.ifr_metric = mtu; 24897c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCSIFMTU, &ifr) < 0) { 24907c478bd9Sstevel@tonic-gate error("Couldn't set IP MTU on %s to %d: %m", ifr.ifr_name, 24917c478bd9Sstevel@tonic-gate mtu); 24927c478bd9Sstevel@tonic-gate return (0); 24937c478bd9Sstevel@tonic-gate } 24947c478bd9Sstevel@tonic-gate return (1); 24957c478bd9Sstevel@tonic-gate } 24967c478bd9Sstevel@tonic-gate 24977c478bd9Sstevel@tonic-gate /* 24987c478bd9Sstevel@tonic-gate * sifaddr() 24997c478bd9Sstevel@tonic-gate * 25007c478bd9Sstevel@tonic-gate * Config the interface IP addresses and netmask. 25017c478bd9Sstevel@tonic-gate */ 25027c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 25037c478bd9Sstevel@tonic-gate int 25047c478bd9Sstevel@tonic-gate sifaddr(u, o, h, m) 25057c478bd9Sstevel@tonic-gate int u; 25067c478bd9Sstevel@tonic-gate u_int32_t o; 25077c478bd9Sstevel@tonic-gate u_int32_t h; 25087c478bd9Sstevel@tonic-gate u_int32_t m; 25097c478bd9Sstevel@tonic-gate { 25107c478bd9Sstevel@tonic-gate struct ifreq ifr; 25117c478bd9Sstevel@tonic-gate struct sockaddr_in sin; 25127c478bd9Sstevel@tonic-gate 25137c478bd9Sstevel@tonic-gate if (!IPCP_ENABLED || (ipmuxid == -1 && plumb_ipif(u) == 0)) { 25147c478bd9Sstevel@tonic-gate return (0); 25157c478bd9Sstevel@tonic-gate } 25167c478bd9Sstevel@tonic-gate if (ipfd == -1 && open_ipfd() == -1) 25177c478bd9Sstevel@tonic-gate return (0); 25187c478bd9Sstevel@tonic-gate /* 25197c478bd9Sstevel@tonic-gate * Set the IP interface MTU. 25207c478bd9Sstevel@tonic-gate */ 25217c478bd9Sstevel@tonic-gate if (!sifmtu(link_mtu)) { 25227c478bd9Sstevel@tonic-gate return (0); 25237c478bd9Sstevel@tonic-gate } 25247c478bd9Sstevel@tonic-gate /* 25257c478bd9Sstevel@tonic-gate * Set the IP interface local point-to-point address. 25267c478bd9Sstevel@tonic-gate */ 25277c478bd9Sstevel@tonic-gate BZERO(&sin, sizeof (sin)); 25287c478bd9Sstevel@tonic-gate sin.sin_family = AF_INET; 25297c478bd9Sstevel@tonic-gate sin.sin_addr.s_addr = o; 25307c478bd9Sstevel@tonic-gate 25317c478bd9Sstevel@tonic-gate BZERO(&ifr, sizeof (ifr)); 25327c478bd9Sstevel@tonic-gate (void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 25337c478bd9Sstevel@tonic-gate ifr.ifr_addr = *(struct sockaddr *)&sin; 25347c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCSIFADDR, &ifr) < 0) { 25357c478bd9Sstevel@tonic-gate error("Couldn't set local IP address (%s): %m", ifr.ifr_name); 25367c478bd9Sstevel@tonic-gate return (0); 25377c478bd9Sstevel@tonic-gate } 25387c478bd9Sstevel@tonic-gate /* 25397c478bd9Sstevel@tonic-gate * Set the IP interface remote point-to-point address. 25407c478bd9Sstevel@tonic-gate */ 25417c478bd9Sstevel@tonic-gate sin.sin_addr.s_addr = h; 25427c478bd9Sstevel@tonic-gate 25437c478bd9Sstevel@tonic-gate ifr.ifr_dstaddr = *(struct sockaddr *)&sin; 25447c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCSIFDSTADDR, &ifr) < 0) { 25457c478bd9Sstevel@tonic-gate error("Couldn't set remote IP address (%s): %m", ifr.ifr_name); 25467c478bd9Sstevel@tonic-gate return (0); 25477c478bd9Sstevel@tonic-gate } 25487c478bd9Sstevel@tonic-gate remote_addr = h; 25497c478bd9Sstevel@tonic-gate return (1); 25507c478bd9Sstevel@tonic-gate } 25517c478bd9Sstevel@tonic-gate 25527c478bd9Sstevel@tonic-gate /* 25537c478bd9Sstevel@tonic-gate * cifaddr() 25547c478bd9Sstevel@tonic-gate * 25557c478bd9Sstevel@tonic-gate * Clear the interface IP addresses. 25567c478bd9Sstevel@tonic-gate */ 25577c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 25587c478bd9Sstevel@tonic-gate int 25597c478bd9Sstevel@tonic-gate cifaddr(u, o, h) 25607c478bd9Sstevel@tonic-gate int u; 25617c478bd9Sstevel@tonic-gate u_int32_t o; 25627c478bd9Sstevel@tonic-gate u_int32_t h; 25637c478bd9Sstevel@tonic-gate { 25647c478bd9Sstevel@tonic-gate if (!IPCP_ENABLED) { 25657c478bd9Sstevel@tonic-gate return (0); 25667c478bd9Sstevel@tonic-gate } 25677c478bd9Sstevel@tonic-gate /* 25687c478bd9Sstevel@tonic-gate * Most of the work is done in sifdown(). 25697c478bd9Sstevel@tonic-gate */ 25707c478bd9Sstevel@tonic-gate remote_addr = 0; 25717c478bd9Sstevel@tonic-gate return (1); 25727c478bd9Sstevel@tonic-gate } 25737c478bd9Sstevel@tonic-gate 25747c478bd9Sstevel@tonic-gate /* 25757c478bd9Sstevel@tonic-gate * sifroute() 25767c478bd9Sstevel@tonic-gate * 25777c478bd9Sstevel@tonic-gate * Add or delete a route. 25787c478bd9Sstevel@tonic-gate */ 25797c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 25807c478bd9Sstevel@tonic-gate static int 25817c478bd9Sstevel@tonic-gate sifroute(int u, u_int32_t l, u_int32_t g, int add, const char *str) 25827c478bd9Sstevel@tonic-gate { 25837c478bd9Sstevel@tonic-gate struct sockaddr_in sin_dst, sin_gtw; 25847c478bd9Sstevel@tonic-gate struct rtentry rt; 25857c478bd9Sstevel@tonic-gate 25867c478bd9Sstevel@tonic-gate if (!IPCP_ENABLED || (ipmuxid == -1)) { 25877c478bd9Sstevel@tonic-gate error("Can't %s route: IP is not enabled", str); 25887c478bd9Sstevel@tonic-gate return (0); 25897c478bd9Sstevel@tonic-gate } 25907c478bd9Sstevel@tonic-gate if (ipfd == -1 && open_ipfd() == -1) 25917c478bd9Sstevel@tonic-gate return (0); 25927c478bd9Sstevel@tonic-gate 25937c478bd9Sstevel@tonic-gate BZERO(&sin_dst, sizeof (sin_dst)); 25947c478bd9Sstevel@tonic-gate sin_dst.sin_family = AF_INET; 25957c478bd9Sstevel@tonic-gate sin_dst.sin_addr.s_addr = l; 25967c478bd9Sstevel@tonic-gate 25977c478bd9Sstevel@tonic-gate BZERO(&sin_gtw, sizeof (sin_gtw)); 25987c478bd9Sstevel@tonic-gate sin_gtw.sin_family = AF_INET; 25997c478bd9Sstevel@tonic-gate sin_gtw.sin_addr.s_addr = g; 26007c478bd9Sstevel@tonic-gate 26017c478bd9Sstevel@tonic-gate BZERO(&rt, sizeof (rt)); 26027c478bd9Sstevel@tonic-gate rt.rt_dst = *(struct sockaddr *)&sin_dst; 26037c478bd9Sstevel@tonic-gate rt.rt_gateway = *(struct sockaddr *)&sin_gtw; 26047c478bd9Sstevel@tonic-gate rt.rt_flags = (RTF_GATEWAY|RTF_STATIC); 26057c478bd9Sstevel@tonic-gate 26067c478bd9Sstevel@tonic-gate if (myioctl(ipfd, (add ? SIOCADDRT : SIOCDELRT), &rt) < 0) { 26077c478bd9Sstevel@tonic-gate error("Can't %s route: %m", str); 26087c478bd9Sstevel@tonic-gate return (0); 26097c478bd9Sstevel@tonic-gate } 26107c478bd9Sstevel@tonic-gate return (1); 26117c478bd9Sstevel@tonic-gate } 26127c478bd9Sstevel@tonic-gate 26137c478bd9Sstevel@tonic-gate /* 26147c478bd9Sstevel@tonic-gate * sifdefaultroute() 26157c478bd9Sstevel@tonic-gate * 26167c478bd9Sstevel@tonic-gate * Assign a default route through the address given. 26177c478bd9Sstevel@tonic-gate */ 26187c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 26197c478bd9Sstevel@tonic-gate int 26207c478bd9Sstevel@tonic-gate sifdefaultroute(u, l, g) 26217c478bd9Sstevel@tonic-gate int u; 26227c478bd9Sstevel@tonic-gate u_int32_t l; 26237c478bd9Sstevel@tonic-gate u_int32_t g; 26247c478bd9Sstevel@tonic-gate { 26257c478bd9Sstevel@tonic-gate if (!sifroute(u, 0, g, 1, "add default")) { 26267c478bd9Sstevel@tonic-gate return (0); 26277c478bd9Sstevel@tonic-gate } 26287c478bd9Sstevel@tonic-gate default_route_gateway = g; 26297c478bd9Sstevel@tonic-gate return (1); 26307c478bd9Sstevel@tonic-gate } 26317c478bd9Sstevel@tonic-gate 26327c478bd9Sstevel@tonic-gate /* 26337c478bd9Sstevel@tonic-gate * cifdefaultroute() 26347c478bd9Sstevel@tonic-gate * 26357c478bd9Sstevel@tonic-gate * Delete a default route through the address given. 26367c478bd9Sstevel@tonic-gate */ 26377c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 26387c478bd9Sstevel@tonic-gate int 26397c478bd9Sstevel@tonic-gate cifdefaultroute(u, l, g) 26407c478bd9Sstevel@tonic-gate int u; 26417c478bd9Sstevel@tonic-gate u_int32_t l; 26427c478bd9Sstevel@tonic-gate u_int32_t g; 26437c478bd9Sstevel@tonic-gate { 26447c478bd9Sstevel@tonic-gate if (!sifroute(u, 0, g, 0, "delete default")) { 26457c478bd9Sstevel@tonic-gate return (0); 26467c478bd9Sstevel@tonic-gate } 26477c478bd9Sstevel@tonic-gate default_route_gateway = 0; 26487c478bd9Sstevel@tonic-gate return (1); 26497c478bd9Sstevel@tonic-gate } 26507c478bd9Sstevel@tonic-gate 26517c478bd9Sstevel@tonic-gate /* 26527c478bd9Sstevel@tonic-gate * sifproxyarp() 26537c478bd9Sstevel@tonic-gate * 26547c478bd9Sstevel@tonic-gate * Make a proxy ARP entry for the peer. 26557c478bd9Sstevel@tonic-gate */ 26567c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 26577c478bd9Sstevel@tonic-gate int 26587c478bd9Sstevel@tonic-gate sifproxyarp(unit, hisaddr, quietflag) 26597c478bd9Sstevel@tonic-gate int unit; 26607c478bd9Sstevel@tonic-gate u_int32_t hisaddr; 26617c478bd9Sstevel@tonic-gate int quietflag; 26627c478bd9Sstevel@tonic-gate { 26637c478bd9Sstevel@tonic-gate struct sockaddr_in sin; 26647c478bd9Sstevel@tonic-gate struct xarpreq arpreq; 26657c478bd9Sstevel@tonic-gate const uchar_t *cp; 26667c478bd9Sstevel@tonic-gate char *str = NULL; 26677c478bd9Sstevel@tonic-gate 26687c478bd9Sstevel@tonic-gate if (!IPCP_ENABLED || (ipmuxid == -1)) { 26697c478bd9Sstevel@tonic-gate return (0); 26707c478bd9Sstevel@tonic-gate } 26717c478bd9Sstevel@tonic-gate if (ipfd == -1 && open_ipfd() == -1) 26727c478bd9Sstevel@tonic-gate return (0); 26737c478bd9Sstevel@tonic-gate 26747c478bd9Sstevel@tonic-gate BZERO(&sin, sizeof (sin)); 26757c478bd9Sstevel@tonic-gate sin.sin_family = AF_INET; 26767c478bd9Sstevel@tonic-gate sin.sin_addr.s_addr = hisaddr; 26777c478bd9Sstevel@tonic-gate 26787c478bd9Sstevel@tonic-gate BZERO(&arpreq, sizeof (arpreq)); 26797c478bd9Sstevel@tonic-gate if (!get_ether_addr(hisaddr, &arpreq.xarp_ha, quietflag)) { 26807c478bd9Sstevel@tonic-gate return (0); 26817c478bd9Sstevel@tonic-gate } 26827c478bd9Sstevel@tonic-gate BCOPY(&sin, &arpreq.xarp_pa, sizeof (sin)); 26837c478bd9Sstevel@tonic-gate arpreq.xarp_flags = ATF_PERM | ATF_PUBL; 26847c478bd9Sstevel@tonic-gate arpreq.xarp_ha.sdl_family = AF_LINK; 26857c478bd9Sstevel@tonic-gate 26867c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCSXARP, (caddr_t)&arpreq) < 0) { 26877c478bd9Sstevel@tonic-gate if (!quietflag) 26887c478bd9Sstevel@tonic-gate error("Couldn't set proxy ARP entry: %m"); 26897c478bd9Sstevel@tonic-gate return (0); 26907c478bd9Sstevel@tonic-gate } 26917c478bd9Sstevel@tonic-gate cp = (const uchar_t *)LLADDR(&arpreq.xarp_ha); 26927c478bd9Sstevel@tonic-gate str = _link_ntoa(cp, str, arpreq.xarp_ha.sdl_alen, IFT_OTHER); 26937c478bd9Sstevel@tonic-gate if (str != NULL) { 26947c478bd9Sstevel@tonic-gate dbglog("established proxy ARP for %I using %s", hisaddr, 26957c478bd9Sstevel@tonic-gate str); 26967c478bd9Sstevel@tonic-gate free(str); 26977c478bd9Sstevel@tonic-gate } 26987c478bd9Sstevel@tonic-gate proxy_arp_addr = hisaddr; 26997c478bd9Sstevel@tonic-gate return (1); 27007c478bd9Sstevel@tonic-gate } 27017c478bd9Sstevel@tonic-gate 27027c478bd9Sstevel@tonic-gate /* 27037c478bd9Sstevel@tonic-gate * cifproxyarp() 27047c478bd9Sstevel@tonic-gate * 27057c478bd9Sstevel@tonic-gate * Delete the proxy ARP entry for the peer. 27067c478bd9Sstevel@tonic-gate */ 27077c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 27087c478bd9Sstevel@tonic-gate int 27097c478bd9Sstevel@tonic-gate cifproxyarp(unit, hisaddr) 27107c478bd9Sstevel@tonic-gate int unit; 27117c478bd9Sstevel@tonic-gate u_int32_t hisaddr; 27127c478bd9Sstevel@tonic-gate { 27137c478bd9Sstevel@tonic-gate struct sockaddr_in sin; 27147c478bd9Sstevel@tonic-gate struct xarpreq arpreq; 27157c478bd9Sstevel@tonic-gate 27167c478bd9Sstevel@tonic-gate if (!IPCP_ENABLED || (ipmuxid == -1)) { 27177c478bd9Sstevel@tonic-gate return (0); 27187c478bd9Sstevel@tonic-gate } 27197c478bd9Sstevel@tonic-gate if (ipfd == -1 && open_ipfd() == -1) 27207c478bd9Sstevel@tonic-gate return (0); 27217c478bd9Sstevel@tonic-gate 27227c478bd9Sstevel@tonic-gate BZERO(&sin, sizeof (sin)); 27237c478bd9Sstevel@tonic-gate sin.sin_family = AF_INET; 27247c478bd9Sstevel@tonic-gate sin.sin_addr.s_addr = hisaddr; 27257c478bd9Sstevel@tonic-gate 27267c478bd9Sstevel@tonic-gate BZERO(&arpreq, sizeof (arpreq)); 27277c478bd9Sstevel@tonic-gate BCOPY(&sin, &arpreq.xarp_pa, sizeof (sin)); 27287c478bd9Sstevel@tonic-gate arpreq.xarp_ha.sdl_family = AF_LINK; 27297c478bd9Sstevel@tonic-gate 27307c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCDXARP, (caddr_t)&arpreq) < 0) { 27317c478bd9Sstevel@tonic-gate error("Couldn't delete proxy ARP entry: %m"); 27327c478bd9Sstevel@tonic-gate return (0); 27337c478bd9Sstevel@tonic-gate } 27347c478bd9Sstevel@tonic-gate proxy_arp_addr = 0; 27357c478bd9Sstevel@tonic-gate return (1); 27367c478bd9Sstevel@tonic-gate } 27377c478bd9Sstevel@tonic-gate 27387c478bd9Sstevel@tonic-gate /* 27397c478bd9Sstevel@tonic-gate * get_ether_addr() 27407c478bd9Sstevel@tonic-gate * 27417c478bd9Sstevel@tonic-gate * Get the hardware address of an interface on the the same subnet as 27427c478bd9Sstevel@tonic-gate * ipaddr. This routine uses old-style interfaces for intentional 27437c478bd9Sstevel@tonic-gate * backward compatibility -- SIOCGLIF* isn't in older Solaris 27447c478bd9Sstevel@tonic-gate * releases. 27457c478bd9Sstevel@tonic-gate */ 27467c478bd9Sstevel@tonic-gate static int 27477c478bd9Sstevel@tonic-gate get_ether_addr(u_int32_t ipaddr, struct sockaddr_dl *hwaddr, int quietflag) 27487c478bd9Sstevel@tonic-gate { 27497c478bd9Sstevel@tonic-gate struct ifreq *ifr, *ifend, ifreq; 27507c478bd9Sstevel@tonic-gate int nif, s, retv; 27517c478bd9Sstevel@tonic-gate struct ifconf ifc; 27527c478bd9Sstevel@tonic-gate u_int32_t ina, mask; 27537c478bd9Sstevel@tonic-gate struct xarpreq req; 27547c478bd9Sstevel@tonic-gate struct sockaddr_in sin; 27557c478bd9Sstevel@tonic-gate 27567c478bd9Sstevel@tonic-gate if (ipfd == -1 && open_ipfd() == -1) 27577c478bd9Sstevel@tonic-gate return (0); 27587c478bd9Sstevel@tonic-gate 27597c478bd9Sstevel@tonic-gate /* 27607c478bd9Sstevel@tonic-gate * Scan through the system's network interfaces. 27617c478bd9Sstevel@tonic-gate */ 27627c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCGIFNUM, &nif) < 0) { 27637c478bd9Sstevel@tonic-gate nif = MAXIFS; 27647c478bd9Sstevel@tonic-gate } 27657c478bd9Sstevel@tonic-gate if (nif <= 0) 27667c478bd9Sstevel@tonic-gate return (0); 27677c478bd9Sstevel@tonic-gate ifc.ifc_len = nif * sizeof (struct ifreq); 27687c478bd9Sstevel@tonic-gate ifc.ifc_buf = (caddr_t)malloc(ifc.ifc_len); 27697c478bd9Sstevel@tonic-gate if (ifc.ifc_buf == NULL) { 27707c478bd9Sstevel@tonic-gate return (0); 27717c478bd9Sstevel@tonic-gate } 27727c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCGIFCONF, &ifc) < 0) { 27737c478bd9Sstevel@tonic-gate error("Couldn't get system interface list: %m"); 27747c478bd9Sstevel@tonic-gate free(ifc.ifc_buf); 27757c478bd9Sstevel@tonic-gate return (0); 27767c478bd9Sstevel@tonic-gate } 27777c478bd9Sstevel@tonic-gate /* LINTED */ 27787c478bd9Sstevel@tonic-gate ifend = (struct ifreq *)(ifc.ifc_buf + ifc.ifc_len); 27797c478bd9Sstevel@tonic-gate for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) { 27807c478bd9Sstevel@tonic-gate if (ifr->ifr_addr.sa_family != AF_INET) { 27817c478bd9Sstevel@tonic-gate continue; 27827c478bd9Sstevel@tonic-gate } 27837c478bd9Sstevel@tonic-gate /* 27847c478bd9Sstevel@tonic-gate * Check that the interface is up, and not 27857c478bd9Sstevel@tonic-gate * point-to-point or loopback. 27867c478bd9Sstevel@tonic-gate */ 27877c478bd9Sstevel@tonic-gate (void) strlcpy(ifreq.ifr_name, ifr->ifr_name, 2788fb60e41dSss sizeof (ifreq.ifr_name)); 27897c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0) { 27907c478bd9Sstevel@tonic-gate continue; 27917c478bd9Sstevel@tonic-gate } 27927c478bd9Sstevel@tonic-gate if ((ifreq.ifr_flags & (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT| 27937c478bd9Sstevel@tonic-gate IFF_LOOPBACK|IFF_NOARP)) != (IFF_UP|IFF_BROADCAST)) { 27947c478bd9Sstevel@tonic-gate continue; 27957c478bd9Sstevel@tonic-gate } 27967c478bd9Sstevel@tonic-gate /* 27977c478bd9Sstevel@tonic-gate * Get its netmask and check that it's on the right subnet. 27987c478bd9Sstevel@tonic-gate */ 27997c478bd9Sstevel@tonic-gate if (myioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0) { 28007c478bd9Sstevel@tonic-gate continue; 28017c478bd9Sstevel@tonic-gate } 28027c478bd9Sstevel@tonic-gate (void) memcpy(&sin, &ifr->ifr_addr, sizeof (sin)); 28037c478bd9Sstevel@tonic-gate ina = sin.sin_addr.s_addr; 28047c478bd9Sstevel@tonic-gate (void) memcpy(&sin, &ifreq.ifr_addr, sizeof (sin)); 28057c478bd9Sstevel@tonic-gate mask = sin.sin_addr.s_addr; 28067c478bd9Sstevel@tonic-gate if ((ipaddr & mask) == (ina & mask)) { 28077c478bd9Sstevel@tonic-gate break; 28087c478bd9Sstevel@tonic-gate } 28097c478bd9Sstevel@tonic-gate } 28107c478bd9Sstevel@tonic-gate if (ifr >= ifend) { 28117c478bd9Sstevel@tonic-gate if (!quietflag) 28127c478bd9Sstevel@tonic-gate warn("No suitable interface found for proxy ARP of %I", 28137c478bd9Sstevel@tonic-gate ipaddr); 28147c478bd9Sstevel@tonic-gate free(ifc.ifc_buf); 28157c478bd9Sstevel@tonic-gate return (0); 28167c478bd9Sstevel@tonic-gate } 28177c478bd9Sstevel@tonic-gate info("found interface %s for proxy ARP of %I", ifr->ifr_name, ipaddr); 28187c478bd9Sstevel@tonic-gate 28197c478bd9Sstevel@tonic-gate /* 28207c478bd9Sstevel@tonic-gate * New way - get the address by doing an arp request. 28217c478bd9Sstevel@tonic-gate */ 28227c478bd9Sstevel@tonic-gate s = socket(AF_INET, SOCK_DGRAM, 0); 28237c478bd9Sstevel@tonic-gate if (s < 0) { 28247c478bd9Sstevel@tonic-gate error("get_ether_addr: error opening IP socket: %m"); 28257c478bd9Sstevel@tonic-gate free(ifc.ifc_buf); 28267c478bd9Sstevel@tonic-gate return (0); 28277c478bd9Sstevel@tonic-gate } 28287c478bd9Sstevel@tonic-gate BZERO(&sin, sizeof (sin)); 28297c478bd9Sstevel@tonic-gate sin.sin_family = AF_INET; 28307c478bd9Sstevel@tonic-gate sin.sin_addr.s_addr = ina; 28317c478bd9Sstevel@tonic-gate 28327c478bd9Sstevel@tonic-gate BZERO(&req, sizeof (req)); 28337c478bd9Sstevel@tonic-gate BCOPY(&sin, &req.xarp_pa, sizeof (sin)); 28347c478bd9Sstevel@tonic-gate req.xarp_ha.sdl_family = AF_LINK; 28357c478bd9Sstevel@tonic-gate 28367c478bd9Sstevel@tonic-gate if (myioctl(s, SIOCGXARP, &req) < 0) { 28377c478bd9Sstevel@tonic-gate error("Couldn't get ARP entry for %I: %m", ina); 28387c478bd9Sstevel@tonic-gate retv = 0; 28397c478bd9Sstevel@tonic-gate } else { 28407c478bd9Sstevel@tonic-gate (void) memcpy(hwaddr, &req.xarp_ha, 28417c478bd9Sstevel@tonic-gate sizeof (struct sockaddr_dl)); 28427c478bd9Sstevel@tonic-gate retv = 1; 28437c478bd9Sstevel@tonic-gate } 28447c478bd9Sstevel@tonic-gate (void) close(s); 28457c478bd9Sstevel@tonic-gate free(ifc.ifc_buf); 28467c478bd9Sstevel@tonic-gate return (retv); 28477c478bd9Sstevel@tonic-gate } 28487c478bd9Sstevel@tonic-gate 28497c478bd9Sstevel@tonic-gate /* 28507c478bd9Sstevel@tonic-gate * GetMask() 28517c478bd9Sstevel@tonic-gate * 28527c478bd9Sstevel@tonic-gate * Return mask (bogus, but needed for compatibility with other platforms). 28537c478bd9Sstevel@tonic-gate */ 28547c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 28557c478bd9Sstevel@tonic-gate u_int32_t 28567c478bd9Sstevel@tonic-gate GetMask(addr) 28577c478bd9Sstevel@tonic-gate u_int32_t addr; 28587c478bd9Sstevel@tonic-gate { 28597c478bd9Sstevel@tonic-gate return (0xffffffffUL); 28607c478bd9Sstevel@tonic-gate } 28617c478bd9Sstevel@tonic-gate 28627c478bd9Sstevel@tonic-gate /* 28637c478bd9Sstevel@tonic-gate * logwtmp() 28647c478bd9Sstevel@tonic-gate * 28657c478bd9Sstevel@tonic-gate * Write an accounting record to the /var/adm/wtmp file. 28667c478bd9Sstevel@tonic-gate */ 28677c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 28687c478bd9Sstevel@tonic-gate void 28697c478bd9Sstevel@tonic-gate logwtmp(line, name, host) 28707c478bd9Sstevel@tonic-gate const char *line; 28717c478bd9Sstevel@tonic-gate const char *name; 28727c478bd9Sstevel@tonic-gate const char *host; 28737c478bd9Sstevel@tonic-gate { 28747c478bd9Sstevel@tonic-gate static struct utmpx utmpx; 28757c478bd9Sstevel@tonic-gate 28767c478bd9Sstevel@tonic-gate if (name[0] != '\0') { 28777c478bd9Sstevel@tonic-gate /* 28787c478bd9Sstevel@tonic-gate * logging in 28797c478bd9Sstevel@tonic-gate */ 28807c478bd9Sstevel@tonic-gate (void) strncpy(utmpx.ut_user, name, sizeof (utmpx.ut_user)); 28817c478bd9Sstevel@tonic-gate (void) strncpy(utmpx.ut_id, ifname, sizeof (utmpx.ut_id)); 28827c478bd9Sstevel@tonic-gate (void) strncpy(utmpx.ut_line, line, sizeof (utmpx.ut_line)); 28837c478bd9Sstevel@tonic-gate 28847c478bd9Sstevel@tonic-gate utmpx.ut_pid = getpid(); 28857c478bd9Sstevel@tonic-gate utmpx.ut_type = USER_PROCESS; 28867c478bd9Sstevel@tonic-gate } else { 28877c478bd9Sstevel@tonic-gate utmpx.ut_type = DEAD_PROCESS; 28887c478bd9Sstevel@tonic-gate } 28897c478bd9Sstevel@tonic-gate (void) gettimeofday(&utmpx.ut_tv, NULL); 28907c478bd9Sstevel@tonic-gate updwtmpx("/var/adm/wtmpx", &utmpx); 28917c478bd9Sstevel@tonic-gate } 28927c478bd9Sstevel@tonic-gate 28937c478bd9Sstevel@tonic-gate /* 28947c478bd9Sstevel@tonic-gate * get_host_seed() 28957c478bd9Sstevel@tonic-gate * 28967c478bd9Sstevel@tonic-gate * Return the serial number of this machine. 28977c478bd9Sstevel@tonic-gate */ 28987c478bd9Sstevel@tonic-gate int 28997c478bd9Sstevel@tonic-gate get_host_seed() 29007c478bd9Sstevel@tonic-gate { 29017c478bd9Sstevel@tonic-gate char buf[32]; 29027c478bd9Sstevel@tonic-gate 29037c478bd9Sstevel@tonic-gate if (sysinfo(SI_HW_SERIAL, buf, sizeof (buf)) < 0) { 29047c478bd9Sstevel@tonic-gate error("sysinfo: %m"); 29057c478bd9Sstevel@tonic-gate return (0); 29067c478bd9Sstevel@tonic-gate } 29077c478bd9Sstevel@tonic-gate return ((int)strtoul(buf, NULL, 16)); 29087c478bd9Sstevel@tonic-gate } 29097c478bd9Sstevel@tonic-gate 29107c478bd9Sstevel@tonic-gate /* 29117c478bd9Sstevel@tonic-gate * strioctl() 29127c478bd9Sstevel@tonic-gate * 29137c478bd9Sstevel@tonic-gate * Wrapper for STREAMS I_STR ioctl. Masks out EINTR from caller. 29147c478bd9Sstevel@tonic-gate */ 29157c478bd9Sstevel@tonic-gate static int 29167c478bd9Sstevel@tonic-gate strioctl(int fd, int cmd, void *ptr, int ilen, int olen) 29177c478bd9Sstevel@tonic-gate { 29187c478bd9Sstevel@tonic-gate struct strioctl str; 29197c478bd9Sstevel@tonic-gate 29207c478bd9Sstevel@tonic-gate str.ic_cmd = cmd; 29217c478bd9Sstevel@tonic-gate str.ic_timout = PPPSTRTIMOUT; 29227c478bd9Sstevel@tonic-gate str.ic_len = ilen; 29237c478bd9Sstevel@tonic-gate str.ic_dp = ptr; 29247c478bd9Sstevel@tonic-gate 29257c478bd9Sstevel@tonic-gate if (myioctl(fd, I_STR, &str) == -1) { 29267c478bd9Sstevel@tonic-gate return (-1); 29277c478bd9Sstevel@tonic-gate } 29287c478bd9Sstevel@tonic-gate if (str.ic_len != olen) { 29297c478bd9Sstevel@tonic-gate dbglog("strioctl: expected %d bytes, got %d for cmd %x\n", 29307c478bd9Sstevel@tonic-gate olen, str.ic_len, cmd); 29317c478bd9Sstevel@tonic-gate } 29327c478bd9Sstevel@tonic-gate return (0); 29337c478bd9Sstevel@tonic-gate } 29347c478bd9Sstevel@tonic-gate 29357c478bd9Sstevel@tonic-gate /* 29367c478bd9Sstevel@tonic-gate * have_route_to() 29377c478bd9Sstevel@tonic-gate * 29387c478bd9Sstevel@tonic-gate * Determine if the system has a route to the specified IP address. 29397c478bd9Sstevel@tonic-gate * Returns 0 if not, 1 if so, -1 if we can't tell. `addr' is in network 29407c478bd9Sstevel@tonic-gate * byte order. For demand mode to work properly, we have to ignore routes 29417c478bd9Sstevel@tonic-gate * through our own interface. XXX Would be nice to use routing socket. 29427c478bd9Sstevel@tonic-gate */ 29437c478bd9Sstevel@tonic-gate int 29447c478bd9Sstevel@tonic-gate have_route_to(addr) 29457c478bd9Sstevel@tonic-gate u_int32_t addr; 29467c478bd9Sstevel@tonic-gate { 29477c478bd9Sstevel@tonic-gate int r, flags, i; 29487c478bd9Sstevel@tonic-gate struct { 29497c478bd9Sstevel@tonic-gate struct T_optmgmt_req req; 29507c478bd9Sstevel@tonic-gate struct opthdr hdr; 29517c478bd9Sstevel@tonic-gate } req; 29527c478bd9Sstevel@tonic-gate union { 29537c478bd9Sstevel@tonic-gate struct T_optmgmt_ack ack; 29547c478bd9Sstevel@tonic-gate unsigned char space[64]; 29557c478bd9Sstevel@tonic-gate } ack; 29567c478bd9Sstevel@tonic-gate struct opthdr *rh; 29577c478bd9Sstevel@tonic-gate struct strbuf cbuf, dbuf; 29587c478bd9Sstevel@tonic-gate int nroutes; 29597c478bd9Sstevel@tonic-gate mib2_ipRouteEntry_t routes[8]; 29607c478bd9Sstevel@tonic-gate mib2_ipRouteEntry_t *rp; 29617c478bd9Sstevel@tonic-gate 29627c478bd9Sstevel@tonic-gate if (ipfd == -1 && open_ipfd() == -1) 29637c478bd9Sstevel@tonic-gate return (0); 29647c478bd9Sstevel@tonic-gate 29657c478bd9Sstevel@tonic-gate req.req.PRIM_type = T_OPTMGMT_REQ; 29667c478bd9Sstevel@tonic-gate req.req.OPT_offset = (caddr_t)&req.hdr - (caddr_t)&req; 29677c478bd9Sstevel@tonic-gate req.req.OPT_length = sizeof (req.hdr); 29687c478bd9Sstevel@tonic-gate #ifdef T_CURRENT 29697c478bd9Sstevel@tonic-gate req.req.MGMT_flags = T_CURRENT; 29707c478bd9Sstevel@tonic-gate #else 29717c478bd9Sstevel@tonic-gate /* Old-style */ 29727c478bd9Sstevel@tonic-gate req.req.MGMT_flags = T_CHECK; 29737c478bd9Sstevel@tonic-gate #endif 29747c478bd9Sstevel@tonic-gate 29757c478bd9Sstevel@tonic-gate req.hdr.level = MIB2_IP; 29767c478bd9Sstevel@tonic-gate req.hdr.name = 0; 29777c478bd9Sstevel@tonic-gate req.hdr.len = 0; 29787c478bd9Sstevel@tonic-gate 29797c478bd9Sstevel@tonic-gate cbuf.buf = (caddr_t)&req; 29807c478bd9Sstevel@tonic-gate cbuf.len = sizeof (req); 29817c478bd9Sstevel@tonic-gate 29827c478bd9Sstevel@tonic-gate if (putmsg(ipfd, &cbuf, NULL, 0) == -1) { 29837c478bd9Sstevel@tonic-gate warn("have_route_to: putmsg: %m"); 29847c478bd9Sstevel@tonic-gate return (-1); 29857c478bd9Sstevel@tonic-gate } 29867c478bd9Sstevel@tonic-gate 29877c478bd9Sstevel@tonic-gate for (;;) { 29887c478bd9Sstevel@tonic-gate cbuf.buf = (caddr_t)&ack; 29897c478bd9Sstevel@tonic-gate cbuf.maxlen = sizeof (ack); 29907c478bd9Sstevel@tonic-gate dbuf.buf = (caddr_t)routes; 29917c478bd9Sstevel@tonic-gate dbuf.maxlen = sizeof (routes); 29927c478bd9Sstevel@tonic-gate flags = 0; 29937c478bd9Sstevel@tonic-gate r = getmsg(ipfd, &cbuf, &dbuf, &flags); 29947c478bd9Sstevel@tonic-gate if (r == -1) { 29957c478bd9Sstevel@tonic-gate warn("have_route_to: getmsg: %m"); 29967c478bd9Sstevel@tonic-gate return (-1); 29977c478bd9Sstevel@tonic-gate } 29987c478bd9Sstevel@tonic-gate 29997c478bd9Sstevel@tonic-gate if (cbuf.len < sizeof (struct T_optmgmt_ack) || 30007c478bd9Sstevel@tonic-gate ack.ack.PRIM_type != T_OPTMGMT_ACK || 30017c478bd9Sstevel@tonic-gate ack.ack.MGMT_flags != T_SUCCESS || 30027c478bd9Sstevel@tonic-gate ack.ack.OPT_length < sizeof (struct opthdr)) { 30037c478bd9Sstevel@tonic-gate dbglog("have_route_to: bad message len=%d prim=%d", 30047c478bd9Sstevel@tonic-gate cbuf.len, ack.ack.PRIM_type); 30057c478bd9Sstevel@tonic-gate return (-1); 30067c478bd9Sstevel@tonic-gate } 30077c478bd9Sstevel@tonic-gate /* LINTED */ 30087c478bd9Sstevel@tonic-gate rh = (struct opthdr *)((caddr_t)&ack + ack.ack.OPT_offset); 30097c478bd9Sstevel@tonic-gate if (rh->level == 0 && rh->name == 0) { 30107c478bd9Sstevel@tonic-gate break; 30117c478bd9Sstevel@tonic-gate } 30127c478bd9Sstevel@tonic-gate if (rh->level != MIB2_IP || rh->name != MIB2_IP_21) { 30137c478bd9Sstevel@tonic-gate while (r == MOREDATA) { 30147c478bd9Sstevel@tonic-gate r = getmsg(ipfd, NULL, &dbuf, &flags); 30157c478bd9Sstevel@tonic-gate } 30167c478bd9Sstevel@tonic-gate continue; 30177c478bd9Sstevel@tonic-gate } 30187c478bd9Sstevel@tonic-gate 30197c478bd9Sstevel@tonic-gate /* 30207c478bd9Sstevel@tonic-gate * Note that we have to skip routes to our own 30217c478bd9Sstevel@tonic-gate * interface in order for demand dial to work. 30227c478bd9Sstevel@tonic-gate * 30237c478bd9Sstevel@tonic-gate * XXX awful hack here. We don't know our own 30247c478bd9Sstevel@tonic-gate * ifIndex, so we can't check ipRouteIfIndex here. 30257c478bd9Sstevel@tonic-gate * Instead, we check the next hop address. 30267c478bd9Sstevel@tonic-gate */ 30277c478bd9Sstevel@tonic-gate for (;;) { 30287c478bd9Sstevel@tonic-gate nroutes = dbuf.len / sizeof (mib2_ipRouteEntry_t); 30297c478bd9Sstevel@tonic-gate for (rp = routes, i = 0; i < nroutes; ++i, ++rp) { 30307c478bd9Sstevel@tonic-gate if (rp->ipRouteNextHop != remote_addr && 30317c478bd9Sstevel@tonic-gate ((addr ^ rp->ipRouteDest) & 30327c478bd9Sstevel@tonic-gate rp->ipRouteMask) == 0) { 30337c478bd9Sstevel@tonic-gate dbglog("have route to %I/%I via %I", 30347c478bd9Sstevel@tonic-gate rp->ipRouteDest, 30357c478bd9Sstevel@tonic-gate rp->ipRouteMask, 30367c478bd9Sstevel@tonic-gate rp->ipRouteNextHop); 30377c478bd9Sstevel@tonic-gate return (1); 30387c478bd9Sstevel@tonic-gate } 30397c478bd9Sstevel@tonic-gate } 30407c478bd9Sstevel@tonic-gate if (r == 0) { 30417c478bd9Sstevel@tonic-gate break; 30427c478bd9Sstevel@tonic-gate } 30437c478bd9Sstevel@tonic-gate r = getmsg(ipfd, NULL, &dbuf, &flags); 30447c478bd9Sstevel@tonic-gate } 30457c478bd9Sstevel@tonic-gate } 30467c478bd9Sstevel@tonic-gate return (0); 30477c478bd9Sstevel@tonic-gate } 30487c478bd9Sstevel@tonic-gate 30497c478bd9Sstevel@tonic-gate /* 30507c478bd9Sstevel@tonic-gate * get_pty() 30517c478bd9Sstevel@tonic-gate * 30527c478bd9Sstevel@tonic-gate * Get a pty master/slave pair and chown the slave side to the uid given. 30537c478bd9Sstevel@tonic-gate * Assumes slave_name points to MAXPATHLEN bytes of space. 30547c478bd9Sstevel@tonic-gate */ 30557c478bd9Sstevel@tonic-gate int 30567c478bd9Sstevel@tonic-gate get_pty(master_fdp, slave_fdp, slave_name, uid) 30577c478bd9Sstevel@tonic-gate int *master_fdp; 30587c478bd9Sstevel@tonic-gate int *slave_fdp; 30597c478bd9Sstevel@tonic-gate char *slave_name; 30607c478bd9Sstevel@tonic-gate int uid; 30617c478bd9Sstevel@tonic-gate { 30627c478bd9Sstevel@tonic-gate int mfd; 30637c478bd9Sstevel@tonic-gate int sfd; 30647c478bd9Sstevel@tonic-gate char *pty_name; 30657c478bd9Sstevel@tonic-gate 30667c478bd9Sstevel@tonic-gate mfd = open("/dev/ptmx", O_NOCTTY | O_RDWR); 30677c478bd9Sstevel@tonic-gate if (mfd < 0) { 30687c478bd9Sstevel@tonic-gate error("Couldn't open pty master: %m"); 30697c478bd9Sstevel@tonic-gate return (0); 30707c478bd9Sstevel@tonic-gate } 30717c478bd9Sstevel@tonic-gate pty_name = ptsname(mfd); 30727c478bd9Sstevel@tonic-gate if (pty_name == NULL) { 30737c478bd9Sstevel@tonic-gate dbglog("Didn't get pty slave name on first try; sleeping."); 30747c478bd9Sstevel@tonic-gate /* In case "grow" operation is in progress; try again. */ 30757c478bd9Sstevel@tonic-gate (void) sleep(1); 30767c478bd9Sstevel@tonic-gate pty_name = ptsname(mfd); 30777c478bd9Sstevel@tonic-gate } 30787c478bd9Sstevel@tonic-gate if (pty_name == NULL) { 30797c478bd9Sstevel@tonic-gate error("Couldn't get name of pty slave"); 30807c478bd9Sstevel@tonic-gate (void) close(mfd); 30817c478bd9Sstevel@tonic-gate return (0); 30827c478bd9Sstevel@tonic-gate } 30837c478bd9Sstevel@tonic-gate if (chown(pty_name, uid, -1) < 0) { 30847c478bd9Sstevel@tonic-gate warn("Couldn't change owner of pty slave: %m"); 30857c478bd9Sstevel@tonic-gate } 30867c478bd9Sstevel@tonic-gate if (chmod(pty_name, S_IRUSR | S_IWUSR) < 0) { 30877c478bd9Sstevel@tonic-gate warn("Couldn't change permissions on pty slave: %m"); 30887c478bd9Sstevel@tonic-gate } 30897c478bd9Sstevel@tonic-gate if (unlockpt(mfd) < 0) { 30907c478bd9Sstevel@tonic-gate warn("Couldn't unlock pty slave: %m"); 30917c478bd9Sstevel@tonic-gate } 30927c478bd9Sstevel@tonic-gate sfd = open(pty_name, O_RDWR); 30937c478bd9Sstevel@tonic-gate if (sfd < 0) { 30947c478bd9Sstevel@tonic-gate error("Couldn't open pty slave %s: %m", pty_name); 30957c478bd9Sstevel@tonic-gate (void) close(mfd); 30967c478bd9Sstevel@tonic-gate return (0); 30977c478bd9Sstevel@tonic-gate } 30987c478bd9Sstevel@tonic-gate if (myioctl(sfd, I_PUSH, "ptem") < 0) { 30997c478bd9Sstevel@tonic-gate warn("Couldn't push ptem module on pty slave: %m"); 31007c478bd9Sstevel@tonic-gate } 31017c478bd9Sstevel@tonic-gate dbglog("Using %s; master fd %d, slave fd %d", pty_name, mfd, sfd); 31027c478bd9Sstevel@tonic-gate 31037c478bd9Sstevel@tonic-gate (void) strlcpy(slave_name, pty_name, MAXPATHLEN); 31047c478bd9Sstevel@tonic-gate 31057c478bd9Sstevel@tonic-gate *master_fdp = mfd; 31067c478bd9Sstevel@tonic-gate *slave_fdp = sfd; 31077c478bd9Sstevel@tonic-gate 31087c478bd9Sstevel@tonic-gate return (1); 31097c478bd9Sstevel@tonic-gate } 31107c478bd9Sstevel@tonic-gate 31117c478bd9Sstevel@tonic-gate #ifdef INET6 31127c478bd9Sstevel@tonic-gate static int 31137c478bd9Sstevel@tonic-gate open_udp6fd(void) 31147c478bd9Sstevel@tonic-gate { 31157c478bd9Sstevel@tonic-gate int udp6fd; 31167c478bd9Sstevel@tonic-gate 31177c478bd9Sstevel@tonic-gate udp6fd = open(UDP6_DEV_NAME, O_RDWR | O_NONBLOCK, 0); 31187c478bd9Sstevel@tonic-gate if (udp6fd < 0) { 31197c478bd9Sstevel@tonic-gate error("Couldn't open UDPv6 device (%s): %m", UDP6_DEV_NAME); 31207c478bd9Sstevel@tonic-gate } 31217c478bd9Sstevel@tonic-gate return (udp6fd); 31227c478bd9Sstevel@tonic-gate } 31237c478bd9Sstevel@tonic-gate 31247c478bd9Sstevel@tonic-gate /* 31257c478bd9Sstevel@tonic-gate * plumb_ip6if() 31267c478bd9Sstevel@tonic-gate * 31277c478bd9Sstevel@tonic-gate * Perform IPv6 interface plumbing. 31287c478bd9Sstevel@tonic-gate */ 31297c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 31307c478bd9Sstevel@tonic-gate static int 31317c478bd9Sstevel@tonic-gate plumb_ip6if(int unit) 31327c478bd9Sstevel@tonic-gate { 31337c478bd9Sstevel@tonic-gate int udp6fd = -1, tmpfd; 31347c478bd9Sstevel@tonic-gate uint32_t x; 31357c478bd9Sstevel@tonic-gate struct lifreq lifr; 31367c478bd9Sstevel@tonic-gate 31377c478bd9Sstevel@tonic-gate if (!IPV6CP_ENABLED || (ifunit == -1) || (pppfd == -1)) { 31387c478bd9Sstevel@tonic-gate return (0); 31397c478bd9Sstevel@tonic-gate } 31407c478bd9Sstevel@tonic-gate if (plumbed) 31417c478bd9Sstevel@tonic-gate return (1); 31427c478bd9Sstevel@tonic-gate if (ip6fd == -1 && open_ip6fd() == -1) 31437c478bd9Sstevel@tonic-gate return (0); 31447c478bd9Sstevel@tonic-gate if (use_plink && (udp6fd = open_udp6fd()) == -1) 31457c478bd9Sstevel@tonic-gate return (0); 31467c478bd9Sstevel@tonic-gate tmpfd = open(drvnam, O_RDWR | O_NONBLOCK, 0); 31477c478bd9Sstevel@tonic-gate if (tmpfd < 0) { 31487c478bd9Sstevel@tonic-gate error("Couldn't open PPP device (%s): %m", drvnam); 31497c478bd9Sstevel@tonic-gate if (udp6fd != -1) 31507c478bd9Sstevel@tonic-gate (void) close(udp6fd); 31517c478bd9Sstevel@tonic-gate return (0); 31527c478bd9Sstevel@tonic-gate } 31537c478bd9Sstevel@tonic-gate if (kdebugflag & 1) { 31547c478bd9Sstevel@tonic-gate x = PPPDBG_LOG + PPPDBG_DRIVER; 31557c478bd9Sstevel@tonic-gate if (strioctl(tmpfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) { 31567c478bd9Sstevel@tonic-gate warn("PPPIO_DEBUG ioctl for mux failed: %m"); 31577c478bd9Sstevel@tonic-gate } 31587c478bd9Sstevel@tonic-gate } 31597c478bd9Sstevel@tonic-gate if (myioctl(tmpfd, I_PUSH, IP_MOD_NAME) < 0) { 31607c478bd9Sstevel@tonic-gate error("Couldn't push IP module(%s): %m", IP_MOD_NAME); 31617c478bd9Sstevel@tonic-gate goto err_ret; 31627c478bd9Sstevel@tonic-gate } 31637c478bd9Sstevel@tonic-gate /* 31647c478bd9Sstevel@tonic-gate * Sets interface ppa and flags (refer to comments in plumb_ipif for 31657c478bd9Sstevel@tonic-gate * the IF_UNITSEL ioctl). In addition, the IFF_IPV6 bit must be set in 31667c478bd9Sstevel@tonic-gate * order to declare this as an IPv6 interface. 31677c478bd9Sstevel@tonic-gate */ 31687c478bd9Sstevel@tonic-gate BZERO(&lifr, sizeof (lifr)); 31697c478bd9Sstevel@tonic-gate if (myioctl(tmpfd, SIOCGLIFFLAGS, &lifr) < 0) { 31707c478bd9Sstevel@tonic-gate error("Couldn't get IPv6 interface flags: %m"); 31717c478bd9Sstevel@tonic-gate goto err_ret; 31727c478bd9Sstevel@tonic-gate } 31737c478bd9Sstevel@tonic-gate lifr.lifr_flags |= IFF_IPV6; 31747c478bd9Sstevel@tonic-gate lifr.lifr_flags &= ~(IFF_BROADCAST | IFF_IPV4); 31757c478bd9Sstevel@tonic-gate lifr.lifr_ppa = ifunit; 31767c478bd9Sstevel@tonic-gate (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 31777c478bd9Sstevel@tonic-gate if (myioctl(tmpfd, SIOCSLIFNAME, &lifr) < 0) { 31787c478bd9Sstevel@tonic-gate error("Can't set ifname for unit %d: %m", ifunit); 31797c478bd9Sstevel@tonic-gate goto err_ret; 31807c478bd9Sstevel@tonic-gate } 31817c478bd9Sstevel@tonic-gate if (use_plink) { 31827c478bd9Sstevel@tonic-gate ip6muxid = myioctl(udp6fd, I_PLINK, (void *)tmpfd); 31837c478bd9Sstevel@tonic-gate if (ip6muxid < 0) { 31847c478bd9Sstevel@tonic-gate error("Can't I_PLINK PPP device to IPv6: %m"); 31857c478bd9Sstevel@tonic-gate goto err_ret; 31867c478bd9Sstevel@tonic-gate } 31877c478bd9Sstevel@tonic-gate } else { 31887c478bd9Sstevel@tonic-gate ip6muxid = myioctl(ip6fd, I_LINK, (void *)tmpfd); 31897c478bd9Sstevel@tonic-gate if (ip6muxid < 0) { 31907c478bd9Sstevel@tonic-gate error("Can't I_LINK PPP device to IPv6: %m"); 31917c478bd9Sstevel@tonic-gate goto err_ret; 31927c478bd9Sstevel@tonic-gate } 31937c478bd9Sstevel@tonic-gate } 31947c478bd9Sstevel@tonic-gate lifr.lifr_ip_muxid = ip6muxid; 31957c478bd9Sstevel@tonic-gate lifr.lifr_arp_muxid = -1; 31967c478bd9Sstevel@tonic-gate if (myioctl(ip6fd, SIOCSLIFMUXID, (caddr_t)&lifr) < 0) { 31977c478bd9Sstevel@tonic-gate error("Can't set mux ID: SIOCSLIFMUXID: %m"); 31987c478bd9Sstevel@tonic-gate goto err_ret; 31997c478bd9Sstevel@tonic-gate } 32007c478bd9Sstevel@tonic-gate (void) close(tmpfd); 32017c478bd9Sstevel@tonic-gate if (udp6fd != -1) 32027c478bd9Sstevel@tonic-gate (void) close(udp6fd); 32037c478bd9Sstevel@tonic-gate return (1); 32047c478bd9Sstevel@tonic-gate 32057c478bd9Sstevel@tonic-gate err_ret: 32067c478bd9Sstevel@tonic-gate (void) close(tmpfd); 32077c478bd9Sstevel@tonic-gate if (udp6fd != -1) 32087c478bd9Sstevel@tonic-gate (void) close(udp6fd); 32097c478bd9Sstevel@tonic-gate return (0); 32107c478bd9Sstevel@tonic-gate } 32117c478bd9Sstevel@tonic-gate 32127c478bd9Sstevel@tonic-gate /* 32137c478bd9Sstevel@tonic-gate * unplumb_ip6if() 32147c478bd9Sstevel@tonic-gate * 32157c478bd9Sstevel@tonic-gate * Perform IPv6 interface unplumbing. Possibly called from die(), so there 32167c478bd9Sstevel@tonic-gate * shouldn't be any call to die() here. 32177c478bd9Sstevel@tonic-gate */ 32187c478bd9Sstevel@tonic-gate static int 32197c478bd9Sstevel@tonic-gate unplumb_ip6if(int unit) 32207c478bd9Sstevel@tonic-gate { 32217c478bd9Sstevel@tonic-gate int udp6fd = -1, fd = -1; 32227c478bd9Sstevel@tonic-gate int id; 32237c478bd9Sstevel@tonic-gate struct lifreq lifr; 32247c478bd9Sstevel@tonic-gate 32257c478bd9Sstevel@tonic-gate if (!IPV6CP_ENABLED || ifunit == -1) { 32267c478bd9Sstevel@tonic-gate return (0); 32277c478bd9Sstevel@tonic-gate } 32287c478bd9Sstevel@tonic-gate if (!plumbed && (ip6muxid == -1 || (ip6fd == -1 && !use_plink))) { 32297c478bd9Sstevel@tonic-gate return (1); 32307c478bd9Sstevel@tonic-gate } 32317c478bd9Sstevel@tonic-gate id = ip6muxid; 32327c478bd9Sstevel@tonic-gate if (!plumbed && use_plink) { 32337c478bd9Sstevel@tonic-gate if ((udp6fd = open_udp6fd()) == -1) 32347c478bd9Sstevel@tonic-gate return (0); 32357c478bd9Sstevel@tonic-gate /* 32367c478bd9Sstevel@tonic-gate * Note: must re-get mux ID, since any intervening 32377c478bd9Sstevel@tonic-gate * ifconfigs will change this. 32387c478bd9Sstevel@tonic-gate */ 32397c478bd9Sstevel@tonic-gate BZERO(&lifr, sizeof (lifr)); 32407c478bd9Sstevel@tonic-gate (void) strlcpy(lifr.lifr_name, ifname, 32417c478bd9Sstevel@tonic-gate sizeof (lifr.lifr_name)); 32427c478bd9Sstevel@tonic-gate if (myioctl(ip6fd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) { 32437c478bd9Sstevel@tonic-gate warn("Can't get mux fd: SIOCGLIFMUXID: %m"); 32447c478bd9Sstevel@tonic-gate } else { 32457c478bd9Sstevel@tonic-gate id = lifr.lifr_ip_muxid; 32467c478bd9Sstevel@tonic-gate fd = myioctl(udp6fd, _I_MUXID2FD, (void *)id); 32477c478bd9Sstevel@tonic-gate if (fd < 0) { 32487c478bd9Sstevel@tonic-gate warn("Can't get mux fd: _I_MUXID2FD: %m"); 32497c478bd9Sstevel@tonic-gate } 32507c478bd9Sstevel@tonic-gate } 32517c478bd9Sstevel@tonic-gate } 32527c478bd9Sstevel@tonic-gate /* 32537c478bd9Sstevel@tonic-gate * Mark down and unlink the IPv6 interface. 32547c478bd9Sstevel@tonic-gate */ 32557c478bd9Sstevel@tonic-gate (void) sif6down(unit); 32567c478bd9Sstevel@tonic-gate if (plumbed) 32577c478bd9Sstevel@tonic-gate return (1); 32587c478bd9Sstevel@tonic-gate ip6muxid = -1; 32597c478bd9Sstevel@tonic-gate if (use_plink) { 32607c478bd9Sstevel@tonic-gate if ((fd = myioctl(udp6fd, _I_MUXID2FD, (void *)id)) < 0) { 32617c478bd9Sstevel@tonic-gate error("Can't recapture mux fd: _I_MUXID2FD: %m"); 32627c478bd9Sstevel@tonic-gate (void) close(udp6fd); 32637c478bd9Sstevel@tonic-gate return (0); 32647c478bd9Sstevel@tonic-gate } 32657c478bd9Sstevel@tonic-gate if (myioctl(udp6fd, I_PUNLINK, (void *)id) < 0) { 32667c478bd9Sstevel@tonic-gate error("Can't I_PUNLINK PPP from IPv6: %m"); 32677c478bd9Sstevel@tonic-gate (void) close(fd); 32687c478bd9Sstevel@tonic-gate (void) close(udp6fd); 32697c478bd9Sstevel@tonic-gate return (0); 32707c478bd9Sstevel@tonic-gate } 32717c478bd9Sstevel@tonic-gate (void) close(fd); 32727c478bd9Sstevel@tonic-gate (void) close(udp6fd); 32737c478bd9Sstevel@tonic-gate } else { 32747c478bd9Sstevel@tonic-gate if (myioctl(ip6fd, I_UNLINK, (void *)id) < 0) { 32757c478bd9Sstevel@tonic-gate error("Can't I_UNLINK PPP from IPv6: %m"); 32767c478bd9Sstevel@tonic-gate return (0); 32777c478bd9Sstevel@tonic-gate } 32787c478bd9Sstevel@tonic-gate } 32797c478bd9Sstevel@tonic-gate return (1); 32807c478bd9Sstevel@tonic-gate } 32817c478bd9Sstevel@tonic-gate 32827c478bd9Sstevel@tonic-gate /* 32837c478bd9Sstevel@tonic-gate * sif6flags() 32847c478bd9Sstevel@tonic-gate * 32857c478bd9Sstevel@tonic-gate * Set or clear the IPv6 interface flags. 32867c478bd9Sstevel@tonic-gate */ 32877c478bd9Sstevel@tonic-gate int 32887c478bd9Sstevel@tonic-gate sif6flags(f, set) 32897c478bd9Sstevel@tonic-gate u_int32_t f; 32907c478bd9Sstevel@tonic-gate int set; 32917c478bd9Sstevel@tonic-gate { 32927c478bd9Sstevel@tonic-gate struct lifreq lifr; 32937c478bd9Sstevel@tonic-gate int fd; 32947c478bd9Sstevel@tonic-gate 32957c478bd9Sstevel@tonic-gate if (!IPV6CP_ENABLED || (ip6muxid == -1)) { 32967c478bd9Sstevel@tonic-gate return (0); 32977c478bd9Sstevel@tonic-gate } 32987c478bd9Sstevel@tonic-gate fd = socket(AF_INET6, SOCK_DGRAM, 0); 32997c478bd9Sstevel@tonic-gate if (fd < 0) { 33007c478bd9Sstevel@tonic-gate error("sif6flags: error opening IPv6 socket: %m"); 33017c478bd9Sstevel@tonic-gate return (0); 33027c478bd9Sstevel@tonic-gate } 33037c478bd9Sstevel@tonic-gate BZERO(&lifr, sizeof (lifr)); 33047c478bd9Sstevel@tonic-gate (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 33057c478bd9Sstevel@tonic-gate if (myioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) { 33067c478bd9Sstevel@tonic-gate error("Couldn't get IPv6 interface flags: %m"); 33077c478bd9Sstevel@tonic-gate (void) close(fd); 33087c478bd9Sstevel@tonic-gate return (0); 33097c478bd9Sstevel@tonic-gate } 33107c478bd9Sstevel@tonic-gate if (set) { 33117c478bd9Sstevel@tonic-gate lifr.lifr_flags |= f; 33127c478bd9Sstevel@tonic-gate } else { 33137c478bd9Sstevel@tonic-gate lifr.lifr_flags &= ~f; 33147c478bd9Sstevel@tonic-gate } 33157c478bd9Sstevel@tonic-gate (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 33167c478bd9Sstevel@tonic-gate if (myioctl(fd, SIOCSLIFFLAGS, &lifr) < 0) { 33177c478bd9Sstevel@tonic-gate error("Couldn't set IPv6 interface flags: %m"); 33187c478bd9Sstevel@tonic-gate (void) close(fd); 33197c478bd9Sstevel@tonic-gate return (0); 33207c478bd9Sstevel@tonic-gate } 33217c478bd9Sstevel@tonic-gate (void) close(fd); 33227c478bd9Sstevel@tonic-gate return (1); 33237c478bd9Sstevel@tonic-gate } 33247c478bd9Sstevel@tonic-gate 33257c478bd9Sstevel@tonic-gate /* 33267c478bd9Sstevel@tonic-gate * sif6up() 33277c478bd9Sstevel@tonic-gate * 33287c478bd9Sstevel@tonic-gate * Config the IPv6 interface up and enable IPv6 packets to pass. 33297c478bd9Sstevel@tonic-gate */ 33307c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 33317c478bd9Sstevel@tonic-gate int 33327c478bd9Sstevel@tonic-gate sif6up(unit) 33337c478bd9Sstevel@tonic-gate int unit; 33347c478bd9Sstevel@tonic-gate { 33357c478bd9Sstevel@tonic-gate if (if6_is_up) { 33367c478bd9Sstevel@tonic-gate return (1); 33377c478bd9Sstevel@tonic-gate } else if (!IPV6CP_ENABLED) { 33387c478bd9Sstevel@tonic-gate warn("sif6up called when IPV6CP is disabled"); 33397c478bd9Sstevel@tonic-gate return (0); 33407c478bd9Sstevel@tonic-gate } else if (ip6muxid == -1) { 33417c478bd9Sstevel@tonic-gate warn("sif6up called in wrong state"); 33427c478bd9Sstevel@tonic-gate return (0); 33437c478bd9Sstevel@tonic-gate } else if (!sif6flags(IFF_UP, 1)) { 33447c478bd9Sstevel@tonic-gate error("Unable to mark the IPv6 interface UP"); 33457c478bd9Sstevel@tonic-gate return (0); 33467c478bd9Sstevel@tonic-gate } 33477c478bd9Sstevel@tonic-gate if6_is_up = 1; 33487c478bd9Sstevel@tonic-gate return (1); 33497c478bd9Sstevel@tonic-gate } 33507c478bd9Sstevel@tonic-gate 33517c478bd9Sstevel@tonic-gate /* 33527c478bd9Sstevel@tonic-gate * sif6down() 33537c478bd9Sstevel@tonic-gate * 33547c478bd9Sstevel@tonic-gate * Config the IPv6 interface down and disable IPv6. Possibly called from 33557c478bd9Sstevel@tonic-gate * die(), so there shouldn't be any call to die() here. 33567c478bd9Sstevel@tonic-gate */ 33577c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 33587c478bd9Sstevel@tonic-gate int 33597c478bd9Sstevel@tonic-gate sif6down(unit) 33607c478bd9Sstevel@tonic-gate int unit; 33617c478bd9Sstevel@tonic-gate { 33627c478bd9Sstevel@tonic-gate if (!IPV6CP_ENABLED) { 33637c478bd9Sstevel@tonic-gate warn("sif6down called when IPV6CP is disabled"); 33647c478bd9Sstevel@tonic-gate return (0); 33657c478bd9Sstevel@tonic-gate } else if (!if6_is_up || (ip6muxid == -1)) { 33667c478bd9Sstevel@tonic-gate return (1); 33677c478bd9Sstevel@tonic-gate } else if (!sif6flags(IFF_UP, 0)) { 33687c478bd9Sstevel@tonic-gate error("Unable to mark the IPv6 interface DOWN"); 33697c478bd9Sstevel@tonic-gate return (0); 33707c478bd9Sstevel@tonic-gate } 33717c478bd9Sstevel@tonic-gate if6_is_up = 0; 33727c478bd9Sstevel@tonic-gate return (1); 33737c478bd9Sstevel@tonic-gate } 33747c478bd9Sstevel@tonic-gate 33757c478bd9Sstevel@tonic-gate /* 33767c478bd9Sstevel@tonic-gate * sif6mtu() 33777c478bd9Sstevel@tonic-gate * 33787c478bd9Sstevel@tonic-gate * Config the IPv6 interface MTU. 33797c478bd9Sstevel@tonic-gate */ 33807c478bd9Sstevel@tonic-gate int 33817c478bd9Sstevel@tonic-gate sif6mtu(mtu) 33827c478bd9Sstevel@tonic-gate int mtu; 33837c478bd9Sstevel@tonic-gate { 33847c478bd9Sstevel@tonic-gate struct lifreq lifr; 33857c478bd9Sstevel@tonic-gate int s; 33867c478bd9Sstevel@tonic-gate 33877c478bd9Sstevel@tonic-gate if (!IPV6CP_ENABLED || (ip6muxid == -1)) { 33887c478bd9Sstevel@tonic-gate return (0); 33897c478bd9Sstevel@tonic-gate } 33907c478bd9Sstevel@tonic-gate s = socket(AF_INET6, SOCK_DGRAM, 0); 33917c478bd9Sstevel@tonic-gate if (s < 0) { 33927c478bd9Sstevel@tonic-gate error("sif6mtu: error opening IPv6 socket: %m"); 33937c478bd9Sstevel@tonic-gate return (0); 33947c478bd9Sstevel@tonic-gate } 33957c478bd9Sstevel@tonic-gate BZERO(&lifr, sizeof (lifr)); 33967c478bd9Sstevel@tonic-gate (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 33977c478bd9Sstevel@tonic-gate lifr.lifr_mtu = mtu; 33987c478bd9Sstevel@tonic-gate if (myioctl(s, SIOCSLIFMTU, &lifr) < 0) { 33997c478bd9Sstevel@tonic-gate error("Couldn't set IPv6 MTU (%s): %m", lifr.lifr_name); 34007c478bd9Sstevel@tonic-gate (void) close(s); 34017c478bd9Sstevel@tonic-gate return (0); 34027c478bd9Sstevel@tonic-gate } 34037c478bd9Sstevel@tonic-gate (void) close(s); 34047c478bd9Sstevel@tonic-gate return (1); 34057c478bd9Sstevel@tonic-gate } 34067c478bd9Sstevel@tonic-gate 34077c478bd9Sstevel@tonic-gate /* 34087c478bd9Sstevel@tonic-gate * sif6addr() 34097c478bd9Sstevel@tonic-gate * 34107c478bd9Sstevel@tonic-gate * Config the interface with an IPv6 link-local address. 34117c478bd9Sstevel@tonic-gate */ 34127c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 34137c478bd9Sstevel@tonic-gate int 34147c478bd9Sstevel@tonic-gate sif6addr(unit, ourid, hisid) 34157c478bd9Sstevel@tonic-gate int unit; 34167c478bd9Sstevel@tonic-gate eui64_t ourid; 34177c478bd9Sstevel@tonic-gate eui64_t hisid; 34187c478bd9Sstevel@tonic-gate { 34197c478bd9Sstevel@tonic-gate struct lifreq lifr; 34207c478bd9Sstevel@tonic-gate struct sockaddr_storage laddr; 34217c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&laddr; 34227c478bd9Sstevel@tonic-gate int fd; 34237c478bd9Sstevel@tonic-gate 34247c478bd9Sstevel@tonic-gate if (!IPV6CP_ENABLED || (ip6muxid == -1 && plumb_ip6if(unit) == 0)) { 34257c478bd9Sstevel@tonic-gate return (0); 34267c478bd9Sstevel@tonic-gate } 34277c478bd9Sstevel@tonic-gate fd = socket(AF_INET6, SOCK_DGRAM, 0); 34287c478bd9Sstevel@tonic-gate if (fd < 0) { 34297c478bd9Sstevel@tonic-gate error("sif6addr: error opening IPv6 socket: %m"); 34307c478bd9Sstevel@tonic-gate return (0); 34317c478bd9Sstevel@tonic-gate } 34327c478bd9Sstevel@tonic-gate /* 34337c478bd9Sstevel@tonic-gate * Set the IPv6 interface MTU. 34347c478bd9Sstevel@tonic-gate */ 34357c478bd9Sstevel@tonic-gate if (!sif6mtu(link_mtu)) { 34367c478bd9Sstevel@tonic-gate (void) close(fd); 34377c478bd9Sstevel@tonic-gate return (0); 34387c478bd9Sstevel@tonic-gate } 34397c478bd9Sstevel@tonic-gate /* 34407c478bd9Sstevel@tonic-gate * Set the interface address token. Do this because /dev/ppp responds 34417c478bd9Sstevel@tonic-gate * to DL_PHYS_ADDR_REQ with zero values, hence the interface token 34427c478bd9Sstevel@tonic-gate * came to be zero too, and without this, in.ndpd will complain. 34437c478bd9Sstevel@tonic-gate */ 34447c478bd9Sstevel@tonic-gate BZERO(&lifr, sizeof (lifr)); 34457c478bd9Sstevel@tonic-gate (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 34467c478bd9Sstevel@tonic-gate BZERO(sin6, sizeof (struct sockaddr_in6)); 34477c478bd9Sstevel@tonic-gate IN6_LLTOKEN_FROM_EUI64(lifr, sin6, ourid); 34487c478bd9Sstevel@tonic-gate if (myioctl(fd, SIOCSLIFTOKEN, &lifr) < 0) { 34497c478bd9Sstevel@tonic-gate error("Couldn't set IPv6 token (%s): %m", lifr.lifr_name); 34507c478bd9Sstevel@tonic-gate (void) close(fd); 34517c478bd9Sstevel@tonic-gate return (0); 34527c478bd9Sstevel@tonic-gate } 34537c478bd9Sstevel@tonic-gate /* 34547c478bd9Sstevel@tonic-gate * Set the IPv6 interface local point-to-point address. 34557c478bd9Sstevel@tonic-gate */ 34567c478bd9Sstevel@tonic-gate IN6_LLADDR_FROM_EUI64(lifr, sin6, ourid); 34577c478bd9Sstevel@tonic-gate if (myioctl(fd, SIOCSLIFADDR, &lifr) < 0) { 34587c478bd9Sstevel@tonic-gate error("Couldn't set local IPv6 address (%s): %m", 34597c478bd9Sstevel@tonic-gate lifr.lifr_name); 34607c478bd9Sstevel@tonic-gate (void) close(fd); 34617c478bd9Sstevel@tonic-gate return (0); 34627c478bd9Sstevel@tonic-gate } 34637c478bd9Sstevel@tonic-gate /* 34647c478bd9Sstevel@tonic-gate * Set the IPv6 interface local point-to-point address. 34657c478bd9Sstevel@tonic-gate */ 34667c478bd9Sstevel@tonic-gate BZERO(&lifr, sizeof (lifr)); 34677c478bd9Sstevel@tonic-gate (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 34687c478bd9Sstevel@tonic-gate IN6_LLADDR_FROM_EUI64(lifr, sin6, hisid); 34697c478bd9Sstevel@tonic-gate if (myioctl(fd, SIOCSLIFDSTADDR, &lifr) < 0) { 34707c478bd9Sstevel@tonic-gate error("Couldn't set remote IPv6 address (%s): %m", 34717c478bd9Sstevel@tonic-gate lifr.lifr_name); 34727c478bd9Sstevel@tonic-gate (void) close(fd); 34737c478bd9Sstevel@tonic-gate return (0); 34747c478bd9Sstevel@tonic-gate } 34757c478bd9Sstevel@tonic-gate (void) close(fd); 34767c478bd9Sstevel@tonic-gate return (1); 34777c478bd9Sstevel@tonic-gate } 34787c478bd9Sstevel@tonic-gate 34797c478bd9Sstevel@tonic-gate /* 34807c478bd9Sstevel@tonic-gate * cif6addr() 34817c478bd9Sstevel@tonic-gate */ 34827c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 34837c478bd9Sstevel@tonic-gate int 34847c478bd9Sstevel@tonic-gate cif6addr(u, o, h) 34857c478bd9Sstevel@tonic-gate int u; 34867c478bd9Sstevel@tonic-gate eui64_t o; 34877c478bd9Sstevel@tonic-gate eui64_t h; 34887c478bd9Sstevel@tonic-gate { 34897c478bd9Sstevel@tonic-gate if (!IPV6CP_ENABLED) { 34907c478bd9Sstevel@tonic-gate return (0); 34917c478bd9Sstevel@tonic-gate } 34927c478bd9Sstevel@tonic-gate /* 34937c478bd9Sstevel@tonic-gate * Do nothing here, as everything has been done in sif6down(). 34947c478bd9Sstevel@tonic-gate */ 34957c478bd9Sstevel@tonic-gate return (1); 34967c478bd9Sstevel@tonic-gate } 34977c478bd9Sstevel@tonic-gate 34987c478bd9Sstevel@tonic-gate /* 34997c478bd9Sstevel@tonic-gate * ether_to_eui64() 35007c478bd9Sstevel@tonic-gate * 35017c478bd9Sstevel@tonic-gate * Convert 48-bit Ethernet address into 64-bit EUI. Walks the list of valid 35027c478bd9Sstevel@tonic-gate * ethernet interfaces, and convert the first found 48-bit MAC address into 35037c478bd9Sstevel@tonic-gate * EUI 64. caller also assumes that the system has a properly configured 35047c478bd9Sstevel@tonic-gate * Ethernet interface for this function to return non-zero. 35057c478bd9Sstevel@tonic-gate */ 35067c478bd9Sstevel@tonic-gate int 35077c478bd9Sstevel@tonic-gate ether_to_eui64(p_eui64) 35087c478bd9Sstevel@tonic-gate eui64_t *p_eui64; 35097c478bd9Sstevel@tonic-gate { 35107c478bd9Sstevel@tonic-gate struct ether_addr eth_addr; 35117c478bd9Sstevel@tonic-gate 35127c478bd9Sstevel@tonic-gate if (p_eui64 == NULL) { 35137c478bd9Sstevel@tonic-gate return (0); 35147c478bd9Sstevel@tonic-gate } 35157c478bd9Sstevel@tonic-gate if (!get_first_hwaddr(eth_addr.ether_addr_octet, 35167c478bd9Sstevel@tonic-gate sizeof (eth_addr.ether_addr_octet))) { 35177c478bd9Sstevel@tonic-gate return (0); 35187c478bd9Sstevel@tonic-gate } 35197c478bd9Sstevel@tonic-gate /* 35207c478bd9Sstevel@tonic-gate * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1] 35217c478bd9Sstevel@tonic-gate */ 35227c478bd9Sstevel@tonic-gate p_eui64->e8[0] = (eth_addr.ether_addr_octet[0] & 0xFF) | 0x02; 35237c478bd9Sstevel@tonic-gate p_eui64->e8[1] = (eth_addr.ether_addr_octet[1] & 0xFF); 35247c478bd9Sstevel@tonic-gate p_eui64->e8[2] = (eth_addr.ether_addr_octet[2] & 0xFF); 35257c478bd9Sstevel@tonic-gate p_eui64->e8[3] = 0xFF; 35267c478bd9Sstevel@tonic-gate p_eui64->e8[4] = 0xFE; 35277c478bd9Sstevel@tonic-gate p_eui64->e8[5] = (eth_addr.ether_addr_octet[3] & 0xFF); 35287c478bd9Sstevel@tonic-gate p_eui64->e8[6] = (eth_addr.ether_addr_octet[4] & 0xFF); 35297c478bd9Sstevel@tonic-gate p_eui64->e8[7] = (eth_addr.ether_addr_octet[5] & 0xFF); 35307c478bd9Sstevel@tonic-gate return (1); 35317c478bd9Sstevel@tonic-gate } 35327c478bd9Sstevel@tonic-gate #endif /* INET6 */ 35337c478bd9Sstevel@tonic-gate 35347c478bd9Sstevel@tonic-gate struct bit_ent { 35357c478bd9Sstevel@tonic-gate int val; 35367c478bd9Sstevel@tonic-gate char *off, *on; 35377c478bd9Sstevel@tonic-gate }; 35387c478bd9Sstevel@tonic-gate 35397c478bd9Sstevel@tonic-gate /* see sbuf[] below if you change this list */ 35407c478bd9Sstevel@tonic-gate static struct bit_ent bit_list[] = { 35417c478bd9Sstevel@tonic-gate { TIOCM_DTR, "dtr", "DTR" }, 35427c478bd9Sstevel@tonic-gate { TIOCM_RTS, "rts", "RTS" }, 35437c478bd9Sstevel@tonic-gate { TIOCM_CTS, "cts", "CTS" }, 35447c478bd9Sstevel@tonic-gate { TIOCM_CD, "dcd", "DCD" }, 35457c478bd9Sstevel@tonic-gate { TIOCM_RI, "ri", "RI" }, 35467c478bd9Sstevel@tonic-gate { TIOCM_DSR, "dsr", "DSR" }, 35477c478bd9Sstevel@tonic-gate #if 0 35487c478bd9Sstevel@tonic-gate { TIOCM_LE, "disabled", "ENABLED" }, 35497c478bd9Sstevel@tonic-gate { TIOCM_ST, NULL, "2nd-XMIT" }, 35507c478bd9Sstevel@tonic-gate { TIOCM_SR, NULL, "2nd-RECV" }, 35517c478bd9Sstevel@tonic-gate #endif 35527c478bd9Sstevel@tonic-gate { 0, NULL, NULL } 35537c478bd9Sstevel@tonic-gate }; 35547c478bd9Sstevel@tonic-gate 35557c478bd9Sstevel@tonic-gate static void 35567c478bd9Sstevel@tonic-gate getbits(int fd, char *name, FILE *strptr) 35577c478bd9Sstevel@tonic-gate { 35587c478bd9Sstevel@tonic-gate int nmods, i; 35597c478bd9Sstevel@tonic-gate struct str_list strlist; 35607c478bd9Sstevel@tonic-gate struct bit_ent *be; 35617c478bd9Sstevel@tonic-gate int mstate; 35627c478bd9Sstevel@tonic-gate char sbuf[50]; /* sum of string lengths in bit_list */ 35637c478bd9Sstevel@tonic-gate char *str; 35647c478bd9Sstevel@tonic-gate 35657c478bd9Sstevel@tonic-gate nmods = ioctl(fd, I_LIST, NULL); 35667c478bd9Sstevel@tonic-gate if (nmods < 0) { 35677c478bd9Sstevel@tonic-gate error("unable to get module count: %m"); 35687c478bd9Sstevel@tonic-gate } else { 35697c478bd9Sstevel@tonic-gate strlist.sl_nmods = nmods; 35707c478bd9Sstevel@tonic-gate strlist.sl_modlist = malloc(sizeof (struct str_mlist) * nmods); 35717c478bd9Sstevel@tonic-gate if (strlist.sl_modlist == NULL) 35727c478bd9Sstevel@tonic-gate novm("module list"); 35737c478bd9Sstevel@tonic-gate if (ioctl(fd, I_LIST, (caddr_t)&strlist) < 0) { 35747c478bd9Sstevel@tonic-gate error("unable to get module names: %m"); 35757c478bd9Sstevel@tonic-gate } else { 35767c478bd9Sstevel@tonic-gate for (i = 0; i < strlist.sl_nmods; i++) 35777c478bd9Sstevel@tonic-gate (void) flprintf(strptr, "%d: %s", i, 35787c478bd9Sstevel@tonic-gate strlist.sl_modlist[i].l_name); 35797c478bd9Sstevel@tonic-gate free(strlist.sl_modlist); 35807c478bd9Sstevel@tonic-gate } 35817c478bd9Sstevel@tonic-gate } 35827c478bd9Sstevel@tonic-gate if (ioctl(fd, TIOCMGET, &mstate) < 0) { 35837c478bd9Sstevel@tonic-gate error("unable to get modem state: %m"); 35847c478bd9Sstevel@tonic-gate } else { 35857c478bd9Sstevel@tonic-gate sbuf[0] = '\0'; 35867c478bd9Sstevel@tonic-gate for (be = bit_list; be->val != 0; be++) { 35877c478bd9Sstevel@tonic-gate str = (be->val & mstate) ? be->on : be->off; 35887c478bd9Sstevel@tonic-gate if (str != NULL) { 35897c478bd9Sstevel@tonic-gate if (sbuf[0] != '\0') 35907c478bd9Sstevel@tonic-gate (void) strcat(sbuf, " "); 35917c478bd9Sstevel@tonic-gate (void) strcat(sbuf, str); 35927c478bd9Sstevel@tonic-gate } 35937c478bd9Sstevel@tonic-gate } 35947c478bd9Sstevel@tonic-gate (void) flprintf(strptr, "%s: %s\n", name, sbuf); 35957c478bd9Sstevel@tonic-gate } 35967c478bd9Sstevel@tonic-gate } 35977c478bd9Sstevel@tonic-gate 35987c478bd9Sstevel@tonic-gate /* 35997c478bd9Sstevel@tonic-gate * Print state of serial link. The stream might be linked under the 36007c478bd9Sstevel@tonic-gate * /dev/sppp driver. If it is, then it's necessary to unlink it first 36017c478bd9Sstevel@tonic-gate * and relink it when done. Otherwise, it's not possible to use 36027c478bd9Sstevel@tonic-gate * ioctl() on the stream. 36037c478bd9Sstevel@tonic-gate */ 36047c478bd9Sstevel@tonic-gate void 36057c478bd9Sstevel@tonic-gate sys_print_state(FILE *strptr) 36067c478bd9Sstevel@tonic-gate { 36077c478bd9Sstevel@tonic-gate bool was_linked; 36087c478bd9Sstevel@tonic-gate 36097c478bd9Sstevel@tonic-gate if (pppfd == -1) 36107c478bd9Sstevel@tonic-gate return; 36117c478bd9Sstevel@tonic-gate if (ttyfd == -1) { 36127c478bd9Sstevel@tonic-gate (void) flprintf(strptr, "serial link is not active"); 36137c478bd9Sstevel@tonic-gate return; 36147c478bd9Sstevel@tonic-gate } 36157c478bd9Sstevel@tonic-gate was_linked = fdmuxid != -1; 36167c478bd9Sstevel@tonic-gate if (was_linked && ioctl(pppfd, I_UNLINK, fdmuxid) == -1) { 36177c478bd9Sstevel@tonic-gate error("I_UNLINK: %m"); 36187c478bd9Sstevel@tonic-gate } else { 36197c478bd9Sstevel@tonic-gate fdmuxid = -1; 36207c478bd9Sstevel@tonic-gate getbits(ttyfd, devnam, strptr); 36217c478bd9Sstevel@tonic-gate if (was_linked && 36227c478bd9Sstevel@tonic-gate (fdmuxid = ioctl(pppfd, I_LINK, (void *)ttyfd)) == -1) 36237c478bd9Sstevel@tonic-gate fatal("I_LINK: %m"); 36247c478bd9Sstevel@tonic-gate } 36257c478bd9Sstevel@tonic-gate } 36267c478bd9Sstevel@tonic-gate 36277c478bd9Sstevel@tonic-gate /* 36287c478bd9Sstevel@tonic-gate * send ioctl to driver asking it to block packets with network protocol 36297c478bd9Sstevel@tonic-gate * proto in the control queue until the queue for proto is plumbed. 36307c478bd9Sstevel@tonic-gate */ 36317c478bd9Sstevel@tonic-gate void 36327c478bd9Sstevel@tonic-gate sys_block_proto(uint16_t proto) 36337c478bd9Sstevel@tonic-gate { 36347c478bd9Sstevel@tonic-gate if (proto > 0x7fff) { 36357c478bd9Sstevel@tonic-gate warn("cannot block: not a network proto 0x%lx\n", proto); 36367c478bd9Sstevel@tonic-gate return; 36377c478bd9Sstevel@tonic-gate } 36387c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_BLOCKNP, &proto, sizeof (proto), 0) < 0) { 36397c478bd9Sstevel@tonic-gate warn("PPPIO_BLOCKNP ioctl failed %m"); 36407c478bd9Sstevel@tonic-gate } 36417c478bd9Sstevel@tonic-gate } 36427c478bd9Sstevel@tonic-gate /* 36437c478bd9Sstevel@tonic-gate * send ioctl to driver asking it to release packets with network protocol 36447c478bd9Sstevel@tonic-gate * proto from control queue to the protocol specific queue. 36457c478bd9Sstevel@tonic-gate */ 36467c478bd9Sstevel@tonic-gate void 36477c478bd9Sstevel@tonic-gate sys_unblock_proto(uint16_t proto) 36487c478bd9Sstevel@tonic-gate { 36497c478bd9Sstevel@tonic-gate if (proto > 0x7fff) { 36507c478bd9Sstevel@tonic-gate warn("cannot unblock: not a network proto 0x%lx\n", proto); 36517c478bd9Sstevel@tonic-gate return; 36527c478bd9Sstevel@tonic-gate } 36537c478bd9Sstevel@tonic-gate if (strioctl(pppfd, PPPIO_UNBLOCKNP, &proto, sizeof (proto), 0) < 0) { 36547c478bd9Sstevel@tonic-gate warn("PPPIO_UNBLOCKNP ioctl failed %m"); 36557c478bd9Sstevel@tonic-gate } 36567c478bd9Sstevel@tonic-gate } 3657