]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-solaris.c
65b173a79695b7e80b8b421072532073be513ca0
[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  * tty_send_config - configure the transmit characteristics of
1556  * the ppp interface.
1557  */
1558 void
1559 tty_send_config(mtu, asyncmap, pcomp, accomp)
1560     int mtu;
1561     u_int32_t asyncmap;
1562     int pcomp, accomp;
1563 {
1564     int cf[2];
1565
1566     link_mtu = mtu;
1567     if (strioctl(pppfd, PPPIO_MTU, &mtu, sizeof(mtu), 0) < 0) {
1568         if (hungup && errno == ENXIO) {
1569             ++error_count;
1570             return;
1571         }
1572         error("Couldn't set MTU: %m");
1573     }
1574     if (fdmuxid >= 0) {
1575         if (!sync_serial) {
1576             if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, sizeof(asyncmap), 0) < 0)
1577                 error("Couldn't set transmit ACCM: %m");
1578         }
1579         cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0);
1580         cf[1] = COMP_PROT | COMP_AC;
1581         if (any_compressions() &&
1582             strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0)
1583             error("Couldn't set prot/AC compression: %m");
1584     }
1585 }
1586
1587 /*
1588  * tty_set_xaccm - set the extended transmit ACCM for the interface.
1589  */
1590 void
1591 tty_set_xaccm(accm)
1592     ext_accm accm;
1593 {
1594     if (sync_serial)
1595         return;
1596
1597     if (fdmuxid >= 0
1598         && strioctl(pppfd, PPPIO_XACCM, accm, sizeof(ext_accm), 0) < 0) {
1599         if (!hungup || errno != ENXIO)
1600             warn("Couldn't set extended ACCM: %m");
1601     }
1602 }
1603
1604 /*
1605  * tty_recv_config - configure the receive-side characteristics of
1606  * the ppp interface.
1607  */
1608 void
1609 tty_recv_config(mru, asyncmap, pcomp, accomp)
1610     int mru;
1611     u_int32_t asyncmap;
1612     int pcomp, accomp;
1613 {
1614     int cf[2];
1615
1616     link_mru = mru;
1617     if (strioctl(pppfd, PPPIO_MRU, &mru, sizeof(mru), 0) < 0) {
1618         if (hungup && errno == ENXIO) {
1619             ++error_count;
1620             return;
1621         }
1622         error("Couldn't set MRU: %m");
1623     }
1624     if (fdmuxid >= 0) {
1625         if (!sync_serial) {
1626             if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, sizeof(asyncmap), 0) < 0)
1627                 error("Couldn't set receive ACCM: %m");
1628         }
1629         cf[0] = (pcomp? DECOMP_PROT: 0) + (accomp? DECOMP_AC: 0);
1630         cf[1] = DECOMP_PROT | DECOMP_AC;
1631         if (any_compressions() &&
1632             strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0)
1633             error("Couldn't set prot/AC decompression: %m");
1634     }
1635 }
1636
1637 /*
1638  * ccp_test - ask kernel whether a given compression method
1639  * is acceptable for use.
1640  */
1641 int
1642 ccp_test(unit, opt_ptr, opt_len, for_transmit)
1643     int unit, opt_len, for_transmit;
1644     u_char *opt_ptr;
1645 {
1646     if (strioctl(pppfd, (for_transmit? PPPIO_XCOMP: PPPIO_RCOMP),
1647                  opt_ptr, opt_len, 0) >= 0)
1648         return 1;
1649     return (errno == ENOSR)? 0: -1;
1650 }
1651
1652 /*
1653  * ccp_flags_set - inform kernel about the current state of CCP.
1654  */
1655 void
1656 ccp_flags_set(unit, isopen, isup)
1657     int unit, isopen, isup;
1658 {
1659     int cf[2];
1660
1661     cf[0] = (isopen? CCP_ISOPEN: 0) + (isup? CCP_ISUP: 0);
1662     cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR;
1663     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
1664         if (!hungup || errno != ENXIO)
1665             error("Couldn't set kernel CCP state: %m");
1666     }
1667 }
1668
1669 /*
1670  * get_idle_time - return how long the link has been idle.
1671  */
1672 int
1673 get_idle_time(u, ip)
1674     int u;
1675     struct ppp_idle *ip;
1676 {
1677     return strioctl(pppfd, PPPIO_GIDLE, ip, 0, sizeof(struct ppp_idle)) >= 0;
1678 }
1679
1680 /*
1681  * get_ppp_stats - return statistics for the link.
1682  */
1683 int
1684 get_ppp_stats(u, stats)
1685     int u;
1686     struct pppd_stats *stats;
1687 {
1688     struct ppp_stats s;
1689
1690     if (!sync_serial && 
1691         strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof(s)) < 0) {
1692         error("Couldn't get link statistics: %m");
1693         return 0;
1694     }
1695     stats->bytes_in = s.p.ppp_ibytes;
1696     stats->bytes_out = s.p.ppp_obytes;
1697     stats->pkts_in = s.p.ppp_ipackets;
1698     stats->pkts_out = s.p.ppp_opackets;
1699     return 1;
1700 }
1701
1702 #if 0
1703 /*
1704  * set_filters - transfer the pass and active filters to the kernel.
1705  */
1706 int
1707 set_filters(pass, active)
1708     struct bpf_program *pass, *active;
1709 {
1710     int ret = 1;
1711
1712     if (pass->bf_len > 0) {
1713         if (strioctl(pppfd, PPPIO_PASSFILT, pass,
1714                      sizeof(struct bpf_program), 0) < 0) {
1715             error("Couldn't set pass-filter in kernel: %m");
1716             ret = 0;
1717         }
1718     }
1719     if (active->bf_len > 0) {
1720         if (strioctl(pppfd, PPPIO_ACTIVEFILT, active,
1721                      sizeof(struct bpf_program), 0) < 0) {
1722             error("Couldn't set active-filter in kernel: %m");
1723             ret = 0;
1724         }
1725     }
1726     return ret;
1727 }
1728 #endif
1729
1730 /*
1731  * ccp_fatal_error - returns 1 if decompression was disabled as a
1732  * result of an error detected after decompression of a packet,
1733  * 0 otherwise.  This is necessary because of patent nonsense.
1734  */
1735 int
1736 ccp_fatal_error(unit)
1737     int unit;
1738 {
1739     int cf[2];
1740
1741     cf[0] = cf[1] = 0;
1742     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
1743         if (errno != ENXIO && errno != EINVAL)
1744             error("Couldn't get compression flags: %m");
1745         return 0;
1746     }
1747     return cf[0] & CCP_FATALERROR;
1748 }
1749
1750 /*
1751  * sifvjcomp - config tcp header compression
1752  */
1753 int
1754 sifvjcomp(u, vjcomp, xcidcomp, xmaxcid)
1755     int u, vjcomp, xcidcomp, xmaxcid;
1756 {
1757     int cf[2];
1758     char maxcid[2];
1759
1760     if (vjcomp) {
1761         maxcid[0] = xcidcomp;
1762         maxcid[1] = 15;         /* XXX should be rmaxcid */
1763         if (strioctl(pppfd, PPPIO_VJINIT, maxcid, sizeof(maxcid), 0) < 0) {
1764             error("Couldn't initialize VJ compression: %m");
1765         }
1766     }
1767
1768     cf[0] = (vjcomp? COMP_VJC + DECOMP_VJC: 0)  /* XXX this is wrong */
1769         + (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0);
1770     cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID;
1771     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
1772         if (vjcomp)
1773             error("Couldn't enable VJ compression: %m");
1774     }
1775
1776     return 1;
1777 }
1778
1779 /*
1780  * sifup - Config the interface up and enable IP packets to pass.
1781  */
1782 int
1783 sifup(u)
1784     int u;
1785 {
1786     struct ifreq ifr;
1787
1788     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1789     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
1790         error("Couldn't mark interface up (get): %m");
1791         return 0;
1792     }
1793     ifr.ifr_flags |= IFF_UP;
1794     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
1795         error("Couldn't mark interface up (set): %m");
1796         return 0;
1797     }
1798     if_is_up = 1;
1799     return 1;
1800 }
1801
1802 /*
1803  * sifdown - Config the interface down and disable IP.
1804  */
1805 int
1806 sifdown(u)
1807     int u;
1808 {
1809     struct ifreq ifr;
1810
1811     if (ipmuxid < 0)
1812         return 1;
1813     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1814     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
1815         error("Couldn't mark interface down (get): %m");
1816         return 0;
1817     }
1818     ifr.ifr_flags &= ~IFF_UP;
1819     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
1820         error("Couldn't mark interface down (set): %m");
1821         return 0;
1822     }
1823     if_is_up = 0;
1824     return 1;
1825 }
1826
1827 /*
1828  * sifnpmode - Set the mode for handling packets for a given NP.
1829  */
1830 int
1831 sifnpmode(u, proto, mode)
1832     int u;
1833     int proto;
1834     enum NPmode mode;
1835 {
1836     int npi[2];
1837
1838     npi[0] = proto;
1839     npi[1] = (int) mode;
1840     if (strioctl(pppfd, PPPIO_NPMODE, &npi, 2 * sizeof(int), 0) < 0) {
1841         error("ioctl(set NP %d mode to %d): %m", proto, mode);
1842         return 0;
1843     }
1844     return 1;
1845 }
1846
1847 #if defined(SOL2) && defined(INET6)
1848 /*
1849  * sif6up - Config the IPv6 interface up and enable IPv6 packets to pass.
1850  */
1851 int
1852 sif6up(u)
1853     int u;
1854 {
1855     struct lifreq lifr;
1856     int fd;
1857
1858     fd = socket(AF_INET6, SOCK_DGRAM, 0);
1859     if (fd < 0) {
1860         return 0;
1861     }
1862
1863     memset(&lifr, 0, sizeof(lifr));
1864     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1865     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
1866         close(fd);
1867         return 0;
1868     }
1869
1870     lifr.lifr_flags |= IFF_UP;
1871     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1872     if (ioctl(fd, SIOCSLIFFLAGS, &lifr) < 0) {
1873         close(fd);
1874         return 0;
1875     }
1876
1877     if6_is_up = 1;
1878     close(fd);
1879     return 1;
1880 }
1881
1882 /*
1883  * sifdown - Config the IPv6 interface down and disable IPv6.
1884  */
1885 int
1886 sif6down(u)
1887     int u;
1888 {
1889     struct lifreq lifr;
1890     int fd;
1891
1892     fd = socket(AF_INET6, SOCK_DGRAM, 0);
1893     if (fd < 0)
1894         return 0;
1895
1896     memset(&lifr, 0, sizeof(lifr));
1897     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1898     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
1899         close(fd);
1900         return 0;
1901     }
1902
1903     lifr.lifr_flags &= ~IFF_UP;
1904     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1905     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
1906         close(fd);
1907         return 0;
1908     }
1909
1910     if6_is_up = 0;
1911     close(fd);
1912     return 1;
1913 }
1914
1915 /*
1916  * sif6addr - Config the interface with an IPv6 link-local address
1917  */
1918 int
1919 sif6addr(u, o, h)
1920     int u;
1921     eui64_t o, h;
1922 {
1923     struct lifreq lifr;
1924     struct sockaddr_storage laddr;
1925     struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&laddr;
1926     int fd;
1927
1928     fd = socket(AF_INET6, SOCK_DGRAM, 0);
1929     if (fd < 0)
1930         return 0;
1931
1932     memset(&lifr, 0, sizeof(lifr));
1933     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1934
1935     /*
1936      * Do this because /dev/ppp responds to DL_PHYS_ADDR_REQ with
1937      * zero values, hence the interface token came to be zero too,
1938      * and without this, in.ndpd will complain
1939      */
1940     IN6_LLTOKEN_FROM_EUI64(lifr, sin6, o);
1941     if (ioctl(fd, SIOCSLIFTOKEN, &lifr) < 0) {
1942         close(fd);
1943         return 0;
1944     }
1945
1946     /*
1947      * Set the interface address and destination address
1948      */
1949     IN6_LLADDR_FROM_EUI64(lifr, sin6, o);
1950     if (ioctl(fd, SIOCSLIFADDR, &lifr) < 0) {
1951         close(fd);
1952         return 0;
1953     }
1954
1955     memset(&lifr, 0, sizeof(lifr));
1956     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1957     IN6_LLADDR_FROM_EUI64(lifr, sin6, h);
1958     if (ioctl(fd, SIOCSLIFDSTADDR, &lifr) < 0) {
1959         close(fd);
1960         return 0;
1961     }
1962
1963     return 1;
1964 }
1965
1966 /*
1967  * cif6addr - Remove the IPv6 address from interface
1968  */
1969 int
1970 cif6addr(u, o, h)
1971     int u;
1972     eui64_t o, h;
1973 {
1974     return 1;
1975 }
1976
1977 /*
1978  * sif6defaultroute - assign a default route through the address given.
1979  */
1980 int
1981 sif6defaultroute(u, l, g)
1982     int u;
1983     eui64_t l, g;
1984 {
1985     struct {
1986         struct rt_msghdr rtm;
1987         struct sockaddr_in6 dst;
1988         struct sockaddr_in6 gw;
1989     } rmsg;
1990     static int seq;
1991     int rtsock;
1992
1993 #if defined(__USLC__)
1994     g = l;                      /* use the local address as gateway */
1995 #endif
1996     memset(&rmsg, 0, sizeof(rmsg));
1997
1998     rmsg.rtm.rtm_msglen = sizeof (rmsg);
1999     rmsg.rtm.rtm_version = RTM_VERSION;
2000     rmsg.rtm.rtm_type = RTM_ADD;
2001     rmsg.rtm.rtm_flags = RTF_GATEWAY;
2002     rmsg.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
2003     rmsg.rtm.rtm_pid = getpid();
2004     rmsg.rtm.rtm_seq = seq++;
2005
2006     rmsg.dst.sin6_family = AF_INET6;
2007
2008     rmsg.gw.sin6_family = AF_INET6;
2009     IN6_SOCKADDR_FROM_EUI64(&rmsg.gw, g);
2010
2011     rtsock = socket(PF_ROUTE, SOCK_RAW, 0);
2012
2013     if (rtsock < 0) {
2014         error("Can't add default route: %m");
2015         return 0;
2016     }
2017
2018     if (write(rtsock, &rmsg, sizeof(rmsg)) < 0)
2019         error("Can't add default route: %m");
2020
2021     close(rtsock);
2022
2023     default_route_gateway6 = g;
2024     return 1;
2025 }
2026
2027 /*
2028  * cif6defaultroute - delete a default route through the address given.
2029  */
2030 int
2031 cif6defaultroute(u, l, g)
2032     int u;
2033     eui64_t l, g;
2034 {
2035     /* No need to do this on Solaris; the kernel deletes the
2036        route when the interface goes down. */
2037     memset(&default_route_gateway6, 0, sizeof(default_route_gateway6));
2038     return 1;
2039 }
2040
2041 #endif /* defined(SOL2) && defined(INET6) */
2042
2043
2044 #define INET_ADDR(x)    (((struct sockaddr_in *) &(x))->sin_addr.s_addr)
2045
2046 /*
2047  * sifaddr - Config the interface IP addresses and netmask.
2048  */
2049 int
2050 sifaddr(u, o, h, m)
2051     int u;
2052     u_int32_t o, h, m;
2053 {
2054     struct ifreq ifr;
2055     int ret = 1;
2056
2057     memset(&ifr, 0, sizeof(ifr));
2058     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2059     ifr.ifr_addr.sa_family = AF_INET;
2060     INET_ADDR(ifr.ifr_addr) = m;
2061     if (ioctl(ipfd, SIOCSIFNETMASK, &ifr) < 0) {
2062         error("Couldn't set IP netmask: %m");
2063         ret = 0;
2064     }
2065     ifr.ifr_addr.sa_family = AF_INET;
2066     INET_ADDR(ifr.ifr_addr) = o;
2067     if (ioctl(ipfd, SIOCSIFADDR, &ifr) < 0) {
2068         error("Couldn't set local IP address: %m");
2069         ret = 0;
2070     }
2071
2072     /*
2073      * On some systems, we have to explicitly set the point-to-point
2074      * flag bit before we can set a destination address.
2075      */
2076     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) >= 0
2077         && (ifr.ifr_flags & IFF_POINTOPOINT) == 0) {
2078         ifr.ifr_flags |= IFF_POINTOPOINT;
2079         if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
2080             error("Couldn't mark interface pt-to-pt: %m");
2081             ret = 0;
2082         }
2083     }
2084     ifr.ifr_dstaddr.sa_family = AF_INET;
2085     INET_ADDR(ifr.ifr_dstaddr) = h;
2086     if (ioctl(ipfd, SIOCSIFDSTADDR, &ifr) < 0) {
2087         error("Couldn't set remote IP address: %m");
2088         ret = 0;
2089     }
2090
2091     remote_addr = h;
2092     return ret;
2093 }
2094
2095 /*
2096  * cifaddr - Clear the interface IP addresses, and delete routes
2097  * through the interface if possible.
2098  */
2099 int
2100 cifaddr(u, o, h)
2101     int u;
2102     u_int32_t o, h;
2103 {
2104 #if defined(__USLC__)           /* was: #if 0 */
2105     cifroute(unit, ouraddr, hisaddr);
2106     if (ipmuxid >= 0) {
2107         notice("Removing ppp interface unit");
2108         if (ioctl(ipfd, I_UNLINK, ipmuxid) < 0) {
2109             error("Can't remove ppp interface unit: %m");
2110             return 0;
2111         }
2112         ipmuxid = -1;
2113     }
2114 #endif
2115     remote_addr = 0;
2116     return 1;
2117 }
2118
2119 /*
2120  * sifdefaultroute - assign a default route through the address given.
2121  */
2122 int
2123 sifdefaultroute(u, l, g)
2124     int u;
2125     u_int32_t l, g;
2126 {
2127     struct rtentry rt;
2128
2129 #if defined(__USLC__)
2130     g = l;                      /* use the local address as gateway */
2131 #endif
2132     memset(&rt, 0, sizeof(rt));
2133     rt.rt_dst.sa_family = AF_INET;
2134     INET_ADDR(rt.rt_dst) = 0;
2135     rt.rt_gateway.sa_family = AF_INET;
2136     INET_ADDR(rt.rt_gateway) = g;
2137     rt.rt_flags = RTF_GATEWAY;
2138
2139     if (ioctl(ipfd, SIOCADDRT, &rt) < 0) {
2140         error("Can't add default route: %m");
2141         return 0;
2142     }
2143
2144     default_route_gateway = g;
2145     return 1;
2146 }
2147
2148 /*
2149  * cifdefaultroute - delete a default route through the address given.
2150  */
2151 int
2152 cifdefaultroute(u, l, g)
2153     int u;
2154     u_int32_t l, g;
2155 {
2156     struct rtentry rt;
2157
2158 #if defined(__USLC__)
2159     g = l;                      /* use the local address as gateway */
2160 #endif
2161     memset(&rt, 0, sizeof(rt));
2162     rt.rt_dst.sa_family = AF_INET;
2163     INET_ADDR(rt.rt_dst) = 0;
2164     rt.rt_gateway.sa_family = AF_INET;
2165     INET_ADDR(rt.rt_gateway) = g;
2166     rt.rt_flags = RTF_GATEWAY;
2167
2168     if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
2169         error("Can't delete default route: %m");
2170         return 0;
2171     }
2172
2173     default_route_gateway = 0;
2174     return 1;
2175 }
2176
2177 /*
2178  * sifproxyarp - Make a proxy ARP entry for the peer.
2179  */
2180 int
2181 sifproxyarp(unit, hisaddr)
2182     int unit;
2183     u_int32_t hisaddr;
2184 {
2185     struct arpreq arpreq;
2186
2187     memset(&arpreq, 0, sizeof(arpreq));
2188     if (!get_ether_addr(hisaddr, &arpreq.arp_ha))
2189         return 0;
2190
2191     arpreq.arp_pa.sa_family = AF_INET;
2192     INET_ADDR(arpreq.arp_pa) = hisaddr;
2193     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
2194     if (ioctl(ipfd, SIOCSARP, (caddr_t) &arpreq) < 0) {
2195         error("Couldn't set proxy ARP entry: %m");
2196         return 0;
2197     }
2198
2199     proxy_arp_addr = hisaddr;
2200     return 1;
2201 }
2202
2203 /*
2204  * cifproxyarp - Delete the proxy ARP entry for the peer.
2205  */
2206 int
2207 cifproxyarp(unit, hisaddr)
2208     int unit;
2209     u_int32_t hisaddr;
2210 {
2211     struct arpreq arpreq;
2212
2213     memset(&arpreq, 0, sizeof(arpreq));
2214     arpreq.arp_pa.sa_family = AF_INET;
2215     INET_ADDR(arpreq.arp_pa) = hisaddr;
2216     if (ioctl(ipfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
2217         error("Couldn't delete proxy ARP entry: %m");
2218         return 0;
2219     }
2220
2221     proxy_arp_addr = 0;
2222     return 1;
2223 }
2224
2225 /*
2226  * get_ether_addr - get the hardware address of an interface on the
2227  * the same subnet as ipaddr.
2228  */
2229 #define MAX_IFS         32
2230
2231 static int
2232 get_ether_addr(ipaddr, hwaddr)
2233     u_int32_t ipaddr;
2234     struct sockaddr *hwaddr;
2235 {
2236     struct ifreq *ifr, *ifend, ifreq;
2237     int nif;
2238     struct ifconf ifc;
2239     u_int32_t ina, mask;
2240
2241     /*
2242      * Scan through the system's network interfaces.
2243      */
2244 #ifdef SIOCGIFNUM
2245     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
2246 #endif
2247         nif = MAX_IFS;
2248     ifc.ifc_len = nif * sizeof(struct ifreq);
2249     ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len);
2250     if (ifc.ifc_buf == 0)
2251         return 0;
2252     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
2253         warn("Couldn't get system interface list: %m");
2254         free(ifc.ifc_buf);
2255         return 0;
2256     }
2257     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
2258     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
2259         if (ifr->ifr_addr.sa_family != AF_INET)
2260             continue;
2261         /*
2262          * Check that the interface is up, and not point-to-point or loopback.
2263          */
2264         strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
2265         if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
2266             continue;
2267         if ((ifreq.ifr_flags &
2268              (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
2269             != (IFF_UP|IFF_BROADCAST))
2270             continue;
2271         /*
2272          * Get its netmask and check that it's on the right subnet.
2273          */
2274         if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
2275             continue;
2276         ina = INET_ADDR(ifr->ifr_addr);
2277         mask = INET_ADDR(ifreq.ifr_addr);
2278         if ((ipaddr & mask) == (ina & mask))
2279             break;
2280     }
2281
2282     if (ifr >= ifend) {
2283         warn("No suitable interface found for proxy ARP");
2284         free(ifc.ifc_buf);
2285         return 0;
2286     }
2287
2288     info("found interface %s for proxy ARP", ifr->ifr_name);
2289     if (!get_hw_addr(ifr->ifr_name, ina, hwaddr)) {
2290         error("Couldn't get hardware address for %s", ifr->ifr_name);
2291         free(ifc.ifc_buf);
2292         return 0;
2293     }
2294
2295     free(ifc.ifc_buf);
2296     return 1;
2297 }
2298
2299 /*
2300  * get_hw_addr_dlpi - obtain the hardware address using DLPI
2301  */
2302 static int
2303 get_hw_addr_dlpi(name, hwaddr)
2304     char *name;
2305     struct sockaddr *hwaddr;
2306 {
2307     char *q;
2308     int unit, iffd, adrlen;
2309     unsigned char *adrp;
2310     char ifdev[24];
2311     struct {
2312         union DL_primitives prim;
2313         char space[64];
2314     } reply;
2315
2316     /*
2317      * We have to open the device and ask it for its hardware address.
2318      * First split apart the device name and unit.
2319      */
2320     slprintf(ifdev, sizeof(ifdev), "/dev/%s", name);
2321     for (q = ifdev + strlen(ifdev); --q >= ifdev; )
2322         if (!isdigit(*q))
2323             break;
2324     unit = atoi(q+1);
2325     q[1] = 0;
2326
2327     /*
2328      * Open the device and do a DLPI attach and phys_addr_req.
2329      */
2330     iffd = open(ifdev, O_RDWR);
2331     if (iffd < 0) {
2332         error("Can't open %s: %m", ifdev);
2333         return 0;
2334     }
2335     if (dlpi_attach(iffd, unit) < 0
2336         || dlpi_get_reply(iffd, &reply.prim, DL_OK_ACK, sizeof(reply)) < 0
2337         || dlpi_info_req(iffd) < 0
2338         || dlpi_get_reply(iffd, &reply.prim, DL_INFO_ACK, sizeof(reply)) < 0) {
2339         close(iffd);
2340         return 0;
2341     }
2342
2343     adrlen = reply.prim.info_ack.dl_addr_length;
2344     adrp = (unsigned char *)&reply + reply.prim.info_ack.dl_addr_offset;
2345
2346 #if DL_CURRENT_VERSION >= 2
2347     if (reply.prim.info_ack.dl_sap_length < 0)
2348         adrlen += reply.prim.info_ack.dl_sap_length;
2349     else
2350         adrp += reply.prim.info_ack.dl_sap_length;
2351 #endif
2352
2353     hwaddr->sa_family = AF_UNSPEC;
2354     memcpy(hwaddr->sa_data, adrp, adrlen);
2355
2356     return 1;
2357 }
2358 /*
2359  * get_hw_addr - obtain the hardware address for a named interface.
2360  */
2361 static int
2362 get_hw_addr(name, ina, hwaddr)
2363     char *name;
2364     u_int32_t ina;
2365     struct sockaddr *hwaddr;
2366 {
2367     /* New way - get the address by doing an arp request. */
2368     int s;
2369     struct arpreq req;
2370
2371     s = socket(AF_INET, SOCK_DGRAM, 0);
2372     if (s < 0)
2373         return 0;
2374     memset(&req, 0, sizeof(req));
2375     req.arp_pa.sa_family = AF_INET;
2376     INET_ADDR(req.arp_pa) = ina;
2377     if (ioctl(s, SIOCGARP, &req) < 0) {
2378         error("Couldn't get ARP entry for %s: %m", ip_ntoa(ina));
2379         return 0;
2380     }
2381     *hwaddr = req.arp_ha;
2382     hwaddr->sa_family = AF_UNSPEC;
2383
2384     return 1;
2385 }
2386
2387 static int
2388 dlpi_attach(fd, ppa)
2389     int fd, ppa;
2390 {
2391     dl_attach_req_t req;
2392     struct strbuf buf;
2393
2394     req.dl_primitive = DL_ATTACH_REQ;
2395     req.dl_ppa = ppa;
2396     buf.len = sizeof(req);
2397     buf.buf = (void *) &req;
2398     return putmsg(fd, &buf, NULL, RS_HIPRI);
2399 }
2400
2401 static int
2402 dlpi_info_req(fd)
2403     int fd;
2404 {
2405     dl_info_req_t req;
2406     struct strbuf buf;
2407
2408     req.dl_primitive = DL_INFO_REQ;
2409     buf.len = sizeof(req);
2410     buf.buf = (void *) &req;
2411     return putmsg(fd, &buf, NULL, RS_HIPRI);
2412 }
2413
2414 static int
2415 dlpi_get_reply(fd, reply, expected_prim, maxlen)
2416     union DL_primitives *reply;
2417     int fd, expected_prim, maxlen;
2418 {
2419     struct strbuf buf;
2420     int flags, n;
2421     struct pollfd pfd;
2422
2423     /*
2424      * Use poll to wait for a message with a timeout.
2425      */
2426     pfd.fd = fd;
2427     pfd.events = POLLIN | POLLPRI;
2428     do {
2429         n = poll(&pfd, 1, 1000);
2430     } while (n == -1 && errno == EINTR);
2431     if (n <= 0)
2432         return -1;
2433
2434     /*
2435      * Get the reply.
2436      */
2437     buf.maxlen = maxlen;
2438     buf.buf = (void *) reply;
2439     flags = 0;
2440     if (getmsg(fd, &buf, NULL, &flags) < 0)
2441         return -1;
2442
2443     if (buf.len < sizeof(ulong)) {
2444         if (debug)
2445             dbglog("dlpi response short (len=%d)\n", buf.len);
2446         return -1;
2447     }
2448
2449     if (reply->dl_primitive == expected_prim)
2450         return 0;
2451
2452     if (debug) {
2453         if (reply->dl_primitive == DL_ERROR_ACK) {
2454             dbglog("dlpi error %d (unix errno %d) for prim %x\n",
2455                    reply->error_ack.dl_errno, reply->error_ack.dl_unix_errno,
2456                    reply->error_ack.dl_error_primitive);
2457         } else {
2458             dbglog("dlpi unexpected response prim %x\n",
2459                    reply->dl_primitive);
2460         }
2461     }
2462
2463     return -1;
2464 }
2465
2466 /*
2467  * Return user specified netmask, modified by any mask we might determine
2468  * for address `addr' (in network byte order).
2469  * Here we scan through the system's list of interfaces, looking for
2470  * any non-point-to-point interfaces which might appear to be on the same
2471  * network as `addr'.  If we find any, we OR in their netmask to the
2472  * user-specified netmask.
2473  */
2474 u_int32_t
2475 GetMask(addr)
2476     u_int32_t addr;
2477 {
2478     u_int32_t mask, nmask, ina;
2479     struct ifreq *ifr, *ifend, ifreq;
2480     int nif;
2481     struct ifconf ifc;
2482
2483     addr = ntohl(addr);
2484     if (IN_CLASSA(addr))        /* determine network mask for address class */
2485         nmask = IN_CLASSA_NET;
2486     else if (IN_CLASSB(addr))
2487         nmask = IN_CLASSB_NET;
2488     else
2489         nmask = IN_CLASSC_NET;
2490     /* class D nets are disallowed by bad_ip_adrs */
2491     mask = netmask | htonl(nmask);
2492
2493     /*
2494      * Scan through the system's network interfaces.
2495      */
2496 #ifdef SIOCGIFNUM
2497     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
2498 #endif
2499         nif = MAX_IFS;
2500     ifc.ifc_len = nif * sizeof(struct ifreq);
2501     ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len);
2502     if (ifc.ifc_buf == 0)
2503         return mask;
2504     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
2505         warn("Couldn't get system interface list: %m");
2506         free(ifc.ifc_buf);
2507         return mask;
2508     }
2509     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
2510     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
2511         /*
2512          * Check the interface's internet address.
2513          */
2514         if (ifr->ifr_addr.sa_family != AF_INET)
2515             continue;
2516         ina = INET_ADDR(ifr->ifr_addr);
2517         if ((ntohl(ina) & nmask) != (addr & nmask))
2518             continue;
2519         /*
2520          * Check that the interface is up, and not point-to-point or loopback.
2521          */
2522         strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
2523         if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
2524             continue;
2525         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
2526             != IFF_UP)
2527             continue;
2528         /*
2529          * Get its netmask and OR it into our mask.
2530          */
2531         if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
2532             continue;
2533         mask |= INET_ADDR(ifreq.ifr_addr);
2534     }
2535
2536     free(ifc.ifc_buf);
2537     return mask;
2538 }
2539
2540 /*
2541  * logwtmp - write an accounting record to the /var/adm/wtmp file.
2542  */
2543 void
2544 logwtmp(line, name, host)
2545     const char *line, *name, *host;
2546 {
2547     static struct utmpx utmpx;
2548
2549     if (name[0] != 0) {
2550         /* logging in */
2551         strncpy(utmpx.ut_user, name, sizeof(utmpx.ut_user));
2552         strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line));
2553         strncpy(utmpx.ut_host, host, sizeof(utmpx.ut_host));
2554         if (*host != '\0') {
2555             utmpx.ut_syslen = strlen(host) + 1;
2556             if (utmpx.ut_syslen > sizeof(utmpx.ut_host))
2557                 utmpx.ut_syslen = sizeof(utmpx.ut_host);
2558         }
2559         utmpx.ut_pid = getpid();
2560         utmpx.ut_type = USER_PROCESS;
2561     } else {
2562         utmpx.ut_type = DEAD_PROCESS;
2563     }
2564     gettimeofday(&utmpx.ut_tv, NULL);
2565     updwtmpx("/var/adm/wtmpx", &utmpx);
2566 }
2567
2568 /*
2569  * get_host_seed - return the serial number of this machine.
2570  */
2571 int
2572 get_host_seed()
2573 {
2574     char buf[32];
2575
2576     if (sysinfo(SI_HW_SERIAL, buf, sizeof(buf)) < 0) {
2577         error("sysinfo: %m");
2578         return 0;
2579     }
2580     return (int) strtoul(buf, NULL, 16);
2581 }
2582
2583 static int
2584 strioctl(fd, cmd, ptr, ilen, olen)
2585     int fd, cmd, ilen, olen;
2586     void *ptr;
2587 {
2588     struct strioctl str;
2589
2590     str.ic_cmd = cmd;
2591     str.ic_timout = 0;
2592     str.ic_len = ilen;
2593     str.ic_dp = ptr;
2594     if (ioctl(fd, I_STR, &str) == -1)
2595         return -1;
2596     if (str.ic_len != olen)
2597         dbglog("strioctl: expected %d bytes, got %d for cmd %x\n",
2598                olen, str.ic_len, cmd);
2599     return 0;
2600 }
2601
2602 #if 0
2603 /*
2604  * lock - create a lock file for the named lock device
2605  */
2606
2607 #define LOCK_PREFIX     "/var/spool/locks/LK."
2608 static char lock_file[40];      /* name of lock file created */
2609
2610 int
2611 lock(dev)
2612     char *dev;
2613 {
2614     int n, fd, pid;
2615     struct stat sbuf;
2616     char ascii_pid[12];
2617
2618     if (stat(dev, &sbuf) < 0) {
2619         error("Can't get device number for %s: %m", dev);
2620         return -1;
2621     }
2622     if ((sbuf.st_mode & S_IFMT) != S_IFCHR) {
2623         error("Can't lock %s: not a character device", dev);
2624         return -1;
2625     }
2626     slprintf(lock_file, sizeof(lock_file), "%s%03d.%03d.%03d",
2627              LOCK_PREFIX, major(sbuf.st_dev),
2628              major(sbuf.st_rdev), minor(sbuf.st_rdev));
2629
2630     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
2631         if (errno == EEXIST
2632             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
2633             /* Read the lock file to find out who has the device locked */
2634             n = read(fd, ascii_pid, 11);
2635             if (n <= 0) {
2636                 error("Can't read pid from lock file %s", lock_file);
2637                 close(fd);
2638             } else {
2639                 ascii_pid[n] = 0;
2640                 pid = atoi(ascii_pid);
2641                 if (pid > 0 && kill(pid, 0) == -1 && errno == ESRCH) {
2642                     /* pid no longer exists - remove the lock file */
2643                     if (unlink(lock_file) == 0) {
2644                         close(fd);
2645                         notice("Removed stale lock on %s (pid %d)",
2646                                dev, pid);
2647                         continue;
2648                     } else
2649                         warn("Couldn't remove stale lock on %s",
2650                                dev);
2651                 } else
2652                     notice("Device %s is locked by pid %d",
2653                            dev, pid);
2654             }
2655             close(fd);
2656         } else
2657             error("Can't create lock file %s: %m", lock_file);
2658         lock_file[0] = 0;
2659         return -1;
2660     }
2661
2662     slprintf(ascii_pid, sizeof(ascii_pid), "%10d\n", getpid());
2663     write(fd, ascii_pid, 11);
2664
2665     close(fd);
2666     return 1;
2667 }
2668
2669 /*
2670  * unlock - remove our lockfile
2671  */
2672 void
2673 unlock()
2674 {
2675     if (lock_file[0]) {
2676         unlink(lock_file);
2677         lock_file[0] = 0;
2678     }
2679 }
2680 #endif
2681
2682 /*
2683  * cifroute - delete a route through the addresses given.
2684  */
2685 int
2686 cifroute(u, our, his)
2687     int u;
2688     u_int32_t our, his;
2689 {
2690     struct rtentry rt;
2691
2692     memset(&rt, 0, sizeof(rt));
2693     rt.rt_dst.sa_family = AF_INET;
2694     INET_ADDR(rt.rt_dst) = his;
2695     rt.rt_gateway.sa_family = AF_INET;
2696     INET_ADDR(rt.rt_gateway) = our;
2697     rt.rt_flags = RTF_HOST;
2698
2699     if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
2700         error("Can't delete route: %m");
2701         return 0;
2702     }
2703
2704     return 1;
2705 }
2706
2707 /*
2708  * have_route_to - determine if the system has a route to the specified
2709  * IP address.  Returns 0 if not, 1 if so, -1 if we can't tell.
2710  * `addr' is in network byte order.
2711  * For demand mode to work properly, we have to ignore routes
2712  * through our own interface.
2713  */
2714 #ifndef T_CURRENT               /* needed for Solaris 2.5 */
2715 #define T_CURRENT       MI_T_CURRENT
2716 #endif
2717
2718 int
2719 have_route_to(addr)
2720     u_int32_t addr;
2721 {
2722 #ifdef SOL2
2723     int fd, r, flags, i;
2724     struct {
2725         struct T_optmgmt_req req;
2726         struct opthdr hdr;
2727     } req;
2728     union {
2729         struct T_optmgmt_ack ack;
2730         unsigned char space[64];
2731     } ack;
2732     struct opthdr *rh;
2733     struct strbuf cbuf, dbuf;
2734     int nroutes;
2735     mib2_ipRouteEntry_t routes[8];
2736     mib2_ipRouteEntry_t *rp;
2737
2738     fd = open(mux_dev_name, O_RDWR);
2739     if (fd < 0) {
2740         warn("have_route_to: couldn't open %s: %m", mux_dev_name);
2741         return -1;
2742     }
2743
2744     req.req.PRIM_type = T_OPTMGMT_REQ;
2745     req.req.OPT_offset = (char *) &req.hdr - (char *) &req;
2746     req.req.OPT_length = sizeof(req.hdr);
2747     req.req.MGMT_flags = T_CURRENT;
2748
2749     req.hdr.level = MIB2_IP;
2750     req.hdr.name = 0;
2751     req.hdr.len = 0;
2752
2753     cbuf.buf = (char *) &req;
2754     cbuf.len = sizeof(req);
2755
2756     if (putmsg(fd, &cbuf, NULL, 0) == -1) {
2757         warn("have_route_to: putmsg: %m");
2758         close(fd);
2759         return -1;
2760     }
2761
2762     for (;;) {
2763         cbuf.buf = (char *) &ack;
2764         cbuf.maxlen = sizeof(ack);
2765         dbuf.buf = (char *) routes;
2766         dbuf.maxlen = sizeof(routes);
2767         flags = 0;
2768         r = getmsg(fd, &cbuf, &dbuf, &flags);
2769         if (r == -1) {
2770             warn("have_route_to: getmsg: %m");
2771             close(fd);
2772             return -1;
2773         }
2774
2775         if (cbuf.len < sizeof(struct T_optmgmt_ack)
2776             || ack.ack.PRIM_type != T_OPTMGMT_ACK
2777             || ack.ack.MGMT_flags != T_SUCCESS
2778             || ack.ack.OPT_length < sizeof(struct opthdr)) {
2779             dbglog("have_route_to: bad message len=%d prim=%d",
2780                    cbuf.len, ack.ack.PRIM_type);
2781             close(fd);
2782             return -1;
2783         }
2784
2785         rh = (struct opthdr *) ((char *)&ack + ack.ack.OPT_offset);
2786         if (rh->level == 0 && rh->name == 0)
2787             break;
2788         if (rh->level != MIB2_IP || rh->name != MIB2_IP_21) {
2789             while (r == MOREDATA)
2790                 r = getmsg(fd, NULL, &dbuf, &flags);
2791             continue;
2792         }
2793
2794         for (;;) {
2795             nroutes = dbuf.len / sizeof(mib2_ipRouteEntry_t);
2796             for (rp = routes, i = 0; i < nroutes; ++i, ++rp) {
2797                 if (rp->ipRouteMask != ~0) {
2798                     dbglog("have_route_to: dest=%x gw=%x mask=%x\n",
2799                            rp->ipRouteDest, rp->ipRouteNextHop,
2800                            rp->ipRouteMask);
2801                     if (((addr ^ rp->ipRouteDest) & rp->ipRouteMask) == 0
2802                         && rp->ipRouteNextHop != remote_addr)
2803                         return 1;
2804                 }
2805             }
2806             if (r == 0)
2807                 break;
2808             r = getmsg(fd, NULL, &dbuf, &flags);
2809         }
2810     }
2811     close(fd);
2812     return 0;
2813 #else
2814     return -1;
2815 #endif /* SOL2 */
2816 }
2817
2818 /*
2819  * get_pty - get a pty master/slave pair and chown the slave side to
2820  * the uid given.  Assumes slave_name points to MAXPATHLEN bytes of space.
2821  */
2822 int
2823 get_pty(master_fdp, slave_fdp, slave_name, uid)
2824     int *master_fdp;
2825     int *slave_fdp;
2826     char *slave_name;
2827     int uid;
2828 {
2829     int mfd, sfd;
2830     char *pty_name;
2831
2832     mfd = open("/dev/ptmx", O_RDWR);
2833     if (mfd < 0) {
2834         error("Couldn't open pty master: %m");
2835         return 0;
2836     }
2837
2838     pty_name = ptsname(mfd);
2839     if (pty_name == NULL) {
2840         error("Couldn't get name of pty slave");
2841         close(mfd);
2842         return 0;
2843     }
2844     if (chown(pty_name, uid, -1) < 0)
2845         warn("Couldn't change owner of pty slave: %m");
2846     if (chmod(pty_name, S_IRUSR | S_IWUSR) < 0)
2847         warn("Couldn't change permissions on pty slave: %m");
2848     if (unlockpt(mfd) < 0)
2849         warn("Couldn't unlock pty slave: %m");
2850
2851     sfd = open(pty_name, O_RDWR);
2852     if (sfd < 0) {
2853         error("Couldn't open pty slave %s: %m", pty_name);
2854         close(mfd);
2855         return 0;
2856     }
2857     if (ioctl(sfd, I_PUSH, "ptem") < 0)
2858         warn("Couldn't push ptem module on pty slave: %m");
2859
2860     dbglog("Using %s", pty_name);
2861     strlcpy(slave_name, pty_name, MAXPATHLEN);
2862     *master_fdp = mfd;
2863     *slave_fdp = sfd;
2864
2865     return 1;
2866 }
2867
2868 /********************************************************************
2869  *
2870  * get_time - Get current time, monotonic if possible.
2871  */
2872 int
2873 get_time(struct timeval *tv)
2874 {
2875     return gettimeofday(tv, NULL);
2876 }