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.13 2004/11/04 10:02:26 paulus 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 = 10;			\
    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     tios.c_cflag |= CS8 | CREAD | HUPCL;
   1229     if (local || !modem)
   1230 	tios.c_cflag |= CLOCAL;
   1231     tios.c_iflag = IGNBRK | IGNPAR;
   1232     tios.c_oflag = 0;
   1233     tios.c_lflag = 0;
   1234     tios.c_cc[VMIN] = 1;
   1235     tios.c_cc[VTIME] = 0;
   1236 
   1237     if (crtscts == -2) {
   1238 	tios.c_iflag |= IXON | IXOFF;
   1239 	tios.c_cc[VSTOP] = 0x13;	/* DC3 = XOFF = ^S */
   1240 	tios.c_cc[VSTART] = 0x11;	/* DC1 = XON  = ^Q */
   1241     }
   1242 
   1243     speed = translate_speed(inspeed);
   1244     if (speed) {
   1245 	cfsetospeed(&tios, speed);
   1246 	cfsetispeed(&tios, speed);
   1247     } else {
   1248 	speed = cfgetospeed(&tios);
   1249 	/*
   1250 	 * We can't proceed if the serial port speed is 0,
   1251 	 * since that implies that the serial port is disabled.
   1252 	 */
   1253 	if ((speed == B0) && !sync_serial)
   1254 	    fatal("Baud rate for %s is 0; need explicit baud rate", devnam);
   1255     }
   1256 
   1257     if (!sync_serial && tcsetattr(fd, TCSAFLUSH, &tios) < 0)
   1258 	fatal("tcsetattr: %m");
   1259 
   1260 #ifndef CRTSCTS
   1261     if (!sync_serial && termiox_ok && ioctl (fd, TCSETXF, &tiox) < 0){
   1262 	error("TCSETXF: %m");
   1263     }
   1264 #endif
   1265 
   1266     baud_rate = inspeed = baud_rate_of(speed);
   1267     if (!sync_serial)
   1268 	restore_term = 1;
   1269 }
   1270 
   1271 /*
   1272  * restore_tty - restore the terminal to the saved settings.
   1273  */
   1274 void
   1275 restore_tty(fd)
   1276     int fd;
   1277 {
   1278     if (restore_term) {
   1279 	if (!default_device) {
   1280 	    /*
   1281 	     * Turn off echoing, because otherwise we can get into
   1282 	     * a loop with the tty and the modem echoing to each other.
   1283 	     * We presume we are the sole user of this tty device, so
   1284 	     * when we close it, it will revert to its defaults anyway.
   1285 	     */
   1286 	    inittermios.c_lflag &= ~(ECHO | ECHONL);
   1287 	}
   1288 	if (!sync_serial && tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
   1289 	    if (!hungup && errno != ENXIO)
   1290 		warn("tcsetattr: %m");
   1291 #ifndef CRTSCTS
   1292 	if (!sync_serial && ioctl (fd, TCSETXF, &inittermiox) < 0){
   1293 	    if (!hungup && errno != ENXIO)
   1294 		error("TCSETXF: %m");
   1295 	}
   1296 #endif
   1297 	if (!sync_serial)
   1298 	    ioctl(fd, TIOCSWINSZ, &wsinfo);
   1299 	restore_term = 0;
   1300     }
   1301 }
   1302 
   1303 /*
   1304  * setdtr - control the DTR line on the serial port.
   1305  * This is called from die(), so it shouldn't call die().
   1306  */
   1307 void
   1308 setdtr(fd, on)
   1309 int fd, on;
   1310 {
   1311     int modembits = TIOCM_DTR;
   1312 
   1313     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
   1314 }
   1315 
   1316 /*
   1317  * open_loopback - open the device we use for getting packets
   1318  * in demand mode.  Under Solaris 2, we use our existing fd
   1319  * to the ppp driver.
   1320  */
   1321 int
   1322 open_ppp_loopback()
   1323 {
   1324     return pppfd;
   1325 }
   1326 
   1327 /*
   1328  * output - Output PPP packet.
   1329  */
   1330 void
   1331 output(unit, p, len)
   1332     int unit;
   1333     u_char *p;
   1334     int len;
   1335 {
   1336     struct strbuf data;
   1337     int retries;
   1338     struct pollfd pfd;
   1339 
   1340     dump_packet("sent", p, len);
   1341     if (snoop_send_hook) snoop_send_hook(p, len);
   1342 
   1343     data.len = len;
   1344     data.buf = (caddr_t) p;
   1345     retries = 4;
   1346     while (putmsg(pppfd, NULL, &data, 0) < 0) {
   1347 	if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) {
   1348 	    if (errno != ENXIO)
   1349 		error("Couldn't send packet: %m");
   1350 	    break;
   1351 	}
   1352 	pfd.fd = pppfd;
   1353 	pfd.events = POLLOUT;
   1354 	poll(&pfd, 1, 250);	/* wait for up to 0.25 seconds */
   1355     }
   1356 }
   1357 
   1358 
   1359 /*
   1360  * wait_input - wait until there is data available,
   1361  * for the length of time specified by *timo (indefinite
   1362  * if timo is NULL).
   1363  */
   1364 void
   1365 wait_input(timo)
   1366     struct timeval *timo;
   1367 {
   1368     int t;
   1369 
   1370     t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000;
   1371     if (poll(pollfds, n_pollfds, t) < 0 && errno != EINTR)
   1372 	fatal("poll: %m");
   1373 }
   1374 
   1375 /*
   1376  * add_fd - add an fd to the set that wait_input waits for.
   1377  */
   1378 void add_fd(fd)
   1379     int fd;
   1380 {
   1381     int n;
   1382 
   1383     for (n = 0; n < n_pollfds; ++n)
   1384 	if (pollfds[n].fd == fd)
   1385 	    return;
   1386     if (n_pollfds < MAX_POLLFDS) {
   1387 	pollfds[n_pollfds].fd = fd;
   1388 	pollfds[n_pollfds].events = POLLIN | POLLPRI | POLLHUP;
   1389 	++n_pollfds;
   1390     } else
   1391 	error("Too many inputs!");
   1392 }
   1393 
   1394 /*
   1395  * remove_fd - remove an fd from the set that wait_input waits for.
   1396  */
   1397 void remove_fd(fd)
   1398     int fd;
   1399 {
   1400     int n;
   1401 
   1402     for (n = 0; n < n_pollfds; ++n) {
   1403 	if (pollfds[n].fd == fd) {
   1404 	    while (++n < n_pollfds)
   1405 		pollfds[n-1] = pollfds[n];
   1406 	    --n_pollfds;
   1407 	    break;
   1408 	}
   1409     }
   1410 }
   1411 
   1412 #if 0
   1413 /*
   1414  * wait_loop_output - wait until there is data available on the
   1415  * loopback, for the length of time specified by *timo (indefinite
   1416  * if timo is NULL).
   1417  */
   1418 void
   1419 wait_loop_output(timo)
   1420     struct timeval *timo;
   1421 {
   1422     wait_input(timo);
   1423 }
   1424 
   1425 /*
   1426  * wait_time - wait for a given length of time or until a
   1427  * signal is received.
   1428  */
   1429 void
   1430 wait_time(timo)
   1431     struct timeval *timo;
   1432 {
   1433     int n;
   1434 
   1435     n = select(0, NULL, NULL, NULL, timo);
   1436     if (n < 0 && errno != EINTR)
   1437 	fatal("select: %m");
   1438 }
   1439 #endif
   1440 
   1441 
   1442 /*
   1443  * read_packet - get a PPP packet from the serial device.
   1444  */
   1445 int
   1446 read_packet(buf)
   1447     u_char *buf;
   1448 {
   1449     struct strbuf ctrl, data;
   1450     int flags, len;
   1451     unsigned char ctrlbuf[sizeof(union DL_primitives) + 64];
   1452 
   1453     for (;;) {
   1454 	data.maxlen = PPP_MRU + PPP_HDRLEN;
   1455 	data.buf = (caddr_t) buf;
   1456 	ctrl.maxlen = sizeof(ctrlbuf);
   1457 	ctrl.buf = (caddr_t) ctrlbuf;
   1458 	flags = 0;
   1459 	len = getmsg(pppfd, &ctrl, &data, &flags);
   1460 	if (len < 0) {
   1461 	    if (errno == EAGAIN || errno == EINTR)
   1462 		return -1;
   1463 	    fatal("Error reading packet: %m");
   1464 	}
   1465 
   1466 	if (ctrl.len <= 0)
   1467 	    return data.len;
   1468 
   1469 	/*
   1470 	 * Got a M_PROTO or M_PCPROTO message.  Interpret it
   1471 	 * as a DLPI primitive??
   1472 	 */
   1473 	if (debug)
   1474 	    dbglog("got dlpi prim 0x%x, len=%d",
   1475 		   ((union DL_primitives *)ctrlbuf)->dl_primitive, ctrl.len);
   1476 
   1477     }
   1478 }
   1479 
   1480 /*
   1481  * get_loop_output - get outgoing packets from the ppp device,
   1482  * and detect when we want to bring the real link up.
   1483  * Return value is 1 if we need to bring up the link, 0 otherwise.
   1484  */
   1485 int
   1486 get_loop_output()
   1487 {
   1488     int len;
   1489     int rv = 0;
   1490 
   1491     while ((len = read_packet(inpacket_buf)) > 0) {
   1492 	if (loop_frame(inpacket_buf, len))
   1493 	    rv = 1;
   1494     }
   1495     return rv;
   1496 }
   1497 
   1498 /*
   1499  * netif_set_mtu - set the MTU on the PPP network interface.
   1500  */
   1501 void
   1502 netif_set_mtu(unit, mtu)
   1503     int unit, mtu;
   1504 {
   1505     struct ifreq ifr;
   1506 #if defined(INET6) && defined(SOL2)
   1507     struct lifreq lifr;
   1508     int	fd;
   1509 #endif /* defined(INET6) && defined(SOL2) */
   1510 
   1511     memset(&ifr, 0, sizeof(ifr));
   1512     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
   1513     ifr.ifr_metric = link_mtu;
   1514     if (ioctl(ipfd, SIOCSIFMTU, &ifr) < 0) {
   1515 	error("Couldn't set IP MTU (%s): %m", ifr.ifr_name);
   1516     }
   1517 
   1518 #if defined(INET6) && defined(SOL2)
   1519     fd = socket(AF_INET6, SOCK_DGRAM, 0);
   1520     if (fd < 0)
   1521 	error("Couldn't open IPv6 socket: %m");
   1522 
   1523     memset(&lifr, 0, sizeof(lifr));
   1524     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1525     lifr.lifr_mtu = link_mtu;
   1526     if (ioctl(fd, SIOCSLIFMTU, &lifr) < 0) {
   1527 	close(fd);
   1528 	error("Couldn't set IPv6 MTU (%s): %m", ifr.ifr_name);
   1529     }
   1530     close(fd);
   1531 #endif /* defined(INET6) && defined(SOL2) */
   1532 }
   1533 
   1534 /*
   1535  * tty_send_config - configure the transmit characteristics of
   1536  * the ppp interface.
   1537  */
   1538 void
   1539 tty_send_config(mtu, asyncmap, pcomp, accomp)
   1540     int mtu;
   1541     u_int32_t asyncmap;
   1542     int pcomp, accomp;
   1543 {
   1544     int cf[2];
   1545 
   1546     link_mtu = mtu;
   1547     if (strioctl(pppfd, PPPIO_MTU, &mtu, sizeof(mtu), 0) < 0) {
   1548 	if (hungup && errno == ENXIO) {
   1549 	    ++error_count;
   1550 	    return;
   1551 	}
   1552 	error("Couldn't set MTU: %m");
   1553     }
   1554     if (fdmuxid >= 0) {
   1555 	if (!sync_serial) {
   1556 	    if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, sizeof(asyncmap), 0) < 0)
   1557 		error("Couldn't set transmit ACCM: %m");
   1558 	}
   1559 	cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0);
   1560 	cf[1] = COMP_PROT | COMP_AC;
   1561 	if (any_compressions() &&
   1562 	    strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0)
   1563 	    error("Couldn't set prot/AC compression: %m");
   1564     }
   1565 }
   1566 
   1567 /*
   1568  * tty_set_xaccm - set the extended transmit ACCM for the interface.
   1569  */
   1570 void
   1571 tty_set_xaccm(accm)
   1572     ext_accm accm;
   1573 {
   1574     if (sync_serial)
   1575 	return;
   1576 
   1577     if (fdmuxid >= 0
   1578 	&& strioctl(pppfd, PPPIO_XACCM, accm, sizeof(ext_accm), 0) < 0) {
   1579 	if (!hungup || errno != ENXIO)
   1580 	    warn("Couldn't set extended ACCM: %m");
   1581     }
   1582 }
   1583 
   1584 /*
   1585  * tty_recv_config - configure the receive-side characteristics of
   1586  * the ppp interface.
   1587  */
   1588 void
   1589 tty_recv_config(mru, asyncmap, pcomp, accomp)
   1590     int mru;
   1591     u_int32_t asyncmap;
   1592     int pcomp, accomp;
   1593 {
   1594     int cf[2];
   1595 
   1596     link_mru = mru;
   1597     if (strioctl(pppfd, PPPIO_MRU, &mru, sizeof(mru), 0) < 0) {
   1598 	if (hungup && errno == ENXIO) {
   1599 	    ++error_count;
   1600 	    return;
   1601 	}
   1602 	error("Couldn't set MRU: %m");
   1603     }
   1604     if (fdmuxid >= 0) {
   1605 	if (!sync_serial) {
   1606 	    if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, sizeof(asyncmap), 0) < 0)
   1607 		error("Couldn't set receive ACCM: %m");
   1608 	}
   1609 	cf[0] = (pcomp? DECOMP_PROT: 0) + (accomp? DECOMP_AC: 0);
   1610 	cf[1] = DECOMP_PROT | DECOMP_AC;
   1611 	if (any_compressions() &&
   1612 	    strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0)
   1613 	    error("Couldn't set prot/AC decompression: %m");
   1614     }
   1615 }
   1616 
   1617 /*
   1618  * ccp_test - ask kernel whether a given compression method
   1619  * is acceptable for use.
   1620  */
   1621 int
   1622 ccp_test(unit, opt_ptr, opt_len, for_transmit)
   1623     int unit, opt_len, for_transmit;
   1624     u_char *opt_ptr;
   1625 {
   1626     if (strioctl(pppfd, (for_transmit? PPPIO_XCOMP: PPPIO_RCOMP),
   1627 		 opt_ptr, opt_len, 0) >= 0)
   1628 	return 1;
   1629     return (errno == ENOSR)? 0: -1;
   1630 }
   1631 
   1632 /*
   1633  * ccp_flags_set - inform kernel about the current state of CCP.
   1634  */
   1635 void
   1636 ccp_flags_set(unit, isopen, isup)
   1637     int unit, isopen, isup;
   1638 {
   1639     int cf[2];
   1640 
   1641     cf[0] = (isopen? CCP_ISOPEN: 0) + (isup? CCP_ISUP: 0);
   1642     cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR;
   1643     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
   1644 	if (!hungup || errno != ENXIO)
   1645 	    error("Couldn't set kernel CCP state: %m");
   1646     }
   1647 }
   1648 
   1649 /*
   1650  * get_idle_time - return how long the link has been idle.
   1651  */
   1652 int
   1653 get_idle_time(u, ip)
   1654     int u;
   1655     struct ppp_idle *ip;
   1656 {
   1657     return strioctl(pppfd, PPPIO_GIDLE, ip, 0, sizeof(struct ppp_idle)) >= 0;
   1658 }
   1659 
   1660 /*
   1661  * get_ppp_stats - return statistics for the link.
   1662  */
   1663 int
   1664 get_ppp_stats(u, stats)
   1665     int u;
   1666     struct pppd_stats *stats;
   1667 {
   1668     struct ppp_stats s;
   1669 
   1670     if (!sync_serial &&
   1671 	strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof(s)) < 0) {
   1672 	error("Couldn't get link statistics: %m");
   1673 	return 0;
   1674     }
   1675     stats->bytes_in = s.p.ppp_ibytes;
   1676     stats->bytes_out = s.p.ppp_obytes;
   1677     stats->pkts_in = s.p.ppp_ipackets;
   1678     stats->pkts_out = s.p.ppp_opackets;
   1679     return 1;
   1680 }
   1681 
   1682 #if 0
   1683 /*
   1684  * set_filters - transfer the pass and active filters to the kernel.
   1685  */
   1686 int
   1687 set_filters(pass, active)
   1688     struct bpf_program *pass, *active;
   1689 {
   1690     int ret = 1;
   1691 
   1692     if (pass->bf_len > 0) {
   1693 	if (strioctl(pppfd, PPPIO_PASSFILT, pass,
   1694 		     sizeof(struct bpf_program), 0) < 0) {
   1695 	    error("Couldn't set pass-filter in kernel: %m");
   1696 	    ret = 0;
   1697 	}
   1698     }
   1699     if (active->bf_len > 0) {
   1700 	if (strioctl(pppfd, PPPIO_ACTIVEFILT, active,
   1701 		     sizeof(struct bpf_program), 0) < 0) {
   1702 	    error("Couldn't set active-filter in kernel: %m");
   1703 	    ret = 0;
   1704 	}
   1705     }
   1706     return ret;
   1707 }
   1708 #endif
   1709 
   1710 /*
   1711  * ccp_fatal_error - returns 1 if decompression was disabled as a
   1712  * result of an error detected after decompression of a packet,
   1713  * 0 otherwise.  This is necessary because of patent nonsense.
   1714  */
   1715 int
   1716 ccp_fatal_error(unit)
   1717     int unit;
   1718 {
   1719     int cf[2];
   1720 
   1721     cf[0] = cf[1] = 0;
   1722     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
   1723 	if (errno != ENXIO && errno != EINVAL)
   1724 	    error("Couldn't get compression flags: %m");
   1725 	return 0;
   1726     }
   1727     return cf[0] & CCP_FATALERROR;
   1728 }
   1729 
   1730 /*
   1731  * sifvjcomp - config tcp header compression
   1732  */
   1733 int
   1734 sifvjcomp(u, vjcomp, xcidcomp, xmaxcid)
   1735     int u, vjcomp, xcidcomp, xmaxcid;
   1736 {
   1737     int cf[2];
   1738     char maxcid[2];
   1739 
   1740     if (vjcomp) {
   1741 	maxcid[0] = xcidcomp;
   1742 	maxcid[1] = 15;		/* XXX should be rmaxcid */
   1743 	if (strioctl(pppfd, PPPIO_VJINIT, maxcid, sizeof(maxcid), 0) < 0) {
   1744 	    error("Couldn't initialize VJ compression: %m");
   1745 	}
   1746     }
   1747 
   1748     cf[0] = (vjcomp? COMP_VJC + DECOMP_VJC: 0)	/* XXX this is wrong */
   1749 	+ (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0);
   1750     cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID;
   1751     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
   1752 	if (vjcomp)
   1753 	    error("Couldn't enable VJ compression: %m");
   1754     }
   1755 
   1756     return 1;
   1757 }
   1758 
   1759 /*
   1760  * sifup - Config the interface up and enable IP packets to pass.
   1761  */
   1762 int
   1763 sifup(u)
   1764     int u;
   1765 {
   1766     struct ifreq ifr;
   1767 
   1768     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
   1769     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
   1770 	error("Couldn't mark interface up (get): %m");
   1771 	return 0;
   1772     }
   1773     ifr.ifr_flags |= IFF_UP;
   1774     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
   1775 	error("Couldn't mark interface up (set): %m");
   1776 	return 0;
   1777     }
   1778     if_is_up = 1;
   1779     return 1;
   1780 }
   1781 
   1782 /*
   1783  * sifdown - Config the interface down and disable IP.
   1784  */
   1785 int
   1786 sifdown(u)
   1787     int u;
   1788 {
   1789     struct ifreq ifr;
   1790 
   1791     if (ipmuxid < 0)
   1792 	return 1;
   1793     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
   1794     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
   1795 	error("Couldn't mark interface down (get): %m");
   1796 	return 0;
   1797     }
   1798     ifr.ifr_flags &= ~IFF_UP;
   1799     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
   1800 	error("Couldn't mark interface down (set): %m");
   1801 	return 0;
   1802     }
   1803     if_is_up = 0;
   1804     return 1;
   1805 }
   1806 
   1807 /*
   1808  * sifnpmode - Set the mode for handling packets for a given NP.
   1809  */
   1810 int
   1811 sifnpmode(u, proto, mode)
   1812     int u;
   1813     int proto;
   1814     enum NPmode mode;
   1815 {
   1816     int npi[2];
   1817 
   1818     npi[0] = proto;
   1819     npi[1] = (int) mode;
   1820     if (strioctl(pppfd, PPPIO_NPMODE, &npi, 2 * sizeof(int), 0) < 0) {
   1821 	error("ioctl(set NP %d mode to %d): %m", proto, mode);
   1822 	return 0;
   1823     }
   1824     return 1;
   1825 }
   1826 
   1827 #if defined(SOL2) && defined(INET6)
   1828 /*
   1829  * sif6up - Config the IPv6 interface up and enable IPv6 packets to pass.
   1830  */
   1831 int
   1832 sif6up(u)
   1833     int u;
   1834 {
   1835     struct lifreq lifr;
   1836     int fd;
   1837 
   1838     fd = socket(AF_INET6, SOCK_DGRAM, 0);
   1839     if (fd < 0) {
   1840 	return 0;
   1841     }
   1842 
   1843     memset(&lifr, 0, sizeof(lifr));
   1844     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1845     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
   1846 	close(fd);
   1847 	return 0;
   1848     }
   1849 
   1850     lifr.lifr_flags |= IFF_UP;
   1851     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1852     if (ioctl(fd, SIOCSLIFFLAGS, &lifr) < 0) {
   1853 	close(fd);
   1854 	return 0;
   1855     }
   1856 
   1857     if6_is_up = 1;
   1858     close(fd);
   1859     return 1;
   1860 }
   1861 
   1862 /*
   1863  * sifdown - Config the IPv6 interface down and disable IPv6.
   1864  */
   1865 int
   1866 sif6down(u)
   1867     int u;
   1868 {
   1869     struct lifreq lifr;
   1870     int fd;
   1871 
   1872     fd = socket(AF_INET6, SOCK_DGRAM, 0);
   1873     if (fd < 0)
   1874 	return 0;
   1875 
   1876     memset(&lifr, 0, sizeof(lifr));
   1877     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1878     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
   1879 	close(fd);
   1880 	return 0;
   1881     }
   1882 
   1883     lifr.lifr_flags &= ~IFF_UP;
   1884     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1885     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
   1886 	close(fd);
   1887 	return 0;
   1888     }
   1889 
   1890     if6_is_up = 0;
   1891     close(fd);
   1892     return 1;
   1893 }
   1894 
   1895 /*
   1896  * sif6addr - Config the interface with an IPv6 link-local address
   1897  */
   1898 int
   1899 sif6addr(u, o, h)
   1900     int u;
   1901     eui64_t o, h;
   1902 {
   1903     struct lifreq lifr;
   1904     struct sockaddr_storage laddr;
   1905     struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&laddr;
   1906     int fd;
   1907 
   1908     fd = socket(AF_INET6, SOCK_DGRAM, 0);
   1909     if (fd < 0)
   1910 	return 0;
   1911 
   1912     memset(&lifr, 0, sizeof(lifr));
   1913     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1914 
   1915     /*
   1916      * Do this because /dev/ppp responds to DL_PHYS_ADDR_REQ with
   1917      * zero values, hence the interface token came to be zero too,
   1918      * and without this, in.ndpd will complain
   1919      */
   1920     IN6_LLTOKEN_FROM_EUI64(lifr, sin6, o);
   1921     if (ioctl(fd, SIOCSLIFTOKEN, &lifr) < 0) {
   1922 	close(fd);
   1923 	return 0;
   1924     }
   1925 
   1926     /*
   1927      * Set the interface address and destination address
   1928      */
   1929     IN6_LLADDR_FROM_EUI64(lifr, sin6, o);
   1930     if (ioctl(fd, SIOCSLIFADDR, &lifr) < 0) {
   1931 	close(fd);
   1932 	return 0;
   1933     }
   1934 
   1935     memset(&lifr, 0, sizeof(lifr));
   1936     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
   1937     IN6_LLADDR_FROM_EUI64(lifr, sin6, h);
   1938     if (ioctl(fd, SIOCSLIFDSTADDR, &lifr) < 0) {
   1939 	close(fd);
   1940 	return 0;
   1941     }
   1942 
   1943     return 1;
   1944 }
   1945 
   1946 /*
   1947  * cif6addr - Remove the IPv6 address from interface
   1948  */
   1949 int
   1950 cif6addr(u, o, h)
   1951     int u;
   1952     eui64_t o, h;
   1953 {
   1954     return 1;
   1955 }
   1956 
   1957 #endif /* defined(SOL2) && defined(INET6) */
   1958 
   1959 
   1960 #define INET_ADDR(x)	(((struct sockaddr_in *) &(x))->sin_addr.s_addr)
   1961 
   1962 /*
   1963  * sifaddr - Config the interface IP addresses and netmask.
   1964  */
   1965 int
   1966 sifaddr(u, o, h, m)
   1967     int u;
   1968     u_int32_t o, h, m;
   1969 {
   1970     struct ifreq ifr;
   1971     int ret = 1;
   1972 
   1973     memset(&ifr, 0, sizeof(ifr));
   1974     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
   1975     ifr.ifr_addr.sa_family = AF_INET;
   1976     INET_ADDR(ifr.ifr_addr) = m;
   1977     if (ioctl(ipfd, SIOCSIFNETMASK, &ifr) < 0) {
   1978 	error("Couldn't set IP netmask: %m");
   1979 	ret = 0;
   1980     }
   1981     ifr.ifr_addr.sa_family = AF_INET;
   1982     INET_ADDR(ifr.ifr_addr) = o;
   1983     if (ioctl(ipfd, SIOCSIFADDR, &ifr) < 0) {
   1984 	error("Couldn't set local IP address: %m");
   1985 	ret = 0;
   1986     }
   1987 
   1988     /*
   1989      * On some systems, we have to explicitly set the point-to-point
   1990      * flag bit before we can set a destination address.
   1991      */
   1992     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) >= 0
   1993 	&& (ifr.ifr_flags & IFF_POINTOPOINT) == 0) {
   1994 	ifr.ifr_flags |= IFF_POINTOPOINT;
   1995 	if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
   1996 	    error("Couldn't mark interface pt-to-pt: %m");
   1997 	    ret = 0;
   1998 	}
   1999     }
   2000     ifr.ifr_dstaddr.sa_family = AF_INET;
   2001     INET_ADDR(ifr.ifr_dstaddr) = h;
   2002     if (ioctl(ipfd, SIOCSIFDSTADDR, &ifr) < 0) {
   2003 	error("Couldn't set remote IP address: %m");
   2004 	ret = 0;
   2005     }
   2006 
   2007     remote_addr = h;
   2008     return ret;
   2009 }
   2010 
   2011 /*
   2012  * cifaddr - Clear the interface IP addresses, and delete routes
   2013  * through the interface if possible.
   2014  */
   2015 int
   2016 cifaddr(u, o, h)
   2017     int u;
   2018     u_int32_t o, h;
   2019 {
   2020 #if defined(__USLC__)		/* was: #if 0 */
   2021     cifroute(unit, ouraddr, hisaddr);
   2022     if (ipmuxid >= 0) {
   2023 	notice("Removing ppp interface unit");
   2024 	if (ioctl(ipfd, I_UNLINK, ipmuxid) < 0) {
   2025 	    error("Can't remove ppp interface unit: %m");
   2026 	    return 0;
   2027 	}
   2028 	ipmuxid = -1;
   2029     }
   2030 #endif
   2031     remote_addr = 0;
   2032     return 1;
   2033 }
   2034 
   2035 /*
   2036  * sifdefaultroute - assign a default route through the address given.
   2037  */
   2038 int
   2039 sifdefaultroute(u, l, g)
   2040     int u;
   2041     u_int32_t l, g;
   2042 {
   2043     struct rtentry rt;
   2044 
   2045 #if defined(__USLC__)
   2046     g = l;			/* use the local address as gateway */
   2047 #endif
   2048     memset(&rt, 0, sizeof(rt));
   2049     rt.rt_dst.sa_family = AF_INET;
   2050     INET_ADDR(rt.rt_dst) = 0;
   2051     rt.rt_gateway.sa_family = AF_INET;
   2052     INET_ADDR(rt.rt_gateway) = g;
   2053     rt.rt_flags = RTF_GATEWAY;
   2054 
   2055     if (ioctl(ipfd, SIOCADDRT, &rt) < 0) {
   2056 	error("Can't add default route: %m");
   2057 	return 0;
   2058     }
   2059 
   2060     default_route_gateway = g;
   2061     return 1;
   2062 }
   2063 
   2064 /*
   2065  * cifdefaultroute - delete a default route through the address given.
   2066  */
   2067 int
   2068 cifdefaultroute(u, l, g)
   2069     int u;
   2070     u_int32_t l, g;
   2071 {
   2072     struct rtentry rt;
   2073 
   2074 #if defined(__USLC__)
   2075     g = l;			/* use the local address as gateway */
   2076 #endif
   2077     memset(&rt, 0, sizeof(rt));
   2078     rt.rt_dst.sa_family = AF_INET;
   2079     INET_ADDR(rt.rt_dst) = 0;
   2080     rt.rt_gateway.sa_family = AF_INET;
   2081     INET_ADDR(rt.rt_gateway) = g;
   2082     rt.rt_flags = RTF_GATEWAY;
   2083 
   2084     if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
   2085 	error("Can't delete default route: %m");
   2086 	return 0;
   2087     }
   2088 
   2089     default_route_gateway = 0;
   2090     return 1;
   2091 }
   2092 
   2093 /*
   2094  * sifproxyarp - Make a proxy ARP entry for the peer.
   2095  */
   2096 int
   2097 sifproxyarp(unit, hisaddr)
   2098     int unit;
   2099     u_int32_t hisaddr;
   2100 {
   2101     struct arpreq arpreq;
   2102 
   2103     memset(&arpreq, 0, sizeof(arpreq));
   2104     if (!get_ether_addr(hisaddr, &arpreq.arp_ha))
   2105 	return 0;
   2106 
   2107     arpreq.arp_pa.sa_family = AF_INET;
   2108     INET_ADDR(arpreq.arp_pa) = hisaddr;
   2109     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
   2110     if (ioctl(ipfd, SIOCSARP, (caddr_t) &arpreq) < 0) {
   2111 	error("Couldn't set proxy ARP entry: %m");
   2112 	return 0;
   2113     }
   2114 
   2115     proxy_arp_addr = hisaddr;
   2116     return 1;
   2117 }
   2118 
   2119 /*
   2120  * cifproxyarp - Delete the proxy ARP entry for the peer.
   2121  */
   2122 int
   2123 cifproxyarp(unit, hisaddr)
   2124     int unit;
   2125     u_int32_t hisaddr;
   2126 {
   2127     struct arpreq arpreq;
   2128 
   2129     memset(&arpreq, 0, sizeof(arpreq));
   2130     arpreq.arp_pa.sa_family = AF_INET;
   2131     INET_ADDR(arpreq.arp_pa) = hisaddr;
   2132     if (ioctl(ipfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
   2133 	error("Couldn't delete proxy ARP entry: %m");
   2134 	return 0;
   2135     }
   2136 
   2137     proxy_arp_addr = 0;
   2138     return 1;
   2139 }
   2140 
   2141 /*
   2142  * get_ether_addr - get the hardware address of an interface on the
   2143  * the same subnet as ipaddr.
   2144  */
   2145 #define MAX_IFS		32
   2146 
   2147 static int
   2148 get_ether_addr(ipaddr, hwaddr)
   2149     u_int32_t ipaddr;
   2150     struct sockaddr *hwaddr;
   2151 {
   2152     struct ifreq *ifr, *ifend, ifreq;
   2153     int nif;
   2154     struct ifconf ifc;
   2155     u_int32_t ina, mask;
   2156 
   2157     /*
   2158      * Scan through the system's network interfaces.
   2159      */
   2160 #ifdef SIOCGIFNUM
   2161     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
   2162 #endif
   2163 	nif = MAX_IFS;
   2164     ifc.ifc_len = nif * sizeof(struct ifreq);
   2165     ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len);
   2166     if (ifc.ifc_buf == 0)
   2167 	return 0;
   2168     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
   2169 	warn("Couldn't get system interface list: %m");
   2170 	free(ifc.ifc_buf);
   2171 	return 0;
   2172     }
   2173     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
   2174     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
   2175 	if (ifr->ifr_addr.sa_family != AF_INET)
   2176 	    continue;
   2177 	/*
   2178 	 * Check that the interface is up, and not point-to-point or loopback.
   2179 	 */
   2180 	strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
   2181 	if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
   2182 	    continue;
   2183 	if ((ifreq.ifr_flags &
   2184 	     (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
   2185 	    != (IFF_UP|IFF_BROADCAST))
   2186 	    continue;
   2187 	/*
   2188 	 * Get its netmask and check that it's on the right subnet.
   2189 	 */
   2190 	if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
   2191 	    continue;
   2192 	ina = INET_ADDR(ifr->ifr_addr);
   2193 	mask = INET_ADDR(ifreq.ifr_addr);
   2194 	if ((ipaddr & mask) == (ina & mask))
   2195 	    break;
   2196     }
   2197 
   2198     if (ifr >= ifend) {
   2199 	warn("No suitable interface found for proxy ARP");
   2200 	free(ifc.ifc_buf);
   2201 	return 0;
   2202     }
   2203 
   2204     info("found interface %s for proxy ARP", ifr->ifr_name);
   2205     if (!get_hw_addr(ifr->ifr_name, ina, hwaddr)) {
   2206 	error("Couldn't get hardware address for %s", ifr->ifr_name);
   2207 	free(ifc.ifc_buf);
   2208 	return 0;
   2209     }
   2210 
   2211     free(ifc.ifc_buf);
   2212     return 1;
   2213 }
   2214 
   2215 /*
   2216  * get_hw_addr_dlpi - obtain the hardware address using DLPI
   2217  */
   2218 static int
   2219 get_hw_addr_dlpi(name, hwaddr)
   2220     char *name;
   2221     struct sockaddr *hwaddr;
   2222 {
   2223     char *p, *q;
   2224     int unit, iffd, adrlen;
   2225     unsigned char *adrp;
   2226     char ifdev[24];
   2227     struct {
   2228 	union DL_primitives prim;
   2229 	char space[64];
   2230     } reply;
   2231 
   2232     /*
   2233      * We have to open the device and ask it for its hardware address.
   2234      * First split apart the device name and unit.
   2235      */
   2236     slprintf(ifdev, sizeof(ifdev), "/dev/%s", name);
   2237     for (q = ifdev + strlen(ifdev); --q >= ifdev; )
   2238 	if (!isdigit(*q))
   2239 	    break;
   2240     unit = atoi(q+1);
   2241     q[1] = 0;
   2242 
   2243     /*
   2244      * Open the device and do a DLPI attach and phys_addr_req.
   2245      */
   2246     iffd = open(ifdev, O_RDWR);
   2247     if (iffd < 0) {
   2248 	error("Can't open %s: %m", ifdev);
   2249 	return 0;
   2250     }
   2251     if (dlpi_attach(iffd, unit) < 0
   2252 	|| dlpi_get_reply(iffd, &reply.prim, DL_OK_ACK, sizeof(reply)) < 0
   2253 	|| dlpi_info_req(iffd) < 0
   2254 	|| dlpi_get_reply(iffd, &reply.prim, DL_INFO_ACK, sizeof(reply)) < 0) {
   2255 	close(iffd);
   2256 	return 0;
   2257     }
   2258 
   2259     adrlen = reply.prim.info_ack.dl_addr_length;
   2260     adrp = (unsigned char *)&reply + reply.prim.info_ack.dl_addr_offset;
   2261 
   2262 #if DL_CURRENT_VERSION >= 2
   2263     if (reply.prim.info_ack.dl_sap_length < 0)
   2264 	adrlen += reply.prim.info_ack.dl_sap_length;
   2265     else
   2266 	adrp += reply.prim.info_ack.dl_sap_length;
   2267 #endif
   2268 
   2269     hwaddr->sa_family = AF_UNSPEC;
   2270     memcpy(hwaddr->sa_data, adrp, adrlen);
   2271 
   2272     return 1;
   2273 }
   2274 /*
   2275  * get_hw_addr - obtain the hardware address for a named interface.
   2276  */
   2277 static int
   2278 get_hw_addr(name, ina, hwaddr)
   2279     char *name;
   2280     u_int32_t ina;
   2281     struct sockaddr *hwaddr;
   2282 {
   2283     /* New way - get the address by doing an arp request. */
   2284     int s;
   2285     struct arpreq req;
   2286 
   2287     s = socket(AF_INET, SOCK_DGRAM, 0);
   2288     if (s < 0)
   2289 	return 0;
   2290     memset(&req, 0, sizeof(req));
   2291     req.arp_pa.sa_family = AF_INET;
   2292     INET_ADDR(req.arp_pa) = ina;
   2293     if (ioctl(s, SIOCGARP, &req) < 0) {
   2294 	error("Couldn't get ARP entry for %s: %m", ip_ntoa(ina));
   2295 	return 0;
   2296     }
   2297     *hwaddr = req.arp_ha;
   2298     hwaddr->sa_family = AF_UNSPEC;
   2299 
   2300     return 1;
   2301 }
   2302 
   2303 static int
   2304 dlpi_attach(fd, ppa)
   2305     int fd, ppa;
   2306 {
   2307     dl_attach_req_t req;
   2308     struct strbuf buf;
   2309 
   2310     req.dl_primitive = DL_ATTACH_REQ;
   2311     req.dl_ppa = ppa;
   2312     buf.len = sizeof(req);
   2313     buf.buf = (void *) &req;
   2314     return putmsg(fd, &buf, NULL, RS_HIPRI);
   2315 }
   2316 
   2317 static int
   2318 dlpi_info_req(fd)
   2319     int fd;
   2320 {
   2321     dl_info_req_t req;
   2322     struct strbuf buf;
   2323 
   2324     req.dl_primitive = DL_INFO_REQ;
   2325     buf.len = sizeof(req);
   2326     buf.buf = (void *) &req;
   2327     return putmsg(fd, &buf, NULL, RS_HIPRI);
   2328 }
   2329 
   2330 static int
   2331 dlpi_get_reply(fd, reply, expected_prim, maxlen)
   2332     union DL_primitives *reply;
   2333     int fd, expected_prim, maxlen;
   2334 {
   2335     struct strbuf buf;
   2336     int flags, n;
   2337     struct pollfd pfd;
   2338 
   2339     /*
   2340      * Use poll to wait for a message with a timeout.
   2341      */
   2342     pfd.fd = fd;
   2343     pfd.events = POLLIN | POLLPRI;
   2344     do {
   2345 	n = poll(&pfd, 1, 1000);
   2346     } while (n == -1 && errno == EINTR);
   2347     if (n <= 0)
   2348 	return -1;
   2349 
   2350     /*
   2351      * Get the reply.
   2352      */
   2353     buf.maxlen = maxlen;
   2354     buf.buf = (void *) reply;
   2355     flags = 0;
   2356     if (getmsg(fd, &buf, NULL, &flags) < 0)
   2357 	return -1;
   2358 
   2359     if (buf.len < sizeof(ulong)) {
   2360 	if (debug)
   2361 	    dbglog("dlpi response short (len=%d)\n", buf.len);
   2362 	return -1;
   2363     }
   2364 
   2365     if (reply->dl_primitive == expected_prim)
   2366 	return 0;
   2367 
   2368     if (debug) {
   2369 	if (reply->dl_primitive == DL_ERROR_ACK) {
   2370 	    dbglog("dlpi error %d (unix errno %d) for prim %x\n",
   2371 		   reply->error_ack.dl_errno, reply->error_ack.dl_unix_errno,
   2372 		   reply->error_ack.dl_error_primitive);
   2373 	} else {
   2374 	    dbglog("dlpi unexpected response prim %x\n",
   2375 		   reply->dl_primitive);
   2376 	}
   2377     }
   2378 
   2379     return -1;
   2380 }
   2381 
   2382 /*
   2383  * Return user specified netmask, modified by any mask we might determine
   2384  * for address `addr' (in network byte order).
   2385  * Here we scan through the system's list of interfaces, looking for
   2386  * any non-point-to-point interfaces which might appear to be on the same
   2387  * network as `addr'.  If we find any, we OR in their netmask to the
   2388  * user-specified netmask.
   2389  */
   2390 u_int32_t
   2391 GetMask(addr)
   2392     u_int32_t addr;
   2393 {
   2394     u_int32_t mask, nmask, ina;
   2395     struct ifreq *ifr, *ifend, ifreq;
   2396     int nif;
   2397     struct ifconf ifc;
   2398 
   2399     addr = ntohl(addr);
   2400     if (IN_CLASSA(addr))	/* determine network mask for address class */
   2401 	nmask = IN_CLASSA_NET;
   2402     else if (IN_CLASSB(addr))
   2403 	nmask = IN_CLASSB_NET;
   2404     else
   2405 	nmask = IN_CLASSC_NET;
   2406     /* class D nets are disallowed by bad_ip_adrs */
   2407     mask = netmask | htonl(nmask);
   2408 
   2409     /*
   2410      * Scan through the system's network interfaces.
   2411      */
   2412 #ifdef SIOCGIFNUM
   2413     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
   2414 #endif
   2415 	nif = MAX_IFS;
   2416     ifc.ifc_len = nif * sizeof(struct ifreq);
   2417     ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len);
   2418     if (ifc.ifc_buf == 0)
   2419 	return mask;
   2420     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
   2421 	warn("Couldn't get system interface list: %m");
   2422 	free(ifc.ifc_buf);
   2423 	return mask;
   2424     }
   2425     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
   2426     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
   2427 	/*
   2428 	 * Check the interface's internet address.
   2429 	 */
   2430 	if (ifr->ifr_addr.sa_family != AF_INET)
   2431 	    continue;
   2432 	ina = INET_ADDR(ifr->ifr_addr);
   2433 	if ((ntohl(ina) & nmask) != (addr & nmask))
   2434 	    continue;
   2435 	/*
   2436 	 * Check that the interface is up, and not point-to-point or loopback.
   2437 	 */
   2438 	strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
   2439 	if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
   2440 	    continue;
   2441 	if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
   2442 	    != IFF_UP)
   2443 	    continue;
   2444 	/*
   2445 	 * Get its netmask and OR it into our mask.
   2446 	 */
   2447 	if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
   2448 	    continue;
   2449 	mask |= INET_ADDR(ifreq.ifr_addr);
   2450     }
   2451 
   2452     free(ifc.ifc_buf);
   2453     return mask;
   2454 }
   2455 
   2456 /*
   2457  * logwtmp - write an accounting record to the /var/adm/wtmp file.
   2458  */
   2459 void
   2460 logwtmp(line, name, host)
   2461     const char *line, *name, *host;
   2462 {
   2463     static struct utmpx utmpx;
   2464 
   2465     if (name[0] != 0) {
   2466 	/* logging in */
   2467 	strncpy(utmpx.ut_user, name, sizeof(utmpx.ut_user));
   2468 	strncpy(utmpx.ut_id, ifname, sizeof(utmpx.ut_id));
   2469 	strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line));
   2470 	utmpx.ut_pid = getpid();
   2471 	utmpx.ut_type = USER_PROCESS;
   2472     } else {
   2473 	utmpx.ut_type = DEAD_PROCESS;
   2474     }
   2475     gettimeofday(&utmpx.ut_tv, NULL);
   2476     updwtmpx("/var/adm/wtmpx", &utmpx);
   2477 }
   2478 
   2479 /*
   2480  * get_host_seed - return the serial number of this machine.
   2481  */
   2482 int
   2483 get_host_seed()
   2484 {
   2485     char buf[32];
   2486 
   2487     if (sysinfo(SI_HW_SERIAL, buf, sizeof(buf)) < 0) {
   2488 	error("sysinfo: %m");
   2489 	return 0;
   2490     }
   2491     return (int) strtoul(buf, NULL, 16);
   2492 }
   2493 
   2494 static int
   2495 strioctl(fd, cmd, ptr, ilen, olen)
   2496     int fd, cmd, ilen, olen;
   2497     void *ptr;
   2498 {
   2499     struct strioctl str;
   2500 
   2501     str.ic_cmd = cmd;
   2502     str.ic_timout = 0;
   2503     str.ic_len = ilen;
   2504     str.ic_dp = ptr;
   2505     if (ioctl(fd, I_STR, &str) == -1)
   2506 	return -1;
   2507     if (str.ic_len != olen)
   2508 	dbglog("strioctl: expected %d bytes, got %d for cmd %x\n",
   2509 	       olen, str.ic_len, cmd);
   2510     return 0;
   2511 }
   2512 
   2513 #if 0
   2514 /*
   2515  * lock - create a lock file for the named lock device
   2516  */
   2517 
   2518 #define LOCK_PREFIX	"/var/spool/locks/LK."
   2519 static char lock_file[40];	/* name of lock file created */
   2520 
   2521 int
   2522 lock(dev)
   2523     char *dev;
   2524 {
   2525     int n, fd, pid;
   2526     struct stat sbuf;
   2527     char ascii_pid[12];
   2528 
   2529     if (stat(dev, &sbuf) < 0) {
   2530 	error("Can't get device number for %s: %m", dev);
   2531 	return -1;
   2532     }
   2533     if ((sbuf.st_mode & S_IFMT) != S_IFCHR) {
   2534 	error("Can't lock %s: not a character device", dev);
   2535 	return -1;
   2536     }
   2537     slprintf(lock_file, sizeof(lock_file), "%s%03d.%03d.%03d",
   2538 	     LOCK_PREFIX, major(sbuf.st_dev),
   2539 	     major(sbuf.st_rdev), minor(sbuf.st_rdev));
   2540 
   2541     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
   2542 	if (errno == EEXIST
   2543 	    && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
   2544 	    /* Read the lock file to find out who has the device locked */
   2545 	    n = read(fd, ascii_pid, 11);
   2546 	    if (n <= 0) {
   2547 		error("Can't read pid from lock file %s", lock_file);
   2548 		close(fd);
   2549 	    } else {
   2550 		ascii_pid[n] = 0;
   2551 		pid = atoi(ascii_pid);
   2552 		if (pid > 0 && kill(pid, 0) == -1 && errno == ESRCH) {
   2553 		    /* pid no longer exists - remove the lock file */
   2554 		    if (unlink(lock_file) == 0) {
   2555 			close(fd);
   2556 			notice("Removed stale lock on %s (pid %d)",
   2557 			       dev, pid);
   2558 			continue;
   2559 		    } else
   2560 			warn("Couldn't remove stale lock on %s",
   2561 			       dev);
   2562 		} else
   2563 		    notice("Device %s is locked by pid %d",
   2564 			   dev, pid);
   2565 	    }
   2566 	    close(fd);
   2567 	} else
   2568 	    error("Can't create lock file %s: %m", lock_file);
   2569 	lock_file[0] = 0;
   2570 	return -1;
   2571     }
   2572 
   2573     slprintf(ascii_pid, sizeof(ascii_pid), "%10d\n", getpid());
   2574     write(fd, ascii_pid, 11);
   2575 
   2576     close(fd);
   2577     return 1;
   2578 }
   2579 
   2580 /*
   2581  * unlock - remove our lockfile
   2582  */
   2583 void
   2584 unlock()
   2585 {
   2586     if (lock_file[0]) {
   2587 	unlink(lock_file);
   2588 	lock_file[0] = 0;
   2589     }
   2590 }
   2591 #endif
   2592 
   2593 /*
   2594  * cifroute - delete a route through the addresses given.
   2595  */
   2596 int
   2597 cifroute(u, our, his)
   2598     int u;
   2599     u_int32_t our, his;
   2600 {
   2601     struct rtentry rt;
   2602 
   2603     memset(&rt, 0, sizeof(rt));
   2604     rt.rt_dst.sa_family = AF_INET;
   2605     INET_ADDR(rt.rt_dst) = his;
   2606     rt.rt_gateway.sa_family = AF_INET;
   2607     INET_ADDR(rt.rt_gateway) = our;
   2608     rt.rt_flags = RTF_HOST;
   2609 
   2610     if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
   2611 	error("Can't delete route: %m");
   2612 	return 0;
   2613     }
   2614 
   2615     return 1;
   2616 }
   2617 
   2618 /*
   2619  * have_route_to - determine if the system has a route to the specified
   2620  * IP address.  Returns 0 if not, 1 if so, -1 if we can't tell.
   2621  * `addr' is in network byte order.
   2622  * For demand mode to work properly, we have to ignore routes
   2623  * through our own interface.
   2624  */
   2625 #ifndef T_CURRENT		/* needed for Solaris 2.5 */
   2626 #define T_CURRENT	MI_T_CURRENT
   2627 #endif
   2628 
   2629 int
   2630 have_route_to(addr)
   2631     u_int32_t addr;
   2632 {
   2633 #ifdef SOL2
   2634     int fd, r, flags, i;
   2635     struct {
   2636 	struct T_optmgmt_req req;
   2637 	struct opthdr hdr;
   2638     } req;
   2639     union {
   2640 	struct T_optmgmt_ack ack;
   2641 	unsigned char space[64];
   2642     } ack;
   2643     struct opthdr *rh;
   2644     struct strbuf cbuf, dbuf;
   2645     int nroutes;
   2646     mib2_ipRouteEntry_t routes[8];
   2647     mib2_ipRouteEntry_t *rp;
   2648 
   2649     fd = open(mux_dev_name, O_RDWR);
   2650     if (fd < 0) {
   2651 	warn("have_route_to: couldn't open %s: %m", mux_dev_name);
   2652 	return -1;
   2653     }
   2654 
   2655     req.req.PRIM_type = T_OPTMGMT_REQ;
   2656     req.req.OPT_offset = (char *) &req.hdr - (char *) &req;
   2657     req.req.OPT_length = sizeof(req.hdr);
   2658     req.req.MGMT_flags = T_CURRENT;
   2659 
   2660     req.hdr.level = MIB2_IP;
   2661     req.hdr.name = 0;
   2662     req.hdr.len = 0;
   2663 
   2664     cbuf.buf = (char *) &req;
   2665     cbuf.len = sizeof(req);
   2666 
   2667     if (putmsg(fd, &cbuf, NULL, 0) == -1) {
   2668 	warn("have_route_to: putmsg: %m");
   2669 	close(fd);
   2670 	return -1;
   2671     }
   2672 
   2673     for (;;) {
   2674 	cbuf.buf = (char *) &ack;
   2675 	cbuf.maxlen = sizeof(ack);
   2676 	dbuf.buf = (char *) routes;
   2677 	dbuf.maxlen = sizeof(routes);
   2678 	flags = 0;
   2679 	r = getmsg(fd, &cbuf, &dbuf, &flags);
   2680 	if (r == -1) {
   2681 	    warn("have_route_to: getmsg: %m");
   2682 	    close(fd);
   2683 	    return -1;
   2684 	}
   2685 
   2686 	if (cbuf.len < sizeof(struct T_optmgmt_ack)
   2687 	    || ack.ack.PRIM_type != T_OPTMGMT_ACK
   2688 	    || ack.ack.MGMT_flags != T_SUCCESS
   2689 	    || ack.ack.OPT_length < sizeof(struct opthdr)) {
   2690 	    dbglog("have_route_to: bad message len=%d prim=%d",
   2691 		   cbuf.len, ack.ack.PRIM_type);
   2692 	    close(fd);
   2693 	    return -1;
   2694 	}
   2695 
   2696 	rh = (struct opthdr *) ((char *)&ack + ack.ack.OPT_offset);
   2697 	if (rh->level == 0 && rh->name == 0)
   2698 	    break;
   2699 	if (rh->level != MIB2_IP || rh->name != MIB2_IP_21) {
   2700 	    while (r == MOREDATA)
   2701 		r = getmsg(fd, NULL, &dbuf, &flags);
   2702 	    continue;
   2703 	}
   2704 
   2705 	for (;;) {
   2706 	    nroutes = dbuf.len / sizeof(mib2_ipRouteEntry_t);
   2707 	    for (rp = routes, i = 0; i < nroutes; ++i, ++rp) {
   2708 		if (rp->ipRouteMask != ~0) {
   2709 		    dbglog("have_route_to: dest=%x gw=%x mask=%x\n",
   2710 			   rp->ipRouteDest, rp->ipRouteNextHop,
   2711 			   rp->ipRouteMask);
   2712 		    if (((addr ^ rp->ipRouteDest) & rp->ipRouteMask) == 0
   2713 			&& rp->ipRouteNextHop != remote_addr)
   2714 			return 1;
   2715 		}
   2716 	    }
   2717 	    if (r == 0)
   2718 		break;
   2719 	    r = getmsg(fd, NULL, &dbuf, &flags);
   2720 	}
   2721     }
   2722     close(fd);
   2723     return 0;
   2724 #else
   2725     return -1;
   2726 #endif /* SOL2 */
   2727 }
   2728 
   2729 /*
   2730  * get_pty - get a pty master/slave pair and chown the slave side to
   2731  * the uid given.  Assumes slave_name points to MAXPATHLEN bytes of space.
   2732  */
   2733 int
   2734 get_pty(master_fdp, slave_fdp, slave_name, uid)
   2735     int *master_fdp;
   2736     int *slave_fdp;
   2737     char *slave_name;
   2738     int uid;
   2739 {
   2740     int mfd, sfd;
   2741     char *pty_name;
   2742     struct termios tios;
   2743 
   2744     mfd = open("/dev/ptmx", O_RDWR);
   2745     if (mfd < 0) {
   2746 	error("Couldn't open pty master: %m");
   2747 	return 0;
   2748     }
   2749 
   2750     pty_name = ptsname(mfd);
   2751     if (pty_name == NULL) {
   2752 	error("Couldn't get name of pty slave");
   2753 	close(mfd);
   2754 	return 0;
   2755     }
   2756     if (chown(pty_name, uid, -1) < 0)
   2757 	warn("Couldn't change owner of pty slave: %m");
   2758     if (chmod(pty_name, S_IRUSR | S_IWUSR) < 0)
   2759 	warn("Couldn't change permissions on pty slave: %m");
   2760     if (unlockpt(mfd) < 0)
   2761 	warn("Couldn't unlock pty slave: %m");
   2762 
   2763     sfd = open(pty_name, O_RDWR);
   2764     if (sfd < 0) {
   2765 	error("Couldn't open pty slave %s: %m", pty_name);
   2766 	close(mfd);
   2767 	return 0;
   2768     }
   2769     if (ioctl(sfd, I_PUSH, "ptem") < 0)
   2770 	warn("Couldn't push ptem module on pty slave: %m");
   2771 
   2772     dbglog("Using %s", pty_name);
   2773     strlcpy(slave_name, pty_name, MAXPATHLEN);
   2774     *master_fdp = mfd;
   2775     *slave_fdp = sfd;
   2776 
   2777     return 1;
   2778 }
   2779