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