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