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