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