]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-bsd.c
Minor fixes from the NetBSD port: fd -> ppp_fd in sys-bsd.c, etc.
[ppp.git] / pppd / sys-bsd.c
1 /*
2  * sys-bsd.c - System-dependent procedures for setting up
3  * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.)
4  *
5  * Copyright (c) 1989 Carnegie Mellon University.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by Carnegie Mellon University.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20
21 #ifndef lint
22 static char rcsid[] = "$Id: sys-bsd.c,v 1.19.2.2 1995/06/06 12:11:45 paulus Exp $";
23 #endif
24
25 /*
26  * TODO:
27  */
28
29 #include <stdio.h>
30 #include <syslog.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <termios.h>
36 #include <sys/ioctl.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/time.h>
40 #include <sys/stat.h>
41
42 #include <net/if.h>
43 #include <net/ppp_defs.h>
44 #include <net/if_ppp.h>
45 #include <net/route.h>
46 #include <net/if_dl.h>
47 #include <netinet/in.h>
48
49 #if RTM_VERSION >= 3
50 #include <netinet/if_ether.h>
51 #endif
52
53 #include "pppd.h"
54
55 static int initdisc = -1;       /* Initial TTY discipline */
56 static int ppp_fd = -1;         /* fd which is set to PPP discipline */
57 static int rtm_seq;
58
59 static int restore_term;        /* 1 => we've munged the terminal */
60 static struct termios inittermios; /* Initial TTY termios */
61
62 static char *lock_file;         /* name of lock file created */
63
64 static int loop_slave = -1;
65 static int loop_master;
66 static char loop_name[20];
67
68 int sockfd;                     /* socket for doing interface ioctls */
69
70 /*
71  * sys_init - System-dependent initialization.
72  */
73 void
74 sys_init()
75 {
76     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
77     setlogmask(LOG_UPTO(LOG_INFO));
78     if (debug)
79         setlogmask(LOG_UPTO(LOG_DEBUG));
80
81     /* Get an internet socket for doing socket ioctl's on. */
82     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
83         syslog(LOG_ERR, "Couldn't create IP socket: %m");
84         die(1);
85     }
86 }
87
88 /*
89  * sys_close - Clean up in a child process before execing.
90  */
91 void
92 sys_close()
93 {
94     close(sockfd);
95     if (loop_slave >= 0) {
96         close(loop_slave);
97         close(loop_master);
98     }
99     closelog();
100 }
101
102
103 /*
104  * note_debug_level - note a change in the debug level.
105  */
106 void
107 note_debug_level()
108 {
109     if (debug) {
110         syslog(LOG_INFO, "Debug turned ON, Level %d", debug);
111         setlogmask(LOG_UPTO(LOG_DEBUG));
112     } else {
113         setlogmask(LOG_UPTO(LOG_WARNING));
114     }
115 }
116
117 /*
118  * ppp_available - check whether the system has any ppp interfaces
119  * (in fact we check whether we can do an ioctl on ppp0).
120  */
121 int
122 ppp_available()
123 {
124     int s, ok;
125     struct ifreq ifr;
126
127     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
128         return 1;               /* can't tell */
129
130     strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
131     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
132     close(s);
133
134     return ok;
135 }
136
137 /*
138  * establish_ppp - Turn the serial port (or loopback) into a ppp interface.
139  */
140 void
141 establish_ppp(fd)
142     int fd;
143 {
144     int pppdisc = PPPDISC;
145     int x;
146
147     if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
148         syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
149         die(1);
150     }
151     if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
152         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
153         die(1);
154     }
155
156     /*
157      * Find out which interface we were given.
158      */
159     if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {  
160         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
161         die(1);
162     }
163     ppp_fd = fd;
164
165     /*
166      * Enable debug in the driver if requested.
167      */
168     if (kdebugflag) {
169         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
170             syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
171         } else {
172             x |= (kdebugflag & 0xFF) * SC_DEBUG;
173             if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
174                 syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
175         }
176     }
177 }
178
179
180 /*
181  * transfer_ppp - make the device on fd `fd' take over the PPP interface
182  * unit that we are using.
183  */
184 void
185 transfer_ppp(fd)
186     int fd;
187 {
188     int x, prevdisc;
189
190     if (fd == ppp_fd)
191         return;                 /* we can't get here */
192
193     /*
194      * Prime the old ppp device to relinquish the unit.
195      */
196     if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) {
197         syslog(LOG_ERR, "ioctl(transfer ppp unit): %m");
198         die(1);
199     }
200
201     /*
202      * Save the old line discipline of fd, and set it to PPP.
203      */
204     if (ioctl(fd, TIOCGETD, &prevdisc) < 0) {
205         syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
206         die(1);
207     }
208     x = PPPDISC;
209     if (ioctl(fd, TIOCSETD, &x) < 0) {
210         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
211         die(1);
212     }
213
214     /*
215      * Set the old ppp device back to its previous discipline.
216      */
217     ioctl(ppp_fd, TIOCSETD, &initdisc);
218     initdisc = prevdisc;
219
220     /*
221      * Check that we got the same unit again.
222      */
223     if (ioctl(fd, PPPIOCGUNIT, &x) < 0) {       
224         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
225         die(1);
226     }
227     if (x != ifunit) {
228         syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
229                ifunit, x);
230         die(1);
231     }
232
233     ppp_fd = fd;
234 }
235
236
237 /*
238  * disestablish_ppp - Restore the serial port to normal operation.
239  * This shouldn't call die() because it's called from die().
240  */
241 void
242 disestablish_ppp(fd)
243     int fd;
244 {
245     if (fd == ppp_fd && fd >= 0 && initdisc >= 0) {
246         if (ioctl(fd, TIOCSETD, &initdisc) < 0)
247             syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
248         initdisc = -1;
249         ppp_fd = -1;
250     }
251 }
252
253 /*
254  * Check whether the link seems not to be 8-bit clean.
255  */
256 void
257 clean_check()
258 {
259     int x;
260     char *s;
261
262     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
263         s = NULL;
264         switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
265         case SC_RCV_B7_0:
266             s = "bit 7 set to 1";
267             break;
268         case SC_RCV_B7_1:
269             s = "bit 7 set to 0";
270             break;
271         case SC_RCV_EVNP:
272             s = "odd parity";
273             break;
274         case SC_RCV_ODDP:
275             s = "even parity";
276             break;
277         }
278         if (s != NULL) {
279             syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
280             syslog(LOG_WARNING, "All received characters had %s", s);
281         }
282     }
283 }
284
285 /*
286  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
287  * at the requested speed, etc.  If `local' is true, set CLOCAL
288  * regardless of whether the modem option was specified.
289  *
290  * For *BSD, we assume that speed_t values numerically equal bits/second.
291  */
292 set_up_tty(fd, local)
293     int fd, local;
294 {
295     struct termios tios;
296
297     if (tcgetattr(fd, &tios) < 0) {
298         syslog(LOG_ERR, "tcgetattr: %m");
299         die(1);
300     }
301
302     if (!restore_term)
303         inittermios = tios;
304
305     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
306     if (crtscts > 0)
307         tios.c_cflag |= CRTSCTS;
308     else if (crtscts < 0)
309         tios.c_cflag &= ~CRTSCTS;
310
311     tios.c_cflag |= CS8 | CREAD | HUPCL;
312     if (local || !modem)
313         tios.c_cflag |= CLOCAL;
314     tios.c_iflag = IGNBRK | IGNPAR;
315     tios.c_oflag = 0;
316     tios.c_lflag = 0;
317     tios.c_cc[VMIN] = 1;
318     tios.c_cc[VTIME] = 0;
319
320     if (crtscts == 2) {
321         tios.c_iflag |= IXOFF;
322         tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
323         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
324     }
325
326     if (inspeed) {
327         cfsetospeed(&tios, inspeed);
328         cfsetispeed(&tios, inspeed);
329     } else {
330         inspeed = cfgetospeed(&tios);
331         /*
332          * We can't proceed if the serial port speed is 0,
333          * since that implies that the serial port is disabled.
334          */
335         if (inspeed == 0) {
336             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
337                    devnam);
338             die(1);
339         }
340     }
341     baud_rate = inspeed;
342
343     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
344         syslog(LOG_ERR, "tcsetattr: %m");
345         die(1);
346     }
347
348     restore_term = 1;
349 }
350
351 /*
352  * restore_tty - restore the terminal to the saved settings.
353  */
354 void
355 restore_tty()
356 {
357     if (restore_term) {
358         if (!default_device) {
359             /*
360              * Turn off echoing, because otherwise we can get into
361              * a loop with the tty and the modem echoing to each other.
362              * We presume we are the sole user of this tty device, so
363              * when we close it, it will revert to its defaults anyway.
364              */
365             inittermios.c_lflag &= ~(ECHO | ECHONL);
366         }
367         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
368             if (errno != ENXIO)
369                 syslog(LOG_WARNING, "tcsetattr: %m");
370         restore_term = 0;
371     }
372 }
373
374 /*
375  * setdtr - control the DTR line on the serial port.
376  * This is called from die(), so it shouldn't call die().
377  */
378 setdtr(fd, on)
379 int fd, on;
380 {
381     int modembits = TIOCM_DTR;
382
383     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
384 }
385
386
387 /*
388  * open_loopback - open the device we use for getting packets
389  * in demand mode.  Here we use a pty.
390  */
391 int
392 open_loopback()
393 {
394     int flags;
395     struct termios tios;
396
397     if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0) {
398         syslog(LOG_ERR, "No free pty for loopback");
399         die(1);
400     }
401     SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name));
402     if (tcgetattr(loop_slave, &tios) == 0) {
403         tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
404         tios.c_cflag |= CS8 | CREAD;
405         tios.c_iflag = IGNPAR;
406         tios.c_oflag = 0;
407         tios.c_lflag = 0;
408         if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0)
409             syslog(LOG_WARNING, "couldn't set attributes on loopback: %m");
410     }
411     if ((flags = fcntl(loop_slave, F_GETFL)) != -1) 
412         if (fcntl(loop_slave, F_SETFL, flags | O_NONBLOCK) == -1)
413             syslog(LOG_WARNING, "couldn't set loopback to nonblock: %m");
414     if ((flags = fcntl(loop_master, F_GETFL)) != -1) 
415         if (fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1)
416             syslog(LOG_WARNING, "couldn't set loopback(m) to nonblock: %m");
417     return loop_slave;
418 }
419
420
421 /*
422  * output - Output PPP packet.
423  */
424 void
425 output(unit, p, len)
426     int unit;
427     u_char *p;
428     int len;
429 {
430     if (unit != 0)
431         SYSDEBUG((LOG_WARNING, "output: unit != 0!"));
432     if (debug)
433         log_packet(p, len, "sent ");
434
435     if (write(ppp_fd, p, len) < 0) {
436         syslog(LOG_ERR, "write: %m");
437         die(1);
438     }
439 }
440
441
442 /*
443  * wait_input - wait until there is data available on fd,
444  * for the length of time specified by *timo (indefinite
445  * if timo is NULL).
446  */
447 wait_input(timo)
448     struct timeval *timo;
449 {
450     fd_set ready;
451     int n;
452
453     FD_ZERO(&ready);
454     FD_SET(fd, &ready);
455     n = select(fd+1, &ready, NULL, &ready, timo);
456     if (n < 0 && errno != EINTR) {
457         syslog(LOG_ERR, "select: %m");
458         die(1);
459     }
460 }
461
462
463 /*
464  * wait_loop_output - wait until there is data available on the,
465  * loopback, for the length of time specified by *timo (indefinite
466  * if timo is NULL).
467  */
468 wait_loop_output(timo)
469     struct timeval *timo;
470 {
471     fd_set ready;
472     int n;
473
474     FD_ZERO(&ready);
475     FD_SET(loop_master, &ready);
476     n = select(loop_master + 1, &ready, NULL, &ready, timo);
477     if (n < 0 && errno != EINTR) {
478         syslog(LOG_ERR, "select: %m");
479         die(1);
480     }
481 }
482
483
484 /*
485  * wait_time - wait for a given length of time or until a
486  * signal is received.
487  */
488 wait_time(timo)
489     struct timeval *timo;
490 {
491     int n;
492
493     n = select(0, NULL, NULL, NULL, timo);
494     if (n < 0 && errno != EINTR) {
495         syslog(LOG_ERR, "select: %m");
496         die(1);
497     }
498 }
499
500
501 /*
502  * read_packet - get a PPP packet from the serial device.
503  */
504 int
505 read_packet(buf)
506     u_char *buf;
507 {
508     int len;
509
510     if ((len = read(fd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
511         if (errno == EWOULDBLOCK || errno == EINTR)
512             return -1;
513         syslog(LOG_ERR, "read(fd): %m");
514         die(1);
515     }
516     return len;
517 }
518
519
520 /*
521  * read_loop_output - get characters from the "bottom" of the loopback.
522  */
523 int
524 read_loop_output(buf, maxlen)
525     u_char *buf;
526     int maxlen;
527 {
528     int len;
529
530     if ((len = read(loop_master, buf, maxlen)) < 0) {
531         if (errno == EWOULDBLOCK)
532             return 0;
533         syslog(LOG_ERR, "read from loopback: %m");
534         die(1);
535     } else if (len == 0) {
536         syslog(LOG_ERR, "eof on loopback");
537         die(1);
538     }
539     return len;
540 }
541
542
543 /*
544  * ppp_send_config - configure the transmit characteristics of
545  * the ppp interface.
546  */
547 void
548 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
549     int unit, mtu;
550     u_int32_t asyncmap;
551     int pcomp, accomp;
552 {
553     u_int x;
554     struct ifreq ifr;
555
556     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
557     ifr.ifr_mtu = mtu;
558     if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
559         syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
560         die(1);
561     }
562
563     if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
564         syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
565         die(1);
566     }
567
568     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
569         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
570         die(1);
571     }
572     x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
573     x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
574     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
575         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
576         die(1);
577     }
578 }
579
580
581 /*
582  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
583  */
584 void
585 ppp_set_xaccm(unit, accm)
586     int unit;
587     ext_accm accm;
588 {
589     if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
590         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
591 }
592
593
594 /*
595  * ppp_recv_config - configure the receive-side characteristics of
596  * the ppp interface.
597  */
598 void
599 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
600     int unit, mru;
601     u_int32_t asyncmap;
602     int pcomp, accomp;
603 {
604     int x;
605
606     if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
607         syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
608         die(1);
609     }
610     if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
611         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
612         die(1);
613     }
614     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
615         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
616         die(1);
617     }
618     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
619     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
620         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
621         die(1);
622     }
623 }
624
625 /*
626  * ccp_test - ask kernel whether a given compression method
627  * is acceptable for use.
628  */
629 ccp_test(unit, opt_ptr, opt_len, for_transmit)
630     int unit, opt_len, for_transmit;
631     u_char *opt_ptr;
632 {
633     struct ppp_option_data data;
634
635     data.ptr = opt_ptr;
636     data.length = opt_len;
637     data.transmit = for_transmit;
638     return ioctl(ppp_fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0;
639 }
640
641 /*
642  * ccp_flags_set - inform kernel about the current state of CCP.
643  */
644 void
645 ccp_flags_set(unit, isopen, isup)
646     int unit, isopen, isup;
647 {
648     int x;
649
650     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
651         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
652         return;
653     }
654     x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
655     x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
656     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
657         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
658 }
659
660 /*
661  * ccp_fatal_error - returns 1 if decompression was disabled as a
662  * result of an error detected after decompression of a packet,
663  * 0 otherwise.  This is necessary because of patent nonsense.
664  */
665 int
666 ccp_fatal_error(unit)
667     int unit;
668 {
669     int x;
670
671     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
672         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
673         return 0;
674     }
675     return x & SC_DC_FERROR;
676 }
677
678 /*
679  * get_idle_time - return how long the link has been idle.
680  */
681 int
682 get_idle_time(u, ip)
683     int u;
684     struct ppp_idle *ip;
685 {
686     return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
687 }
688
689
690 /*
691  * sifvjcomp - config tcp header compression
692  */
693 int
694 sifvjcomp(u, vjcomp, cidcomp, maxcid)
695     int u, vjcomp, cidcomp, maxcid;
696 {
697     u_int x;
698
699     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
700         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
701         return 0;
702     }
703     x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
704     x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
705     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
706         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
707         return 0;
708     }
709     if (ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
710         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
711         return 0;
712     }
713     return 1;
714 }
715
716 /*
717  * sifup - Config the interface up and enable IP packets to pass.
718  */
719 int
720 sifup(u)
721     int u;
722 {
723     struct ifreq ifr;
724     struct npioctl npi;
725
726     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
727     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
728         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
729         return 0;
730     }
731     ifr.ifr_flags |= IFF_UP;
732     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
733         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
734         return 0;
735     }
736     npi.protocol = PPP_IP;
737     npi.mode = NPMODE_PASS;
738     if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
739         syslog(LOG_ERR, "ioctl(set IP mode to PASS): %m");
740         return 0;
741     }
742     return 1;
743 }
744
745 /*
746  * sifnpmode - Set the mode for handling packets for a given NP.
747  */
748 int
749 sifnpmode(u, proto, mode)
750     int u;
751     int proto;
752     enum NPmode mode;
753 {
754     struct npioctl npi;
755
756     npi.protocol = proto;
757     npi.mode = mode;
758     if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
759         syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode);
760         return 0;
761     }
762     return 1;
763 }
764
765 /*
766  * sifdown - Config the interface down and disable IP.
767  */
768 int
769 sifdown(u)
770     int u;
771 {
772     struct ifreq ifr;
773     int rv;
774     struct npioctl npi;
775
776     rv = 1;
777     npi.protocol = PPP_IP;
778     npi.mode = NPMODE_ERROR;
779     ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi);
780     /* ignore errors, because ppp_fd might have been closed by now. */
781
782     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
783     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
784         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
785         rv = 0;
786     } else {
787         ifr.ifr_flags &= ~IFF_UP;
788         if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
789             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
790             rv = 0;
791         }
792     }
793     return rv;
794 }
795
796 /*
797  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
798  * if it exists.
799  */
800 #define SET_SA_FAMILY(addr, family)             \
801     BZERO((char *) &(addr), sizeof(addr));      \
802     addr.sa_family = (family);                  \
803     addr.sa_len = sizeof(addr);
804
805 /*
806  * sifaddr - Config the interface IP addresses and netmask.
807  */
808 int
809 sifaddr(u, o, h, m)
810     int u;
811     u_int32_t o, h, m;
812 {
813     struct ifaliasreq ifra;
814
815     strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
816     SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
817     ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
818     SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
819     ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
820     if (m != 0) {
821         SET_SA_FAMILY(ifra.ifra_mask, AF_INET);
822         ((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
823     } else
824         BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
825     if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
826         if (errno != EEXIST) {
827             syslog(LOG_ERR, "ioctl(SIOCAIFADDR): %m");
828             return 0;
829         }
830         syslog(LOG_WARNING, "ioctl(SIOCAIFADDR): Address already exists");
831     }
832     return 1;
833 }
834
835 /*
836  * cifaddr - Clear the interface IP addresses, and delete routes
837  * through the interface if possible.
838  */
839 int
840 cifaddr(u, o, h)
841     int u;
842     u_int32_t o, h;
843 {
844     struct ifaliasreq ifra;
845
846     strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
847     SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
848     ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
849     SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
850     ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
851     BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
852     if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
853         if (errno != EADDRNOTAVAIL)
854             syslog(LOG_WARNING, "ioctl(SIOCDIFADDR): %m");
855         return 0;
856     }
857     return 1;
858 }
859
860 /*
861  * sifdefaultroute - assign a default route through the address given.
862  */
863 int
864 sifdefaultroute(u, g)
865     int u;
866     u_int32_t g;
867 {
868     return dodefaultroute(g, 's');
869 }
870
871 /*
872  * cifdefaultroute - delete a default route through the address given.
873  */
874 int
875 cifdefaultroute(u, g)
876     int u;
877     u_int32_t g;
878 {
879     return dodefaultroute(g, 'c');
880 }
881
882 /*
883  * dodefaultroute - talk to a routing socket to add/delete a default route.
884  */
885 int
886 dodefaultroute(g, cmd)
887     u_int32_t g;
888     int cmd;
889 {
890     int routes;
891     struct {
892         struct rt_msghdr        hdr;
893         struct sockaddr_in      dst;
894         struct sockaddr_in      gway;
895         struct sockaddr_in      mask;
896     } rtmsg;
897
898     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
899         syslog(LOG_ERR, "%cifdefaultroute: opening routing socket: %m", cmd);
900         return 0;
901     }
902
903     memset(&rtmsg, 0, sizeof(rtmsg));
904     rtmsg.hdr.rtm_type = cmd == 's'? RTM_ADD: RTM_DELETE;
905     rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY;
906     rtmsg.hdr.rtm_version = RTM_VERSION;
907     rtmsg.hdr.rtm_seq = ++rtm_seq;
908     rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
909     rtmsg.dst.sin_len = sizeof(rtmsg.dst);
910     rtmsg.dst.sin_family = AF_INET;
911     rtmsg.gway.sin_len = sizeof(rtmsg.gway);
912     rtmsg.gway.sin_family = AF_INET;
913     rtmsg.gway.sin_addr.s_addr = g;
914     rtmsg.mask.sin_len = sizeof(rtmsg.dst);
915     rtmsg.mask.sin_family = AF_INET;
916
917     rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
918     if (write(routes, &rtmsg, sizeof(rtmsg)) < 0) {
919         syslog(LOG_ERR, "%s default route: %m", cmd=='s'? "add": "delete");
920         close(routes);
921         return 0;
922     }
923
924     close(routes);
925     return 1;
926 }
927
928 #if RTM_VERSION >= 3
929
930 /*
931  * sifproxyarp - Make a proxy ARP entry for the peer.
932  */
933 static struct {
934     struct rt_msghdr            hdr;
935     struct sockaddr_inarp       dst;
936     struct sockaddr_dl          hwa;
937     char                        extra[128];
938 } arpmsg;
939
940 static int arpmsg_valid;
941
942 int
943 sifproxyarp(unit, hisaddr)
944     int unit;
945     u_int32_t hisaddr;
946 {
947     int routes;
948     int l;
949
950     /*
951      * Get the hardware address of an interface on the same subnet
952      * as our local address.
953      */
954     memset(&arpmsg, 0, sizeof(arpmsg));
955     if (!get_ether_addr(hisaddr, &arpmsg.hwa)) {
956         syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
957         return 0;
958     }
959
960     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
961         syslog(LOG_ERR, "sifproxyarp: opening routing socket: %m");
962         return 0;
963     }
964
965     arpmsg.hdr.rtm_type = RTM_ADD;
966     arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC;
967     arpmsg.hdr.rtm_version = RTM_VERSION;
968     arpmsg.hdr.rtm_seq = ++rtm_seq;
969     arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
970     arpmsg.hdr.rtm_inits = RTV_EXPIRE;
971     arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
972     arpmsg.dst.sin_family = AF_INET;
973     arpmsg.dst.sin_addr.s_addr = hisaddr;
974     arpmsg.dst.sin_other = SIN_PROXY;
975
976     arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
977         + arpmsg.hwa.sdl_len;
978     if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
979         syslog(LOG_ERR, "add proxy arp entry: %m");
980         close(routes);
981         return 0;
982     }
983
984     close(routes);
985     arpmsg_valid = 1;
986     return 1;
987 }
988
989 /*
990  * cifproxyarp - Delete the proxy ARP entry for the peer.
991  */
992 int
993 cifproxyarp(unit, hisaddr)
994     int unit;
995     u_int32_t hisaddr;
996 {
997     int routes;
998
999     if (!arpmsg_valid)
1000         return 0;
1001     arpmsg_valid = 0;
1002
1003     arpmsg.hdr.rtm_type = RTM_DELETE;
1004     arpmsg.hdr.rtm_seq = ++rtm_seq;
1005
1006     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1007         syslog(LOG_ERR, "sifproxyarp: opening routing socket: %m");
1008         return 0;
1009     }
1010
1011     if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1012         syslog(LOG_ERR, "delete proxy arp entry: %m");
1013         close(routes);
1014         return 0;
1015     }
1016
1017     close(routes);
1018     return 1;
1019 }
1020
1021 #else   /* RTM_VERSION */
1022
1023 /*
1024  * sifproxyarp - Make a proxy ARP entry for the peer.
1025  */
1026 int
1027 sifproxyarp(unit, hisaddr)
1028     int unit;
1029     u_int32_t hisaddr;
1030 {
1031     struct arpreq arpreq;
1032     struct {
1033         struct sockaddr_dl      sdl;
1034         char                    space[128];
1035     } dls;
1036
1037     BZERO(&arpreq, sizeof(arpreq));
1038
1039     /*
1040      * Get the hardware address of an interface on the same subnet
1041      * as our local address.
1042      */
1043     if (!get_ether_addr(hisaddr, &dls.sdl)) {
1044         syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1045         return 0;
1046     }
1047
1048     arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
1049     arpreq.arp_ha.sa_family = AF_UNSPEC;
1050     BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen);
1051     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1052     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1053     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1054     if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
1055         syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
1056         return 0;
1057     }
1058
1059     return 1;
1060 }
1061
1062 /*
1063  * cifproxyarp - Delete the proxy ARP entry for the peer.
1064  */
1065 int
1066 cifproxyarp(unit, hisaddr)
1067     int unit;
1068     u_int32_t hisaddr;
1069 {
1070     struct arpreq arpreq;
1071
1072     BZERO(&arpreq, sizeof(arpreq));
1073     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1074     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1075     if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1076         syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
1077         return 0;
1078     }
1079     return 1;
1080 }
1081 #endif  /* RTM_VERSION */
1082
1083
1084 /*
1085  * get_ether_addr - get the hardware address of an interface on the
1086  * the same subnet as ipaddr.
1087  */
1088 #define MAX_IFS         32
1089
1090 int
1091 get_ether_addr(ipaddr, hwaddr)
1092     u_int32_t ipaddr;
1093     struct sockaddr_dl *hwaddr;
1094 {
1095     struct ifreq *ifr, *ifend, *ifp;
1096     u_int32_t ina, mask;
1097     struct sockaddr_dl *dla;
1098     struct ifreq ifreq;
1099     struct ifconf ifc;
1100     struct ifreq ifs[MAX_IFS];
1101
1102     ifc.ifc_len = sizeof(ifs);
1103     ifc.ifc_req = ifs;
1104     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1105         syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
1106         return 0;
1107     }
1108
1109     /*
1110      * Scan through looking for an interface with an Internet
1111      * address on the same subnet as `ipaddr'.
1112      */
1113     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1114     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1115                 ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) {
1116         if (ifr->ifr_addr.sa_family == AF_INET) {
1117             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1118             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1119             /*
1120              * Check that the interface is up, and not point-to-point
1121              * or loopback.
1122              */
1123             if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1124                 continue;
1125             if ((ifreq.ifr_flags &
1126                  (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1127                  != (IFF_UP|IFF_BROADCAST))
1128                 continue;
1129             /*
1130              * Get its netmask and check that it's on the right subnet.
1131              */
1132             if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1133                 continue;
1134             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1135             if ((ipaddr & mask) != (ina & mask))
1136                 continue;
1137
1138             break;
1139         }
1140     }
1141
1142     if (ifr >= ifend)
1143         return 0;
1144     syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
1145
1146     /*
1147      * Now scan through again looking for a link-level address
1148      * for this interface.
1149      */
1150     ifp = ifr;
1151     for (ifr = ifc.ifc_req; ifr < ifend; ) {
1152         if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0
1153             && ifr->ifr_addr.sa_family == AF_LINK) {
1154             /*
1155              * Found the link-level address - copy it out
1156              */
1157             dla = (struct sockaddr_dl *) &ifr->ifr_addr;
1158             BCOPY(dla, hwaddr, dla->sdl_len);
1159             return 1;
1160         }
1161         ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len);
1162     }
1163
1164     return 0;
1165 }
1166
1167 /*
1168  * Return user specified netmask, modified by any mask we might determine
1169  * for address `addr' (in network byte order).
1170  * Here we scan through the system's list of interfaces, looking for
1171  * any non-point-to-point interfaces which might appear to be on the same
1172  * network as `addr'.  If we find any, we OR in their netmask to the
1173  * user-specified netmask.
1174  */
1175 u_int32_t
1176 GetMask(addr)
1177     u_int32_t addr;
1178 {
1179     u_int32_t mask, nmask, ina;
1180     struct ifreq *ifr, *ifend, ifreq;
1181     struct ifconf ifc;
1182     struct ifreq ifs[MAX_IFS];
1183
1184     addr = ntohl(addr);
1185     if (IN_CLASSA(addr))        /* determine network mask for address class */
1186         nmask = IN_CLASSA_NET;
1187     else if (IN_CLASSB(addr))
1188         nmask = IN_CLASSB_NET;
1189     else
1190         nmask = IN_CLASSC_NET;
1191     /* class D nets are disallowed by bad_ip_adrs */
1192     mask = netmask | htonl(nmask);
1193
1194     /*
1195      * Scan through the system's network interfaces.
1196      */
1197     ifc.ifc_len = sizeof(ifs);
1198     ifc.ifc_req = ifs;
1199     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1200         syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1201         return mask;
1202     }
1203     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1204     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1205                 ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) {
1206         /*
1207          * Check the interface's internet address.
1208          */
1209         if (ifr->ifr_addr.sa_family != AF_INET)
1210             continue;
1211         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1212         if ((ntohl(ina) & nmask) != (addr & nmask))
1213             continue;
1214         /*
1215          * Check that the interface is up, and not point-to-point or loopback.
1216          */
1217         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1218         if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1219             continue;
1220         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1221             != IFF_UP)
1222             continue;
1223         /*
1224          * Get its netmask and OR it into our mask.
1225          */
1226         if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1227             continue;
1228         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1229     }
1230
1231     return mask;
1232 }
1233
1234 /*
1235  * lock - create a lock file for the named lock device
1236  */
1237 #define LOCK_PREFIX     "/var/spool/lock/LCK.."
1238
1239 int
1240 lock(dev)
1241     char *dev;
1242 {
1243     char hdb_lock_buffer[12];
1244     int fd, pid, n;
1245     char *p;
1246
1247     if ((p = strrchr(dev, '/')) != NULL)
1248         dev = p + 1;
1249     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1250     if (lock_file == NULL)
1251         novm("lock file name");
1252     strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1253
1254     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1255         if (errno == EEXIST
1256             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1257             /* Read the lock file to find out who has the device locked */
1258             n = read(fd, hdb_lock_buffer, 11);
1259             if (n > 0) {
1260                 hdb_lock_buffer[n] = 0;
1261                 pid = atoi(hdb_lock_buffer);
1262             }
1263             if (n <= 0) {
1264                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1265                 close(fd);
1266             } else {
1267                 if (kill(pid, 0) == -1 && errno == ESRCH) {
1268                     /* pid no longer exists - remove the lock file */
1269                     if (unlink(lock_file) == 0) {
1270                         close(fd);
1271                         syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1272                                dev, pid);
1273                         continue;
1274                     } else
1275                         syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1276                                dev);
1277                 } else
1278                     syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1279                            dev, pid);
1280             }
1281             close(fd);
1282         } else
1283             syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1284         free(lock_file);
1285         lock_file = NULL;
1286         return -1;
1287     }
1288
1289     sprintf(hdb_lock_buffer, "%10d\n", getpid());
1290     write(fd, hdb_lock_buffer, 11);
1291
1292     close(fd);
1293     return 0;
1294 }
1295
1296 /*
1297  * unlock - remove our lockfile
1298  */
1299 unlock()
1300 {
1301     if (lock_file) {
1302         unlink(lock_file);
1303         free(lock_file);
1304         lock_file = NULL;
1305     }
1306 }