]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-svr4.c
When 'sync' option is present, the ppp_ahdl module isn't plumbed, so
[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.40 2000/01/28 01:51:19 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 (!sync_serial && 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         if (!sync_serial)
977             ioctl(fd, TIOCGWINSZ, &wsinfo);
978     }
979
980     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
981 #ifdef CRTSCTS
982     if (crtscts > 0)
983         tios.c_cflag |= CRTSCTS;
984     else if (crtscts < 0)
985         tios.c_cflag &= ~CRTSCTS;
986 #else
987     if (crtscts != 0 && !termiox_ok) {
988         error("Can't set RTS/CTS flow control");
989     } else if (crtscts > 0) {
990         tiox.x_hflag |= RTSXOFF|CTSXON;
991     } else if (crtscts < 0) {
992         tiox.x_hflag &= ~(RTSXOFF|CTSXON);
993     }
994 #endif
995
996     tios.c_cflag |= CS8 | CREAD | HUPCL;
997     if (local || !modem)
998         tios.c_cflag |= CLOCAL;
999     tios.c_iflag = IGNBRK | IGNPAR;
1000     tios.c_oflag = 0;
1001     tios.c_lflag = 0;
1002     tios.c_cc[VMIN] = 1;
1003     tios.c_cc[VTIME] = 0;
1004
1005     if (crtscts == -2) {
1006         tios.c_iflag |= IXON | IXOFF;
1007         tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
1008         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
1009     }
1010
1011     speed = translate_speed(inspeed);
1012     if (speed) {
1013         cfsetospeed(&tios, speed);
1014         cfsetispeed(&tios, speed);
1015     } else {
1016         speed = cfgetospeed(&tios);
1017         /*
1018          * We can't proceed if the serial port speed is 0,
1019          * since that implies that the serial port is disabled.
1020          */
1021         if ((speed == B0) && !sync_serial)
1022             fatal("Baud rate for %s is 0; need explicit baud rate", devnam);
1023     }
1024
1025     if (!sync_serial && tcsetattr(fd, TCSAFLUSH, &tios) < 0)
1026         fatal("tcsetattr: %m");
1027
1028 #ifndef CRTSCTS
1029     if (!sync_serial && termiox_ok && ioctl (fd, TCSETXF, &tiox) < 0){
1030         error("TCSETXF: %m");
1031     }
1032 #endif
1033
1034     baud_rate = inspeed = baud_rate_of(speed);
1035     if (!sync_serial)
1036         restore_term = 1;
1037 }
1038
1039 /*
1040  * restore_tty - restore the terminal to the saved settings.
1041  */
1042 void
1043 restore_tty(fd)
1044     int fd;
1045 {
1046     if (restore_term) {
1047         if (!default_device) {
1048             /*
1049              * Turn off echoing, because otherwise we can get into
1050              * a loop with the tty and the modem echoing to each other.
1051              * We presume we are the sole user of this tty device, so
1052              * when we close it, it will revert to its defaults anyway.
1053              */
1054             inittermios.c_lflag &= ~(ECHO | ECHONL);
1055         }
1056         if (!sync_serial && tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
1057             if (!hungup && errno != ENXIO)
1058                 warn("tcsetattr: %m");
1059 #ifndef CRTSCTS
1060         if (!sync_serial && ioctl (fd, TCSETXF, &inittermiox) < 0){
1061             if (!hungup && errno != ENXIO)
1062                 error("TCSETXF: %m");
1063         }
1064 #endif
1065         if (!sync_serial)
1066             ioctl(fd, TIOCSWINSZ, &wsinfo);
1067         restore_term = 0;
1068     }
1069 }
1070
1071 /*
1072  * setdtr - control the DTR line on the serial port.
1073  * This is called from die(), so it shouldn't call die().
1074  */
1075 void
1076 setdtr(fd, on)
1077 int fd, on;
1078 {
1079     int modembits = TIOCM_DTR;
1080
1081     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
1082 }
1083
1084 /*
1085  * open_loopback - open the device we use for getting packets
1086  * in demand mode.  Under Solaris 2, we use our existing fd
1087  * to the ppp driver.
1088  */
1089 int
1090 open_ppp_loopback()
1091 {
1092     return pppfd;
1093 }
1094
1095 /*
1096  * output - Output PPP packet.
1097  */
1098 void
1099 output(unit, p, len)
1100     int unit;
1101     u_char *p;
1102     int len;
1103 {
1104     struct strbuf data;
1105     int retries;
1106     struct pollfd pfd;
1107
1108     if (debug)
1109         dbglog("sent %P", p, len);
1110
1111     data.len = len;
1112     data.buf = (caddr_t) p;
1113     retries = 4;
1114     while (putmsg(pppfd, NULL, &data, 0) < 0) {
1115         if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) {
1116             if (errno != ENXIO)
1117                 error("Couldn't send packet: %m");
1118             break;
1119         }
1120         pfd.fd = pppfd;
1121         pfd.events = POLLOUT;
1122         poll(&pfd, 1, 250);     /* wait for up to 0.25 seconds */
1123     }
1124 }
1125
1126
1127 /*
1128  * wait_input - wait until there is data available,
1129  * for the length of time specified by *timo (indefinite
1130  * if timo is NULL).
1131  */
1132 void
1133 wait_input(timo)
1134     struct timeval *timo;
1135 {
1136     int t;
1137
1138     t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000;
1139     if (poll(pollfds, n_pollfds, t) < 0 && errno != EINTR)
1140         fatal("poll: %m");
1141 }
1142
1143 /*
1144  * add_fd - add an fd to the set that wait_input waits for.
1145  */
1146 void add_fd(fd)
1147     int fd;
1148 {
1149     int n;
1150
1151     for (n = 0; n < n_pollfds; ++n)
1152         if (pollfds[n].fd == fd)
1153             return;
1154     if (n_pollfds < MAX_POLLFDS) {
1155         pollfds[n_pollfds].fd = fd;
1156         pollfds[n_pollfds].events = POLLIN | POLLPRI | POLLHUP;
1157         ++n_pollfds;
1158     } else
1159         error("Too many inputs!");
1160 }
1161
1162 /*
1163  * remove_fd - remove an fd from the set that wait_input waits for.
1164  */
1165 void remove_fd(fd)
1166     int fd;
1167 {
1168     int n;
1169
1170     for (n = 0; n < n_pollfds; ++n) {
1171         if (pollfds[n].fd == fd) {
1172             while (++n < n_pollfds)
1173                 pollfds[n-1] = pollfds[n];
1174             --n_pollfds;
1175             break;
1176         }
1177     }
1178 }
1179
1180 #if 0
1181 /*
1182  * wait_loop_output - wait until there is data available on the
1183  * loopback, for the length of time specified by *timo (indefinite
1184  * if timo is NULL).
1185  */
1186 void
1187 wait_loop_output(timo)
1188     struct timeval *timo;
1189 {
1190     wait_input(timo);
1191 }
1192
1193 /*
1194  * wait_time - wait for a given length of time or until a
1195  * signal is received.
1196  */
1197 void
1198 wait_time(timo)
1199     struct timeval *timo;
1200 {
1201     int n;
1202
1203     n = select(0, NULL, NULL, NULL, timo);
1204     if (n < 0 && errno != EINTR)
1205         fatal("select: %m");
1206 }
1207 #endif
1208
1209
1210 /*
1211  * read_packet - get a PPP packet from the serial device.
1212  */
1213 int
1214 read_packet(buf)
1215     u_char *buf;
1216 {
1217     struct strbuf ctrl, data;
1218     int flags, len;
1219     unsigned char ctrlbuf[sizeof(union DL_primitives) + 64];
1220
1221     for (;;) {
1222         data.maxlen = PPP_MRU + PPP_HDRLEN;
1223         data.buf = (caddr_t) buf;
1224         ctrl.maxlen = sizeof(ctrlbuf);
1225         ctrl.buf = (caddr_t) ctrlbuf;
1226         flags = 0;
1227         len = getmsg(pppfd, &ctrl, &data, &flags);
1228         if (len < 0) {
1229             if (errno == EAGAIN || errno == EINTR)
1230                 return -1;
1231             fatal("Error reading packet: %m");
1232         }
1233
1234         if (ctrl.len <= 0)
1235             return data.len;
1236
1237         /*
1238          * Got a M_PROTO or M_PCPROTO message.  Interpret it
1239          * as a DLPI primitive??
1240          */
1241         if (debug)
1242             dbglog("got dlpi prim 0x%x, len=%d",
1243                    ((union DL_primitives *)ctrlbuf)->dl_primitive, ctrl.len);
1244
1245     }
1246 }
1247
1248 /*
1249  * get_loop_output - get outgoing packets from the ppp device,
1250  * and detect when we want to bring the real link up.
1251  * Return value is 1 if we need to bring up the link, 0 otherwise.
1252  */
1253 int
1254 get_loop_output()
1255 {
1256     int len;
1257     int rv = 0;
1258
1259     while ((len = read_packet(inpacket_buf)) > 0) {
1260         if (loop_frame(inpacket_buf, len))
1261             rv = 1;
1262     }
1263     return rv;
1264 }
1265
1266 /*
1267  * ppp_send_config - configure the transmit characteristics of
1268  * the ppp interface.
1269  */
1270 void
1271 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
1272     int unit, mtu;
1273     u_int32_t asyncmap;
1274     int pcomp, accomp;
1275 {
1276     int cf[2];
1277     struct ifreq ifr;
1278 #if defined(INET6) && defined(SOL2)
1279     struct lifreq lifr;
1280     int fd;
1281 #endif /* defined(INET6) && defined(SOL2) */
1282
1283     link_mtu = mtu;
1284     if (strioctl(pppfd, PPPIO_MTU, &mtu, sizeof(mtu), 0) < 0) {
1285         if (hungup && errno == ENXIO)
1286             return;
1287         error("Couldn't set MTU: %m");
1288     }
1289     if (fdmuxid >= 0) {
1290         if (!sync_serial) {
1291             if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
1292                 error("Couldn't set transmit ACCM: %m");
1293             }
1294         }
1295         cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0);
1296         cf[1] = COMP_PROT | COMP_AC;
1297         if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
1298             error("Couldn't set prot/AC compression: %m");
1299         }
1300     }
1301
1302     /* set the MTU for IP as well */
1303     memset(&ifr, 0, sizeof(ifr));
1304     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1305     ifr.ifr_metric = link_mtu;
1306     if (ioctl(ipfd, SIOCSIFMTU, &ifr) < 0) {
1307         error("Couldn't set IP MTU: %m");
1308     }
1309
1310 #if defined(INET6) && defined(SOL2) 
1311     fd = socket(AF_INET6, SOCK_DGRAM, 0);
1312     if (fd < 0)
1313         error("Couldn't open IPv6 socket: %m");
1314
1315     memset(&lifr, 0, sizeof(lifr));
1316     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1317     lifr.lifr_mtu = link_mtu;
1318     if (ioctl(fd, SIOCSLIFMTU, &lifr) < 0) {
1319         close(fd);
1320         error("Couldn't set IPv6 MTU: %m");
1321     }
1322     close(fd);
1323 #endif /* defined(INET6) && defined(SOL2) */
1324 }
1325
1326 /*
1327  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
1328  */
1329 void
1330 ppp_set_xaccm(unit, accm)
1331     int unit;
1332     ext_accm accm;
1333 {
1334     if (sync_serial)
1335         return;
1336
1337     if (fdmuxid >= 0
1338         && strioctl(pppfd, PPPIO_XACCM, accm, sizeof(ext_accm), 0) < 0) {
1339         if (!hungup || errno != ENXIO)
1340             warn("Couldn't set extended ACCM: %m");
1341     }
1342 }
1343
1344 /*
1345  * ppp_recv_config - configure the receive-side characteristics of
1346  * the ppp interface.
1347  */
1348 void
1349 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
1350     int unit, mru;
1351     u_int32_t asyncmap;
1352     int pcomp, accomp;
1353 {
1354     int cf[2];
1355
1356     link_mru = mru;
1357     if (strioctl(pppfd, PPPIO_MRU, &mru, sizeof(mru), 0) < 0) {
1358         if (hungup && errno == ENXIO)
1359             return;
1360         error("Couldn't set MRU: %m");
1361     }
1362     if (fdmuxid >= 0) {
1363         if (!sync_serial) {
1364             if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
1365                 error("Couldn't set receive ACCM: %m");
1366             }
1367         }
1368         cf[0] = (pcomp? DECOMP_PROT: 0) + (accomp? DECOMP_AC: 0);
1369         cf[1] = DECOMP_PROT | DECOMP_AC;
1370         if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
1371             error("Couldn't set prot/AC decompression: %m");
1372         }
1373     }
1374 }
1375
1376 /*
1377  * ccp_test - ask kernel whether a given compression method
1378  * is acceptable for use.
1379  */
1380 int
1381 ccp_test(unit, opt_ptr, opt_len, for_transmit)
1382     int unit, opt_len, for_transmit;
1383     u_char *opt_ptr;
1384 {
1385     if (strioctl(pppfd, (for_transmit? PPPIO_XCOMP: PPPIO_RCOMP),
1386                  opt_ptr, opt_len, 0) >= 0)
1387         return 1;
1388     return (errno == ENOSR)? 0: -1;
1389 }
1390
1391 /*
1392  * ccp_flags_set - inform kernel about the current state of CCP.
1393  */
1394 void
1395 ccp_flags_set(unit, isopen, isup)
1396     int unit, isopen, isup;
1397 {
1398     int cf[2];
1399
1400     cf[0] = (isopen? CCP_ISOPEN: 0) + (isup? CCP_ISUP: 0);
1401     cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR;
1402     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
1403         if (!hungup || errno != ENXIO)
1404             error("Couldn't set kernel CCP state: %m");
1405     }
1406 }
1407
1408 /*
1409  * get_idle_time - return how long the link has been idle.
1410  */
1411 int
1412 get_idle_time(u, ip)
1413     int u;
1414     struct ppp_idle *ip;
1415 {
1416     return strioctl(pppfd, PPPIO_GIDLE, ip, 0, sizeof(struct ppp_idle)) >= 0;
1417 }
1418
1419 /*
1420  * get_ppp_stats - return statistics for the link.
1421  */
1422 int
1423 get_ppp_stats(u, stats)
1424     int u;
1425     struct pppd_stats *stats;
1426 {
1427     struct ppp_stats s;
1428
1429     if (!sync_serial && 
1430         strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof(s)) < 0) {
1431         error("Couldn't get link statistics: %m");
1432         return 0;
1433     }
1434     stats->bytes_in = s.p.ppp_ibytes;
1435     stats->bytes_out = s.p.ppp_obytes;
1436     return 1;
1437 }
1438
1439 #if 0
1440 /*
1441  * set_filters - transfer the pass and active filters to the kernel.
1442  */
1443 int
1444 set_filters(pass, active)
1445     struct bpf_program *pass, *active;
1446 {
1447     int ret = 1;
1448
1449     if (pass->bf_len > 0) {
1450         if (strioctl(pppfd, PPPIO_PASSFILT, pass,
1451                      sizeof(struct bpf_program), 0) < 0) {
1452             error("Couldn't set pass-filter in kernel: %m");
1453             ret = 0;
1454         }
1455     }
1456     if (active->bf_len > 0) {
1457         if (strioctl(pppfd, PPPIO_ACTIVEFILT, active,
1458                      sizeof(struct bpf_program), 0) < 0) {
1459             error("Couldn't set active-filter in kernel: %m");
1460             ret = 0;
1461         }
1462     }
1463     return ret;
1464 }
1465 #endif
1466
1467 /*
1468  * ccp_fatal_error - returns 1 if decompression was disabled as a
1469  * result of an error detected after decompression of a packet,
1470  * 0 otherwise.  This is necessary because of patent nonsense.
1471  */
1472 int
1473 ccp_fatal_error(unit)
1474     int unit;
1475 {
1476     int cf[2];
1477
1478     cf[0] = cf[1] = 0;
1479     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
1480         if (errno != ENXIO && errno != EINVAL)
1481             error("Couldn't get compression flags: %m");
1482         return 0;
1483     }
1484     return cf[0] & CCP_FATALERROR;
1485 }
1486
1487 /*
1488  * sifvjcomp - config tcp header compression
1489  */
1490 int
1491 sifvjcomp(u, vjcomp, xcidcomp, xmaxcid)
1492     int u, vjcomp, xcidcomp, xmaxcid;
1493 {
1494     int cf[2];
1495     char maxcid[2];
1496
1497     if (vjcomp) {
1498         maxcid[0] = xcidcomp;
1499         maxcid[1] = 15;         /* XXX should be rmaxcid */
1500         if (strioctl(pppfd, PPPIO_VJINIT, maxcid, sizeof(maxcid), 0) < 0) {
1501             error("Couldn't initialize VJ compression: %m");
1502         }
1503     }
1504
1505     cf[0] = (vjcomp? COMP_VJC + DECOMP_VJC: 0)  /* XXX this is wrong */
1506         + (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0);
1507     cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID;
1508     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
1509         if (vjcomp)
1510             error("Couldn't enable VJ compression: %m");
1511     }
1512
1513     return 1;
1514 }
1515
1516 /*
1517  * sifup - Config the interface up and enable IP packets to pass.
1518  */
1519 int
1520 sifup(u)
1521     int u;
1522 {
1523     struct ifreq ifr;
1524
1525     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1526     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
1527         error("Couldn't mark interface up (get): %m");
1528         return 0;
1529     }
1530     ifr.ifr_flags |= IFF_UP;
1531     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
1532         error("Couldn't mark interface up (set): %m");
1533         return 0;
1534     }
1535     if_is_up = 1;
1536     return 1;
1537 }
1538
1539 /*
1540  * sifdown - Config the interface down and disable IP.
1541  */
1542 int
1543 sifdown(u)
1544     int u;
1545 {
1546     struct ifreq ifr;
1547
1548     if (ipmuxid < 0)
1549         return 1;
1550     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1551     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
1552         error("Couldn't mark interface down (get): %m");
1553         return 0;
1554     }
1555     ifr.ifr_flags &= ~IFF_UP;
1556     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
1557         error("Couldn't mark interface down (set): %m");
1558         return 0;
1559     }
1560     if_is_up = 0;
1561     return 1;
1562 }
1563
1564 /*
1565  * sifnpmode - Set the mode for handling packets for a given NP.
1566  */
1567 int
1568 sifnpmode(u, proto, mode)
1569     int u;
1570     int proto;
1571     enum NPmode mode;
1572 {
1573     int npi[2];
1574
1575     npi[0] = proto;
1576     npi[1] = (int) mode;
1577     if (strioctl(pppfd, PPPIO_NPMODE, &npi, 2 * sizeof(int), 0) < 0) {
1578         error("ioctl(set NP %d mode to %d): %m", proto, mode);
1579         return 0;
1580     }
1581     return 1;
1582 }
1583
1584 #if defined(SOL2) && defined(INET6)
1585 /*
1586  * sif6up - Config the IPv6 interface up and enable IPv6 packets to pass.
1587  */
1588 int
1589 sif6up(u)
1590     int u;
1591 {
1592     struct lifreq lifr;
1593     int fd;
1594
1595     fd = socket(AF_INET6, SOCK_DGRAM, 0);
1596     if (fd < 0) {
1597         return 0;
1598     }
1599
1600     memset(&lifr, 0, sizeof(lifr));
1601     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1602     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
1603         close(fd);
1604         return 0;
1605     }
1606
1607     lifr.lifr_flags |= IFF_UP;
1608     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1609     if (ioctl(fd, SIOCSLIFFLAGS, &lifr) < 0) {
1610         close(fd);
1611         return 0;
1612     }
1613
1614     if6_is_up = 1;
1615     close(fd);
1616     return 1;
1617 }
1618
1619 /*
1620  * sifdown - Config the IPv6 interface down and disable IPv6.
1621  */
1622 int
1623 sif6down(u)
1624     int u;
1625 {
1626     struct lifreq lifr;
1627     int fd;
1628
1629     fd = socket(AF_INET6, SOCK_DGRAM, 0);
1630     if (fd < 0)
1631         return 0;
1632
1633     memset(&lifr, 0, sizeof(lifr));
1634     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1635     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
1636         close(fd);
1637         return 0;
1638     }
1639
1640     lifr.lifr_flags &= ~IFF_UP;
1641     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1642     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
1643         close(fd);
1644         return 0;
1645     }
1646
1647     if6_is_up = 0;
1648     close(fd);
1649     return 1;
1650 }
1651
1652 /*
1653  * sif6addr - Config the interface with an IPv6 link-local address
1654  */
1655 int
1656 sif6addr(u, o, h)
1657     int u;
1658     eui64_t o, h;
1659 {
1660     struct lifreq lifr;
1661     struct sockaddr_storage laddr;
1662     struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&laddr;
1663     int fd;
1664
1665     fd = socket(AF_INET6, SOCK_DGRAM, 0);
1666     if (fd < 0)
1667         return 0;
1668
1669     memset(&lifr, 0, sizeof(lifr));
1670     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1671
1672     /*
1673      * Do this because /dev/ppp responds to DL_PHYS_ADDR_REQ with
1674      * zero values, hence the interface token came to be zero too,
1675      * and without this, in.ndpd will complain
1676      */
1677     IN6_LLTOKEN_FROM_EUI64(lifr, sin6, o);
1678     if (ioctl(fd, SIOCSLIFTOKEN, &lifr) < 0) {
1679         close(fd);
1680         return 0;
1681     }
1682
1683     /*
1684      * Set the interface address and destination address
1685      */
1686     IN6_LLADDR_FROM_EUI64(lifr, sin6, o);
1687     if (ioctl(fd, SIOCSLIFADDR, &lifr) < 0) {
1688         close(fd);
1689         return 0;
1690     }
1691
1692     memset(&lifr, 0, sizeof(lifr));
1693     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1694     IN6_LLADDR_FROM_EUI64(lifr, sin6, h);
1695     if (ioctl(fd, SIOCSLIFDSTADDR, &lifr) < 0) {
1696         close(fd);
1697         return 0;
1698     }
1699
1700     return 1;
1701 }
1702
1703 /*
1704  * cif6addr - Remove the IPv6 address from interface
1705  */
1706 int
1707 cif6addr(u, o, h)
1708     int u;
1709     eui64_t o, h;
1710 {
1711     return 1;
1712 }
1713
1714 #endif /* defined(SOL2) && defined(INET6) */
1715
1716
1717 #define INET_ADDR(x)    (((struct sockaddr_in *) &(x))->sin_addr.s_addr)
1718
1719 /*
1720  * sifaddr - Config the interface IP addresses and netmask.
1721  */
1722 int
1723 sifaddr(u, o, h, m)
1724     int u;
1725     u_int32_t o, h, m;
1726 {
1727     struct ifreq ifr;
1728     int ret = 1;
1729
1730     memset(&ifr, 0, sizeof(ifr));
1731     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1732     ifr.ifr_addr.sa_family = AF_INET;
1733     INET_ADDR(ifr.ifr_addr) = m;
1734     if (ioctl(ipfd, SIOCSIFNETMASK, &ifr) < 0) {
1735         error("Couldn't set IP netmask: %m");
1736         ret = 0;
1737     }
1738     ifr.ifr_addr.sa_family = AF_INET;
1739     INET_ADDR(ifr.ifr_addr) = o;
1740     if (ioctl(ipfd, SIOCSIFADDR, &ifr) < 0) {
1741         error("Couldn't set local IP address: %m");
1742         ret = 0;
1743     }
1744
1745     /*
1746      * On some systems, we have to explicitly set the point-to-point
1747      * flag bit before we can set a destination address.
1748      */
1749     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) >= 0
1750         && (ifr.ifr_flags & IFF_POINTOPOINT) == 0) {
1751         ifr.ifr_flags |= IFF_POINTOPOINT;
1752         if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
1753             error("Couldn't mark interface pt-to-pt: %m");
1754             ret = 0;
1755         }
1756     }
1757     ifr.ifr_dstaddr.sa_family = AF_INET;
1758     INET_ADDR(ifr.ifr_dstaddr) = h;
1759     if (ioctl(ipfd, SIOCSIFDSTADDR, &ifr) < 0) {
1760         error("Couldn't set remote IP address: %m");
1761         ret = 0;
1762     }
1763 #if 0   /* now done in ppp_send_config */
1764     ifr.ifr_metric = link_mtu;
1765     if (ioctl(ipfd, SIOCSIFMTU, &ifr) < 0) {
1766         error("Couldn't set IP MTU: %m");
1767     }
1768 #endif
1769
1770     remote_addr = h;
1771     return ret;
1772 }
1773
1774 /*
1775  * cifaddr - Clear the interface IP addresses, and delete routes
1776  * through the interface if possible.
1777  */
1778 int
1779 cifaddr(u, o, h)
1780     int u;
1781     u_int32_t o, h;
1782 {
1783 #if defined(__USLC__)           /* was: #if 0 */
1784     cifroute(unit, ouraddr, hisaddr);
1785     if (ipmuxid >= 0) {
1786         notice("Removing ppp interface unit");
1787         if (ioctl(ipfd, I_UNLINK, ipmuxid) < 0) {
1788             error("Can't remove ppp interface unit: %m");
1789             return 0;
1790         }
1791         ipmuxid = -1;
1792     }
1793 #endif
1794     remote_addr = 0;
1795     return 1;
1796 }
1797
1798 /*
1799  * sifdefaultroute - assign a default route through the address given.
1800  */
1801 int
1802 sifdefaultroute(u, l, g)
1803     int u;
1804     u_int32_t l, g;
1805 {
1806     struct rtentry rt;
1807
1808 #if defined(__USLC__)
1809     g = l;                      /* use the local address as gateway */
1810 #endif
1811     memset(&rt, 0, sizeof(rt));
1812     rt.rt_dst.sa_family = AF_INET;
1813     INET_ADDR(rt.rt_dst) = 0;
1814     rt.rt_gateway.sa_family = AF_INET;
1815     INET_ADDR(rt.rt_gateway) = g;
1816     rt.rt_flags = RTF_GATEWAY;
1817
1818     if (ioctl(ipfd, SIOCADDRT, &rt) < 0) {
1819         error("Can't add default route: %m");
1820         return 0;
1821     }
1822
1823     default_route_gateway = g;
1824     return 1;
1825 }
1826
1827 /*
1828  * cifdefaultroute - delete a default route through the address given.
1829  */
1830 int
1831 cifdefaultroute(u, l, g)
1832     int u;
1833     u_int32_t l, g;
1834 {
1835     struct rtentry rt;
1836
1837 #if defined(__USLC__)
1838     g = l;                      /* use the local address as gateway */
1839 #endif
1840     memset(&rt, 0, sizeof(rt));
1841     rt.rt_dst.sa_family = AF_INET;
1842     INET_ADDR(rt.rt_dst) = 0;
1843     rt.rt_gateway.sa_family = AF_INET;
1844     INET_ADDR(rt.rt_gateway) = g;
1845     rt.rt_flags = RTF_GATEWAY;
1846
1847     if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
1848         error("Can't delete default route: %m");
1849         return 0;
1850     }
1851
1852     default_route_gateway = 0;
1853     return 1;
1854 }
1855
1856 /*
1857  * sifproxyarp - Make a proxy ARP entry for the peer.
1858  */
1859 int
1860 sifproxyarp(unit, hisaddr)
1861     int unit;
1862     u_int32_t hisaddr;
1863 {
1864     struct arpreq arpreq;
1865
1866     memset(&arpreq, 0, sizeof(arpreq));
1867     if (!get_ether_addr(hisaddr, &arpreq.arp_ha))
1868         return 0;
1869
1870     arpreq.arp_pa.sa_family = AF_INET;
1871     INET_ADDR(arpreq.arp_pa) = hisaddr;
1872     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1873     if (ioctl(ipfd, SIOCSARP, (caddr_t) &arpreq) < 0) {
1874         error("Couldn't set proxy ARP entry: %m");
1875         return 0;
1876     }
1877
1878     proxy_arp_addr = hisaddr;
1879     return 1;
1880 }
1881
1882 /*
1883  * cifproxyarp - Delete the proxy ARP entry for the peer.
1884  */
1885 int
1886 cifproxyarp(unit, hisaddr)
1887     int unit;
1888     u_int32_t hisaddr;
1889 {
1890     struct arpreq arpreq;
1891
1892     memset(&arpreq, 0, sizeof(arpreq));
1893     arpreq.arp_pa.sa_family = AF_INET;
1894     INET_ADDR(arpreq.arp_pa) = hisaddr;
1895     if (ioctl(ipfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1896         error("Couldn't delete proxy ARP entry: %m");
1897         return 0;
1898     }
1899
1900     proxy_arp_addr = 0;
1901     return 1;
1902 }
1903
1904 /*
1905  * get_ether_addr - get the hardware address of an interface on the
1906  * the same subnet as ipaddr.
1907  */
1908 #define MAX_IFS         32
1909
1910 static int
1911 get_ether_addr(ipaddr, hwaddr)
1912     u_int32_t ipaddr;
1913     struct sockaddr *hwaddr;
1914 {
1915     struct ifreq *ifr, *ifend, ifreq;
1916     int nif;
1917     struct ifconf ifc;
1918     u_int32_t ina, mask;
1919
1920     /*
1921      * Scan through the system's network interfaces.
1922      */
1923 #ifdef SIOCGIFNUM
1924     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
1925 #endif
1926         nif = MAX_IFS;
1927     ifc.ifc_len = nif * sizeof(struct ifreq);
1928     ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len);
1929     if (ifc.ifc_buf == 0)
1930         return 0;
1931     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
1932         warn("Couldn't get system interface list: %m");
1933         free(ifc.ifc_buf);
1934         return 0;
1935     }
1936     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1937     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
1938         if (ifr->ifr_addr.sa_family != AF_INET)
1939             continue;
1940         /*
1941          * Check that the interface is up, and not point-to-point or loopback.
1942          */
1943         strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1944         if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
1945             continue;
1946         if ((ifreq.ifr_flags &
1947              (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1948             != (IFF_UP|IFF_BROADCAST))
1949             continue;
1950         /*
1951          * Get its netmask and check that it's on the right subnet.
1952          */
1953         if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
1954             continue;
1955         ina = INET_ADDR(ifr->ifr_addr);
1956         mask = INET_ADDR(ifreq.ifr_addr);
1957         if ((ipaddr & mask) == (ina & mask))
1958             break;
1959     }
1960
1961     if (ifr >= ifend) {
1962         warn("No suitable interface found for proxy ARP");
1963         free(ifc.ifc_buf);
1964         return 0;
1965     }
1966
1967     info("found interface %s for proxy ARP", ifr->ifr_name);
1968     if (!get_hw_addr(ifr->ifr_name, ina, hwaddr)) {
1969         error("Couldn't get hardware address for %s", ifr->ifr_name);
1970         free(ifc.ifc_buf);
1971         return 0;
1972     }
1973
1974     free(ifc.ifc_buf);
1975     return 1;
1976 }
1977
1978 /*
1979  * get_hw_addr_dlpi - obtain the hardware address using DLPI
1980  */
1981 static int
1982 get_hw_addr_dlpi(name, hwaddr)
1983     char *name;
1984     struct sockaddr *hwaddr;
1985 {
1986     char *p, *q;
1987     int unit, iffd, adrlen;
1988     unsigned char *adrp;
1989     char ifdev[24];
1990     struct {
1991         union DL_primitives prim;
1992         char space[64];
1993     } reply;
1994
1995     /*
1996      * We have to open the device and ask it for its hardware address.
1997      * First split apart the device name and unit.
1998      */
1999     slprintf(ifdev, sizeof(ifdev), "/dev/%s", name);
2000     for (q = ifdev + strlen(ifdev); --q >= ifdev; )
2001         if (!isdigit(*q))
2002             break;
2003     unit = atoi(q+1);
2004     q[1] = 0;
2005
2006     /*
2007      * Open the device and do a DLPI attach and phys_addr_req.
2008      */
2009     iffd = open(ifdev, O_RDWR);
2010     if (iffd < 0) {
2011         error("Can't open %s: %m", ifdev);
2012         return 0;
2013     }
2014     if (dlpi_attach(iffd, unit) < 0
2015         || dlpi_get_reply(iffd, &reply.prim, DL_OK_ACK, sizeof(reply)) < 0
2016         || dlpi_info_req(iffd) < 0
2017         || dlpi_get_reply(iffd, &reply.prim, DL_INFO_ACK, sizeof(reply)) < 0) {
2018         close(iffd);
2019         return 0;
2020     }
2021
2022     adrlen = reply.prim.info_ack.dl_addr_length;
2023     adrp = (unsigned char *)&reply + reply.prim.info_ack.dl_addr_offset;
2024
2025 #if DL_CURRENT_VERSION >= 2
2026     if (reply.prim.info_ack.dl_sap_length < 0)
2027         adrlen += reply.prim.info_ack.dl_sap_length;
2028     else
2029         adrp += reply.prim.info_ack.dl_sap_length;
2030 #endif
2031
2032     hwaddr->sa_family = AF_UNSPEC;
2033     memcpy(hwaddr->sa_data, adrp, adrlen);
2034
2035     return 1;
2036 }
2037 /*
2038  * get_hw_addr - obtain the hardware address for a named interface.
2039  */
2040 static int
2041 get_hw_addr(name, ina, hwaddr)
2042     char *name;
2043     u_int32_t ina;
2044     struct sockaddr *hwaddr;
2045 {
2046     /* New way - get the address by doing an arp request. */
2047     int s;
2048     struct arpreq req;
2049
2050     s = socket(AF_INET, SOCK_DGRAM, 0);
2051     if (s < 0)
2052         return 0;
2053     memset(&req, 0, sizeof(req));
2054     req.arp_pa.sa_family = AF_INET;
2055     INET_ADDR(req.arp_pa) = ina;
2056     if (ioctl(s, SIOCGARP, &req) < 0) {
2057         error("Couldn't get ARP entry for %s: %m", ip_ntoa(ina));
2058         return 0;
2059     }
2060     *hwaddr = req.arp_ha;
2061     hwaddr->sa_family = AF_UNSPEC;
2062
2063     return 1;
2064 }
2065
2066 static int
2067 dlpi_attach(fd, ppa)
2068     int fd, ppa;
2069 {
2070     dl_attach_req_t req;
2071     struct strbuf buf;
2072
2073     req.dl_primitive = DL_ATTACH_REQ;
2074     req.dl_ppa = ppa;
2075     buf.len = sizeof(req);
2076     buf.buf = (void *) &req;
2077     return putmsg(fd, &buf, NULL, RS_HIPRI);
2078 }
2079
2080 static int
2081 dlpi_info_req(fd)
2082     int fd;
2083 {
2084     dl_info_req_t req;
2085     struct strbuf buf;
2086
2087     req.dl_primitive = DL_INFO_REQ;
2088     buf.len = sizeof(req);
2089     buf.buf = (void *) &req;
2090     return putmsg(fd, &buf, NULL, RS_HIPRI);
2091 }
2092
2093 static int
2094 dlpi_get_reply(fd, reply, expected_prim, maxlen)
2095     union DL_primitives *reply;
2096     int fd, expected_prim, maxlen;
2097 {
2098     struct strbuf buf;
2099     int flags, n;
2100     struct pollfd pfd;
2101
2102     /*
2103      * Use poll to wait for a message with a timeout.
2104      */
2105     pfd.fd = fd;
2106     pfd.events = POLLIN | POLLPRI;
2107     do {
2108         n = poll(&pfd, 1, 1000);
2109     } while (n == -1 && errno == EINTR);
2110     if (n <= 0)
2111         return -1;
2112
2113     /*
2114      * Get the reply.
2115      */
2116     buf.maxlen = maxlen;
2117     buf.buf = (void *) reply;
2118     flags = 0;
2119     if (getmsg(fd, &buf, NULL, &flags) < 0)
2120         return -1;
2121
2122     if (buf.len < sizeof(ulong)) {
2123         if (debug)
2124             dbglog("dlpi response short (len=%d)\n", buf.len);
2125         return -1;
2126     }
2127
2128     if (reply->dl_primitive == expected_prim)
2129         return 0;
2130
2131     if (debug) {
2132         if (reply->dl_primitive == DL_ERROR_ACK) {
2133             dbglog("dlpi error %d (unix errno %d) for prim %x\n",
2134                    reply->error_ack.dl_errno, reply->error_ack.dl_unix_errno,
2135                    reply->error_ack.dl_error_primitive);
2136         } else {
2137             dbglog("dlpi unexpected response prim %x\n",
2138                    reply->dl_primitive);
2139         }
2140     }
2141
2142     return -1;
2143 }
2144
2145 /*
2146  * Return user specified netmask, modified by any mask we might determine
2147  * for address `addr' (in network byte order).
2148  * Here we scan through the system's list of interfaces, looking for
2149  * any non-point-to-point interfaces which might appear to be on the same
2150  * network as `addr'.  If we find any, we OR in their netmask to the
2151  * user-specified netmask.
2152  */
2153 u_int32_t
2154 GetMask(addr)
2155     u_int32_t addr;
2156 {
2157     u_int32_t mask, nmask, ina;
2158     struct ifreq *ifr, *ifend, ifreq;
2159     int nif;
2160     struct ifconf ifc;
2161
2162     addr = ntohl(addr);
2163     if (IN_CLASSA(addr))        /* determine network mask for address class */
2164         nmask = IN_CLASSA_NET;
2165     else if (IN_CLASSB(addr))
2166         nmask = IN_CLASSB_NET;
2167     else
2168         nmask = IN_CLASSC_NET;
2169     /* class D nets are disallowed by bad_ip_adrs */
2170     mask = netmask | htonl(nmask);
2171
2172     /*
2173      * Scan through the system's network interfaces.
2174      */
2175 #ifdef SIOCGIFNUM
2176     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
2177 #endif
2178         nif = MAX_IFS;
2179     ifc.ifc_len = nif * sizeof(struct ifreq);
2180     ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len);
2181     if (ifc.ifc_buf == 0)
2182         return mask;
2183     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
2184         warn("Couldn't get system interface list: %m");
2185         free(ifc.ifc_buf);
2186         return mask;
2187     }
2188     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
2189     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
2190         /*
2191          * Check the interface's internet address.
2192          */
2193         if (ifr->ifr_addr.sa_family != AF_INET)
2194             continue;
2195         ina = INET_ADDR(ifr->ifr_addr);
2196         if ((ntohl(ina) & nmask) != (addr & nmask))
2197             continue;
2198         /*
2199          * Check that the interface is up, and not point-to-point or loopback.
2200          */
2201         strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
2202         if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
2203             continue;
2204         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
2205             != IFF_UP)
2206             continue;
2207         /*
2208          * Get its netmask and OR it into our mask.
2209          */
2210         if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
2211             continue;
2212         mask |= INET_ADDR(ifreq.ifr_addr);
2213     }
2214
2215     free(ifc.ifc_buf);
2216     return mask;
2217 }
2218
2219 /*
2220  * logwtmp - write an accounting record to the /var/adm/wtmp file.
2221  */
2222 void
2223 logwtmp(line, name, host)
2224     const char *line, *name, *host;
2225 {
2226     static struct utmpx utmpx;
2227
2228     if (name[0] != 0) {
2229         /* logging in */
2230         strncpy(utmpx.ut_user, name, sizeof(utmpx.ut_user));
2231         strncpy(utmpx.ut_id, ifname, sizeof(utmpx.ut_id));
2232         strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line));
2233         utmpx.ut_pid = getpid();
2234         utmpx.ut_type = USER_PROCESS;
2235     } else {
2236         utmpx.ut_type = DEAD_PROCESS;
2237     }
2238     gettimeofday(&utmpx.ut_tv, NULL);
2239     updwtmpx("/var/adm/wtmpx", &utmpx);
2240 }
2241
2242 /*
2243  * get_host_seed - return the serial number of this machine.
2244  */
2245 int
2246 get_host_seed()
2247 {
2248     char buf[32];
2249
2250     if (sysinfo(SI_HW_SERIAL, buf, sizeof(buf)) < 0) {
2251         error("sysinfo: %m");
2252         return 0;
2253     }
2254     return (int) strtoul(buf, NULL, 16);
2255 }
2256
2257 static int
2258 strioctl(fd, cmd, ptr, ilen, olen)
2259     int fd, cmd, ilen, olen;
2260     void *ptr;
2261 {
2262     struct strioctl str;
2263
2264     str.ic_cmd = cmd;
2265     str.ic_timout = 0;
2266     str.ic_len = ilen;
2267     str.ic_dp = ptr;
2268     if (ioctl(fd, I_STR, &str) == -1)
2269         return -1;
2270     if (str.ic_len != olen)
2271         dbglog("strioctl: expected %d bytes, got %d for cmd %x\n",
2272                olen, str.ic_len, cmd);
2273     return 0;
2274 }
2275
2276 #if 0
2277 /*
2278  * lock - create a lock file for the named lock device
2279  */
2280
2281 #define LOCK_PREFIX     "/var/spool/locks/LK."
2282 static char lock_file[40];      /* name of lock file created */
2283
2284 int
2285 lock(dev)
2286     char *dev;
2287 {
2288     int n, fd, pid;
2289     struct stat sbuf;
2290     char ascii_pid[12];
2291
2292     if (stat(dev, &sbuf) < 0) {
2293         error("Can't get device number for %s: %m", dev);
2294         return -1;
2295     }
2296     if ((sbuf.st_mode & S_IFMT) != S_IFCHR) {
2297         error("Can't lock %s: not a character device", dev);
2298         return -1;
2299     }
2300     slprintf(lock_file, sizeof(lock_file), "%s%03d.%03d.%03d",
2301              LOCK_PREFIX, major(sbuf.st_dev),
2302              major(sbuf.st_rdev), minor(sbuf.st_rdev));
2303
2304     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
2305         if (errno == EEXIST
2306             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
2307             /* Read the lock file to find out who has the device locked */
2308             n = read(fd, ascii_pid, 11);
2309             if (n <= 0) {
2310                 error("Can't read pid from lock file %s", lock_file);
2311                 close(fd);
2312             } else {
2313                 ascii_pid[n] = 0;
2314                 pid = atoi(ascii_pid);
2315                 if (pid > 0 && kill(pid, 0) == -1 && errno == ESRCH) {
2316                     /* pid no longer exists - remove the lock file */
2317                     if (unlink(lock_file) == 0) {
2318                         close(fd);
2319                         notice("Removed stale lock on %s (pid %d)",
2320                                dev, pid);
2321                         continue;
2322                     } else
2323                         warn("Couldn't remove stale lock on %s",
2324                                dev);
2325                 } else
2326                     notice("Device %s is locked by pid %d",
2327                            dev, pid);
2328             }
2329             close(fd);
2330         } else
2331             error("Can't create lock file %s: %m", lock_file);
2332         lock_file[0] = 0;
2333         return -1;
2334     }
2335
2336     slprintf(ascii_pid, sizeof(ascii_pid), "%10d\n", getpid());
2337     write(fd, ascii_pid, 11);
2338
2339     close(fd);
2340     return 1;
2341 }
2342
2343 /*
2344  * unlock - remove our lockfile
2345  */
2346 void
2347 unlock()
2348 {
2349     if (lock_file[0]) {
2350         unlink(lock_file);
2351         lock_file[0] = 0;
2352     }
2353 }
2354 #endif
2355
2356 /*
2357  * cifroute - delete a route through the addresses given.
2358  */
2359 int
2360 cifroute(u, our, his)
2361     int u;
2362     u_int32_t our, his;
2363 {
2364     struct rtentry rt;
2365
2366     memset(&rt, 0, sizeof(rt));
2367     rt.rt_dst.sa_family = AF_INET;
2368     INET_ADDR(rt.rt_dst) = his;
2369     rt.rt_gateway.sa_family = AF_INET;
2370     INET_ADDR(rt.rt_gateway) = our;
2371     rt.rt_flags = RTF_HOST;
2372
2373     if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
2374         error("Can't delete route: %m");
2375         return 0;
2376     }
2377
2378     return 1;
2379 }
2380
2381 /*
2382  * have_route_to - determine if the system has a route to the specified
2383  * IP address.  Returns 0 if not, 1 if so, -1 if we can't tell.
2384  * `addr' is in network byte order.
2385  * For demand mode to work properly, we have to ignore routes
2386  * through our own interface.
2387  */
2388 #ifndef T_CURRENT               /* needed for Solaris 2.5 */
2389 #define T_CURRENT       MI_T_CURRENT
2390 #endif
2391
2392 int
2393 have_route_to(addr)
2394     u_int32_t addr;
2395 {
2396 #ifdef SOL2
2397     int fd, r, flags, i;
2398     struct {
2399         struct T_optmgmt_req req;
2400         struct opthdr hdr;
2401     } req;
2402     union {
2403         struct T_optmgmt_ack ack;
2404         unsigned char space[64];
2405     } ack;
2406     struct opthdr *rh;
2407     struct strbuf cbuf, dbuf;
2408     int nroutes;
2409     mib2_ipRouteEntry_t routes[8];
2410     mib2_ipRouteEntry_t *rp;
2411
2412     fd = open(mux_dev_name, O_RDWR);
2413     if (fd < 0) {
2414         warn("have_route_to: couldn't open %s: %m", mux_dev_name);
2415         return -1;
2416     }
2417
2418     req.req.PRIM_type = T_OPTMGMT_REQ;
2419     req.req.OPT_offset = (char *) &req.hdr - (char *) &req;
2420     req.req.OPT_length = sizeof(req.hdr);
2421     req.req.MGMT_flags = T_CURRENT;
2422
2423     req.hdr.level = MIB2_IP;
2424     req.hdr.name = 0;
2425     req.hdr.len = 0;
2426
2427     cbuf.buf = (char *) &req;
2428     cbuf.len = sizeof(req);
2429
2430     if (putmsg(fd, &cbuf, NULL, 0) == -1) {
2431         warn("have_route_to: putmsg: %m");
2432         close(fd);
2433         return -1;
2434     }
2435
2436     for (;;) {
2437         cbuf.buf = (char *) &ack;
2438         cbuf.maxlen = sizeof(ack);
2439         dbuf.buf = (char *) routes;
2440         dbuf.maxlen = sizeof(routes);
2441         flags = 0;
2442         r = getmsg(fd, &cbuf, &dbuf, &flags);
2443         if (r == -1) {
2444             warn("have_route_to: getmsg: %m");
2445             close(fd);
2446             return -1;
2447         }
2448
2449         if (cbuf.len < sizeof(struct T_optmgmt_ack)
2450             || ack.ack.PRIM_type != T_OPTMGMT_ACK
2451             || ack.ack.MGMT_flags != T_SUCCESS
2452             || ack.ack.OPT_length < sizeof(struct opthdr)) {
2453             dbglog("have_route_to: bad message len=%d prim=%d",
2454                    cbuf.len, ack.ack.PRIM_type);
2455             close(fd);
2456             return -1;
2457         }
2458
2459         rh = (struct opthdr *) ((char *)&ack + ack.ack.OPT_offset);
2460         if (rh->level == 0 && rh->name == 0)
2461             break;
2462         if (rh->level != MIB2_IP || rh->name != MIB2_IP_21) {
2463             while (r == MOREDATA)
2464                 r = getmsg(fd, NULL, &dbuf, &flags);
2465             continue;
2466         }
2467
2468         for (;;) {
2469             nroutes = dbuf.len / sizeof(mib2_ipRouteEntry_t);
2470             for (rp = routes, i = 0; i < nroutes; ++i, ++rp) {
2471                 if (rp->ipRouteMask != ~0) {
2472                     dbglog("have_route_to: dest=%x gw=%x mask=%x\n",
2473                            rp->ipRouteDest, rp->ipRouteNextHop,
2474                            rp->ipRouteMask);
2475                     if (((addr ^ rp->ipRouteDest) & rp->ipRouteMask) == 0
2476                         && rp->ipRouteNextHop != remote_addr)
2477                         return 1;
2478                 }
2479             }
2480             if (r == 0)
2481                 break;
2482             r = getmsg(fd, NULL, &dbuf, &flags);
2483         }
2484     }
2485     close(fd);
2486     return 0;
2487 #else
2488     return -1;
2489 #endif /* SOL2 */
2490 }
2491
2492 /*
2493  * get_pty - get a pty master/slave pair and chown the slave side to
2494  * the uid given.  Assumes slave_name points to MAXPATHLEN bytes of space.
2495  */
2496 int
2497 get_pty(master_fdp, slave_fdp, slave_name, uid)
2498     int *master_fdp;
2499     int *slave_fdp;
2500     char *slave_name;
2501     int uid;
2502 {
2503     int mfd, sfd;
2504     char *pty_name;
2505     struct termios tios;
2506
2507     mfd = open("/dev/ptmx", O_RDWR);
2508     if (mfd < 0) {
2509         error("Couldn't open pty master: %m");
2510         return 0;
2511     }
2512
2513     pty_name = ptsname(mfd);
2514     if (pty_name == NULL) {
2515         error("Couldn't get name of pty slave");
2516         close(mfd);
2517         return 0;
2518     }
2519     if (chown(pty_name, uid, -1) < 0)
2520         warn("Couldn't change owner of pty slave: %m");
2521     if (chmod(pty_name, S_IRUSR | S_IWUSR) < 0)
2522         warn("Couldn't change permissions on pty slave: %m");
2523     if (unlockpt(mfd) < 0)
2524         warn("Couldn't unlock pty slave: %m");
2525
2526     sfd = open(pty_name, O_RDWR);
2527     if (sfd < 0) {
2528         error("Couldn't open pty slave %s: %m", pty_name);
2529         close(mfd);
2530         return 0;
2531     }
2532     if (ioctl(sfd, I_PUSH, "ptem") < 0)
2533         warn("Couldn't push ptem module on pty slave: %m");
2534
2535     dbglog("Using %s", pty_name);
2536     strlcpy(slave_name, pty_name, MAXPATHLEN);
2537     *master_fdp = mfd;
2538     *slave_fdp = sfd;
2539
2540     return 1;
2541 }