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