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