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