]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-svr4.c
68e38cda5d757ab8b2d2f46d97da39e9ae8036f8
[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 #ifndef lint
29 static char rcsid[] = "$Id: sys-svr4.c,v 1.2 1995/06/01 01:31:28 paulus Exp $";
30 #endif
31
32 #include <stdio.h>
33 #include <stddef.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39 #include <termios.h>
40 #include <sys/types.h>
41 #include <sys/ioccom.h>
42 #include <sys/stream.h>
43 #include <sys/stropts.h>
44 #include <sys/socket.h>
45 #include <sys/sockio.h>
46 #include <sys/syslog.h>
47 #include <sys/systeminfo.h>
48 #include <sys/dlpi.h>
49 #include <sys/stat.h>
50 #include <net/if.h>
51 #include <net/if_arp.h>
52 #include <net/route.h>
53 #include <net/ppp_defs.h>
54 #include <net/pppio.h>
55 #include <netinet/in.h>
56
57 #include "pppd.h"
58
59 static int      pppfd;
60 static int      fdmuxid = -1;
61 static int      ipfd;
62 static int      ipmuxid = -1;
63
64 static int      restore_term;
65 static struct termios inittermios;
66
67 static int      link_mtu, link_mru;
68
69 #define NMODULES        32
70 static int      tty_nmodules;
71 static char     tty_modules[NMODULES][FMNAMESZ+1];
72
73 /*
74  * sys_init - System-dependent initialization.
75  */
76 void
77 sys_init()
78 {
79     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
80     setlogmask(LOG_UPTO(LOG_INFO));
81     if (debug)
82         setlogmask(LOG_UPTO(LOG_DEBUG));
83
84     ipfd = open("/dev/ip", O_RDWR, 0);
85     if (ipfd < 0) {
86         syslog(LOG_ERR, "Couldn't open IP device: %m");
87         die(1);
88     }
89 }
90
91 /*
92  * daemon - Detach us from controlling terminal session.
93  */
94 int
95 daemon(nochdir, noclose)
96     int nochdir, noclose;
97 {
98     int pid;
99
100     if ((pid = fork()) < 0)
101         return -1;
102     if (pid != 0)
103         exit(0);                /* parent dies */
104     setsid();
105     if (!nochdir)
106         chdir("/");
107     if (!noclose) {
108         fclose(stdin);          /* don't need stdin, stdout, stderr */
109         fclose(stdout);
110         fclose(stderr);
111     }
112     return 0;
113 }
114
115 /*
116  * note_debug_level - note a change in the debug level.
117  */
118 void
119 note_debug_level()
120 {
121     if (debug) {
122         syslog(LOG_INFO, "Debug turned ON, Level %d", debug);
123         setlogmask(LOG_UPTO(LOG_DEBUG));
124     } else {
125         setlogmask(LOG_UPTO(LOG_WARNING));
126     }
127 }
128
129 /*
130  * ppp_available - check whether the system has any ppp interfaces
131  */
132 int
133 ppp_available()
134 {
135     struct stat buf;
136
137     return stat("/dev/ppp", &buf) >= 0;
138 }
139
140 /*
141  * establish_ppp - Turn the serial port into a ppp interface.
142  */
143 void
144 establish_ppp()
145 {
146     int i;
147
148     pppfd = open("/dev/ppp", O_RDWR | O_NONBLOCK, 0);
149     if (pppfd < 0) {
150         syslog(LOG_ERR, "Can't open /dev/ppp: %m");
151         die(1);
152     }
153
154     /* Assign a new PPA and get its unit number. */
155     if (strioctl(pppfd, PPPIO_NEWPPA, &ifunit, 0, sizeof(int)) < 0) {
156         syslog(LOG_ERR, "Can't create new PPP interface: %m");
157         die(1);
158     }
159
160     /* Pop any existing modules off the tty stream. */
161     for (i = 0;; ++i)
162         if (ioctl(fd, I_LOOK, tty_modules[i]) < 0
163             || ioctl(fd, I_POP, 0) < 0)
164             break;
165     tty_nmodules = i;
166
167     /* Push the async hdlc module and the compressor module. */
168     if (ioctl(fd, I_PUSH, "ppp_ahdl") < 0) {
169         syslog(LOG_ERR, "Couldn't push PPP Async HDLC module: %m");
170         die(1);
171     }
172     if (ioctl(fd, I_PUSH, "ppp_comp") < 0) {
173         syslog(LOG_ERR, "Couldn't push PPP compression module: %m");
174 /*      die(1); */
175     }
176
177     /* Link the serial port under the PPP multiplexor. */
178     if ((fdmuxid = ioctl(pppfd, I_LINK, fd)) < 0) {
179         syslog(LOG_ERR, "Can't link tty to PPP mux: %m");
180         die(1);
181     }
182 }
183
184 /*
185  * disestablish_ppp - Restore the serial port to normal operation.
186  * This shouldn't call die() because it's called from die().
187  */
188 void
189 disestablish_ppp()
190 {
191     int i;
192
193     if (fdmuxid >= 0) {
194         if (ioctl(pppfd, I_UNLINK, fdmuxid) < 0) {
195             if (!hungup)
196                 syslog(LOG_ERR, "Can't unlink tty from PPP mux: %m");
197         }
198         fdmuxid = -1;
199
200         if (!hungup) {
201             while (ioctl(fd, I_POP, 0) >= 0)
202                 ;
203             for (i = tty_nmodules - 1; i >= 0; --i)
204                 if (ioctl(fd, I_PUSH, tty_modules[i]) < 0)
205                     syslog(LOG_ERR, "Couldn't restore tty module %s: %m",
206                            tty_modules[i]);
207         }
208     }
209 }
210
211 /*
212  * List of valid speeds.
213  */
214 struct speed {
215     int speed_int, speed_val;
216 } speeds[] = {
217 #ifdef B50
218     { 50, B50 },
219 #endif
220 #ifdef B75
221     { 75, B75 },
222 #endif
223 #ifdef B110
224     { 110, B110 },
225 #endif
226 #ifdef B134
227     { 134, B134 },
228 #endif
229 #ifdef B150
230     { 150, B150 },
231 #endif
232 #ifdef B200
233     { 200, B200 },
234 #endif
235 #ifdef B300
236     { 300, B300 },
237 #endif
238 #ifdef B600
239     { 600, B600 },
240 #endif
241 #ifdef B1200
242     { 1200, B1200 },
243 #endif
244 #ifdef B1800
245     { 1800, B1800 },
246 #endif
247 #ifdef B2000
248     { 2000, B2000 },
249 #endif
250 #ifdef B2400
251     { 2400, B2400 },
252 #endif
253 #ifdef B3600
254     { 3600, B3600 },
255 #endif
256 #ifdef B4800
257     { 4800, B4800 },
258 #endif
259 #ifdef B7200
260     { 7200, B7200 },
261 #endif
262 #ifdef B9600
263     { 9600, B9600 },
264 #endif
265 #ifdef B19200
266     { 19200, B19200 },
267 #endif
268 #ifdef B38400
269     { 38400, B38400 },
270 #endif
271 #ifdef EXTA
272     { 19200, EXTA },
273 #endif
274 #ifdef EXTB
275     { 38400, EXTB },
276 #endif
277 #ifdef B57600
278     { 57600, B57600 },
279 #endif
280 #ifdef B115200
281     { 115200, B115200 },
282 #endif
283     { 0, 0 }
284 };
285
286 /*
287  * Translate from bits/second to a speed_t.
288  */
289 int
290 translate_speed(bps)
291     int bps;
292 {
293     struct speed *speedp;
294
295     if (bps == 0)
296         return 0;
297     for (speedp = speeds; speedp->speed_int; speedp++)
298         if (bps == speedp->speed_int)
299             return speedp->speed_val;
300     syslog(LOG_WARNING, "speed %d not supported", bps);
301     return 0;
302 }
303
304 /*
305  * Translate from a speed_t to bits/second.
306  */
307 int
308 baud_rate_of(speed)
309     int speed;
310 {
311     struct speed *speedp;
312
313     if (speed == 0)
314         return 0;
315     for (speedp = speeds; speedp->speed_int; speedp++)
316         if (speed == speedp->speed_val)
317             return speedp->speed_int;
318     return 0;
319 }
320
321 /*
322  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
323  * at the requested speed, etc.  If `local' is true, set CLOCAL
324  * regardless of whether the modem option was specified.
325  */
326 set_up_tty(fd, local)
327     int fd, local;
328 {
329     int speed;
330     struct termios tios;
331
332     if (tcgetattr(fd, &tios) < 0) {
333         syslog(LOG_ERR, "tcgetattr: %m");
334         die(1);
335     }
336
337     if (!restore_term)
338         inittermios = tios;
339
340     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
341     if (crtscts > 0)
342         tios.c_cflag |= CRTSCTS;
343     else if (crtscts < 0)
344         tios.c_cflag &= ~CRTSCTS;
345
346     tios.c_cflag |= CS8 | CREAD | HUPCL;
347     if (local || !modem)
348         tios.c_cflag |= CLOCAL;
349     tios.c_iflag = IGNBRK | IGNPAR;
350     tios.c_oflag = 0;
351     tios.c_lflag = 0;
352     tios.c_cc[VMIN] = 1;
353     tios.c_cc[VTIME] = 0;
354
355     if (crtscts == 2) {
356         tios.c_iflag |= IXOFF;
357         tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
358         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
359     }
360
361     speed = translate_speed(inspeed);
362     if (speed) {
363         cfsetospeed(&tios, speed);
364         cfsetispeed(&tios, speed);
365     } else {
366         speed = cfgetospeed(&tios);
367         /*
368          * We can't proceed if the serial port speed is 0,
369          * since that implies that the serial port is disabled.
370          */
371         if (speed == B0) {
372             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
373                    devnam);
374             die(1);
375         }
376     }
377
378     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
379         syslog(LOG_ERR, "tcsetattr: %m");
380         die(1);
381     }
382
383     baud_rate = inspeed = baud_rate_of(speed);
384     restore_term = 1;
385 }
386
387 /*
388  * restore_tty - restore the terminal to the saved settings.
389  */
390 void
391 restore_tty()
392 {
393     if (restore_term) {
394         if (!default_device) {
395             /*
396              * Turn off echoing, because otherwise we can get into
397              * a loop with the tty and the modem echoing to each other.
398              * We presume we are the sole user of this tty device, so
399              * when we close it, it will revert to its defaults anyway.
400              */
401             inittermios.c_lflag &= ~(ECHO | ECHONL);
402         }
403         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
404             if (!hungup && errno != ENXIO)
405                 syslog(LOG_WARNING, "tcsetattr: %m");
406         restore_term = 0;
407     }
408 }
409
410 /*
411  * setdtr - control the DTR line on the serial port.
412  * This is called from die(), so it shouldn't call die().
413  */
414 setdtr(fd, on)
415 int fd, on;
416 {
417     int modembits = TIOCM_DTR;
418
419     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
420 }
421
422 /*
423  * output - Output PPP packet.
424  */
425 void
426 output(unit, p, len)
427     int unit;
428     u_char *p;
429     int len;
430 {
431     struct strbuf data;
432
433     if (debug)
434         log_packet(p, len, "sent ");
435
436     data.len = len;
437     data.buf = (caddr_t) p;
438     if (putmsg(pppfd, NULL, &data, 0) < 0) {
439         if (errno != ENXIO) {
440             syslog(LOG_ERR, "Couldn't send packet: %m");
441             die(1);
442         }
443     }
444 }
445
446 /*
447  * wait_input - wait until there is data available on fd,
448  * for the length of time specified by *timo (indefinite
449  * if timo is NULL).
450  */
451 wait_input(timo)
452     struct timeval *timo;
453 {
454     int t;
455     struct pollfd pfd;
456
457     t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000;
458     pfd.fd = pppfd;
459     pfd.events = POLLIN | POLLPRI | POLLHUP;
460     if (poll(&pfd, 1, t) < 0 && errno != EINTR) {
461         syslog(LOG_ERR, "poll: %m");
462         die(1);
463     }
464 }
465
466 /*
467  * read_packet - get a PPP packet from the serial device.
468  */
469 int
470 read_packet(buf)
471     u_char *buf;
472 {
473     struct strbuf ctrl, data;
474     int flags, len;
475     unsigned char ctrlbuf[sizeof(union DL_primitives) + 64];
476
477     for (;;) {
478         data.maxlen = PPP_MRU + PPP_HDRLEN;
479         data.buf = (caddr_t) buf;
480         ctrl.maxlen = sizeof(ctrlbuf);
481         ctrl.buf = (caddr_t) ctrlbuf;
482         flags = 0;
483         len = getmsg(pppfd, &ctrl, &data, &flags);
484         if (len < 0) {
485             if (errno = EAGAIN || errno == EINTR)
486                 return -1;
487             syslog(LOG_ERR, "Error reading packet: %m");
488             die(1);
489         }
490
491         if (ctrl.len <= 0)
492             return data.len;
493
494         /*
495          * Got a M_PROTO or M_PCPROTO message.  Interpret it
496          * as a DLPI primitive.
497          */
498         if (debug)
499             syslog(LOG_DEBUG, "got dlpi prim 0x%x, len=%d",
500                    ((union DL_primitives *)ctrlbuf)->dl_primitive, ctrl.len);
501
502     }
503 }
504
505 /*
506  * ppp_send_config - configure the transmit characteristics of
507  * the ppp interface.
508  */
509 void
510 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
511     int unit, mtu;
512     u_int32_t asyncmap;
513     int pcomp, accomp;
514 {
515     int cf[2];
516
517     link_mtu = mtu;
518     if (strioctl(pppfd, PPPIO_MTU, &mtu, sizeof(mtu), 0) < 0) {
519         if (hungup && errno == ENXIO)
520             return;
521         syslog(LOG_ERR, "Couldn't set MTU: %m");
522     }
523     if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
524         syslog(LOG_ERR, "Couldn't set transmit ACCM: %m");
525     }
526     cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0);
527     cf[1] = COMP_PROT | COMP_AC;
528     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
529         syslog(LOG_ERR, "Couldn't set prot/AC compression: %m");
530     }
531 }
532
533 /*
534  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
535  */
536 void
537 ppp_set_xaccm(unit, accm)
538     int unit;
539     ext_accm accm;
540 {
541     if (strioctl(pppfd, PPPIO_XACCM, accm, sizeof(ext_accm), 0) < 0) {
542         if (!hungup || errno != ENXIO)
543             syslog(LOG_WARNING, "Couldn't set extended ACCM: %m");
544     }
545 }
546
547 /*
548  * ppp_recv_config - configure the receive-side characteristics of
549  * the ppp interface.
550  */
551 void
552 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
553     int unit, mru;
554     u_int32_t asyncmap;
555     int pcomp, accomp;
556 {
557     int cf[2];
558
559     link_mru = mru;
560     if (strioctl(pppfd, PPPIO_MRU, &mru, sizeof(mru), 0) < 0) {
561         if (hungup && errno == ENXIO)
562             return;
563         syslog(LOG_ERR, "Couldn't set MRU: %m");
564     }
565     if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
566         syslog(LOG_ERR, "Couldn't set receive ACCM: %m");
567     }
568     cf[0] = (pcomp? DECOMP_PROT: 0) + (accomp? DECOMP_AC: 0);
569     cf[1] = DECOMP_PROT | DECOMP_AC;
570     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
571         syslog(LOG_ERR, "Couldn't set prot/AC decompression: %m");
572     }
573 }
574
575 /*
576  * ccp_test - ask kernel whether a given compression method
577  * is acceptable for use.
578  */
579 ccp_test(unit, opt_ptr, opt_len, for_transmit)
580     int unit, opt_len, for_transmit;
581     u_char *opt_ptr;
582 {
583     return strioctl(pppfd, (for_transmit? PPPIO_XCOMP: PPPIO_RCOMP),
584                     opt_ptr, opt_len, 0) >= 0;
585 }
586
587 /*
588  * ccp_flags_set - inform kernel about the current state of CCP.
589  */
590 void
591 ccp_flags_set(unit, isopen, isup)
592     int unit, isopen, isup;
593 {
594     int cf[2];
595
596     cf[0] = (isopen? CCP_ISOPEN: 0) + (isup? CCP_ISUP: 0);
597     cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR;
598     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
599         if (!hungup || errno != ENXIO)
600             syslog(LOG_ERR, "Couldn't set kernel CCP state: %m");
601     }
602 }
603
604 /*
605  * ccp_fatal_error - returns 1 if decompression was disabled as a
606  * result of an error detected after decompression of a packet,
607  * 0 otherwise.  This is necessary because of patent nonsense.
608  */
609 int
610 ccp_fatal_error(unit)
611     int unit;
612 {
613     int cf[2];
614
615     cf[0] = cf[1] = 0;
616     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
617         if (errno != ENXIO && errno != EINVAL)
618             syslog(LOG_ERR, "Couldn't get compression flags: %m");
619         return 0;
620     }
621     return cf[0] & CCP_FATALERROR;
622 }
623
624 /*
625  * sifvjcomp - config tcp header compression
626  */
627 int
628 sifvjcomp(u, vjcomp, xcidcomp, xmaxcid)
629     int u, vjcomp, xcidcomp, xmaxcid;
630 {
631     int cf[2];
632     char maxcid[2];
633
634     if (vjcomp) {
635         maxcid[0] = xcidcomp;
636         maxcid[1] = 15;         /* XXX should be rmaxcid */
637         if (strioctl(pppfd, PPPIO_VJINIT, maxcid, sizeof(maxcid), 0) < 0) {
638             syslog(LOG_ERR, "Couldn't initialize VJ compression: %m");
639         }
640     }
641
642     cf[0] = (vjcomp? COMP_VJC + DECOMP_VJC: 0)  /* XXX this is wrong */
643         + (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0);
644     cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID;
645     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
646         if (vjcomp)
647             syslog(LOG_ERR, "Couldn't enable VJ compression: %m");
648     }
649
650     return 1;
651 }
652
653 /*
654  * sifup - Config the interface up and enable IP packets to pass.
655  */
656 int
657 sifup(u)
658     int u;
659 {
660     struct ifreq ifr;
661
662     if (ipmuxid < 0) {
663         syslog(LOG_DEBUG, "sifup: not plumbed!");
664         return 0;
665     }
666     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
667     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
668         syslog(LOG_ERR, "Couldn't mark interface up (get): %m");
669         return 0;
670     }
671     ifr.ifr_flags |= IFF_UP;
672     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
673         syslog(LOG_ERR, "Couldn't mark interface up (set): %m");
674         return 0;
675     }
676     return 1;
677 }
678
679 /*
680  * sifdown - Config the interface down and disable IP.
681  */
682 int
683 sifdown(u)
684     int u;
685 {
686     struct ifreq ifr;
687
688     if (ipmuxid < 0)
689         return 1;
690     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
691     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
692         syslog(LOG_ERR, "Couldn't mark interface down (get): %m");
693         return 0;
694     }
695     ifr.ifr_flags &= ~IFF_UP;
696     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
697         syslog(LOG_ERR, "Couldn't mark interface down (set): %m");
698         return 0;
699     }
700     return 1;
701 }
702
703 #define INET_ADDR(x)    (((struct sockaddr_in *) &(x))->sin_addr.s_addr)
704
705 /*
706  * sifaddr - Config the interface IP addresses and netmask.
707  */
708 int
709 sifaddr(u, o, h, m)
710     int u;
711     u_int32_t o, h, m;
712 {
713     int fd;
714     struct ifreq ifr;
715
716     fd = open("/dev/ppp", O_RDWR, 0);
717     if (fd < 0) {
718         syslog(LOG_ERR, "Can't open /dev/ppp (2): %m");
719         die(1);
720     }
721     if (ioctl(fd, I_PUSH, "ip") < 0) {
722         syslog(LOG_ERR, "Can't push IP module: %m");
723         close(fd);
724         return 0;
725     }
726     ipmuxid = ioctl(ipfd, I_LINK, fd);
727     close(fd);
728     if (ipmuxid < 0) {
729         syslog(LOG_ERR, "Can't link PPP device to IP: %m");
730         return 0;
731     }
732
733     memset(&ifr, 0, sizeof(ifr));
734     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
735     ifr.ifr_addr.sa_family = AF_INET;
736     INET_ADDR(ifr.ifr_addr) = o;
737     if (ioctl(ipfd, SIOCSIFADDR, &ifr) < 0) {
738         syslog(LOG_ERR, "Couldn't set local IP address: %m");
739     }
740     ifr.ifr_dstaddr.sa_family = AF_INET;
741     INET_ADDR(ifr.ifr_dstaddr) = h;
742     if (ioctl(ipfd, SIOCSIFDSTADDR, &ifr) < 0) {
743         syslog(LOG_ERR, "Couldn't set remote IP address: %m");
744     }
745     ifr.ifr_addr.sa_family = AF_INET;
746     INET_ADDR(ifr.ifr_addr) = m;
747     if (ioctl(ipfd, SIOCSIFNETMASK, &ifr) < 0) {
748         syslog(LOG_ERR, "Couldn't set IP netmask: %m");
749     }
750     ifr.ifr_metric = link_mtu;
751     if (ioctl(ipfd, SIOCSIFMTU, &ifr) < 0) {
752         syslog(LOG_ERR, "Couldn't set IP MTU: %m");
753     }
754
755     return 1;
756 }
757
758 /*
759  * cifaddr - Clear the interface IP addresses, and delete routes
760  * through the interface if possible.
761  */
762 int
763 cifaddr(u, o, h)
764     int u;
765     u_int32_t o, h;
766 {
767     if (ipmuxid >= 0) {
768         if (ioctl(ipfd, I_UNLINK, ipmuxid) < 0) {
769             syslog(LOG_ERR, "Can't remove ppp interface unit: %m");
770             return 0;
771         }
772         ipmuxid = -1;
773     }
774     return 1;
775 }
776
777 /*
778  * sifdefaultroute - assign a default route through the address given.
779  */
780 int
781 sifdefaultroute(u, g)
782     int u;
783     u_int32_t g;
784 {
785     struct rtentry rt;
786
787     rt.rt_dst.sa_family = AF_INET;
788     INET_ADDR(rt.rt_dst) = 0;
789     rt.rt_gateway.sa_family = AF_INET;
790     INET_ADDR(rt.rt_gateway) = g;
791     rt.rt_flags = RTF_GATEWAY;
792
793     if (ioctl(ipfd, SIOCADDRT, &rt) < 0) {
794         syslog(LOG_ERR, "Can't add default route: %m");
795         return 0;
796     }
797
798     return 1;
799 }
800
801 /*
802  * cifdefaultroute - delete a default route through the address given.
803  */
804 int
805 cifdefaultroute(u, g)
806     int u;
807     u_int32_t g;
808 {
809     struct rtentry rt;
810
811     rt.rt_dst.sa_family = AF_INET;
812     INET_ADDR(rt.rt_dst) = 0;
813     rt.rt_gateway.sa_family = AF_INET;
814     INET_ADDR(rt.rt_gateway) = g;
815     rt.rt_flags = RTF_GATEWAY;
816
817     if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
818         syslog(LOG_ERR, "Can't delete default route: %m");
819         return 0;
820     }
821
822     return 1;
823 }
824
825 /*
826  * sifproxyarp - Make a proxy ARP entry for the peer.
827  */
828 int
829 sifproxyarp(unit, hisaddr)
830     int unit;
831     u_int32_t hisaddr;
832 {
833     struct arpreq arpreq;
834
835     memset(&arpreq, 0, sizeof(arpreq));
836     if (!get_ether_addr(hisaddr, &arpreq.arp_ha))
837         return 0;
838
839     arpreq.arp_pa.sa_family = AF_INET;
840     INET_ADDR(arpreq.arp_pa) = hisaddr;
841     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
842     if (ioctl(ipfd, SIOCSARP, (caddr_t) &arpreq) < 0) {
843         syslog(LOG_ERR, "Couldn't set proxy ARP entry: %m");
844         return 0;
845     }
846
847     return 1;
848 }
849
850 /*
851  * cifproxyarp - Delete the proxy ARP entry for the peer.
852  */
853 int
854 cifproxyarp(unit, hisaddr)
855     int unit;
856     u_int32_t hisaddr;
857 {
858     struct arpreq arpreq;
859
860     memset(&arpreq, 0, sizeof(arpreq));
861     arpreq.arp_pa.sa_family = AF_INET;
862     INET_ADDR(arpreq.arp_pa) = hisaddr;
863     if (ioctl(ipfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
864         syslog(LOG_ERR, "Couldn't delete proxy ARP entry: %m");
865         return 0;
866     }
867
868     return 1;
869 }
870
871 /*
872  * get_ether_addr - get the hardware address of an interface on the
873  * the same subnet as ipaddr.
874  */
875 #define MAX_IFS         32
876
877 int
878 get_ether_addr(ipaddr, hwaddr)
879     u_int32_t ipaddr;
880     struct sockaddr *hwaddr;
881 {
882     struct ifreq *ifr, *ifend, ifreq;
883     int nif;
884     struct ifconf ifc;
885     u_int32_t ina, mask;
886
887     /*
888      * Scan through the system's network interfaces.
889      */
890     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
891         nif = MAX_IFS;
892     ifc.ifc_len = nif * sizeof(struct ifreq);
893     ifc.ifc_req = alloca(ifc.ifc_len);
894     if (ifc.ifc_req == 0)
895         return 0;
896     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
897         syslog(LOG_WARNING, "Couldn't get system interface list: %m");
898         return 0;
899     }
900     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
901     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
902         if (ifr->ifr_addr.sa_family != AF_INET)
903             continue;
904         /*
905          * Check that the interface is up, and not point-to-point or loopback.
906          */
907         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
908         if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
909             continue;
910         if ((ifreq.ifr_flags &
911              (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
912             != (IFF_UP|IFF_BROADCAST))
913             continue;
914         /*
915          * Get its netmask and check that it's on the right subnet.
916          */
917         if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
918             continue;
919         ina = INET_ADDR(ifr->ifr_addr);
920         mask = INET_ADDR(ifreq.ifr_addr);
921         if ((ipaddr & mask) == (ina & mask))
922             break;
923     }
924
925     if (ifr >= ifend) {
926         syslog(LOG_WARNING, "No suitable interface found for proxy ARP");
927         return 0;
928     }
929
930     syslog(LOG_INFO, "found interface %s for proxy ARP", ifr->ifr_name);
931     if (!get_hw_addr(ifr->ifr_name, hwaddr)) {
932         syslog(LOG_ERR, "Couldn't get hardware address for %s", ifr->ifr_name);
933         return 0;
934     }
935
936     return 1;
937 }
938
939 /*
940  * get_hw_addr - obtain the hardware address for a named interface.
941  */
942 int
943 get_hw_addr(name, hwaddr)
944     char *name;
945     struct sockaddr *hwaddr;
946 {
947     char *p, *q;
948     int unit, iffd, adrlen;
949     unsigned char *adrp;
950     char ifdev[24];
951     struct {
952         union DL_primitives prim;
953         char space[64];
954     } reply;
955
956     /*
957      * We have to open the device and ask it for its hardware address.
958      * First split apart the device name and unit.
959      */
960     strcpy(ifdev, "/dev/");
961     q = ifdev + 5;              /* strlen("/dev/") */
962     while (*name != 0 && !isdigit(*name))
963         *q++ = *name++;
964     *q = 0;
965     unit = atoi(name);
966
967     /*
968      * Open the device and do a DLPI attach and phys_addr_req.
969      */
970     iffd = open(ifdev, O_RDWR);
971     if (iffd < 0) {
972         syslog(LOG_ERR, "Can't open %s: %m", ifdev);
973         return 0;
974     }
975     if (dlpi_attach(iffd, unit) < 0
976         || dlpi_get_reply(iffd, &reply.prim, DL_OK_ACK, sizeof(reply)) < 0
977         || dlpi_phys_addr_req(iffd) < 0
978         || dlpi_get_reply(iffd, &reply.prim, DL_PHYS_ADDR_ACK,
979                           sizeof(reply)) < 0) {
980         close(iffd);
981         return 0;
982     }
983
984     hwaddr->sa_family = AF_UNSPEC;
985     adrlen = reply.prim.physaddr_ack.dl_addr_length;
986     adrp = (unsigned char *)&reply + reply.prim.physaddr_ack.dl_addr_offset;
987     memcpy(hwaddr->sa_data, adrp, adrlen);
988
989     return 1;
990 }
991
992 int
993 dlpi_attach(fd, ppa)
994     int fd, ppa;
995 {
996     dl_attach_req_t req;
997     struct strbuf buf;
998
999     req.dl_primitive = DL_ATTACH_REQ;
1000     req.dl_ppa = ppa;
1001     buf.len = sizeof(req);
1002     buf.buf = (void *) &req;
1003     return putmsg(fd, &buf, NULL, RS_HIPRI);
1004 }
1005
1006 int
1007 dlpi_phys_addr_req(fd)
1008     int fd;
1009 {
1010     dl_phys_addr_req_t req;
1011     struct strbuf buf;
1012
1013     req.dl_primitive = DL_PHYS_ADDR_REQ;
1014     req.dl_addr_type = DL_CURR_PHYS_ADDR;
1015     buf.len = sizeof(req);
1016     buf.buf = (void *) &req;
1017     return putmsg(fd, &buf, NULL, RS_HIPRI);
1018 }
1019
1020 int
1021 dlpi_get_reply(fd, reply, expected_prim, maxlen)
1022     union DL_primitives *reply;
1023     int fd, expected_prim, maxlen;
1024 {
1025     struct strbuf buf;
1026     int flags, n;
1027     struct pollfd pfd;
1028
1029     /*
1030      * Use poll to wait for a message with a timeout.
1031      */
1032     pfd.fd = fd;
1033     pfd.events = POLLIN | POLLPRI;
1034     do {
1035         n = poll(&pfd, 1, 1000);
1036     } while (n == -1 && errno == EINTR);
1037     if (n <= 0)
1038         return -1;
1039
1040     /*
1041      * Get the reply.
1042      */
1043     buf.maxlen = maxlen;
1044     buf.buf = (void *) reply;
1045     flags = 0;
1046     if (getmsg(fd, &buf, NULL, &flags) < 0)
1047         return -1;
1048
1049     if (buf.len < sizeof(ulong)) {
1050         if (debug)
1051             syslog(LOG_DEBUG, "dlpi response short (len=%d)\n", buf.len);
1052         return -1;
1053     }
1054
1055     if (reply->dl_primitive == expected_prim)
1056         return 0;
1057
1058     if (debug) {
1059         if (reply->dl_primitive == DL_ERROR_ACK) {
1060             syslog(LOG_DEBUG, "dlpi error %d (unix errno %d) for prim %x\n",
1061                    reply->error_ack.dl_errno, reply->error_ack.dl_unix_errno,
1062                    reply->error_ack.dl_error_primitive);
1063         } else {
1064             syslog(LOG_DEBUG, "dlpi unexpected response prim %x\n",
1065                    reply->dl_primitive);
1066         }
1067     }
1068
1069     return -1;
1070 }
1071
1072 /*
1073  * Return user specified netmask, modified by any mask we might determine
1074  * for address `addr' (in network byte order).
1075  * Here we scan through the system's list of interfaces, looking for
1076  * any non-point-to-point interfaces which might appear to be on the same
1077  * network as `addr'.  If we find any, we OR in their netmask to the
1078  * user-specified netmask.
1079  */
1080 u_int32_t
1081 GetMask(addr)
1082     u_int32_t addr;
1083 {
1084     u_int32_t mask, nmask, ina;
1085     struct ifreq *ifr, *ifend, ifreq;
1086     int nif;
1087     struct ifconf ifc;
1088
1089     addr = ntohl(addr);
1090     if (IN_CLASSA(addr))        /* determine network mask for address class */
1091         nmask = IN_CLASSA_NET;
1092     else if (IN_CLASSB(addr))
1093         nmask = IN_CLASSB_NET;
1094     else
1095         nmask = IN_CLASSC_NET;
1096     /* class D nets are disallowed by bad_ip_adrs */
1097     mask = netmask | htonl(nmask);
1098
1099     /*
1100      * Scan through the system's network interfaces.
1101      */
1102     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
1103         nif = MAX_IFS;
1104     ifc.ifc_len = nif * sizeof(struct ifreq);
1105     ifc.ifc_req = alloca(ifc.ifc_len);
1106     if (ifc.ifc_req == 0)
1107         return mask;
1108     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
1109         syslog(LOG_WARNING, "Couldn't get system interface list: %m");
1110         return mask;
1111     }
1112     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1113     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
1114         /*
1115          * Check the interface's internet address.
1116          */
1117         if (ifr->ifr_addr.sa_family != AF_INET)
1118             continue;
1119         ina = INET_ADDR(ifr->ifr_addr);
1120         if ((ntohl(ina) & nmask) != (addr & nmask))
1121             continue;
1122         /*
1123          * Check that the interface is up, and not point-to-point or loopback.
1124          */
1125         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1126         if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
1127             continue;
1128         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1129             != IFF_UP)
1130             continue;
1131         /*
1132          * Get its netmask and OR it into our mask.
1133          */
1134         if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
1135             continue;
1136         mask |= INET_ADDR(ifreq.ifr_addr);
1137     }
1138
1139     return mask;
1140 }
1141
1142 /*
1143  * logwtmp - write an accounting record to the /var/adm/wtmp file.
1144  */
1145 int
1146 logwtmp(line, name, host)
1147     char *line, *name, *host;
1148 {
1149 }
1150
1151 /*
1152  * gethostid - return the serial number of this machine.
1153  */
1154 int
1155 gethostid()
1156 {
1157     char buf[32];
1158
1159     if (sysinfo(SI_HW_SERIAL, buf, sizeof(buf)) < 0) {
1160         syslog(LOG_ERR, "sysinfo: %m");
1161         return 0;
1162     }
1163     return strtol(buf, NULL, 16);
1164 }
1165
1166 int
1167 strioctl(fd, cmd, ptr, ilen, olen)
1168     int fd, cmd, ilen, olen;
1169     char *ptr;
1170 {
1171     struct strioctl str;
1172
1173     str.ic_cmd = cmd;
1174     str.ic_timout = 0;
1175     str.ic_len = ilen;
1176     str.ic_dp = ptr;
1177     if (ioctl(fd, I_STR, &str) == -1)
1178         return -1;
1179     if (str.ic_len != olen)
1180         syslog(LOG_DEBUG, "strioctl: expected %d bytes, got %d for cmd %x\n",
1181                olen, str.ic_len, cmd);
1182     return 0;
1183 }
1184
1185 int
1186 lock(dev)
1187     char *dev;
1188 {
1189     return 1;
1190 }
1191
1192 int
1193 unlock()
1194 {
1195     return 1;
1196 }