Home | History | Annotate | Download | only in pppd
      1 /*
      2  * System-dependent procedures for pppd under Solaris 2.
      3  *
      4  * Parts re-written by Adi Masputra <adi.masputra (at) sun.com>, based on
      5  * the original sys-svr4.c
      6  *
      7  * Copyright (c) 2000 by Sun Microsystems, Inc.
      8  * All rights reserved.
      9  *
     10  * Permission to use, copy, modify, and distribute this software and its
     11  * documentation is hereby granted, provided that the above copyright
     12  * notice appears in all copies.
     13  *
     14  * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
     15  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
     16  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
     17  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT.  SUN SHALL NOT BE LIABLE FOR
     18  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
     19  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
     20  *
     21  * Copyright (c) 1995-2002 Paul Mackerras. All rights reserved.
     22  *
     23  * Redistribution and use in source and binary forms, with or without
     24  * modification, are permitted provided that the following conditions
     25  * are met:
     26  *
     27  * 1. Redistributions of source code must retain the above copyright
     28  *    notice, this list of conditions and the following disclaimer.
     29  *
     30  * 2. The name(s) of the authors of this software must not be used to
     31  *    endorse or promote products derived from this software without
     32  *    prior written permission.
     33  *
     34  * 3. Redistributions of any form whatsoever must retain the following
     35  *    acknowledgment:
     36  *    "This product includes software developed by Paul Mackerras
     37  *     <paulus (at) samba.org>".
     38  *
     39  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
     40  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     41  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
     42  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     43  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
     44  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     45  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     46  *
     47  * Derived from main.c and pppd.h, which are:
     48  *
     49  * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
     50  *
     51  * Redistribution and use in source and binary forms, with or without
     52  * modification, are permitted provided that the following conditions
     53  * are met:
     54  *
     55  * 1. Redistributions of source code must retain the above copyright
     56  *    notice, this list of conditions and the following disclaimer.
     57  *
     58  * 2. Redistributions in binary form must reproduce the above copyright
     59  *    notice, this list of conditions and the following disclaimer in
     60  *    the documentation and/or other materials provided with the
     61  *    distribution.
     62  *
     63  * 3. The name "Carnegie Mellon University" must not be used to
     64  *    endorse or promote products derived from this software without
     65  *    prior written permission. For permission or any legal
     66  *    details, please contact
     67  *      Office of Technology Transfer
     68  *      Carnegie Mellon University
     69  *      5000 Forbes Avenue
     70  *      Pittsburgh, PA  15213-3890
     71  *      (412) 268-4387, fax: (412) 268-7395
     72  *      tech-transfer (at) andrew.cmu.edu
     73  *
     74  * 4. Redistributions of any form whatsoever must retain the following
     75  *    acknowledgment:
     76  *    "This product includes software developed by Computing Services
     77  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
     78  *
     79  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
     80  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     81  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
     82  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     83  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
     84  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     85  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     86  */
     87 
     88 #define RCSID	"$Id: sys-solaris.c,v 1.16 2008/01/30 14:26:53 carlsonj Exp $"
     89 
     90 #include <limits.h>
     91 #include <stdio.h>
     92 #include <stddef.h>
     93 #include <stdlib.h>
     94 #include <string.h>
     95 #include <ctype.h>
     96 #include <errno.h>
     97 #include <fcntl.h>
     98 #include <unistd.h>
     99 #include <termios.h>
    100 #ifndef CRTSCTS
    101 #include <sys/termiox.h>
    102 #endif
    103 #include <signal.h>
    104 #include <utmpx.h>
    105 #include <stropts.h>
    106 #include <sys/types.h>
    107 #include <sys/ioccom.h>
    108 #include <sys/stream.h>
    109 #include <sys/stropts.h>
    110 #include <sys/socket.h>
    111 #include <sys/sockio.h>
    112 #include <sys/sysmacros.h>
    113 #include <sys/systeminfo.h>
    114 #include <sys/dlpi.h>
    115 #include <sys/stat.h>
    116 #include <sys/mkdev.h>
    117 #include <net/if.h>
    118 #include <net/if_arp.h>
    119 #include <net/route.h>
    120 #include <net/ppp_defs.h>
    121 #include <net/pppio.h>
    122 #include <netinet/in.h>
    123 #ifdef SOL2
    124 #include <sys/tihdr.h>
    125 #include <sys/tiuser.h>
    126 #include <inet/common.h>
    127 #include <inet/mib2.h>
    128 #include <sys/ethernet.h>
    129 #endif
    130 
    131 #include "pppd.h"
    132 #include "fsm.h"
    133 #include "lcp.h"
    134 #include "ipcp.h"
    135 #include "ccp.h"
    136 
    137 #if !defined(PPP_DRV_NAME)
    138 #define PPP_DRV_NAME	"ppp"
    139 #endif /* !defined(PPP_DRV_NAME) */
    140 
    141 #if !defined(PPP_DEV_NAME)
    142 #define PPP_DEV_NAME	"/dev/" PPP_DRV_NAME
    143 #endif /* !defined(PPP_DEV_NAME) */
    144 
    145 #if !defined(AHDLC_MOD_NAME)
    146 #define AHDLC_MOD_NAME	"ppp_ahdl"
    147 #endif /* !defined(AHDLC_MOD_NAME) */
    148 
    149 #if !defined(COMP_MOD_NAME)
    150 #define COMP_MOD_NAME	"ppp_comp"
    151 #endif /* !defined(COMP_MOD_NAME) */
    152 
    153 #if !defined(IP_DEV_NAME)
    154 #define	IP_DEV_NAME	"/dev/ip"
    155 #endif /* !defined(IP_DEV_NAME) */
    156 
    157 #if !defined(IP_MOD_NAME)
    158 #define	IP_MOD_NAME	"ip"
    159 #endif /* !defined(IP_MOD_NAME) */
    160 
    161 #if !defined(UDP_DEV_NAME) && defined(SOL2)
    162 #define	UDP_DEV_NAME	"/dev/udp"
    163 #endif /* !defined(UDP_DEV_NAME) && defined(SOL2) */
    164 
    165 #if !defined(UDP6_DEV_NAME) && defined(SOL2)
    166 #define	UDP6_DEV_NAME	"/dev/udp6"
    167 #endif /* !defined(UDP6_DEV_NAME) && defined(SOL2) */
    168 
    169 static const char rcsid[] = RCSID;
    170 
    171 #if defined(SOL2)
    172 /*
    173  * "/dev/udp" is used as a multiplexor to PLINK the interface stream
    174  * under. It is used in place of "/dev/ip" since STREAMS will not let
    175  * a driver be PLINK'ed under itself, and "/dev/ip" is typically the
    176  * driver at the bottom of the tunneling interfaces stream.
    177  */
    178 static char *mux_dev_name = UDP_DEV_NAME;
    179 #else
    180 static char *mux_dev_name = IP_DEV_NAME;
    181 #endif
    182 static int	pppfd;
    183 static int	fdmuxid = -1;
    184 static int	ipfd;
    185 static int	ipmuxid = -1;
    186 
    187 #if defined(INET6) && defined(SOL2)
    188 static int	ip6fd;		/* IP file descriptor */
    189 static int	ip6muxid = -1;	/* Multiplexer file descriptor */
    190 static int	if6_is_up = 0;	/* IPv6 interface has been marked up */
    191 
    192 #define _IN6_LLX_FROM_EUI64(l, s, eui64, as) do {	\
    193 	s->sin6_addr.s6_addr32[0] = htonl(as); 	\
    194 	eui64_copy(eui64, s->sin6_addr.s6_addr32[2]);	\
    195 	s->sin6_family = AF_INET6;		\
    196 	l.lifr_addr.ss_family = AF_INET6;	\
    197 	l.lifr_addrlen = 64;			\
    198 	l.lifr_addr = laddr;			\
    199 	} while (0)
    200 
    201 #define IN6_LLADDR_FROM_EUI64(l, s, eui64)  \
    202     _IN6_LLX_FROM_EUI64(l, s, eui64, 0xfe800000)
    203 
    204 #define IN6_LLTOKEN_FROM_EUI64(l, s, eui64) \
    205     _IN6_LLX_FROM_EUI64(l, s, eui64, 0)
    206 
    207 #endif /* defined(INET6) && defined(SOL2) */
    208 
    209 #if defined(INET6) && defined(SOL2)
    210 static char	first_ether_name[LIFNAMSIZ];	/* Solaris 8 and above */
    211 #else
    212 static char	first_ether_name[IFNAMSIZ];	/* Before Solaris 8 */
    213 #define MAXIFS		256			/* Max # of interfaces */
    214 #endif /* defined(INET6) && defined(SOL2) */
    215 
    216 static int	restore_term;
    217 static struct termios inittermios;
    218 #ifndef CRTSCTS
    219 static struct termiox inittermiox;
    220 static int	termiox_ok;
    221 #endif
    222 static struct winsize wsinfo;	/* Initial window size info */
    223 static pid_t	tty_sid;	/* original session ID for terminal */
    224 
    225 extern u_char	inpacket_buf[];	/* borrowed from main.c */
    226 
    227 #define MAX_POLLFDS	32
    228 static struct pollfd pollfds[MAX_POLLFDS];
    229 static int n_pollfds;
    230 
    231 static int	link_mtu, link_mru;
    232 
    233 #define NMODULES	32
    234 static int	tty_nmodules;
    235 static char	tty_modules[NMODULES][FMNAMESZ+1];
    236 static int	tty_npushed;
    237 
    238 static int	if_is_up;	/* Interface has been marked up */
    239 static u_int32_t remote_addr;		/* IP address of peer */
    240 static u_int32_t default_route_gateway;	/* Gateway for default route added */
    241 static u_int32_t proxy_arp_addr;	/* Addr for proxy arp entry added */
    242 
    243 /* Prototypes for procedures local to this file. */
    244 static int translate_speed __P((int));
    245 static int baud_rate_of __P((int));
    246 static int get_ether_addr __P((u_int32_t, struct sockaddr *));
    247 static int get_hw_addr __P((char *, u_int32_t, struct sockaddr *));
    248 static int get_hw_addr_dlpi __P((char *, struct sockaddr *));
    249 static int dlpi_attach __P((int, int));
    250 static int dlpi_info_req __P((int));
    251 static int dlpi_get_reply __P((int, union DL_primitives *, int, int));
    252 static int strioctl __P((int, int, void *, int, int));
    253 
    254 #ifdef SOL2
    255 /*
    256  * sifppa - Sets interface ppa
    257  *
    258  * without setting the ppa, ip module will return EINVAL upon setting the
    259  * interface UP (SIOCSxIFFLAGS). This is because ip module in 2.8 expects
    260  * two DLPI_INFO_REQ to be sent down to the driver (below ip) before
    261  * IFF_UP can be set. Plumbing the device causes one DLPI_INFO_REQ to
    262  * be sent down, and the second DLPI_INFO_REQ is sent upon receiving
    263  * IF_UNITSEL (old) or SIOCSLIFNAME (new) ioctls. Such setting of the ppa
    264  * is required because the ppp DLPI provider advertises itself as
    265  * a DLPI style 2 type, which requires a point of attachment to be
    266  * specified. The only way the user can specify a point of attachment
    267  * is via SIOCSLIFNAME or IF_UNITSEL.
    268  *
    269  * Such changes in the behavior of ip module was made to meet new or
    270  * evolving standards requirements.
    271  *
    272  */
    273 static int
    274 sifppa(fd, ppa)
    275     int fd;
    276     int ppa;
    277 {
    278     return (int)ioctl(fd, IF_UNITSEL, (char *)&ppa);
    279 }
    280 #endif /* SOL2 */
    281 
    282 #if defined(SOL2) && defined(INET6)
    283 /*
    284  * get_first_ethernet - returns the first Ethernet interface name found in
    285  * the system, or NULL if none is found
    286  *
    287  * NOTE: This is the lifreq version (Solaris 8 and above)
    288  */
    289 char *
    290 get_first_ethernet()
    291 {
    292     struct lifnum lifn;
    293     struct lifconf lifc;
    294     struct lifreq *plifreq;
    295     struct lifreq lifr;
    296     int	fd, num_ifs, i, found;
    297     uint_t fl, req_size;
    298     char *req;
    299 
    300     fd = socket(AF_INET, SOCK_DGRAM, 0);
    301     if (fd < 0) {
    302 	return 0;
    303     }
    304 
    305     /*
    306      * Find out how many interfaces are running
    307      */
    308     lifn.lifn_family = AF_UNSPEC;
    309     lifn.lifn_flags = LIFC_NOXMIT;
    310     if (ioctl(fd, SIOCGLIFNUM, &lifn) < 0) {
    311 	close(fd);
    312 	error("could not determine number of interfaces: %m");
    313 	return 0;
    314     }
    315 
    316     num_ifs = lifn.lifn_count;
    317     req_size = num_ifs * sizeof(struct lifreq);
    318     req = malloc(req_size);
    319     if (req == NULL) {
    320 	close(fd);
    321 	error("out of memory");
    322 	return 0;
    323     }
    324 
    325     /*
    326      * Get interface configuration info for all interfaces
    327      */
    328     lifc.lifc_family = AF_UNSPEC;
    329     lifc.lifc_flags = LIFC_NOXMIT;
    330     lifc.lifc_len = req_size;
    331     lifc.lifc_buf = req;
    332     if (ioctl(fd, SIOCGLIFCONF, &lifc) < 0) {
    333 	close(fd);
    334 	free(req);
    335 	error("SIOCGLIFCONF: %m");
    336 	return 0;
    337     }
    338 
    339     /*
    340      * And traverse each interface to look specifically for the first
    341      * occurence of an Ethernet interface which has been marked up
    342      */
    343     plifreq = lifc.lifc_req;
    344     found = 0;
    345     for (i = lifc.lifc_len / sizeof(struct lifreq); i > 0; i--, plifreq++) {
    346 
    347 	if (strchr(plifreq->lifr_name, ':') != NULL)
    348 	    continue;
    349 
    350 	memset(&lifr, 0, sizeof(lifr));
    351 	strncpy(lifr.lifr_name, plifreq->lifr_name, sizeof(lifr.lifr_name));
    352 	if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
    353 	    close(fd);
    354 	    free(req);
    355 	    error("SIOCGLIFFLAGS: %m");
    356 	    return 0;
    357 	}
    358 	fl = lifr.lifr_flags;
    359 
    360 	if ((fl & (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
    361 		!= (IFF_UP | IFF_BROADCAST))
    362 	    continue;
    363 
    364 	found = 1;
    365 	break;
    366     }
    367     free(req);
    368     close(fd);
    369 
    370     if (found) {
    371 	strncpy(first_ether_name, lifr.lifr_name, sizeof(first_ether_name));
    372 	return (char *)first_ether_name;
    373     } else
    374 	return NULL;
    375 }
    376 #else
    377 /*
    378  * get_first_ethernet - returns the first Ethernet interface name found in
    379  * the system, or NULL if none is found
    380  *
    381  * NOTE: This is the ifreq version (before Solaris 8).
    382  */
    383 char *
    384 get_first_ethernet()
    385 {
    386     struct ifconf ifc;
    387     struct ifreq *pifreq;
    388     struct ifreq ifr;
    389     int	fd, num_ifs, i, found;
    390     uint_t fl, req_size;
    391     char *req;
    392 
    393     fd = socket(AF_INET, SOCK_DGRAM, 0);
    394     if (fd < 0) {
    395 	return 0;
    396     }
    397 
    398     /*
    399      * Find out how many interfaces are running
    400      */
    401     if (ioctl(fd, SIOCGIFNUM, (char *)&num_ifs) < 0) {
    402 	num_ifs = MAXIFS;
    403     }
    404 
    405     req_size = num_ifs * sizeof(struct ifreq);
    406     req = malloc(req_size);
    407     if (req == NULL) {
    408 	close(fd);
    409 	error("out of memory");
    410 	return 0;
    411     }
    412 
    413     /*
    414      * Get interface configuration info for all interfaces
    415      */
    416     ifc.ifc_len = req_size;
    417     ifc.ifc_buf = req;
    418     if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
    419 	close(fd);
    420 	free(req);
    421 	error("SIOCGIFCONF: %m");
    422 	return 0;
    423     }
    424 
    425     /*
    426      * And traverse each interface to look specifically for the first
    427      * occurence of an Ethernet interface which has been marked up
    428      */
    429     pifreq = ifc.ifc_req;
    430     found = 0;
    431     for (i = ifc.ifc_len / sizeof(struct ifreq); i > 0; i--, pifreq++) {
    432 
    433 	if (strchr(pifreq->ifr_name, ':') != NULL)
    434 	    continue;
    435 
    436 	memset(&ifr, 0, sizeof(ifr));
    437 	strncpy(ifr.ifr_name, pifreq->ifr_name, sizeof(ifr.ifr_name));
    438 	if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
    439 	    close(fd);
    440 	    free(req);
    441 	    error("SIOCGIFFLAGS: %m");
    442 	    return 0;
    443 	}
    444 	fl = ifr.ifr_flags;
    445 
    446 	if ((fl & (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
    447 		!= (IFF_UP | IFF_BROADCAST))
    448 	    continue;
    449 
    450 	found = 1;
    451 	break;
    452     }
    453     free(req);
    454     close(fd);
    455 
    456     if (found) {
    457 	strncpy(first_ether_name, ifr.ifr_name, sizeof(first_ether_name));
    458 	return (char *)first_ether_name;
    459     } else
    460 	return NULL;
    461 }
    462 #endif /* defined(SOL2) && defined(INET6) */
    463 
    464 #if defined(SOL2)
    465 /*
    466  * get_if_hwaddr - get the hardware address for the specified
    467  * network interface device.
    468  */
    469 int
    470 get_if_hwaddr(u_char *addr, char *if_name)
    471 {
    472     struct sockaddr s_eth_addr;
    473     struct ether_addr *eth_addr = (struct ether_addr *)&s_eth_addr.sa_data;
    474 
    475     if (if_name == NULL)
    476 	return -1;
    477 
    478     /*
    479      * Send DL_INFO_REQ to the driver to solicit its MAC address
    480      */
    481     if (!get_hw_addr_dlpi(if_name, &s_eth_addr)) {
    482 	error("could not obtain hardware address for %s", if_name);
    483 	return -1;
    484     }
    485 
    486     memcpy(addr, eth_addr->ether_addr_octet, 6);
    487     return 1;
    488 }
    489 #endif /* SOL2 */
    490 
    491 #if defined(SOL2) && defined(INET6)
    492 /*
    493  * slifname - Sets interface ppa and flags
    494  *
    495  * in addition to the comments stated in sifppa(), IFF_IPV6 bit must
    496  * be set in order to declare this as an IPv6 interface
    497  */
    498 static int
    499 slifname(fd, ppa)
    500     int fd;
    501     int ppa;
    502 {
    503     struct  lifreq lifr;
    504     int	    ret;
    505 
    506     memset(&lifr, 0, sizeof(lifr));
    507     ret = ioctl(fd, SIOCGLIFFLAGS, &lifr);
    508     if (ret < 0)
    509 	goto slifname_done;
    510 
    511     lifr.lifr_flags |= IFF_IPV6;
    512     lifr.lifr_flags &= ~(IFF_BROADCAST | IFF_IPV4);
    513     lifr.lifr_ppa = ppa;
    514     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
    515 
    516     ret = ioctl(fd, SIOCSLIFNAME, &lifr);
    517 
    518 slifname_done:
    519     return ret;
    520 
    521 
    522 }
    523 
    524 
    525 /*
    526  * ether_to_eui64 - Convert 48-bit Ethernet address into 64-bit EUI
    527  *
    528  * walks the list of valid ethernet interfaces, and convert the first
    529  * found 48-bit MAC address into EUI 64. caller also assumes that
    530  * the system has a properly configured Ethernet interface for this
    531  * function to return non-zero.
    532  */
    533 int
    534 ether_to_eui64(eui64_t *p_eui64)
    535 {
    536     struct sockaddr s_eth_addr;
    537     struct ether_addr *eth_addr = (struct ether_addr *)&s_eth_addr.sa_data;
    538     char *if_name;
    539 
    540     if ((if_name = get_first_ethernet()) == NULL) {
    541 	error("no persistent id can be found");
    542 	return 0;
    543     }
    544 
    545     /*
    546      * Send DL_INFO_REQ to the driver to solicit its MAC address
    547      */
    548     if (!get_hw_addr_dlpi(if_name, &s_eth_addr)) {
    549 	error("could not obtain hardware address for %s", if_name);
    550 	return 0;
    551     }
    552 
    553     /*
    554      * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1]
    555      */
    556     p_eui64->e8[0] = (eth_addr->ether_addr_octet[0] & 0xFF) | 0x02;
    557     p_eui64->e8[1] = (eth_addr->ether_addr_octet[1] & 0xFF);
    558     p_eui64->e8[2] = (eth_addr->ether_addr_octet[2] & 0xFF);
    559     p_eui64->e8[3] = 0xFF;
    560     p_eui64->e8[4] = 0xFE;
    561     p_eui64->e8[5] = (eth_addr->ether_addr_octet[3] & 0xFF);
    562     p_eui64->e8[6] = (eth_addr->ether_addr_octet[4] & 0xFF);
    563     p_eui64->e8[7] = (eth_addr->ether_addr_octet[5] & 0xFF);
    564 
    565     return 1;
    566 }
    567 #endif /* defined(SOL2) && defined(INET6) */
    568 
    569 /*
    570  * sys_init - System-dependent initialization.
    571  */
    572 void
    573 sys_init()
    574 {
    575     int ifd, x;
    576     struct ifreq ifr;
    577 #if defined(INET6) && defined(SOL2)
    578     int i6fd;
    579     struct lifreq lifr;
    580 #endif /* defined(INET6) && defined(SOL2) */
    581 #if !defined(SOL2)
    582     struct {
    583 	union DL_primitives prim;
    584 	char space[64];
    585     } reply;
    586 #endif /* !defined(SOL2) */
    587 
    588     ipfd = open(mux_dev_name, O_RDWR, 0);
    589     if (ipfd < 0)
    590 	fatal("Couldn't open IP device: %m");
    591 
    592 #if defined(INET6) && defined(SOL2)
    593     ip6fd = open(UDP6_DEV_NAME, O_RDWR, 0);
    594     if (ip6fd < 0)
    595 	fatal("Couldn't open IP device (2): %m");
    596 #endif /* defined(INET6) && defined(SOL2) */
    597 
    598     if (default_device && !notty)
    599 	tty_sid = getsid((pid_t)0);
    600 
    601     pppfd = open(PPP_DEV_NAME, O_RDWR | O_NONBLOCK, 0);
    602     if (pppfd < 0)
    603 	fatal("Can't open %s: %m", PPP_DEV_NAME);
    604     if (kdebugflag & 1) {
    605 	x = PPPDBG_LOG + PPPDBG_DRIVER;
    606 	strioctl(pppfd, PPPIO_DEBUG, &x, sizeof(int), 0);
    607     }
    608 
    609     /* Assign a new PPA and get its unit number. */
    610     if (strioctl(pppfd, PPPIO_NEWPPA, &ifunit, 0, sizeof(int)) < 0)
    611 	fatal("Can't create new PPP interface: %m");
    612 
    613 #if defined(SOL2)
    614     /*
    615      * Since sys_init() is called prior to ifname being set in main(),
    616      * we need to get the ifname now, otherwise slifname(), and others,
    617      * will fail, or maybe, I should move them to a later point ?
    618      * <adi.masputra (at) sun.com>
    619      */
    620     sprintf(ifname, PPP_DRV_NAME "%d", ifunit);
    621 #endif /* defined(SOL2) */
    622     /*
    623      * Open the ppp device again and link it under the ip multiplexor.
    624      * IP will assign a unit number which hopefully is the same as ifunit.
    625      * I don't know any way to be certain they will be the same. :-(
    626      */
    627     ifd = open(PPP_DEV_NAME, O_RDWR, 0);
    628     if (ifd < 0)
    629 	fatal("Can't open %s (2): %m", PPP_DEV_NAME);
    630     if (kdebugflag & 1) {
    631 	x = PPPDBG_LOG + PPPDBG_DRIVER;
    632 	strioctl(ifd, PPPIO_DEBUG, &x, sizeof(int), 0);
    633     }
    634 
    635 #if defined(INET6) && defined(SOL2)
    636     i6fd = open(PPP_DEV_NAME, O_RDWR, 0);
    637     if (i6fd < 0) {
    638 	close(ifd);
    639 	fatal("Can't open %s (3): %m", PPP_DEV_NAME);
    640     }
    641     if (kdebugflag & 1) {
    642 	x = PPPDBG_LOG + PPPDBG_DRIVER;
    643 	strioctl(i6fd, PPPIO_DEBUG, &x, sizeof(int), 0);
    644     }
    645 #endif /* defined(INET6) && defined(SOL2) */
    646 
    647 #if defined(SOL2)
    648     if (ioctl(ifd, I_PUSH, IP_MOD_NAME) < 0) {
    649 	close(ifd);
    650 #if defined(INET6)
    651 	close(i6fd);
    652 #endif /* defined(INET6) */
    653 	fatal("Can't push IP module: %m");
    654     }
    655 
    656     /*
    657      * Assign ppa according to the unit number returned by ppp device
    658      * after plumbing is completed above.
    659      */
    660     if (sifppa(ifd, ifunit) < 0) {
    661         close (ifd);
    662 #if defined(INET6)
    663 	close(i6fd);
    664 #endif /* defined(INET6) */
    665         fatal("Can't set ppa for unit %d: %m", ifunit);
    666     }
    667 
    668 #if defined(INET6)
    669     /*
    670      * An IPv6 interface is created anyway, even when the user does not
    671      * explicitly enable it. Note that the interface will be marked
    672      * IPv6 during slifname().
    673      */
    674     if (ioctl(i6fd, I_PUSH, IP_MOD_NAME) < 0) {
    675 	close(ifd);
    676 	close(i6fd);
    677 	fatal("Can't push IP module (2): %m");
    678     }
    679 
    680     /*
    681      * Assign ppa according to the unit number returned by ppp device
    682      * after plumbing is completed above. In addition, mark the interface
    683      * as an IPv6 interface.
    684      */
    685     if (slifname(i6fd, ifunit) < 0) {
    686 	close(ifd);
    687 	close(i6fd);
    688 	fatal("Can't set ifname for unit %d: %m", ifunit);
    689     }
    690 #endif /* defined(INET6) */
    691 
    692     ipmuxid = ioctl(ipfd, I_PLINK, ifd);
    693     close(ifd);
    694     if (ipmuxid < 0) {
    695 #if defined(INET6)
    696 	close(i6fd);
    697 #endif /* defined(INET6) */
    698 	fatal("Can't I_PLINK PPP device to IP: %m");
    699     }
    700 
    701     memset(&ifr, 0, sizeof(ifr));
    702     sprintf(ifr.ifr_name, "%s", ifname);
    703     ifr.ifr_ip_muxid = ipmuxid;
    704 
    705     /*
    706      * In Sol 8 and later, STREAMS dynamic module plumbing feature exists.
    707      * This is so that an arbitrary module can be inserted, or deleted,
    708      * between ip module and the device driver without tearing down the
    709      * existing stream. Such feature requires the mux ids, which is set
    710      * by SIOCSIFMUXID (or SIOCLSIFMUXID).
    711      */
    712     if (ioctl(ipfd, SIOCSIFMUXID, &ifr) < 0) {
    713 	ioctl(ipfd, I_PUNLINK, ipmuxid);
    714 #if defined(INET6)
    715 	close(i6fd);
    716 #endif /* defined(INET6) */
    717 	fatal("SIOCSIFMUXID: %m");
    718     }
    719 
    720 #else /* else if !defined(SOL2) */
    721 
    722     if (dlpi_attach(ifd, ifunit) < 0 ||
    723 	dlpi_get_reply(ifd, &reply.prim, DL_OK_ACK, sizeof(reply)) < 0) {
    724 	close(ifd);
    725 	fatal("Can't attach to ppp%d: %m", ifunit);
    726     }
    727 
    728     ipmuxid = ioctl(ipfd, I_LINK, ifd);
    729     close(ifd);
    730     if (ipmuxid < 0)
    731 	fatal("Can't link PPP device to IP: %m");
    732 #endif /* defined(SOL2) */
    733 
    734 #if defined(INET6) && defined(SOL2)
    735     ip6muxid = ioctl(ip6fd, I_PLINK, i6fd);
    736     close(i6fd);
    737     if (ip6muxid < 0) {
    738 	ioctl(ipfd, I_PUNLINK, ipmuxid);
    739 	fatal("Can't I_PLINK PPP device to IP (2): %m");
    740     }
    741 
    742     memset(&lifr, 0, sizeof(lifr));
    743     sprintf(lifr.lifr_name, "%s", ifname);
    744     lifr.lifr_ip_muxid = ip6muxid;
    745 
    746     /*
    747      * Let IP know of the mux id [see comment for SIOCSIFMUXID above]
    748      */
    749     if (ioctl(ip6fd, SIOCSLIFMUXID, &lifr) < 0) {
    750 	ioctl(ipfd, I_PUNLINK, ipmuxid);
    751 	ioctl(ip6fd, I_PUNLINK, ip6muxid);
    752 	fatal("Can't link PPP device to IP (2): %m");
    753     }
    754 #endif /* defined(INET6) && defined(SOL2) */
    755 
    756 #if !defined(SOL2)
    757     /* Set the interface name for the link. */
    758     slprintf(ifr.ifr_name, sizeof(ifr.ifr_name), PPP_DRV_NAME "%d", ifunit);
    759     ifr.ifr_metric = ipmuxid;
    760     if (strioctl(ipfd, SIOCSIFNAME, (char *)&ifr, sizeof ifr, 0) < 0)
    761 	fatal("Can't set interface name %s: %m", ifr.ifr_name);
    762 #endif /* !defined(SOL2) */
    763 
    764     n_pollfds = 0;
    765 }
    766 
    767 /*
    768  * sys_cleanup - restore any system state we modified before exiting:
    769  * mark the interface down, delete default route and/or proxy arp entry.
    770  * This should call die() because it's called from die().
    771  */
    772 void
    773 sys_cleanup()
    774 {
    775 #if defined(SOL2)
    776     struct ifreq ifr;
    777 #if defined(INET6)
    778     struct lifreq lifr;
    779 #endif /* defined(INET6) */
    780 #endif /* defined(SOL2) */
    781 
    782 #if defined(SOL2) && defined(INET6)
    783     if (if6_is_up)
    784 	sif6down(0);
    785 #endif /* defined(SOL2) && defined(INET6) */
    786     if (if_is_up)
    787 	sifdown(0);
    788     if (default_route_gateway)
    789 	cifdefaultroute(0, default_route_gateway, default_route_gateway);
    790     if (proxy_arp_addr)
    791 	cifproxyarp(0, proxy_arp_addr);
    792 #if defined(SOL2)
    793     /*
    794      * Make sure we ask ip what the muxid, because 'ifconfig modlist' will
    795      * unlink and re-link the modules, causing the muxid to change.
    796      */
    797     memset(&ifr, 0, sizeof(ifr));
    798     sprintf(ifr.ifr_name, "%s", ifname);
    799     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
    800 	error("SIOCGIFFLAGS: %m");
    801 	return;
    802     }
    803 
    804     if (ioctl(ipfd, SIOCGIFMUXID, &ifr) < 0) {
    805 	error("SIOCGIFMUXID: %m");
    806 	return;
    807     }
    808 
    809     ipmuxid = ifr.ifr_ip_muxid;
    810 
    811     if (ioctl(ipfd, I_PUNLINK, ipmuxid) < 0) {
    812 	error("Can't I_PUNLINK PPP from IP: %m");
    813 	return;
    814     }
    815 #if defined(INET6)
    816     /*
    817      * Make sure we ask ip what the muxid, because 'ifconfig modlist' will
    818      * unlink and re-link the modules, causing the muxid to change.
    819      */
    820     memset(&lifr, 0, sizeof(lifr));
    821     sprintf(lifr.lifr_name, "%s", ifname);
    822     if (ioctl(ip6fd, SIOCGLIFFLAGS, &lifr) < 0) {
    823 	error("SIOCGLIFFLAGS: %m");
    824 	return;
    825     }
    826 
    827     if (ioctl(ip6fd, SIOCGLIFMUXID, &lifr) < 0) {
    828 	error("SIOCGLIFMUXID: %m");
    829 	return;
    830     }
    831 
    832     ip6muxid = lifr.lifr_ip_muxid;
    833 
    834     if (ioctl(ip6fd, I_PUNLINK, ip6muxid) < 0) {
    835 	error("Can't I_PUNLINK PPP from IP (2): %m");
    836     }
    837 #endif /* defined(INET6) */
    838 #endif /* defined(SOL2) */
    839 }
    840 
    841 /*
    842  * sys_close - Clean up in a child process before execing.
    843  */
    844 void
    845 sys_close()
    846 {
    847     close(ipfd);
    848 #if defined(INET6) && defined(SOL2)
    849     close(ip6fd);
    850 #endif /* defined(INET6) && defined(SOL2) */
    851     if (pppfd >= 0)
    852 	close(pppfd);
    853 }
    854 
    855 /*
    856  * sys_check_options - check the options that the user specified
    857  */
    858 int
    859 sys_check_options()
    860 {
    861     return 1;
    862 }
    863 
    864 #if 0
    865 /*
    866  * daemon - Detach us from controlling terminal session.
    867  */
    868 int
    869 daemon(nochdir, noclose)
    870     int nochdir, noclose;
    871 {
    872     int pid;
    873 
    874     if ((pid = fork()) < 0)
    875 	return -1;
    876     if (pid != 0)
    877 	exit(0);		/* parent dies */
    878     setsid();
    879     if (!nochdir)
    880 	chdir("/");
    881     if (!noclose) {
    882 	fclose(stdin);		/* don't need stdin, stdout, stderr */
    883 	fclose(stdout);
    884 	fclose(stderr);
    885     }
    886     return 0;
    887 }
    888 #endif
    889 
    890 /*
    891  * ppp_available - check whether the system has any ppp interfaces
    892  */
    893 int
    894 ppp_available()
    895 {
    896     struct stat buf;
    897 
    898     return stat(PPP_DEV_NAME, &buf) >= 0;
    899 }
    900 
    901 /*
    902  * any_compressions - see if compression is enabled or not
    903  *
    904  * In the STREAMS implementation of kernel-portion pppd,
    905  * the comp STREAMS module performs the ACFC, PFC, as well
    906  * CCP and VJ compressions. However, if the user has explicitly
    907  * declare to not enable them from the command line, there is
    908  * no point of having the comp module be pushed on the stream.
    909  */
    910 static int
    911 any_compressions()
    912 {
    913     if ((!lcp_wantoptions[0].neg_accompression) &&
    914 	(!lcp_wantoptions[0].neg_pcompression) &&
    915 	(!ccp_protent.enabled_flag) &&
    916 	(!ipcp_wantoptions[0].neg_vj)) {
    917 	    return 0;
    918     }
    919     return 1;
    920 }
    921 
    922 /*
    923  * tty_establish_ppp - Turn the serial port into a ppp interface.
    924  */
    925 int
    926 tty_establish_ppp(fd)
    927     int fd;
    928 {
    929     int i;
    930 
    931     /* Pop any existing modules off the tty stream. */
    932     for (i = 0;; ++i)
    933 	if (ioctl(fd, I_LOOK, tty_modules[i]) < 0
    934 	    || strcmp(tty_modules[i], "ptem") == 0
    935 	    || ioctl(fd, I_POP, 0) < 0)
    936 	    break;
    937     tty_nmodules = i;
    938 
    939     /* Push the async hdlc module and the compressor module. */
    940     tty_npushed = 0;
    941 
    942     if(!sync_serial) {
    943         if (ioctl(fd, I_PUSH, AHDLC_MOD_NAME) < 0) {
    944             error("Couldn't push PPP Async HDLC module: %m");
    945 	    return -1;
    946         }
    947         ++tty_npushed;
    948     }
    949     if (kdebugflag & 4) {
    950 	i = PPPDBG_LOG + PPPDBG_AHDLC;
    951 	strioctl(pppfd, PPPIO_DEBUG, &i, sizeof(int), 0);
    952     }
    953     /*
    954      * There's no need to push comp module if we don't intend
    955      * to compress anything
    956      */
    957     if (any_compressions()) {
    958         if (ioctl(fd, I_PUSH, COMP_MOD_NAME) < 0)
    959 	    error("Couldn't push PPP compression module: %m");
    960 	else
    961 	    ++tty_npushed;
    962     }
    963 
    964     if (kdebugflag & 2) {
    965 	i = PPPDBG_LOG;
    966 	if (any_compressions())
    967 	    i += PPPDBG_COMP;
    968 	strioctl(pppfd, PPPIO_DEBUG, &i, sizeof(int), 0);
    969     }
    970 
    971     /* Link the serial port under the PPP multiplexor. */
    972     if ((fdmuxid = ioctl(pppfd, I_LINK, fd)) < 0) {
    973 	error("Can't link tty to PPP mux: %m");
    974 	return -1;
    975     }
    976 
    977     return pppfd;
    978 }
    979 
    980 /*
    981  * tty_disestablish_ppp - Restore the serial port to normal operation.
    982  * It attempts to reconstruct the stream with the previously popped
    983  * modules.  This shouldn't call die() because it's called from die().
    984  */
    985 void
    986 tty_disestablish_ppp(fd)
    987     int fd;
    988 {
    989     int i;
    990 
    991     if (fdmuxid >= 0) {
    992 	if (ioctl(pppfd, I_UNLINK, fdmuxid) < 0) {
    993 	    if (!hungup)
    994 		error("Can't unlink tty from PPP mux: %m");
    995 	}
    996 	fdmuxid = -1;
    997 
    998 	if (!hungup) {
    999 	    while (tty_npushed > 0 && ioctl(fd, I_POP, 0) >= 0)
   1000 		--tty_npushed;
   1001 	    for (i = tty_nmodules - 1; i >= 0; --i)
   1002 		if (ioctl(fd, I_PUSH, tty_modules[i]) < 0)
   1003 		    error("Couldn't restore tty module %s: %m",
   1004 			   tty_modules[i]);
   1005 	}
   1006 	if (hungup && default_device && tty_sid > 0) {
   1007 	    /*
   1008 	     * If we have received a hangup, we need to send a SIGHUP
   1009 	     * to the terminal's controlling process.  The reason is
   1010 	     * that the original stream head for the terminal hasn't
   1011 	     * seen the M_HANGUP message (it went up through the ppp
   1012 	     * driver to the stream head for our fd to /dev/ppp).
   1013 	     */
   1014 	    kill(tty_sid, SIGHUP);
   1015 	}
   1016     }
   1017 }
   1018 
   1019 /*
   1020  * Check whether the link seems not to be 8-bit clean.
   1021  */
   1022 void
   1023 clean_check()
   1024 {
   1025     int x;
   1026     char *s;
   1027 
   1028     if (strioctl(pppfd, PPPIO_GCLEAN, &x, 0, sizeof(x)) < 0)
   1029 	return;
   1030     s = NULL;
   1031     switch (~x) {
   1032     case RCV_B7_0:
   1033 	s = "bit 7 set to 1";
   1034 	break;
   1035     case RCV_B7_1:
   1036 	s = "bit 7 set to 0";
   1037 	break;
   1038     case RCV_EVNP:
   1039 	s = "odd parity";
   1040 	break;
   1041     case RCV_ODDP:
   1042 	s = "even parity";
   1043 	break;
   1044     }
   1045     if (s != NULL) {
   1046 	warn("Serial link is not 8-bit clean:");
   1047 	warn("All received characters had %s", s);
   1048     }
   1049 }
   1050 
   1051 /*
   1052  * List of valid speeds.
   1053  */
   1054 struct speed {
   1055     int speed_int, speed_val;
   1056 } speeds[] = {
   1057 #ifdef B50
   1058     { 50, B50 },
   1059 #endif
   1060 #ifdef B75
   1061     { 75, B75 },
   1062 #endif
   1063 #ifdef B110
   1064     { 110, B110 },
   1065 #endif
   1066 #ifdef B134
   1067     { 134, B134 },
   1068 #endif
   1069 #ifdef B150
   1070     { 150, B150 },
   1071 #endif
   1072 #ifdef B200
   1073     { 200, B200 },
   1074 #endif
   1075 #ifdef B300
   1076     { 300, B300 },
   1077 #endif
   1078 #ifdef B600
   1079     { 600, B600 },
   1080 #endif
   1081 #ifdef B1200
   1082     { 1200, B1200 },
   1083 #endif
   1084 #ifdef B1800
   1085     { 1800, B1800 },
   1086 #endif
   1087 #ifdef B2000
   1088     { 2000, B2000 },
   1089 #endif
   1090 #ifdef B2400
   1091     { 2400, B2400 },
   1092 #endif
   1093 #ifdef B3600
   1094     { 3600, B3600 },
   1095 #endif
   1096 #ifdef B4800
   1097     { 4800, B4800 },
   1098 #endif
   1099 #ifdef B7200
   1100     { 7200, B7200 },
   1101 #endif
   1102 #ifdef B9600
   1103     { 9600, B9600 },
   1104 #endif
   1105 #ifdef B19200
   1106     { 19200, B19200 },
   1107 #endif
   1108 #ifdef B38400
   1109     { 38400, B38400 },
   1110 #endif
   1111 #ifdef EXTA
   1112     { 19200, EXTA },
   1113 #endif
   1114 #ifdef EXTB
   1115     { 38400, EXTB },
   1116 #endif
   1117 #ifdef B57600
   1118     { 57600, B57600 },
   1119 #endif
   1120 #ifdef B76800
   1121     { 76800, B76800 },
   1122 #endif
   1123 #ifdef B115200
   1124     { 115200, B115200 },
   1125 #endif
   1126 #ifdef B153600
   1127     { 153600, B153600 },
   1128 #endif
   1129 #ifdef B230400
   1130     { 230400, B230400 },
   1131 #endif
   1132 #ifdef B307200
   1133     { 307200, B307200 },
   1134 #endif
   1135 #ifdef B460800
   1136     { 460800, B460800 },
   1137 #endif
   1138     { 0, 0 }
   1139 };
   1140 
   1141 /*
   1142  * Translate from bits/second to a speed_t.
   1143  */
   1144 static int
   1145 translate_speed(bps)
   1146     int bps;
   1147 {
   1148     struct speed *speedp;
   1149 
   1150     if (bps == 0)
   1151 	return 0;
   1152     for (speedp = speeds; speedp->speed_int; speedp++)
   1153 	if (bps == speedp->speed_int)
   1154 	    return speedp->speed_val;
   1155     warn("speed %d not supported", bps);
   1156     return 0;
   1157 }
   1158 
   1159 /*
   1160  * Translate from a speed_t to bits/second.
   1161  */
   1162 static int
   1163 baud_rate_of(speed)
   1164     int speed;
   1165 {
   1166     struct speed *speedp;
   1167 
   1168     if (speed == 0)
   1169 	return 0;
   1170     for (speedp = speeds; speedp->speed_int; speedp++)
   1171 	if (speed == speedp->speed_val)
   1172 	    return speedp->speed_int;
   1173     return 0;
   1174 }
   1175 
   1176 /*
   1177  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
   1178  * at the requested speed, etc.  If `local' is true, set CLOCAL
   1179  * regardless of whether the modem option was specified.
   1180  */
   1181 void
   1182 set_up_tty(fd, local)
   1183     int fd, local;
   1184 {
   1185     int speed;
   1186     struct termios tios;
   1187 #if !defined (CRTSCTS)
   1188     struct termiox tiox;
   1189 #endif
   1190 
   1191     if (!sync_serial && tcgetattr(fd, &tios) < 0)
   1192 	fatal("tcgetattr: %m");
   1193 
   1194 #ifndef CRTSCTS
   1195     termiox_ok = 1;
   1196     if (!sync_serial && ioctl (fd, TCGETX, &tiox) < 0) {
   1197 	termiox_ok = 0;
   1198 	if (errno != ENOTTY)
   1199 	    error("TCGETX: %m");
   1200     }
   1201 #endif
   1202 
   1203     if (!restore_term) {
   1204 	inittermios = tios;
   1205 #ifndef CRTSCTS
   1206 	inittermiox = tiox;
   1207 #endif
   1208 	if (!sync_serial)
   1209 	    ioctl(fd, TIOCGWINSZ, &wsinfo);
   1210     }
   1211 
   1212     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
   1213 #ifdef CRTSCTS
   1214     if (crtscts > 0)
   1215 	tios.c_cflag |= CRTSCTS;
   1216     else if (crtscts < 0)
   1217 	tios.c_cflag &= ~CRTSCTS;
   1218 #else
   1219     if (crtscts != 0 && !termiox_ok) {
   1220 	error("Can't set RTS/CTS flow control");
   1221     } else if (crtscts > 0) {
   1222 	tiox.x_hflag |= RTSXOFF|CTSXON;
   1223     } else if (crtscts < 0) {
   1224 	tiox.x_hflag &= ~(RTSXOFF|CTSXON);
   1225     }
   1226 #endif
   1227 
   1228     if (stop_bits >= 2)
   1229 	tios.c_cflag |= CSTOPB;
   1230 
   1231     tios.c_cflag |= CS8 | CREAD | HUPCL;
   1232     if (local || !modem)
   1233 	tios.c_cflag |= CLOCAL;
   1234     tios.c_iflag = IGNBRK | IGNPAR;
   1235     tios.c_oflag = 0;
   1236     tios.c_lflag = 0;
   1237     tios.c_cc[VMIN] = 1;
   1238     tios.c_cc[VTIME] = 0;
   1239 
   1240     if (crtscts == -2) {
   1241 	tios.c_iflag |= IXON | IXOFF;
   1242 	tios.c_cc[VSTOP] = 0x13;	/* DC3 = XOFF = ^S */
   1243 	tios.c_cc[VSTART] = 0x11;	/* DC1 = XON  = ^Q */
   1244     }
   1245 
   1246     speed = translate_speed(inspeed);
   1247     if (speed) {
   1248 	cfsetospeed(&tios, speed);
   1249 	cfsetispeed(&tios, speed);
   1250     } else {
   1251 	speed = cfgetospeed(&tios);
   1252 	/*
   1253 	 * We can't proceed if the serial port speed is 0,
   1254 	 * since that implies that the serial port is disabled.
   1255 	 */
   1256 	if ((speed == B0) && !sync_serial)
   1257 	    fatal("Baud rate for %s is 0; need explicit baud rate", devnam);
   1258     }
   1259 
   1260     if (!sync_serial && tcsetattr(fd, TCSAFLUSH, &tios) < 0)
   1261 	fatal("tcsetattr: %m");
   1262 
   1263 #ifndef CRTSCTS
   1264     if (!sync_serial && termiox_ok && ioctl (fd, TCSETXF, &tiox) < 0){
   1265 	error("TCSETXF: %m");
   1266     }
   1267 #endif
   1268 
   1269     baud_rate = inspeed = baud_rate_of(speed);
   1270     if (!sync_serial)
   1271 	restore_term = 1;
   1272 }
   1273 
   1274 /*
   1275  * restore_tty - restore the terminal to the saved settings.
   1276  */
   1277 void
   1278 restore_tty(fd)
   1279     int fd;
   1280 {
   1281     if (restore_term) {
   1282 	if (!default_device) {
   1283 	    /*
   1284 	     * Turn off echoing, because otherwise we can get into
   1285 	     * a loop with the tty and the modem echoing to each other.
   1286 	     * We presume we are the sole user of this tty device, so
   1287 	     * when we close it, it will revert to its defaults anyway.
   1288 	     */
   1289 	    inittermios.c_lflag &= ~(ECHO | ECHONL);
   1290 	}
   1291 	if (!sync_serial && tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
   1292 	    if (!hungup && errno != ENXIO)
   1293 		warn("tcsetattr: %m");
   1294 #ifndef CRTSCTS
   1295 	if (!sync_serial && ioctl (fd, TCSETXF, &inittermiox) < 0){
   1296 	    if (!hungup && errno != ENXIO)
   1297 		error("TCSETXF: %m");
   1298 	}
   1299 #endif
   1300 	if (!sync_serial)
   1301 	    ioctl(fd, TIOCSWINSZ, &wsinfo);
   1302 	restore_term = 0;
   1303     }
   1304 }
   1305 
   1306 /*
   1307  * setdtr - control the DTR line on the serial port.
   1308  * This is called from die(), so it shouldn't call die().
   1309  */
   1310 void
   1311 setdtr(fd, on)
   1312 int fd, on;
   1313 {
   1314     int modembits = TIOCM_DTR;
   1315 
   1316     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
   1317 }
   1318 
   1319 /*
   1320  * open_loopback - open the device we use for getting packets
   1321  * in demand mode.  Under Solaris 2, we use our existing fd
   1322  * to the ppp driver.
   1323  */
   1324 int
   1325 open_ppp_loopback()
   1326 {
   1327     return pppfd;
   1328 }
   1329 
   1330 /*
   1331  * output - Output PPP packet.
   1332  */
   1333 void
   1334 output(unit, p, len)
   1335     int unit;
   1336     u_char *p;
   1337     int len;
   1338 {
   1339     struct strbuf data;
   1340     int retries;
   1341     struct pollfd pfd;
   1342 
   1343     dump_packet("sent", p, len);
   1344     if (snoop_send_hook) snoop_send_hook(p, len);
   1345 
   1346     data.len = len;
   1347     data.buf = (caddr_t) p;
   1348     retries = 4;
   1349     while (putmsg(pppfd, NULL, &data, 0) < 0) {
   1350 	if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) {
   1351 	    if (errno != ENXIO)
   1352 		error("Couldn't send packet: %m");
   1353 	    break;
   1354 	}
   1355 	pfd.fd = pppfd;
   1356 	pfd.events = POLLOUT;
   1357 	poll(&pfd, 1, 250);	/* wait for up to 0.25 seconds */
   1358     }
   1359 }
   1360 
   1361 
   1362 /*
   1363  * wait_input - wait until there is data available,
   1364  * for the length of time specified by *timo (indefinite
   1365  * if timo is NULL).
   1366  */
   1367 void
   1368 wait_input(timo)
   1369     struct timeval *timo;
   1370 {
   1371     int t;
   1372 
   1373     t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000;
   1374     if (poll(pollfds, n_pollfds, t) < 0 && errno != EINTR)
   1375 	fatal("poll: %m");
   1376 }
   1377 
   1378 /*
   1379  * add_fd - add an fd to the set that wait_input waits for.
   1380  */
   1381 void add_fd(fd)
   1382     int fd;
   1383 {
   1384     int n;
   1385 
   1386     for (n = 0; n < n_pollfds; ++n)
   1387 	if (pollfds[n].fd == fd)
   1388 	    return;
   1389     if (n_pollfds < MAX_POLLFDS) {
   1390 	pollfds[n_pollfds].fd = fd;
   1391 	pollfds[n_pollfds].events = POLLIN | POLLPRI | POLLHUP;
   1392 	++n_pollfds;
   1393     } else
   1394 	error("Too many inputs!");
   1395 }
   1396 
   1397 /*
   1398  * remove_fd - remove an fd from the set that wait_input waits for.
   1399  */
   1400 void remove_fd(fd)
   1401     int fd;
   1402 {
   1403     int n;
   1404 
   1405     for (n = 0; n < n_pollfds; ++n) {
   1406 	if (pollfds[n].fd == fd) {
   1407 	    while (++n < n_pollfds)
   1408 		pollfds[n-1] = pollfds[n];
   1409 	    --n_pollfds;
   1410 	    break;
   1411 	}
   1412     }
   1413 }
   1414 
   1415 #if 0
   1416 /*
   1417  * wait_loop_output - wait until there is data available on the
   1418  * loopback, for the length of time specified by *timo (indefinite
   1419  * if timo is NULL).
   1420  */
   1421 void
   1422 wait_loop_output(timo)
   1423     struct timeval *timo;
   1424 {
   1425     wait_input(timo);
   1426 }
   1427 
   1428 /*
   1429  * wait_time - wait for a given length of time or until a
   1430  * signal is received.
   1431  */
   1432 void
   1433 wait_time(timo)
   1434     struct timeval *timo;
   1435 {
   1436     int n;
   1437 
   1438     n = select(0, NULL, NULL, NULL, timo);
   1439     if (n < 0 && errno != EINTR)
   1440 	fatal("select: %m");
   1441 }
   1442 #endif
   1443 
   1444 
   1445 /*
   1446  * read_packet - get a PPP packet from the serial device.
   1447  */
   1448 int
   1449 read_packet(buf)
   1450     u_char *buf;
   1451 {
   1452     struct strbuf ctrl, data;
   1453     int flags, len;
   1454     unsigned char ctrlbuf[sizeof(union DL_primitives) + 64];
   1455 
   1456     for (;;) {
   1457 	data.maxlen = PPP_MRU + PPP_HDRLEN;
   1458 	data.buf = (caddr_t) buf;
   1459 	ctrl.maxlen = sizeof(ctrlbuf);
   1460 	ctrl.buf = (caddr_t) ctrlbuf;
   1461 	flags = 0;
   1462 	len = getmsg(pppfd, &ctrl, &data, &flags);
   1463 	if (len < 0) {
   1464 	    if (errno == EAGAIN || errno == EINTR)
   1465 		return -1;
   1466 	    fatal("Error reading packet: %m");
   1467 	}
   1468 
   1469 	if (ctrl.len <= 0)
   1470 	    return data.len;
   1471 
   1472 	/*
   1473 	 * Got a M_PROTO or M_PCPROTO message.  Interpret it
   1474 	 * as a DLPI primitive??
   1475 	 */
   1476 	if (debug)
   1477 	    dbglog("got dlpi prim 0x%x, len=%d",
   1478 		   ((union DL_primitives *)ctrlbuf)->dl_primitive, ctrl.len);
   1479 
   1480     }
   1481 }
   1482 
   1483 /*
   1484  * get_loop_output - get outgoing packets from the ppp device,
   1485  * and detect when we want to bring the real link up.
   1486  * Return value is 1 if we need to bring up the link, 0 otherwise.
   1487  */
   1488 int
   1489 get_loop_output()
   1490 {
   1491     int len;
   1492     int rv = 0;
   1493 
   1494     while ((len = read_packet(inpacket_buf)) > 0) {
   1495 	if (loop_frame(inpacket_buf, len))
   1496 	    rv = 1;
   1497     }
   1498     return rv;
   1499 }
   1500 
   1501 /*
   1502  * netif_set_mtu - set the MTU on the PPP network interface.
   1503  */
   1504 void
   1505 netif_set_mtu(unit, mtu)
   1506     int unit, mtu;
   1507 {
   1508     struct ifreq ifr;
   1509 #if defined(INET6) && defined(SOL2)
   1510     struct lifreq lifr;
   1511     int	fd;
   1512 #endif /* defined(INET6) && defined(SOL2) */
   1513 
   1514     memset(&ifr, 0, sizeof(ifr));
   1515     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
   1516     ifr.ifr_metric = link_mtu;
   1517     if (ioctl(ipfd, SIOCSIFMTU, &ifr) < 0) {
   1518 	error("Couldn't set IP MTU (%s): %m", ifr.ifr_name);
   1519     }
   1520 
   1521 #if defined(INET6) && defined(SOL2)
   1522     fd = socket(AF_INET6, SOCK_DGRAM, 0);
   1523     if (fd < 0)
   1524 	error("Couldn't open IPv6 socket: %m");
   1525 
   1526     memset(&lifr, 0, sizeof(lifr));
   1527     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1528     lifr.lifr_mtu = link_mtu;
   1529     if (ioctl(fd, SIOCSLIFMTU, &lifr) < 0) {
   1530 	close(fd);
   1531 	error("Couldn't set IPv6 MTU (%s): %m", ifr.ifr_name);
   1532     }
   1533     close(fd);
   1534 #endif /* defined(INET6) && defined(SOL2) */
   1535 }
   1536 
   1537 /*
   1538  * tty_send_config - configure the transmit characteristics of
   1539  * the ppp interface.
   1540  */
   1541 void
   1542 tty_send_config(mtu, asyncmap, pcomp, accomp)
   1543     int mtu;
   1544     u_int32_t asyncmap;
   1545     int pcomp, accomp;
   1546 {
   1547     int cf[2];
   1548 
   1549     link_mtu = mtu;
   1550     if (strioctl(pppfd, PPPIO_MTU, &mtu, sizeof(mtu), 0) < 0) {
   1551 	if (hungup && errno == ENXIO) {
   1552 	    ++error_count;
   1553 	    return;
   1554 	}
   1555 	error("Couldn't set MTU: %m");
   1556     }
   1557     if (fdmuxid >= 0) {
   1558 	if (!sync_serial) {
   1559 	    if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, sizeof(asyncmap), 0) < 0)
   1560 		error("Couldn't set transmit ACCM: %m");
   1561 	}
   1562 	cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0);
   1563 	cf[1] = COMP_PROT | COMP_AC;
   1564 	if (any_compressions() &&
   1565 	    strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0)
   1566 	    error("Couldn't set prot/AC compression: %m");
   1567     }
   1568 }
   1569 
   1570 /*
   1571  * tty_set_xaccm - set the extended transmit ACCM for the interface.
   1572  */
   1573 void
   1574 tty_set_xaccm(accm)
   1575     ext_accm accm;
   1576 {
   1577     if (sync_serial)
   1578 	return;
   1579 
   1580     if (fdmuxid >= 0
   1581 	&& strioctl(pppfd, PPPIO_XACCM, accm, sizeof(ext_accm), 0) < 0) {
   1582 	if (!hungup || errno != ENXIO)
   1583 	    warn("Couldn't set extended ACCM: %m");
   1584     }
   1585 }
   1586 
   1587 /*
   1588  * tty_recv_config - configure the receive-side characteristics of
   1589  * the ppp interface.
   1590  */
   1591 void
   1592 tty_recv_config(mru, asyncmap, pcomp, accomp)
   1593     int mru;
   1594     u_int32_t asyncmap;
   1595     int pcomp, accomp;
   1596 {
   1597     int cf[2];
   1598 
   1599     link_mru = mru;
   1600     if (strioctl(pppfd, PPPIO_MRU, &mru, sizeof(mru), 0) < 0) {
   1601 	if (hungup && errno == ENXIO) {
   1602 	    ++error_count;
   1603 	    return;
   1604 	}
   1605 	error("Couldn't set MRU: %m");
   1606     }
   1607     if (fdmuxid >= 0) {
   1608 	if (!sync_serial) {
   1609 	    if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, sizeof(asyncmap), 0) < 0)
   1610 		error("Couldn't set receive ACCM: %m");
   1611 	}
   1612 	cf[0] = (pcomp? DECOMP_PROT: 0) + (accomp? DECOMP_AC: 0);
   1613 	cf[1] = DECOMP_PROT | DECOMP_AC;
   1614 	if (any_compressions() &&
   1615 	    strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0)
   1616 	    error("Couldn't set prot/AC decompression: %m");
   1617     }
   1618 }
   1619 
   1620 /*
   1621  * ccp_test - ask kernel whether a given compression method
   1622  * is acceptable for use.
   1623  */
   1624 int
   1625 ccp_test(unit, opt_ptr, opt_len, for_transmit)
   1626     int unit, opt_len, for_transmit;
   1627     u_char *opt_ptr;
   1628 {
   1629     if (strioctl(pppfd, (for_transmit? PPPIO_XCOMP: PPPIO_RCOMP),
   1630 		 opt_ptr, opt_len, 0) >= 0)
   1631 	return 1;
   1632     return (errno == ENOSR)? 0: -1;
   1633 }
   1634 
   1635 /*
   1636  * ccp_flags_set - inform kernel about the current state of CCP.
   1637  */
   1638 void
   1639 ccp_flags_set(unit, isopen, isup)
   1640     int unit, isopen, isup;
   1641 {
   1642     int cf[2];
   1643 
   1644     cf[0] = (isopen? CCP_ISOPEN: 0) + (isup? CCP_ISUP: 0);
   1645     cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR;
   1646     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
   1647 	if (!hungup || errno != ENXIO)
   1648 	    error("Couldn't set kernel CCP state: %m");
   1649     }
   1650 }
   1651 
   1652 /*
   1653  * get_idle_time - return how long the link has been idle.
   1654  */
   1655 int
   1656 get_idle_time(u, ip)
   1657     int u;
   1658     struct ppp_idle *ip;
   1659 {
   1660     return strioctl(pppfd, PPPIO_GIDLE, ip, 0, sizeof(struct ppp_idle)) >= 0;
   1661 }
   1662 
   1663 /*
   1664  * get_ppp_stats - return statistics for the link.
   1665  */
   1666 int
   1667 get_ppp_stats(u, stats)
   1668     int u;
   1669     struct pppd_stats *stats;
   1670 {
   1671     struct ppp_stats s;
   1672 
   1673     if (!sync_serial &&
   1674 	strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof(s)) < 0) {
   1675 	error("Couldn't get link statistics: %m");
   1676 	return 0;
   1677     }
   1678     stats->bytes_in = s.p.ppp_ibytes;
   1679     stats->bytes_out = s.p.ppp_obytes;
   1680     stats->pkts_in = s.p.ppp_ipackets;
   1681     stats->pkts_out = s.p.ppp_opackets;
   1682     return 1;
   1683 }
   1684 
   1685 #if 0
   1686 /*
   1687  * set_filters - transfer the pass and active filters to the kernel.
   1688  */
   1689 int
   1690 set_filters(pass, active)
   1691     struct bpf_program *pass, *active;
   1692 {
   1693     int ret = 1;
   1694 
   1695     if (pass->bf_len > 0) {
   1696 	if (strioctl(pppfd, PPPIO_PASSFILT, pass,
   1697 		     sizeof(struct bpf_program), 0) < 0) {
   1698 	    error("Couldn't set pass-filter in kernel: %m");
   1699 	    ret = 0;
   1700 	}
   1701     }
   1702     if (active->bf_len > 0) {
   1703 	if (strioctl(pppfd, PPPIO_ACTIVEFILT, active,
   1704 		     sizeof(struct bpf_program), 0) < 0) {
   1705 	    error("Couldn't set active-filter in kernel: %m");
   1706 	    ret = 0;
   1707 	}
   1708     }
   1709     return ret;
   1710 }
   1711 #endif
   1712 
   1713 /*
   1714  * ccp_fatal_error - returns 1 if decompression was disabled as a
   1715  * result of an error detected after decompression of a packet,
   1716  * 0 otherwise.  This is necessary because of patent nonsense.
   1717  */
   1718 int
   1719 ccp_fatal_error(unit)
   1720     int unit;
   1721 {
   1722     int cf[2];
   1723 
   1724     cf[0] = cf[1] = 0;
   1725     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
   1726 	if (errno != ENXIO && errno != EINVAL)
   1727 	    error("Couldn't get compression flags: %m");
   1728 	return 0;
   1729     }
   1730     return cf[0] & CCP_FATALERROR;
   1731 }
   1732 
   1733 /*
   1734  * sifvjcomp - config tcp header compression
   1735  */
   1736 int
   1737 sifvjcomp(u, vjcomp, xcidcomp, xmaxcid)
   1738     int u, vjcomp, xcidcomp, xmaxcid;
   1739 {
   1740     int cf[2];
   1741     char maxcid[2];
   1742 
   1743     if (vjcomp) {
   1744 	maxcid[0] = xcidcomp;
   1745 	maxcid[1] = 15;		/* XXX should be rmaxcid */
   1746 	if (strioctl(pppfd, PPPIO_VJINIT, maxcid, sizeof(maxcid), 0) < 0) {
   1747 	    error("Couldn't initialize VJ compression: %m");
   1748 	}
   1749     }
   1750 
   1751     cf[0] = (vjcomp? COMP_VJC + DECOMP_VJC: 0)	/* XXX this is wrong */
   1752 	+ (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0);
   1753     cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID;
   1754     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
   1755 	if (vjcomp)
   1756 	    error("Couldn't enable VJ compression: %m");
   1757     }
   1758 
   1759     return 1;
   1760 }
   1761 
   1762 /*
   1763  * sifup - Config the interface up and enable IP packets to pass.
   1764  */
   1765 int
   1766 sifup(u)
   1767     int u;
   1768 {
   1769     struct ifreq ifr;
   1770 
   1771     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
   1772     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
   1773 	error("Couldn't mark interface up (get): %m");
   1774 	return 0;
   1775     }
   1776     ifr.ifr_flags |= IFF_UP;
   1777     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
   1778 	error("Couldn't mark interface up (set): %m");
   1779 	return 0;
   1780     }
   1781     if_is_up = 1;
   1782     return 1;
   1783 }
   1784 
   1785 /*
   1786  * sifdown - Config the interface down and disable IP.
   1787  */
   1788 int
   1789 sifdown(u)
   1790     int u;
   1791 {
   1792     struct ifreq ifr;
   1793 
   1794     if (ipmuxid < 0)
   1795 	return 1;
   1796     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
   1797     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
   1798 	error("Couldn't mark interface down (get): %m");
   1799 	return 0;
   1800     }
   1801     ifr.ifr_flags &= ~IFF_UP;
   1802     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
   1803 	error("Couldn't mark interface down (set): %m");
   1804 	return 0;
   1805     }
   1806     if_is_up = 0;
   1807     return 1;
   1808 }
   1809 
   1810 /*
   1811  * sifnpmode - Set the mode for handling packets for a given NP.
   1812  */
   1813 int
   1814 sifnpmode(u, proto, mode)
   1815     int u;
   1816     int proto;
   1817     enum NPmode mode;
   1818 {
   1819     int npi[2];
   1820 
   1821     npi[0] = proto;
   1822     npi[1] = (int) mode;
   1823     if (strioctl(pppfd, PPPIO_NPMODE, &npi, 2 * sizeof(int), 0) < 0) {
   1824 	error("ioctl(set NP %d mode to %d): %m", proto, mode);
   1825 	return 0;
   1826     }
   1827     return 1;
   1828 }
   1829 
   1830 #if defined(SOL2) && defined(INET6)
   1831 /*
   1832  * sif6up - Config the IPv6 interface up and enable IPv6 packets to pass.
   1833  */
   1834 int
   1835 sif6up(u)
   1836     int u;
   1837 {
   1838     struct lifreq lifr;
   1839     int fd;
   1840 
   1841     fd = socket(AF_INET6, SOCK_DGRAM, 0);
   1842     if (fd < 0) {
   1843 	return 0;
   1844     }
   1845 
   1846     memset(&lifr, 0, sizeof(lifr));
   1847     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1848     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
   1849 	close(fd);
   1850 	return 0;
   1851     }
   1852 
   1853     lifr.lifr_flags |= IFF_UP;
   1854     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1855     if (ioctl(fd, SIOCSLIFFLAGS, &lifr) < 0) {
   1856 	close(fd);
   1857 	return 0;
   1858     }
   1859 
   1860     if6_is_up = 1;
   1861     close(fd);
   1862     return 1;
   1863 }
   1864 
   1865 /*
   1866  * sifdown - Config the IPv6 interface down and disable IPv6.
   1867  */
   1868 int
   1869 sif6down(u)
   1870     int u;
   1871 {
   1872     struct lifreq lifr;
   1873     int fd;
   1874 
   1875     fd = socket(AF_INET6, SOCK_DGRAM, 0);
   1876     if (fd < 0)
   1877 	return 0;
   1878 
   1879     memset(&lifr, 0, sizeof(lifr));
   1880     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1881     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
   1882 	close(fd);
   1883 	return 0;
   1884     }
   1885 
   1886     lifr.lifr_flags &= ~IFF_UP;
   1887     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1888     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
   1889 	close(fd);
   1890 	return 0;
   1891     }
   1892 
   1893     if6_is_up = 0;
   1894     close(fd);
   1895     return 1;
   1896 }
   1897 
   1898 /*
   1899  * sif6addr - Config the interface with an IPv6 link-local address
   1900  */
   1901 int
   1902 sif6addr(u, o, h)
   1903     int u;
   1904     eui64_t o, h;
   1905 {
   1906     struct lifreq lifr;
   1907     struct sockaddr_storage laddr;
   1908     struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&laddr;
   1909     int fd;
   1910 
   1911     fd = socket(AF_INET6, SOCK_DGRAM, 0);
   1912     if (fd < 0)
   1913 	return 0;
   1914 
   1915     memset(&lifr, 0, sizeof(lifr));
   1916     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1917 
   1918     /*
   1919      * Do this because /dev/ppp responds to DL_PHYS_ADDR_REQ with
   1920      * zero values, hence the interface token came to be zero too,
   1921      * and without this, in.ndpd will complain
   1922      */
   1923     IN6_LLTOKEN_FROM_EUI64(lifr, sin6, o);
   1924     if (ioctl(fd, SIOCSLIFTOKEN, &lifr) < 0) {
   1925 	close(fd);
   1926 	return 0;
   1927     }
   1928 
   1929     /*
   1930      * Set the interface address and destination address
   1931      */
   1932     IN6_LLADDR_FROM_EUI64(lifr, sin6, o);
   1933     if (ioctl(fd, SIOCSLIFADDR, &lifr) < 0) {
   1934 	close(fd);
   1935 	return 0;
   1936     }
   1937 
   1938     memset(&lifr, 0, sizeof(lifr));
   1939     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1940     IN6_LLADDR_FROM_EUI64(lifr, sin6, h);
   1941     if (ioctl(fd, SIOCSLIFDSTADDR, &lifr) < 0) {
   1942 	close(fd);
   1943 	return 0;
   1944     }
   1945 
   1946     return 1;
   1947 }
   1948 
   1949 /*
   1950  * cif6addr - Remove the IPv6 address from interface
   1951  */
   1952 int
   1953 cif6addr(u, o, h)
   1954     int u;
   1955     eui64_t o, h;
   1956 {
   1957     return 1;
   1958 }
   1959 
   1960 #endif /* defined(SOL2) && defined(INET6) */
   1961 
   1962 
   1963 #define INET_ADDR(x)	(((struct sockaddr_in *) &(x))->sin_addr.s_addr)
   1964 
   1965 /*
   1966  * sifaddr - Config the interface IP addresses and netmask.
   1967  */
   1968 int
   1969 sifaddr(u, o, h, m)
   1970     int u;
   1971     u_int32_t o, h, m;
   1972 {
   1973     struct ifreq ifr;
   1974     int ret = 1;
   1975 
   1976     memset(&ifr, 0, sizeof(ifr));
   1977     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
   1978     ifr.ifr_addr.sa_family = AF_INET;
   1979     INET_ADDR(ifr.ifr_addr) = m;
   1980     if (ioctl(ipfd, SIOCSIFNETMASK, &ifr) < 0) {
   1981 	error("Couldn't set IP netmask: %m");
   1982 	ret = 0;
   1983     }
   1984     ifr.ifr_addr.sa_family = AF_INET;
   1985     INET_ADDR(ifr.ifr_addr) = o;
   1986     if (ioctl(ipfd, SIOCSIFADDR, &ifr) < 0) {
   1987 	error("Couldn't set local IP address: %m");
   1988 	ret = 0;
   1989     }
   1990 
   1991     /*
   1992      * On some systems, we have to explicitly set the point-to-point
   1993      * flag bit before we can set a destination address.
   1994      */
   1995     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) >= 0
   1996 	&& (ifr.ifr_flags & IFF_POINTOPOINT) == 0) {
   1997 	ifr.ifr_flags |= IFF_POINTOPOINT;
   1998 	if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
   1999 	    error("Couldn't mark interface pt-to-pt: %m");
   2000 	    ret = 0;
   2001 	}
   2002     }
   2003     ifr.ifr_dstaddr.sa_family = AF_INET;
   2004     INET_ADDR(ifr.ifr_dstaddr) = h;
   2005     if (ioctl(ipfd, SIOCSIFDSTADDR, &ifr) < 0) {
   2006 	error("Couldn't set remote IP address: %m");
   2007 	ret = 0;
   2008     }
   2009 
   2010     remote_addr = h;
   2011     return ret;
   2012 }
   2013 
   2014 /*
   2015  * cifaddr - Clear the interface IP addresses, and delete routes
   2016  * through the interface if possible.
   2017  */
   2018 int
   2019 cifaddr(u, o, h)
   2020     int u;
   2021     u_int32_t o, h;
   2022 {
   2023 #if defined(__USLC__)		/* was: #if 0 */
   2024     cifroute(unit, ouraddr, hisaddr);
   2025     if (ipmuxid >= 0) {
   2026 	notice("Removing ppp interface unit");
   2027 	if (ioctl(ipfd, I_UNLINK, ipmuxid) < 0) {
   2028 	    error("Can't remove ppp interface unit: %m");
   2029 	    return 0;
   2030 	}
   2031 	ipmuxid = -1;
   2032     }
   2033 #endif
   2034     remote_addr = 0;
   2035     return 1;
   2036 }
   2037 
   2038 /*
   2039  * sifdefaultroute - assign a default route through the address given.
   2040  */
   2041 int
   2042 sifdefaultroute(u, l, g)
   2043     int u;
   2044     u_int32_t l, g;
   2045 {
   2046     struct rtentry rt;
   2047 
   2048 #if defined(__USLC__)
   2049     g = l;			/* use the local address as gateway */
   2050 #endif
   2051     memset(&rt, 0, sizeof(rt));
   2052     rt.rt_dst.sa_family = AF_INET;
   2053     INET_ADDR(rt.rt_dst) = 0;
   2054     rt.rt_gateway.sa_family = AF_INET;
   2055     INET_ADDR(rt.rt_gateway) = g;
   2056     rt.rt_flags = RTF_GATEWAY;
   2057 
   2058     if (ioctl(ipfd, SIOCADDRT, &rt) < 0) {
   2059 	error("Can't add default route: %m");
   2060 	return 0;
   2061     }
   2062 
   2063     default_route_gateway = g;
   2064     return 1;
   2065 }
   2066 
   2067 /*
   2068  * cifdefaultroute - delete a default route through the address given.
   2069  */
   2070 int
   2071 cifdefaultroute(u, l, g)
   2072     int u;
   2073     u_int32_t l, g;
   2074 {
   2075     struct rtentry rt;
   2076 
   2077 #if defined(__USLC__)
   2078     g = l;			/* use the local address as gateway */
   2079 #endif
   2080     memset(&rt, 0, sizeof(rt));
   2081     rt.rt_dst.sa_family = AF_INET;
   2082     INET_ADDR(rt.rt_dst) = 0;
   2083     rt.rt_gateway.sa_family = AF_INET;
   2084     INET_ADDR(rt.rt_gateway) = g;
   2085     rt.rt_flags = RTF_GATEWAY;
   2086 
   2087     if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
   2088 	error("Can't delete default route: %m");
   2089 	return 0;
   2090     }
   2091 
   2092     default_route_gateway = 0;
   2093     return 1;
   2094 }
   2095 
   2096 /*
   2097  * sifproxyarp - Make a proxy ARP entry for the peer.
   2098  */
   2099 int
   2100 sifproxyarp(unit, hisaddr)
   2101     int unit;
   2102     u_int32_t hisaddr;
   2103 {
   2104     struct arpreq arpreq;
   2105 
   2106     memset(&arpreq, 0, sizeof(arpreq));
   2107     if (!get_ether_addr(hisaddr, &arpreq.arp_ha))
   2108 	return 0;
   2109 
   2110     arpreq.arp_pa.sa_family = AF_INET;
   2111     INET_ADDR(arpreq.arp_pa) = hisaddr;
   2112     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
   2113     if (ioctl(ipfd, SIOCSARP, (caddr_t) &arpreq) < 0) {
   2114 	error("Couldn't set proxy ARP entry: %m");
   2115 	return 0;
   2116     }
   2117 
   2118     proxy_arp_addr = hisaddr;
   2119     return 1;
   2120 }
   2121 
   2122 /*
   2123  * cifproxyarp - Delete the proxy ARP entry for the peer.
   2124  */
   2125 int
   2126 cifproxyarp(unit, hisaddr)
   2127     int unit;
   2128     u_int32_t hisaddr;
   2129 {
   2130     struct arpreq arpreq;
   2131 
   2132     memset(&arpreq, 0, sizeof(arpreq));
   2133     arpreq.arp_pa.sa_family = AF_INET;
   2134     INET_ADDR(arpreq.arp_pa) = hisaddr;
   2135     if (ioctl(ipfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
   2136 	error("Couldn't delete proxy ARP entry: %m");
   2137 	return 0;
   2138     }
   2139 
   2140     proxy_arp_addr = 0;
   2141     return 1;
   2142 }
   2143 
   2144 /*
   2145  * get_ether_addr - get the hardware address of an interface on the
   2146  * the same subnet as ipaddr.
   2147  */
   2148 #define MAX_IFS		32
   2149 
   2150 static int
   2151 get_ether_addr(ipaddr, hwaddr)
   2152     u_int32_t ipaddr;
   2153     struct sockaddr *hwaddr;
   2154 {
   2155     struct ifreq *ifr, *ifend, ifreq;
   2156     int nif;
   2157     struct ifconf ifc;
   2158     u_int32_t ina, mask;
   2159 
   2160     /*
   2161      * Scan through the system's network interfaces.
   2162      */
   2163 #ifdef SIOCGIFNUM
   2164     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
   2165 #endif
   2166 	nif = MAX_IFS;
   2167     ifc.ifc_len = nif * sizeof(struct ifreq);
   2168     ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len);
   2169     if (ifc.ifc_buf == 0)
   2170 	return 0;
   2171     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
   2172 	warn("Couldn't get system interface list: %m");
   2173 	free(ifc.ifc_buf);
   2174 	return 0;
   2175     }
   2176     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
   2177     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
   2178 	if (ifr->ifr_addr.sa_family != AF_INET)
   2179 	    continue;
   2180 	/*
   2181 	 * Check that the interface is up, and not point-to-point or loopback.
   2182 	 */
   2183 	strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
   2184 	if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
   2185 	    continue;
   2186 	if ((ifreq.ifr_flags &
   2187 	     (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
   2188 	    != (IFF_UP|IFF_BROADCAST))
   2189 	    continue;
   2190 	/*
   2191 	 * Get its netmask and check that it's on the right subnet.
   2192 	 */
   2193 	if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
   2194 	    continue;
   2195 	ina = INET_ADDR(ifr->ifr_addr);
   2196 	mask = INET_ADDR(ifreq.ifr_addr);
   2197 	if ((ipaddr & mask) == (ina & mask))
   2198 	    break;
   2199     }
   2200 
   2201     if (ifr >= ifend) {
   2202 	warn("No suitable interface found for proxy ARP");
   2203 	free(ifc.ifc_buf);
   2204 	return 0;
   2205     }
   2206 
   2207     info("found interface %s for proxy ARP", ifr->ifr_name);
   2208     if (!get_hw_addr(ifr->ifr_name, ina, hwaddr)) {
   2209 	error("Couldn't get hardware address for %s", ifr->ifr_name);
   2210 	free(ifc.ifc_buf);
   2211 	return 0;
   2212     }
   2213 
   2214     free(ifc.ifc_buf);
   2215     return 1;
   2216 }
   2217 
   2218 /*
   2219  * get_hw_addr_dlpi - obtain the hardware address using DLPI
   2220  */
   2221 static int
   2222 get_hw_addr_dlpi(name, hwaddr)
   2223     char *name;
   2224     struct sockaddr *hwaddr;
   2225 {
   2226     char *q;
   2227     int unit, iffd, adrlen;
   2228     unsigned char *adrp;
   2229     char ifdev[24];
   2230     struct {
   2231 	union DL_primitives prim;
   2232 	char space[64];
   2233     } reply;
   2234 
   2235     /*
   2236      * We have to open the device and ask it for its hardware address.
   2237      * First split apart the device name and unit.
   2238      */
   2239     slprintf(ifdev, sizeof(ifdev), "/dev/%s", name);
   2240     for (q = ifdev + strlen(ifdev); --q >= ifdev; )
   2241 	if (!isdigit(*q))
   2242 	    break;
   2243     unit = atoi(q+1);
   2244     q[1] = 0;
   2245 
   2246     /*
   2247      * Open the device and do a DLPI attach and phys_addr_req.
   2248      */
   2249     iffd = open(ifdev, O_RDWR);
   2250     if (iffd < 0) {
   2251 	error("Can't open %s: %m", ifdev);
   2252 	return 0;
   2253     }
   2254     if (dlpi_attach(iffd, unit) < 0
   2255 	|| dlpi_get_reply(iffd, &reply.prim, DL_OK_ACK, sizeof(reply)) < 0
   2256 	|| dlpi_info_req(iffd) < 0
   2257 	|| dlpi_get_reply(iffd, &reply.prim, DL_INFO_ACK, sizeof(reply)) < 0) {
   2258 	close(iffd);
   2259 	return 0;
   2260     }
   2261 
   2262     adrlen = reply.prim.info_ack.dl_addr_length;
   2263     adrp = (unsigned char *)&reply + reply.prim.info_ack.dl_addr_offset;
   2264 
   2265 #if DL_CURRENT_VERSION >= 2
   2266     if (reply.prim.info_ack.dl_sap_length < 0)
   2267 	adrlen += reply.prim.info_ack.dl_sap_length;
   2268     else
   2269 	adrp += reply.prim.info_ack.dl_sap_length;
   2270 #endif
   2271 
   2272     hwaddr->sa_family = AF_UNSPEC;
   2273     memcpy(hwaddr->sa_data, adrp, adrlen);
   2274 
   2275     return 1;
   2276 }
   2277 /*
   2278  * get_hw_addr - obtain the hardware address for a named interface.
   2279  */
   2280 static int
   2281 get_hw_addr(name, ina, hwaddr)
   2282     char *name;
   2283     u_int32_t ina;
   2284     struct sockaddr *hwaddr;
   2285 {
   2286     /* New way - get the address by doing an arp request. */
   2287     int s;
   2288     struct arpreq req;
   2289 
   2290     s = socket(AF_INET, SOCK_DGRAM, 0);
   2291     if (s < 0)
   2292 	return 0;
   2293     memset(&req, 0, sizeof(req));
   2294     req.arp_pa.sa_family = AF_INET;
   2295     INET_ADDR(req.arp_pa) = ina;
   2296     if (ioctl(s, SIOCGARP, &req) < 0) {
   2297 	error("Couldn't get ARP entry for %s: %m", ip_ntoa(ina));
   2298 	return 0;
   2299     }
   2300     *hwaddr = req.arp_ha;
   2301     hwaddr->sa_family = AF_UNSPEC;
   2302 
   2303     return 1;
   2304 }
   2305 
   2306 static int
   2307 dlpi_attach(fd, ppa)
   2308     int fd, ppa;
   2309 {
   2310     dl_attach_req_t req;
   2311     struct strbuf buf;
   2312 
   2313     req.dl_primitive = DL_ATTACH_REQ;
   2314     req.dl_ppa = ppa;
   2315     buf.len = sizeof(req);
   2316     buf.buf = (void *) &req;
   2317     return putmsg(fd, &buf, NULL, RS_HIPRI);
   2318 }
   2319 
   2320 static int
   2321 dlpi_info_req(fd)
   2322     int fd;
   2323 {
   2324     dl_info_req_t req;
   2325     struct strbuf buf;
   2326 
   2327     req.dl_primitive = DL_INFO_REQ;
   2328     buf.len = sizeof(req);
   2329     buf.buf = (void *) &req;
   2330     return putmsg(fd, &buf, NULL, RS_HIPRI);
   2331 }
   2332 
   2333 static int
   2334 dlpi_get_reply(fd, reply, expected_prim, maxlen)
   2335     union DL_primitives *reply;
   2336     int fd, expected_prim, maxlen;
   2337 {
   2338     struct strbuf buf;
   2339     int flags, n;
   2340     struct pollfd pfd;
   2341 
   2342     /*
   2343      * Use poll to wait for a message with a timeout.
   2344      */
   2345     pfd.fd = fd;
   2346     pfd.events = POLLIN | POLLPRI;
   2347     do {
   2348 	n = poll(&pfd, 1, 1000);
   2349     } while (n == -1 && errno == EINTR);
   2350     if (n <= 0)
   2351 	return -1;
   2352 
   2353     /*
   2354      * Get the reply.
   2355      */
   2356     buf.maxlen = maxlen;
   2357     buf.buf = (void *) reply;
   2358     flags = 0;
   2359     if (getmsg(fd, &buf, NULL, &flags) < 0)
   2360 	return -1;
   2361 
   2362     if (buf.len < sizeof(ulong)) {
   2363 	if (debug)
   2364 	    dbglog("dlpi response short (len=%d)\n", buf.len);
   2365 	return -1;
   2366     }
   2367 
   2368     if (reply->dl_primitive == expected_prim)
   2369 	return 0;
   2370 
   2371     if (debug) {
   2372 	if (reply->dl_primitive == DL_ERROR_ACK) {
   2373 	    dbglog("dlpi error %d (unix errno %d) for prim %x\n",
   2374 		   reply->error_ack.dl_errno, reply->error_ack.dl_unix_errno,
   2375 		   reply->error_ack.dl_error_primitive);
   2376 	} else {
   2377 	    dbglog("dlpi unexpected response prim %x\n",
   2378 		   reply->dl_primitive);
   2379 	}
   2380     }
   2381 
   2382     return -1;
   2383 }
   2384 
   2385 /*
   2386  * Return user specified netmask, modified by any mask we might determine
   2387  * for address `addr' (in network byte order).
   2388  * Here we scan through the system's list of interfaces, looking for
   2389  * any non-point-to-point interfaces which might appear to be on the same
   2390  * network as `addr'.  If we find any, we OR in their netmask to the
   2391  * user-specified netmask.
   2392  */
   2393 u_int32_t
   2394 GetMask(addr)
   2395     u_int32_t addr;
   2396 {
   2397     u_int32_t mask, nmask, ina;
   2398     struct ifreq *ifr, *ifend, ifreq;
   2399     int nif;
   2400     struct ifconf ifc;
   2401 
   2402     addr = ntohl(addr);
   2403     if (IN_CLASSA(addr))	/* determine network mask for address class */
   2404 	nmask = IN_CLASSA_NET;
   2405     else if (IN_CLASSB(addr))
   2406 	nmask = IN_CLASSB_NET;
   2407     else
   2408 	nmask = IN_CLASSC_NET;
   2409     /* class D nets are disallowed by bad_ip_adrs */
   2410     mask = netmask | htonl(nmask);
   2411 
   2412     /*
   2413      * Scan through the system's network interfaces.
   2414      */
   2415 #ifdef SIOCGIFNUM
   2416     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
   2417 #endif
   2418 	nif = MAX_IFS;
   2419     ifc.ifc_len = nif * sizeof(struct ifreq);
   2420     ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len);
   2421     if (ifc.ifc_buf == 0)
   2422 	return mask;
   2423     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
   2424 	warn("Couldn't get system interface list: %m");
   2425 	free(ifc.ifc_buf);
   2426 	return mask;
   2427     }
   2428     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
   2429     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
   2430 	/*
   2431 	 * Check the interface's internet address.
   2432 	 */
   2433 	if (ifr->ifr_addr.sa_family != AF_INET)
   2434 	    continue;
   2435 	ina = INET_ADDR(ifr->ifr_addr);
   2436 	if ((ntohl(ina) & nmask) != (addr & nmask))
   2437 	    continue;
   2438 	/*
   2439 	 * Check that the interface is up, and not point-to-point or loopback.
   2440 	 */
   2441 	strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
   2442 	if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
   2443 	    continue;
   2444 	if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
   2445 	    != IFF_UP)
   2446 	    continue;
   2447 	/*
   2448 	 * Get its netmask and OR it into our mask.
   2449 	 */
   2450 	if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
   2451 	    continue;
   2452 	mask |= INET_ADDR(ifreq.ifr_addr);
   2453     }
   2454 
   2455     free(ifc.ifc_buf);
   2456     return mask;
   2457 }
   2458 
   2459 /*
   2460  * logwtmp - write an accounting record to the /var/adm/wtmp file.
   2461  */
   2462 void
   2463 logwtmp(line, name, host)
   2464     const char *line, *name, *host;
   2465 {
   2466     static struct utmpx utmpx;
   2467 
   2468     if (name[0] != 0) {
   2469 	/* logging in */
   2470 	strncpy(utmpx.ut_user, name, sizeof(utmpx.ut_user));
   2471 	strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line));
   2472 	strncpy(utmpx.ut_host, host, sizeof(utmpx.ut_host));
   2473 	if (*host != '\0') {
   2474 	    utmpx.ut_syslen = strlen(host) + 1;
   2475 	    if (utmpx.ut_syslen > sizeof(utmpx.ut_host))
   2476 		utmpx.ut_syslen = sizeof(utmpx.ut_host);
   2477 	}
   2478 	utmpx.ut_pid = getpid();
   2479 	utmpx.ut_type = USER_PROCESS;
   2480     } else {
   2481 	utmpx.ut_type = DEAD_PROCESS;
   2482     }
   2483     gettimeofday(&utmpx.ut_tv, NULL);
   2484     updwtmpx("/var/adm/wtmpx", &utmpx);
   2485 }
   2486 
   2487 /*
   2488  * get_host_seed - return the serial number of this machine.
   2489  */
   2490 int
   2491 get_host_seed()
   2492 {
   2493     char buf[32];
   2494 
   2495     if (sysinfo(SI_HW_SERIAL, buf, sizeof(buf)) < 0) {
   2496 	error("sysinfo: %m");
   2497 	return 0;
   2498     }
   2499     return (int) strtoul(buf, NULL, 16);
   2500 }
   2501 
   2502 static int
   2503 strioctl(fd, cmd, ptr, ilen, olen)
   2504     int fd, cmd, ilen, olen;
   2505     void *ptr;
   2506 {
   2507     struct strioctl str;
   2508 
   2509     str.ic_cmd = cmd;
   2510     str.ic_timout = 0;
   2511     str.ic_len = ilen;
   2512     str.ic_dp = ptr;
   2513     if (ioctl(fd, I_STR, &str) == -1)
   2514 	return -1;
   2515     if (str.ic_len != olen)
   2516 	dbglog("strioctl: expected %d bytes, got %d for cmd %x\n",
   2517 	       olen, str.ic_len, cmd);
   2518     return 0;
   2519 }
   2520 
   2521 #if 0
   2522 /*
   2523  * lock - create a lock file for the named lock device
   2524  */
   2525 
   2526 #define LOCK_PREFIX	"/var/spool/locks/LK."
   2527 static char lock_file[40];	/* name of lock file created */
   2528 
   2529 int
   2530 lock(dev)
   2531     char *dev;
   2532 {
   2533     int n, fd, pid;
   2534     struct stat sbuf;
   2535     char ascii_pid[12];
   2536 
   2537     if (stat(dev, &sbuf) < 0) {
   2538 	error("Can't get device number for %s: %m", dev);
   2539 	return -1;
   2540     }
   2541     if ((sbuf.st_mode & S_IFMT) != S_IFCHR) {
   2542 	error("Can't lock %s: not a character device", dev);
   2543 	return -1;
   2544     }
   2545     slprintf(lock_file, sizeof(lock_file), "%s%03d.%03d.%03d",
   2546 	     LOCK_PREFIX, major(sbuf.st_dev),
   2547 	     major(sbuf.st_rdev), minor(sbuf.st_rdev));
   2548 
   2549     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
   2550 	if (errno == EEXIST
   2551 	    && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
   2552 	    /* Read the lock file to find out who has the device locked */
   2553 	    n = read(fd, ascii_pid, 11);
   2554 	    if (n <= 0) {
   2555 		error("Can't read pid from lock file %s", lock_file);
   2556 		close(fd);
   2557 	    } else {
   2558 		ascii_pid[n] = 0;
   2559 		pid = atoi(ascii_pid);
   2560 		if (pid > 0 && kill(pid, 0) == -1 && errno == ESRCH) {
   2561 		    /* pid no longer exists - remove the lock file */
   2562 		    if (unlink(lock_file) == 0) {
   2563 			close(fd);
   2564 			notice("Removed stale lock on %s (pid %d)",
   2565 			       dev, pid);
   2566 			continue;
   2567 		    } else
   2568 			warn("Couldn't remove stale lock on %s",
   2569 			       dev);
   2570 		} else
   2571 		    notice("Device %s is locked by pid %d",
   2572 			   dev, pid);
   2573 	    }
   2574 	    close(fd);
   2575 	} else
   2576 	    error("Can't create lock file %s: %m", lock_file);
   2577 	lock_file[0] = 0;
   2578 	return -1;
   2579     }
   2580 
   2581     slprintf(ascii_pid, sizeof(ascii_pid), "%10d\n", getpid());
   2582     write(fd, ascii_pid, 11);
   2583 
   2584     close(fd);
   2585     return 1;
   2586 }
   2587 
   2588 /*
   2589  * unlock - remove our lockfile
   2590  */
   2591 void
   2592 unlock()
   2593 {
   2594     if (lock_file[0]) {
   2595 	unlink(lock_file);
   2596 	lock_file[0] = 0;
   2597     }
   2598 }
   2599 #endif
   2600 
   2601 /*
   2602  * cifroute - delete a route through the addresses given.
   2603  */
   2604 int
   2605 cifroute(u, our, his)
   2606     int u;
   2607     u_int32_t our, his;
   2608 {
   2609     struct rtentry rt;
   2610 
   2611     memset(&rt, 0, sizeof(rt));
   2612     rt.rt_dst.sa_family = AF_INET;
   2613     INET_ADDR(rt.rt_dst) = his;
   2614     rt.rt_gateway.sa_family = AF_INET;
   2615     INET_ADDR(rt.rt_gateway) = our;
   2616     rt.rt_flags = RTF_HOST;
   2617 
   2618     if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
   2619 	error("Can't delete route: %m");
   2620 	return 0;
   2621     }
   2622 
   2623     return 1;
   2624 }
   2625 
   2626 /*
   2627  * have_route_to - determine if the system has a route to the specified
   2628  * IP address.  Returns 0 if not, 1 if so, -1 if we can't tell.
   2629  * `addr' is in network byte order.
   2630  * For demand mode to work properly, we have to ignore routes
   2631  * through our own interface.
   2632  */
   2633 #ifndef T_CURRENT		/* needed for Solaris 2.5 */
   2634 #define T_CURRENT	MI_T_CURRENT
   2635 #endif
   2636 
   2637 int
   2638 have_route_to(addr)
   2639     u_int32_t addr;
   2640 {
   2641 #ifdef SOL2
   2642     int fd, r, flags, i;
   2643     struct {
   2644 	struct T_optmgmt_req req;
   2645 	struct opthdr hdr;
   2646     } req;
   2647     union {
   2648 	struct T_optmgmt_ack ack;
   2649 	unsigned char space[64];
   2650     } ack;
   2651     struct opthdr *rh;
   2652     struct strbuf cbuf, dbuf;
   2653     int nroutes;
   2654     mib2_ipRouteEntry_t routes[8];
   2655     mib2_ipRouteEntry_t *rp;
   2656 
   2657     fd = open(mux_dev_name, O_RDWR);
   2658     if (fd < 0) {
   2659 	warn("have_route_to: couldn't open %s: %m", mux_dev_name);
   2660 	return -1;
   2661     }
   2662 
   2663     req.req.PRIM_type = T_OPTMGMT_REQ;
   2664     req.req.OPT_offset = (char *) &req.hdr - (char *) &req;
   2665     req.req.OPT_length = sizeof(req.hdr);
   2666     req.req.MGMT_flags = T_CURRENT;
   2667 
   2668     req.hdr.level = MIB2_IP;
   2669     req.hdr.name = 0;
   2670     req.hdr.len = 0;
   2671 
   2672     cbuf.buf = (char *) &req;
   2673     cbuf.len = sizeof(req);
   2674 
   2675     if (putmsg(fd, &cbuf, NULL, 0) == -1) {
   2676 	warn("have_route_to: putmsg: %m");
   2677 	close(fd);
   2678 	return -1;
   2679     }
   2680 
   2681     for (;;) {
   2682 	cbuf.buf = (char *) &ack;
   2683 	cbuf.maxlen = sizeof(ack);
   2684 	dbuf.buf = (char *) routes;
   2685 	dbuf.maxlen = sizeof(routes);
   2686 	flags = 0;
   2687 	r = getmsg(fd, &cbuf, &dbuf, &flags);
   2688 	if (r == -1) {
   2689 	    warn("have_route_to: getmsg: %m");
   2690 	    close(fd);
   2691 	    return -1;
   2692 	}
   2693 
   2694 	if (cbuf.len < sizeof(struct T_optmgmt_ack)
   2695 	    || ack.ack.PRIM_type != T_OPTMGMT_ACK
   2696 	    || ack.ack.MGMT_flags != T_SUCCESS
   2697 	    || ack.ack.OPT_length < sizeof(struct opthdr)) {
   2698 	    dbglog("have_route_to: bad message len=%d prim=%d",
   2699 		   cbuf.len, ack.ack.PRIM_type);
   2700 	    close(fd);
   2701 	    return -1;
   2702 	}
   2703 
   2704 	rh = (struct opthdr *) ((char *)&ack + ack.ack.OPT_offset);
   2705 	if (rh->level == 0 && rh->name == 0)
   2706 	    break;
   2707 	if (rh->level != MIB2_IP || rh->name != MIB2_IP_21) {
   2708 	    while (r == MOREDATA)
   2709 		r = getmsg(fd, NULL, &dbuf, &flags);
   2710 	    continue;
   2711 	}
   2712 
   2713 	for (;;) {
   2714 	    nroutes = dbuf.len / sizeof(mib2_ipRouteEntry_t);
   2715 	    for (rp = routes, i = 0; i < nroutes; ++i, ++rp) {
   2716 		if (rp->ipRouteMask != ~0) {
   2717 		    dbglog("have_route_to: dest=%x gw=%x mask=%x\n",
   2718 			   rp->ipRouteDest, rp->ipRouteNextHop,
   2719 			   rp->ipRouteMask);
   2720 		    if (((addr ^ rp->ipRouteDest) & rp->ipRouteMask) == 0
   2721 			&& rp->ipRouteNextHop != remote_addr)
   2722 			return 1;
   2723 		}
   2724 	    }
   2725 	    if (r == 0)
   2726 		break;
   2727 	    r = getmsg(fd, NULL, &dbuf, &flags);
   2728 	}
   2729     }
   2730     close(fd);
   2731     return 0;
   2732 #else
   2733     return -1;
   2734 #endif /* SOL2 */
   2735 }
   2736 
   2737 /*
   2738  * get_pty - get a pty master/slave pair and chown the slave side to
   2739  * the uid given.  Assumes slave_name points to MAXPATHLEN bytes of space.
   2740  */
   2741 int
   2742 get_pty(master_fdp, slave_fdp, slave_name, uid)
   2743     int *master_fdp;
   2744     int *slave_fdp;
   2745     char *slave_name;
   2746     int uid;
   2747 {
   2748     int mfd, sfd;
   2749     char *pty_name;
   2750 
   2751     mfd = open("/dev/ptmx", O_RDWR);
   2752     if (mfd < 0) {
   2753 	error("Couldn't open pty master: %m");
   2754 	return 0;
   2755     }
   2756 
   2757     pty_name = ptsname(mfd);
   2758     if (pty_name == NULL) {
   2759 	error("Couldn't get name of pty slave");
   2760 	close(mfd);
   2761 	return 0;
   2762     }
   2763     if (chown(pty_name, uid, -1) < 0)
   2764 	warn("Couldn't change owner of pty slave: %m");
   2765     if (chmod(pty_name, S_IRUSR | S_IWUSR) < 0)
   2766 	warn("Couldn't change permissions on pty slave: %m");
   2767     if (unlockpt(mfd) < 0)
   2768 	warn("Couldn't unlock pty slave: %m");
   2769 
   2770     sfd = open(pty_name, O_RDWR);
   2771     if (sfd < 0) {
   2772 	error("Couldn't open pty slave %s: %m", pty_name);
   2773 	close(mfd);
   2774 	return 0;
   2775     }
   2776     if (ioctl(sfd, I_PUSH, "ptem") < 0)
   2777 	warn("Couldn't push ptem module on pty slave: %m");
   2778 
   2779     dbglog("Using %s", pty_name);
   2780     strlcpy(slave_name, pty_name, MAXPATHLEN);
   2781     *master_fdp = mfd;
   2782     *slave_fdp = sfd;
   2783 
   2784     return 1;
   2785 }
   2786