]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-svr4.c
Fixed compilation problems on SunOS 4.x
[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.39 2000/01/25 03:25:36 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 (strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof(s)) < 0) {
1430         error("Couldn't get link statistics: %m");
1431         return 0;
1432     }
1433     stats->bytes_in = s.p.ppp_ibytes;
1434     stats->bytes_out = s.p.ppp_obytes;
1435     return 1;
1436 }
1437
1438 #if 0
1439 /*
1440  * set_filters - transfer the pass and active filters to the kernel.
1441  */
1442 int
1443 set_filters(pass, active)
1444     struct bpf_program *pass, *active;
1445 {
1446     int ret = 1;
1447
1448     if (pass->bf_len > 0) {
1449         if (strioctl(pppfd, PPPIO_PASSFILT, pass,
1450                      sizeof(struct bpf_program), 0) < 0) {
1451             error("Couldn't set pass-filter in kernel: %m");
1452             ret = 0;
1453         }
1454     }
1455     if (active->bf_len > 0) {
1456         if (strioctl(pppfd, PPPIO_ACTIVEFILT, active,
1457                      sizeof(struct bpf_program), 0) < 0) {
1458             error("Couldn't set active-filter in kernel: %m");
1459             ret = 0;
1460         }
1461     }
1462     return ret;
1463 }
1464 #endif
1465
1466 /*
1467  * ccp_fatal_error - returns 1 if decompression was disabled as a
1468  * result of an error detected after decompression of a packet,
1469  * 0 otherwise.  This is necessary because of patent nonsense.
1470  */
1471 int
1472 ccp_fatal_error(unit)
1473     int unit;
1474 {
1475     int cf[2];
1476
1477     cf[0] = cf[1] = 0;
1478     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
1479         if (errno != ENXIO && errno != EINVAL)
1480             error("Couldn't get compression flags: %m");
1481         return 0;
1482     }
1483     return cf[0] & CCP_FATALERROR;
1484 }
1485
1486 /*
1487  * sifvjcomp - config tcp header compression
1488  */
1489 int
1490 sifvjcomp(u, vjcomp, xcidcomp, xmaxcid)
1491     int u, vjcomp, xcidcomp, xmaxcid;
1492 {
1493     int cf[2];
1494     char maxcid[2];
1495
1496     if (vjcomp) {
1497         maxcid[0] = xcidcomp;
1498         maxcid[1] = 15;         /* XXX should be rmaxcid */
1499         if (strioctl(pppfd, PPPIO_VJINIT, maxcid, sizeof(maxcid), 0) < 0) {
1500             error("Couldn't initialize VJ compression: %m");
1501         }
1502     }
1503
1504     cf[0] = (vjcomp? COMP_VJC + DECOMP_VJC: 0)  /* XXX this is wrong */
1505         + (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0);
1506     cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID;
1507     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
1508         if (vjcomp)
1509             error("Couldn't enable VJ compression: %m");
1510     }
1511
1512     return 1;
1513 }
1514
1515 /*
1516  * sifup - Config the interface up and enable IP packets to pass.
1517  */
1518 int
1519 sifup(u)
1520     int u;
1521 {
1522     struct ifreq ifr;
1523
1524     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1525     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
1526         error("Couldn't mark interface up (get): %m");
1527         return 0;
1528     }
1529     ifr.ifr_flags |= IFF_UP;
1530     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
1531         error("Couldn't mark interface up (set): %m");
1532         return 0;
1533     }
1534     if_is_up = 1;
1535     return 1;
1536 }
1537
1538 /*
1539  * sifdown - Config the interface down and disable IP.
1540  */
1541 int
1542 sifdown(u)
1543     int u;
1544 {
1545     struct ifreq ifr;
1546
1547     if (ipmuxid < 0)
1548         return 1;
1549     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1550     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
1551         error("Couldn't mark interface down (get): %m");
1552         return 0;
1553     }
1554     ifr.ifr_flags &= ~IFF_UP;
1555     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
1556         error("Couldn't mark interface down (set): %m");
1557         return 0;
1558     }
1559     if_is_up = 0;
1560     return 1;
1561 }
1562
1563 /*
1564  * sifnpmode - Set the mode for handling packets for a given NP.
1565  */
1566 int
1567 sifnpmode(u, proto, mode)
1568     int u;
1569     int proto;
1570     enum NPmode mode;
1571 {
1572     int npi[2];
1573
1574     npi[0] = proto;
1575     npi[1] = (int) mode;
1576     if (strioctl(pppfd, PPPIO_NPMODE, &npi, 2 * sizeof(int), 0) < 0) {
1577         error("ioctl(set NP %d mode to %d): %m", proto, mode);
1578         return 0;
1579     }
1580     return 1;
1581 }
1582
1583 #if defined(SOL2) && defined(INET6)
1584 /*
1585  * sif6up - Config the IPv6 interface up and enable IPv6 packets to pass.
1586  */
1587 int
1588 sif6up(u)
1589     int u;
1590 {
1591     struct lifreq lifr;
1592     int fd;
1593
1594     fd = socket(AF_INET6, SOCK_DGRAM, 0);
1595     if (fd < 0) {
1596         return 0;
1597     }
1598
1599     memset(&lifr, 0, sizeof(lifr));
1600     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1601     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
1602         close(fd);
1603         return 0;
1604     }
1605
1606     lifr.lifr_flags |= IFF_UP;
1607     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1608     if (ioctl(fd, SIOCSLIFFLAGS, &lifr) < 0) {
1609         close(fd);
1610         return 0;
1611     }
1612
1613     if6_is_up = 1;
1614     close(fd);
1615     return 1;
1616 }
1617
1618 /*
1619  * sifdown - Config the IPv6 interface down and disable IPv6.
1620  */
1621 int
1622 sif6down(u)
1623     int u;
1624 {
1625     struct lifreq lifr;
1626     int fd;
1627
1628     fd = socket(AF_INET6, SOCK_DGRAM, 0);
1629     if (fd < 0)
1630         return 0;
1631
1632     memset(&lifr, 0, sizeof(lifr));
1633     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1634     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
1635         close(fd);
1636         return 0;
1637     }
1638
1639     lifr.lifr_flags &= ~IFF_UP;
1640     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1641     if (ioctl(fd, SIOCGLIFFLAGS, &lifr) < 0) {
1642         close(fd);
1643         return 0;
1644     }
1645
1646     if6_is_up = 0;
1647     close(fd);
1648     return 1;
1649 }
1650
1651 /*
1652  * sif6addr - Config the interface with an IPv6 link-local address
1653  */
1654 int
1655 sif6addr(u, o, h)
1656     int u;
1657     eui64_t o, h;
1658 {
1659     struct lifreq lifr;
1660     struct sockaddr_storage laddr;
1661     struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&laddr;
1662     int fd;
1663
1664     fd = socket(AF_INET6, SOCK_DGRAM, 0);
1665     if (fd < 0)
1666         return 0;
1667
1668     memset(&lifr, 0, sizeof(lifr));
1669     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1670
1671     /*
1672      * Do this because /dev/ppp responds to DL_PHYS_ADDR_REQ with
1673      * zero values, hence the interface token came to be zero too,
1674      * and without this, in.ndpd will complain
1675      */
1676     IN6_LLTOKEN_FROM_EUI64(lifr, sin6, o);
1677     if (ioctl(fd, SIOCSLIFTOKEN, &lifr) < 0) {
1678         close(fd);
1679         return 0;
1680     }
1681
1682     /*
1683      * Set the interface address and destination address
1684      */
1685     IN6_LLADDR_FROM_EUI64(lifr, sin6, o);
1686     if (ioctl(fd, SIOCSLIFADDR, &lifr) < 0) {
1687         close(fd);
1688         return 0;
1689     }
1690
1691     memset(&lifr, 0, sizeof(lifr));
1692     strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
1693     IN6_LLADDR_FROM_EUI64(lifr, sin6, h);
1694     if (ioctl(fd, SIOCSLIFDSTADDR, &lifr) < 0) {
1695         close(fd);
1696         return 0;
1697     }
1698
1699     return 1;
1700 }
1701
1702 /*
1703  * cif6addr - Remove the IPv6 address from interface
1704  */
1705 int
1706 cif6addr(u, o, h)
1707     int u;
1708     eui64_t o, h;
1709 {
1710     return 1;
1711 }
1712
1713 #endif /* defined(SOL2) && defined(INET6) */
1714
1715
1716 #define INET_ADDR(x)    (((struct sockaddr_in *) &(x))->sin_addr.s_addr)
1717
1718 /*
1719  * sifaddr - Config the interface IP addresses and netmask.
1720  */
1721 int
1722 sifaddr(u, o, h, m)
1723     int u;
1724     u_int32_t o, h, m;
1725 {
1726     struct ifreq ifr;
1727     int ret = 1;
1728
1729     memset(&ifr, 0, sizeof(ifr));
1730     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1731     ifr.ifr_addr.sa_family = AF_INET;
1732     INET_ADDR(ifr.ifr_addr) = m;
1733     if (ioctl(ipfd, SIOCSIFNETMASK, &ifr) < 0) {
1734         error("Couldn't set IP netmask: %m");
1735         ret = 0;
1736     }
1737     ifr.ifr_addr.sa_family = AF_INET;
1738     INET_ADDR(ifr.ifr_addr) = o;
1739     if (ioctl(ipfd, SIOCSIFADDR, &ifr) < 0) {
1740         error("Couldn't set local IP address: %m");
1741         ret = 0;
1742     }
1743
1744     /*
1745      * On some systems, we have to explicitly set the point-to-point
1746      * flag bit before we can set a destination address.
1747      */
1748     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) >= 0
1749         && (ifr.ifr_flags & IFF_POINTOPOINT) == 0) {
1750         ifr.ifr_flags |= IFF_POINTOPOINT;
1751         if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
1752             error("Couldn't mark interface pt-to-pt: %m");
1753             ret = 0;
1754         }
1755     }
1756     ifr.ifr_dstaddr.sa_family = AF_INET;
1757     INET_ADDR(ifr.ifr_dstaddr) = h;
1758     if (ioctl(ipfd, SIOCSIFDSTADDR, &ifr) < 0) {
1759         error("Couldn't set remote IP address: %m");
1760         ret = 0;
1761     }
1762 #if 0   /* now done in ppp_send_config */
1763     ifr.ifr_metric = link_mtu;
1764     if (ioctl(ipfd, SIOCSIFMTU, &ifr) < 0) {
1765         error("Couldn't set IP MTU: %m");
1766     }
1767 #endif
1768
1769     remote_addr = h;
1770     return ret;
1771 }
1772
1773 /*
1774  * cifaddr - Clear the interface IP addresses, and delete routes
1775  * through the interface if possible.
1776  */
1777 int
1778 cifaddr(u, o, h)
1779     int u;
1780     u_int32_t o, h;
1781 {
1782 #if defined(__USLC__)           /* was: #if 0 */
1783     cifroute(unit, ouraddr, hisaddr);
1784     if (ipmuxid >= 0) {
1785         notice("Removing ppp interface unit");
1786         if (ioctl(ipfd, I_UNLINK, ipmuxid) < 0) {
1787             error("Can't remove ppp interface unit: %m");
1788             return 0;
1789         }
1790         ipmuxid = -1;
1791     }
1792 #endif
1793     remote_addr = 0;
1794     return 1;
1795 }
1796
1797 /*
1798  * sifdefaultroute - assign a default route through the address given.
1799  */
1800 int
1801 sifdefaultroute(u, l, g)
1802     int u;
1803     u_int32_t l, g;
1804 {
1805     struct rtentry rt;
1806
1807 #if defined(__USLC__)
1808     g = l;                      /* use the local address as gateway */
1809 #endif
1810     memset(&rt, 0, sizeof(rt));
1811     rt.rt_dst.sa_family = AF_INET;
1812     INET_ADDR(rt.rt_dst) = 0;
1813     rt.rt_gateway.sa_family = AF_INET;
1814     INET_ADDR(rt.rt_gateway) = g;
1815     rt.rt_flags = RTF_GATEWAY;
1816
1817     if (ioctl(ipfd, SIOCADDRT, &rt) < 0) {
1818         error("Can't add default route: %m");
1819         return 0;
1820     }
1821
1822     default_route_gateway = g;
1823     return 1;
1824 }
1825
1826 /*
1827  * cifdefaultroute - delete a default route through the address given.
1828  */
1829 int
1830 cifdefaultroute(u, l, g)
1831     int u;
1832     u_int32_t l, g;
1833 {
1834     struct rtentry rt;
1835
1836 #if defined(__USLC__)
1837     g = l;                      /* use the local address as gateway */
1838 #endif
1839     memset(&rt, 0, sizeof(rt));
1840     rt.rt_dst.sa_family = AF_INET;
1841     INET_ADDR(rt.rt_dst) = 0;
1842     rt.rt_gateway.sa_family = AF_INET;
1843     INET_ADDR(rt.rt_gateway) = g;
1844     rt.rt_flags = RTF_GATEWAY;
1845
1846     if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
1847         error("Can't delete default route: %m");
1848         return 0;
1849     }
1850
1851     default_route_gateway = 0;
1852     return 1;
1853 }
1854
1855 /*
1856  * sifproxyarp - Make a proxy ARP entry for the peer.
1857  */
1858 int
1859 sifproxyarp(unit, hisaddr)
1860     int unit;
1861     u_int32_t hisaddr;
1862 {
1863     struct arpreq arpreq;
1864
1865     memset(&arpreq, 0, sizeof(arpreq));
1866     if (!get_ether_addr(hisaddr, &arpreq.arp_ha))
1867         return 0;
1868
1869     arpreq.arp_pa.sa_family = AF_INET;
1870     INET_ADDR(arpreq.arp_pa) = hisaddr;
1871     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1872     if (ioctl(ipfd, SIOCSARP, (caddr_t) &arpreq) < 0) {
1873         error("Couldn't set proxy ARP entry: %m");
1874         return 0;
1875     }
1876
1877     proxy_arp_addr = hisaddr;
1878     return 1;
1879 }
1880
1881 /*
1882  * cifproxyarp - Delete the proxy ARP entry for the peer.
1883  */
1884 int
1885 cifproxyarp(unit, hisaddr)
1886     int unit;
1887     u_int32_t hisaddr;
1888 {
1889     struct arpreq arpreq;
1890
1891     memset(&arpreq, 0, sizeof(arpreq));
1892     arpreq.arp_pa.sa_family = AF_INET;
1893     INET_ADDR(arpreq.arp_pa) = hisaddr;
1894     if (ioctl(ipfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1895         error("Couldn't delete proxy ARP entry: %m");
1896         return 0;
1897     }
1898
1899     proxy_arp_addr = 0;
1900     return 1;
1901 }
1902
1903 /*
1904  * get_ether_addr - get the hardware address of an interface on the
1905  * the same subnet as ipaddr.
1906  */
1907 #define MAX_IFS         32
1908
1909 static int
1910 get_ether_addr(ipaddr, hwaddr)
1911     u_int32_t ipaddr;
1912     struct sockaddr *hwaddr;
1913 {
1914     struct ifreq *ifr, *ifend, ifreq;
1915     int nif;
1916     struct ifconf ifc;
1917     u_int32_t ina, mask;
1918
1919     /*
1920      * Scan through the system's network interfaces.
1921      */
1922 #ifdef SIOCGIFNUM
1923     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
1924 #endif
1925         nif = MAX_IFS;
1926     ifc.ifc_len = nif * sizeof(struct ifreq);
1927     ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len);
1928     if (ifc.ifc_buf == 0)
1929         return 0;
1930     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
1931         warn("Couldn't get system interface list: %m");
1932         free(ifc.ifc_buf);
1933         return 0;
1934     }
1935     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1936     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
1937         if (ifr->ifr_addr.sa_family != AF_INET)
1938             continue;
1939         /*
1940          * Check that the interface is up, and not point-to-point or loopback.
1941          */
1942         strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1943         if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
1944             continue;
1945         if ((ifreq.ifr_flags &
1946              (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1947             != (IFF_UP|IFF_BROADCAST))
1948             continue;
1949         /*
1950          * Get its netmask and check that it's on the right subnet.
1951          */
1952         if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
1953             continue;
1954         ina = INET_ADDR(ifr->ifr_addr);
1955         mask = INET_ADDR(ifreq.ifr_addr);
1956         if ((ipaddr & mask) == (ina & mask))
1957             break;
1958     }
1959
1960     if (ifr >= ifend) {
1961         warn("No suitable interface found for proxy ARP");
1962         free(ifc.ifc_buf);
1963         return 0;
1964     }
1965
1966     info("found interface %s for proxy ARP", ifr->ifr_name);
1967     if (!get_hw_addr(ifr->ifr_name, ina, hwaddr)) {
1968         error("Couldn't get hardware address for %s", ifr->ifr_name);
1969         free(ifc.ifc_buf);
1970         return 0;
1971     }
1972
1973     free(ifc.ifc_buf);
1974     return 1;
1975 }
1976
1977 /*
1978  * get_hw_addr_dlpi - obtain the hardware address using DLPI
1979  */
1980 static int
1981 get_hw_addr_dlpi(name, hwaddr)
1982     char *name;
1983     struct sockaddr *hwaddr;
1984 {
1985     char *p, *q;
1986     int unit, iffd, adrlen;
1987     unsigned char *adrp;
1988     char ifdev[24];
1989     struct {
1990         union DL_primitives prim;
1991         char space[64];
1992     } reply;
1993
1994     /*
1995      * We have to open the device and ask it for its hardware address.
1996      * First split apart the device name and unit.
1997      */
1998     slprintf(ifdev, sizeof(ifdev), "/dev/%s", name);
1999     for (q = ifdev + strlen(ifdev); --q >= ifdev; )
2000         if (!isdigit(*q))
2001             break;
2002     unit = atoi(q+1);
2003     q[1] = 0;
2004
2005     /*
2006      * Open the device and do a DLPI attach and phys_addr_req.
2007      */
2008     iffd = open(ifdev, O_RDWR);
2009     if (iffd < 0) {
2010         error("Can't open %s: %m", ifdev);
2011         return 0;
2012     }
2013     if (dlpi_attach(iffd, unit) < 0
2014         || dlpi_get_reply(iffd, &reply.prim, DL_OK_ACK, sizeof(reply)) < 0
2015         || dlpi_info_req(iffd) < 0
2016         || dlpi_get_reply(iffd, &reply.prim, DL_INFO_ACK, sizeof(reply)) < 0) {
2017         close(iffd);
2018         return 0;
2019     }
2020
2021     adrlen = reply.prim.info_ack.dl_addr_length;
2022     adrp = (unsigned char *)&reply + reply.prim.info_ack.dl_addr_offset;
2023
2024 #if DL_CURRENT_VERSION >= 2
2025     if (reply.prim.info_ack.dl_sap_length < 0)
2026         adrlen += reply.prim.info_ack.dl_sap_length;
2027     else
2028         adrp += reply.prim.info_ack.dl_sap_length;
2029 #endif
2030
2031     hwaddr->sa_family = AF_UNSPEC;
2032     memcpy(hwaddr->sa_data, adrp, adrlen);
2033
2034     return 1;
2035 }
2036 /*
2037  * get_hw_addr - obtain the hardware address for a named interface.
2038  */
2039 static int
2040 get_hw_addr(name, ina, hwaddr)
2041     char *name;
2042     u_int32_t ina;
2043     struct sockaddr *hwaddr;
2044 {
2045     /* New way - get the address by doing an arp request. */
2046     int s;
2047     struct arpreq req;
2048
2049     s = socket(AF_INET, SOCK_DGRAM, 0);
2050     if (s < 0)
2051         return 0;
2052     memset(&req, 0, sizeof(req));
2053     req.arp_pa.sa_family = AF_INET;
2054     INET_ADDR(req.arp_pa) = ina;
2055     if (ioctl(s, SIOCGARP, &req) < 0) {
2056         error("Couldn't get ARP entry for %s: %m", ip_ntoa(ina));
2057         return 0;
2058     }
2059     *hwaddr = req.arp_ha;
2060     hwaddr->sa_family = AF_UNSPEC;
2061
2062     return 1;
2063 }
2064
2065 static int
2066 dlpi_attach(fd, ppa)
2067     int fd, ppa;
2068 {
2069     dl_attach_req_t req;
2070     struct strbuf buf;
2071
2072     req.dl_primitive = DL_ATTACH_REQ;
2073     req.dl_ppa = ppa;
2074     buf.len = sizeof(req);
2075     buf.buf = (void *) &req;
2076     return putmsg(fd, &buf, NULL, RS_HIPRI);
2077 }
2078
2079 static int
2080 dlpi_info_req(fd)
2081     int fd;
2082 {
2083     dl_info_req_t req;
2084     struct strbuf buf;
2085
2086     req.dl_primitive = DL_INFO_REQ;
2087     buf.len = sizeof(req);
2088     buf.buf = (void *) &req;
2089     return putmsg(fd, &buf, NULL, RS_HIPRI);
2090 }
2091
2092 static int
2093 dlpi_get_reply(fd, reply, expected_prim, maxlen)
2094     union DL_primitives *reply;
2095     int fd, expected_prim, maxlen;
2096 {
2097     struct strbuf buf;
2098     int flags, n;
2099     struct pollfd pfd;
2100
2101     /*
2102      * Use poll to wait for a message with a timeout.
2103      */
2104     pfd.fd = fd;
2105     pfd.events = POLLIN | POLLPRI;
2106     do {
2107         n = poll(&pfd, 1, 1000);
2108     } while (n == -1 && errno == EINTR);
2109     if (n <= 0)
2110         return -1;
2111
2112     /*
2113      * Get the reply.
2114      */
2115     buf.maxlen = maxlen;
2116     buf.buf = (void *) reply;
2117     flags = 0;
2118     if (getmsg(fd, &buf, NULL, &flags) < 0)
2119         return -1;
2120
2121     if (buf.len < sizeof(ulong)) {
2122         if (debug)
2123             dbglog("dlpi response short (len=%d)\n", buf.len);
2124         return -1;
2125     }
2126
2127     if (reply->dl_primitive == expected_prim)
2128         return 0;
2129
2130     if (debug) {
2131         if (reply->dl_primitive == DL_ERROR_ACK) {
2132             dbglog("dlpi error %d (unix errno %d) for prim %x\n",
2133                    reply->error_ack.dl_errno, reply->error_ack.dl_unix_errno,
2134                    reply->error_ack.dl_error_primitive);
2135         } else {
2136             dbglog("dlpi unexpected response prim %x\n",
2137                    reply->dl_primitive);
2138         }
2139     }
2140
2141     return -1;
2142 }
2143
2144 /*
2145  * Return user specified netmask, modified by any mask we might determine
2146  * for address `addr' (in network byte order).
2147  * Here we scan through the system's list of interfaces, looking for
2148  * any non-point-to-point interfaces which might appear to be on the same
2149  * network as `addr'.  If we find any, we OR in their netmask to the
2150  * user-specified netmask.
2151  */
2152 u_int32_t
2153 GetMask(addr)
2154     u_int32_t addr;
2155 {
2156     u_int32_t mask, nmask, ina;
2157     struct ifreq *ifr, *ifend, ifreq;
2158     int nif;
2159     struct ifconf ifc;
2160
2161     addr = ntohl(addr);
2162     if (IN_CLASSA(addr))        /* determine network mask for address class */
2163         nmask = IN_CLASSA_NET;
2164     else if (IN_CLASSB(addr))
2165         nmask = IN_CLASSB_NET;
2166     else
2167         nmask = IN_CLASSC_NET;
2168     /* class D nets are disallowed by bad_ip_adrs */
2169     mask = netmask | htonl(nmask);
2170
2171     /*
2172      * Scan through the system's network interfaces.
2173      */
2174 #ifdef SIOCGIFNUM
2175     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
2176 #endif
2177         nif = MAX_IFS;
2178     ifc.ifc_len = nif * sizeof(struct ifreq);
2179     ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len);
2180     if (ifc.ifc_buf == 0)
2181         return mask;
2182     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
2183         warn("Couldn't get system interface list: %m");
2184         free(ifc.ifc_buf);
2185         return mask;
2186     }
2187     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
2188     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
2189         /*
2190          * Check the interface's internet address.
2191          */
2192         if (ifr->ifr_addr.sa_family != AF_INET)
2193             continue;
2194         ina = INET_ADDR(ifr->ifr_addr);
2195         if ((ntohl(ina) & nmask) != (addr & nmask))
2196             continue;
2197         /*
2198          * Check that the interface is up, and not point-to-point or loopback.
2199          */
2200         strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
2201         if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
2202             continue;
2203         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
2204             != IFF_UP)
2205             continue;
2206         /*
2207          * Get its netmask and OR it into our mask.
2208          */
2209         if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
2210             continue;
2211         mask |= INET_ADDR(ifreq.ifr_addr);
2212     }
2213
2214     free(ifc.ifc_buf);
2215     return mask;
2216 }
2217
2218 /*
2219  * logwtmp - write an accounting record to the /var/adm/wtmp file.
2220  */
2221 void
2222 logwtmp(line, name, host)
2223     const char *line, *name, *host;
2224 {
2225     static struct utmpx utmpx;
2226
2227     if (name[0] != 0) {
2228         /* logging in */
2229         strncpy(utmpx.ut_user, name, sizeof(utmpx.ut_user));
2230         strncpy(utmpx.ut_id, ifname, sizeof(utmpx.ut_id));
2231         strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line));
2232         utmpx.ut_pid = getpid();
2233         utmpx.ut_type = USER_PROCESS;
2234     } else {
2235         utmpx.ut_type = DEAD_PROCESS;
2236     }
2237     gettimeofday(&utmpx.ut_tv, NULL);
2238     updwtmpx("/var/adm/wtmpx", &utmpx);
2239 }
2240
2241 /*
2242  * get_host_seed - return the serial number of this machine.
2243  */
2244 int
2245 get_host_seed()
2246 {
2247     char buf[32];
2248
2249     if (sysinfo(SI_HW_SERIAL, buf, sizeof(buf)) < 0) {
2250         error("sysinfo: %m");
2251         return 0;
2252     }
2253     return (int) strtoul(buf, NULL, 16);
2254 }
2255
2256 static int
2257 strioctl(fd, cmd, ptr, ilen, olen)
2258     int fd, cmd, ilen, olen;
2259     void *ptr;
2260 {
2261     struct strioctl str;
2262
2263     str.ic_cmd = cmd;
2264     str.ic_timout = 0;
2265     str.ic_len = ilen;
2266     str.ic_dp = ptr;
2267     if (ioctl(fd, I_STR, &str) == -1)
2268         return -1;
2269     if (str.ic_len != olen)
2270         dbglog("strioctl: expected %d bytes, got %d for cmd %x\n",
2271                olen, str.ic_len, cmd);
2272     return 0;
2273 }
2274
2275 #if 0
2276 /*
2277  * lock - create a lock file for the named lock device
2278  */
2279
2280 #define LOCK_PREFIX     "/var/spool/locks/LK."
2281 static char lock_file[40];      /* name of lock file created */
2282
2283 int
2284 lock(dev)
2285     char *dev;
2286 {
2287     int n, fd, pid;
2288     struct stat sbuf;
2289     char ascii_pid[12];
2290
2291     if (stat(dev, &sbuf) < 0) {
2292         error("Can't get device number for %s: %m", dev);
2293         return -1;
2294     }
2295     if ((sbuf.st_mode & S_IFMT) != S_IFCHR) {
2296         error("Can't lock %s: not a character device", dev);
2297         return -1;
2298     }
2299     slprintf(lock_file, sizeof(lock_file), "%s%03d.%03d.%03d",
2300              LOCK_PREFIX, major(sbuf.st_dev),
2301              major(sbuf.st_rdev), minor(sbuf.st_rdev));
2302
2303     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
2304         if (errno == EEXIST
2305             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
2306             /* Read the lock file to find out who has the device locked */
2307             n = read(fd, ascii_pid, 11);
2308             if (n <= 0) {
2309                 error("Can't read pid from lock file %s", lock_file);
2310                 close(fd);
2311             } else {
2312                 ascii_pid[n] = 0;
2313                 pid = atoi(ascii_pid);
2314                 if (pid > 0 && kill(pid, 0) == -1 && errno == ESRCH) {
2315                     /* pid no longer exists - remove the lock file */
2316                     if (unlink(lock_file) == 0) {
2317                         close(fd);
2318                         notice("Removed stale lock on %s (pid %d)",
2319                                dev, pid);
2320                         continue;
2321                     } else
2322                         warn("Couldn't remove stale lock on %s",
2323                                dev);
2324                 } else
2325                     notice("Device %s is locked by pid %d",
2326                            dev, pid);
2327             }
2328             close(fd);
2329         } else
2330             error("Can't create lock file %s: %m", lock_file);
2331         lock_file[0] = 0;
2332         return -1;
2333     }
2334
2335     slprintf(ascii_pid, sizeof(ascii_pid), "%10d\n", getpid());
2336     write(fd, ascii_pid, 11);
2337
2338     close(fd);
2339     return 1;
2340 }
2341
2342 /*
2343  * unlock - remove our lockfile
2344  */
2345 void
2346 unlock()
2347 {
2348     if (lock_file[0]) {
2349         unlink(lock_file);
2350         lock_file[0] = 0;
2351     }
2352 }
2353 #endif
2354
2355 /*
2356  * cifroute - delete a route through the addresses given.
2357  */
2358 int
2359 cifroute(u, our, his)
2360     int u;
2361     u_int32_t our, his;
2362 {
2363     struct rtentry rt;
2364
2365     memset(&rt, 0, sizeof(rt));
2366     rt.rt_dst.sa_family = AF_INET;
2367     INET_ADDR(rt.rt_dst) = his;
2368     rt.rt_gateway.sa_family = AF_INET;
2369     INET_ADDR(rt.rt_gateway) = our;
2370     rt.rt_flags = RTF_HOST;
2371
2372     if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
2373         error("Can't delete route: %m");
2374         return 0;
2375     }
2376
2377     return 1;
2378 }
2379
2380 /*
2381  * have_route_to - determine if the system has a route to the specified
2382  * IP address.  Returns 0 if not, 1 if so, -1 if we can't tell.
2383  * `addr' is in network byte order.
2384  * For demand mode to work properly, we have to ignore routes
2385  * through our own interface.
2386  */
2387 #ifndef T_CURRENT               /* needed for Solaris 2.5 */
2388 #define T_CURRENT       MI_T_CURRENT
2389 #endif
2390
2391 int
2392 have_route_to(addr)
2393     u_int32_t addr;
2394 {
2395 #ifdef SOL2
2396     int fd, r, flags, i;
2397     struct {
2398         struct T_optmgmt_req req;
2399         struct opthdr hdr;
2400     } req;
2401     union {
2402         struct T_optmgmt_ack ack;
2403         unsigned char space[64];
2404     } ack;
2405     struct opthdr *rh;
2406     struct strbuf cbuf, dbuf;
2407     int nroutes;
2408     mib2_ipRouteEntry_t routes[8];
2409     mib2_ipRouteEntry_t *rp;
2410
2411     fd = open(mux_dev_name, O_RDWR);
2412     if (fd < 0) {
2413         warn("have_route_to: couldn't open %s: %m", mux_dev_name);
2414         return -1;
2415     }
2416
2417     req.req.PRIM_type = T_OPTMGMT_REQ;
2418     req.req.OPT_offset = (char *) &req.hdr - (char *) &req;
2419     req.req.OPT_length = sizeof(req.hdr);
2420     req.req.MGMT_flags = T_CURRENT;
2421
2422     req.hdr.level = MIB2_IP;
2423     req.hdr.name = 0;
2424     req.hdr.len = 0;
2425
2426     cbuf.buf = (char *) &req;
2427     cbuf.len = sizeof(req);
2428
2429     if (putmsg(fd, &cbuf, NULL, 0) == -1) {
2430         warn("have_route_to: putmsg: %m");
2431         close(fd);
2432         return -1;
2433     }
2434
2435     for (;;) {
2436         cbuf.buf = (char *) &ack;
2437         cbuf.maxlen = sizeof(ack);
2438         dbuf.buf = (char *) routes;
2439         dbuf.maxlen = sizeof(routes);
2440         flags = 0;
2441         r = getmsg(fd, &cbuf, &dbuf, &flags);
2442         if (r == -1) {
2443             warn("have_route_to: getmsg: %m");
2444             close(fd);
2445             return -1;
2446         }
2447
2448         if (cbuf.len < sizeof(struct T_optmgmt_ack)
2449             || ack.ack.PRIM_type != T_OPTMGMT_ACK
2450             || ack.ack.MGMT_flags != T_SUCCESS
2451             || ack.ack.OPT_length < sizeof(struct opthdr)) {
2452             dbglog("have_route_to: bad message len=%d prim=%d",
2453                    cbuf.len, ack.ack.PRIM_type);
2454             close(fd);
2455             return -1;
2456         }
2457
2458         rh = (struct opthdr *) ((char *)&ack + ack.ack.OPT_offset);
2459         if (rh->level == 0 && rh->name == 0)
2460             break;
2461         if (rh->level != MIB2_IP || rh->name != MIB2_IP_21) {
2462             while (r == MOREDATA)
2463                 r = getmsg(fd, NULL, &dbuf, &flags);
2464             continue;
2465         }
2466
2467         for (;;) {
2468             nroutes = dbuf.len / sizeof(mib2_ipRouteEntry_t);
2469             for (rp = routes, i = 0; i < nroutes; ++i, ++rp) {
2470                 if (rp->ipRouteMask != ~0) {
2471                     dbglog("have_route_to: dest=%x gw=%x mask=%x\n",
2472                            rp->ipRouteDest, rp->ipRouteNextHop,
2473                            rp->ipRouteMask);
2474                     if (((addr ^ rp->ipRouteDest) & rp->ipRouteMask) == 0
2475                         && rp->ipRouteNextHop != remote_addr)
2476                         return 1;
2477                 }
2478             }
2479             if (r == 0)
2480                 break;
2481             r = getmsg(fd, NULL, &dbuf, &flags);
2482         }
2483     }
2484     close(fd);
2485     return 0;
2486 #else
2487     return -1;
2488 #endif /* SOL2 */
2489 }
2490
2491 /*
2492  * get_pty - get a pty master/slave pair and chown the slave side to
2493  * the uid given.  Assumes slave_name points to MAXPATHLEN bytes of space.
2494  */
2495 int
2496 get_pty(master_fdp, slave_fdp, slave_name, uid)
2497     int *master_fdp;
2498     int *slave_fdp;
2499     char *slave_name;
2500     int uid;
2501 {
2502     int mfd, sfd;
2503     char *pty_name;
2504     struct termios tios;
2505
2506     mfd = open("/dev/ptmx", O_RDWR);
2507     if (mfd < 0) {
2508         error("Couldn't open pty master: %m");
2509         return 0;
2510     }
2511
2512     pty_name = ptsname(mfd);
2513     if (pty_name == NULL) {
2514         error("Couldn't get name of pty slave");
2515         close(mfd);
2516         return 0;
2517     }
2518     if (chown(pty_name, uid, -1) < 0)
2519         warn("Couldn't change owner of pty slave: %m");
2520     if (chmod(pty_name, S_IRUSR | S_IWUSR) < 0)
2521         warn("Couldn't change permissions on pty slave: %m");
2522     if (unlockpt(mfd) < 0)
2523         warn("Couldn't unlock pty slave: %m");
2524
2525     sfd = open(pty_name, O_RDWR);
2526     if (sfd < 0) {
2527         error("Couldn't open pty slave %s: %m", pty_name);
2528         close(mfd);
2529         return 0;
2530     }
2531     if (ioctl(sfd, I_PUSH, "ptem") < 0)
2532         warn("Couldn't push ptem module on pty slave: %m");
2533
2534     dbglog("Using %s", pty_name);
2535     strlcpy(slave_name, pty_name, MAXPATHLEN);
2536     *master_fdp = mfd;
2537     *slave_fdp = sfd;
2538
2539     return 1;
2540 }