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