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