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