2 * sys-bsd.c - System-dependent procedures for setting up
3 * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.)
5 * Copyright (c) 1989 Carnegie Mellon University.
6 * Copyright (c) 1995 The Australian National University.
9 * Redistribution and use in source and binary forms are permitted
10 * provided that the above copyright notice and this paragraph are
11 * duplicated in all such forms and that any documentation,
12 * advertising materials, and other materials related to such
13 * distribution and use acknowledge that the software was developed
14 * by Carnegie Mellon University and The Australian National University.
15 * The names of the Universities may not be used to endorse or promote
16 * products derived from this software without specific prior written
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 #define RCSID "$Id: sys-bsd.c,v 1.47 2000/04/13 12:04:23 paulus Exp $"
24 /* $NetBSD: sys-bsd.c,v 1.1.1.3 1997/09/26 18:53:04 christos Exp $ */
38 #include <sys/ioctl.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
43 #include <sys/param.h>
52 #include <net/ppp_defs.h>
53 #include <net/if_ppp.h>
54 #include <net/route.h>
55 #include <net/if_dl.h>
56 #include <netinet/in.h>
59 #include <sys/param.h>
60 #if defined(NetBSD) && (NetBSD >= 199703)
61 #include <netinet/if_inarp.h>
62 #else /* NetBSD 1.2D or later */
64 #include <netinet/if_ether.h>
66 #include <net/if_ether.h>
75 static const char rcsid
[] = RCSID
;
77 static int initdisc
= -1; /* Initial TTY discipline for ppp_fd */
78 static int initfdflags
= -1; /* Initial file descriptor flags for ppp_fd */
79 static int ppp_fd
= -1; /* fd which is set to PPP discipline */
82 static int restore_term
; /* 1 => we've munged the terminal */
83 static struct termios inittermios
; /* Initial TTY termios */
84 static struct winsize wsinfo
; /* Initial window size info */
86 static int loop_slave
= -1;
87 static int loop_master
;
88 static char loop_name
[20];
90 static unsigned char inbuf
[512]; /* buffer for chars read from loopback */
92 static int sockfd
; /* socket for doing interface ioctls */
94 static fd_set in_fds
; /* set of fds that wait_input waits for */
95 static int max_in_fd
; /* highest fd set in in_fds */
97 static int if_is_up
; /* the interface is currently up */
98 static u_int32_t ifaddrs
[2]; /* local and remote addresses we set */
99 static u_int32_t default_route_gateway
; /* gateway addr for default route */
100 static u_int32_t proxy_arp_addr
; /* remote addr for proxy arp */
102 /* Prototypes for procedures local to this file. */
103 static int dodefaultroute
__P((u_int32_t
, int));
104 static int get_ether_addr
__P((u_int32_t
, struct sockaddr_dl
*));
108 * sys_init - System-dependent initialization.
113 /* Get an internet socket for doing socket ioctl's on. */
114 if ((sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
115 fatal("Couldn't create IP socket: %m");
122 * sys_cleanup - restore any system state we modified before exiting:
123 * mark the interface down, delete default route and/or proxy arp entry.
124 * This should call die() because it's called from die().
132 strlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
133 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifr
) >= 0
134 && ((ifr
.ifr_flags
& IFF_UP
) != 0)) {
135 ifr
.ifr_flags
&= ~IFF_UP
;
136 ioctl(sockfd
, SIOCSIFFLAGS
, &ifr
);
140 cifaddr(0, ifaddrs
[0], ifaddrs
[1]);
141 if (default_route_gateway
)
142 cifdefaultroute(0, 0, default_route_gateway
);
144 cifproxyarp(0, proxy_arp_addr
);
148 * sys_close - Clean up in a child process before execing.
154 if (loop_slave
>= 0) {
161 * sys_check_options - check the options that the user specified
168 warn("DTR/CTS flow control is not supported on this system");
176 * ppp_available - check whether the system has any ppp interfaces
177 * (in fact we check whether we can do an ioctl on ppp0).
184 extern char *no_ppp_msg
;
186 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
187 return 1; /* can't tell */
189 strlcpy(ifr
.ifr_name
, "ppp0", sizeof (ifr
.ifr_name
));
190 ok
= ioctl(s
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) >= 0;
194 This system lacks kernel support for PPP. To include PPP support\n\
195 in the kernel, please follow the steps detailed in the README.bsd\n\
196 file in the ppp-2.2 distribution.\n";
201 * establish_ppp - Turn the serial port into a ppp interface.
207 int pppdisc
= PPPDISC
;
212 * Demand mode - prime the old ppp device to relinquish the unit.
214 if (ioctl(ppp_fd
, PPPIOCXFERUNIT
, 0) < 0)
215 fatal("ioctl(transfer ppp unit): %m");
219 * Save the old line discipline of fd, and set it to PPP.
221 if (ioctl(fd
, TIOCGETD
, &initdisc
) < 0)
222 fatal("ioctl(TIOCGETD): %m");
223 if (ioctl(fd
, TIOCSETD
, &pppdisc
) < 0)
224 fatal("ioctl(TIOCSETD): %m");
228 * Find out which interface we were given.
230 if (ioctl(fd
, PPPIOCGUNIT
, &ifunit
) < 0)
231 fatal("ioctl(PPPIOCGUNIT): %m");
234 * Check that we got the same unit again.
236 if (ioctl(fd
, PPPIOCGUNIT
, &x
) < 0)
237 fatal("ioctl(PPPIOCGUNIT): %m");
239 fatal("transfer_ppp failed: wanted unit %d, got %d", ifunit
, x
);
241 ioctl(loop_slave
, TIOCSETD
, &x
);
247 * Enable debug in the driver if requested.
250 if (ioctl(fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
251 warn("ioctl (PPPIOCGFLAGS): %m");
253 x
|= (kdebugflag
& 0xFF) * SC_DEBUG
;
254 if (ioctl(fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0)
255 warn("ioctl(PPPIOCSFLAGS): %m");
260 * Set device for non-blocking reads.
262 if ((initfdflags
= fcntl(fd
, F_GETFL
)) == -1
263 || fcntl(fd
, F_SETFL
, initfdflags
| O_NONBLOCK
) == -1) {
264 warn("Couldn't set device to non-blocking mode: %m");
271 * restore_loop - reattach the ppp unit to the loopback.
279 * Transfer the ppp interface back to the loopback.
281 if (ioctl(ppp_fd
, PPPIOCXFERUNIT
, 0) < 0)
282 fatal("ioctl(transfer ppp unit): %m");
284 if (ioctl(loop_slave
, TIOCSETD
, &x
) < 0)
285 fatal("ioctl(TIOCSETD): %m");
288 * Check that we got the same unit again.
290 if (ioctl(loop_slave
, PPPIOCGUNIT
, &x
) < 0)
291 fatal("ioctl(PPPIOCGUNIT): %m");
293 fatal("transfer_ppp failed: wanted unit %d, got %d", ifunit
, x
);
299 * disestablish_ppp - Restore the serial port to normal operation.
300 * This shouldn't call die() because it's called from die().
306 /* Reset non-blocking mode on fd. */
307 if (initfdflags
!= -1 && fcntl(fd
, F_SETFL
, initfdflags
) < 0)
308 warn("Couldn't restore device fd flags: %m");
311 /* Restore old line discipline. */
312 if (initdisc
>= 0 && ioctl(fd
, TIOCSETD
, &initdisc
) < 0)
313 error("ioctl(TIOCSETD): %m");
321 * Check whether the link seems not to be 8-bit clean.
329 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) == 0) {
331 switch (~x
& (SC_RCV_B7_0
|SC_RCV_B7_1
|SC_RCV_EVNP
|SC_RCV_ODDP
)) {
333 s
= "bit 7 set to 1";
336 s
= "bit 7 set to 0";
346 warn("Serial link is not 8-bit clean:");
347 warn("All received characters had %s", s
);
353 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
354 * at the requested speed, etc. If `local' is true, set CLOCAL
355 * regardless of whether the modem option was specified.
357 * For *BSD, we assume that speed_t values numerically equal bits/second.
360 set_up_tty(fd
, local
)
365 if (tcgetattr(fd
, &tios
) < 0)
366 fatal("tcgetattr: %m");
370 ioctl(fd
, TIOCGWINSZ
, &wsinfo
);
373 tios
.c_cflag
&= ~(CSIZE
| CSTOPB
| PARENB
| CLOCAL
);
374 if (crtscts
> 0 && !local
) {
377 tios
.c_cflag
|= CDTRCTS
;
380 tios
.c_cflag
|= CRTSCTS
;
381 } else if (crtscts
< 0) {
382 tios
.c_cflag
&= ~CRTSCTS
;
384 tios
.c_cflag
&= ~CDTRCTS
;
388 tios
.c_cflag
|= CS8
| CREAD
| HUPCL
;
390 tios
.c_cflag
|= CLOCAL
;
391 tios
.c_iflag
= IGNBRK
| IGNPAR
;
395 tios
.c_cc
[VTIME
] = 0;
398 tios
.c_iflag
|= IXON
| IXOFF
;
399 tios
.c_cc
[VSTOP
] = 0x13; /* DC3 = XOFF = ^S */
400 tios
.c_cc
[VSTART
] = 0x11; /* DC1 = XON = ^Q */
404 cfsetospeed(&tios
, inspeed
);
405 cfsetispeed(&tios
, inspeed
);
407 inspeed
= cfgetospeed(&tios
);
409 * We can't proceed if the serial port speed is 0,
410 * since that implies that the serial port is disabled.
413 fatal("Baud rate for %s is 0; need explicit baud rate", devnam
);
417 if (tcsetattr(fd
, TCSAFLUSH
, &tios
) < 0)
418 fatal("tcsetattr: %m");
424 * restore_tty - restore the terminal to the saved settings.
431 if (!default_device
) {
433 * Turn off echoing, because otherwise we can get into
434 * a loop with the tty and the modem echoing to each other.
435 * We presume we are the sole user of this tty device, so
436 * when we close it, it will revert to its defaults anyway.
438 inittermios
.c_lflag
&= ~(ECHO
| ECHONL
);
440 if (tcsetattr(fd
, TCSAFLUSH
, &inittermios
) < 0)
442 warn("tcsetattr: %m");
443 ioctl(fd
, TIOCSWINSZ
, &wsinfo
);
449 * setdtr - control the DTR line on the serial port.
450 * This is called from die(), so it shouldn't call die().
456 int modembits
= TIOCM_DTR
;
458 ioctl(fd
, (on
? TIOCMBIS
: TIOCMBIC
), &modembits
);
462 * get_pty - get a pty master/slave pair and chown the slave side
463 * to the uid given. Assumes slave_name points to >= 12 bytes of space.
466 get_pty(master_fdp
, slave_fdp
, slave_name
, uid
)
474 if (openpty(master_fdp
, slave_fdp
, slave_name
, NULL
, NULL
) < 0)
477 fchown(*slave_fdp
, uid
, -1);
478 fchmod(*slave_fdp
, S_IRUSR
| S_IWUSR
);
479 if (tcgetattr(*slave_fdp
, &tios
) == 0) {
480 tios
.c_cflag
&= ~(CSIZE
| CSTOPB
| PARENB
);
481 tios
.c_cflag
|= CS8
| CREAD
;
482 tios
.c_iflag
= IGNPAR
| CLOCAL
;
485 if (tcsetattr(*slave_fdp
, TCSAFLUSH
, &tios
) < 0)
486 warn("couldn't set attributes on pty: %m");
488 warn("couldn't get attributes on pty: %m");
495 * open_ppp_loopback - open the device we use for getting
496 * packets in demand mode, and connect it to a ppp interface.
504 int pppdisc
= PPPDISC
;
506 if (openpty(&loop_master
, &loop_slave
, loop_name
, NULL
, NULL
) < 0)
507 fatal("No free pty for loopback");
508 SYSDEBUG(("using %s for loopback", loop_name
));
510 if (tcgetattr(loop_slave
, &tios
) == 0) {
511 tios
.c_cflag
&= ~(CSIZE
| CSTOPB
| PARENB
);
512 tios
.c_cflag
|= CS8
| CREAD
;
513 tios
.c_iflag
= IGNPAR
;
516 if (tcsetattr(loop_slave
, TCSAFLUSH
, &tios
) < 0)
517 warn("couldn't set attributes on loopback: %m");
520 if ((flags
= fcntl(loop_master
, F_GETFL
)) != -1)
521 if (fcntl(loop_master
, F_SETFL
, flags
| O_NONBLOCK
) == -1)
522 warn("couldn't set loopback to nonblock: %m");
525 if (ioctl(ppp_fd
, TIOCSETD
, &pppdisc
) < 0)
526 fatal("ioctl(TIOCSETD): %m");
529 * Find out which interface we were given.
531 if (ioctl(ppp_fd
, PPPIOCGUNIT
, &ifunit
) < 0)
532 fatal("ioctl(PPPIOCGUNIT): %m");
535 * Enable debug in the driver if requested.
538 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &flags
) < 0) {
539 warn("ioctl (PPPIOCGFLAGS): %m");
541 flags
|= (kdebugflag
& 0xFF) * SC_DEBUG
;
542 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &flags
) < 0)
543 warn("ioctl(PPPIOCSFLAGS): %m");
552 * output - Output PPP packet.
561 dbglog("sent %P", p
, len
);
563 if (write(ttyfd
, p
, len
) < 0) {
571 * wait_input - wait until there is data available,
572 * for the length of time specified by *timo (indefinite
577 struct timeval
*timo
;
583 n
= select(max_in_fd
+ 1, &ready
, NULL
, &ready
, timo
);
584 if (n
< 0 && errno
!= EINTR
)
590 * add_fd - add an fd to the set that wait_input waits for.
601 * remove_fd - remove an fd from the set that wait_input waits for.
611 * wait_loop_output - wait until there is data available on the
612 * loopback, for the length of time specified by *timo (indefinite
616 wait_loop_output(timo
)
617 struct timeval
*timo
;
623 FD_SET(loop_master
, &ready
);
624 n
= select(loop_master
+ 1, &ready
, NULL
, &ready
, timo
);
625 if (n
< 0 && errno
!= EINTR
)
631 * wait_time - wait for a given length of time or until a
632 * signal is received.
636 struct timeval
*timo
;
640 n
= select(0, NULL
, NULL
, NULL
, timo
);
641 if (n
< 0 && errno
!= EINTR
)
648 * read_packet - get a PPP packet from the serial device.
656 if ((len
= read(ttyfd
, buf
, PPP_MTU
+ PPP_HDRLEN
)) < 0) {
657 if (errno
== EWOULDBLOCK
|| errno
== EINTR
)
666 * get_loop_output - read characters from the loopback, form them
667 * into frames, and detect when we want to bring the real link up.
668 * Return value is 1 if we need to bring up the link, 0 otherwise.
676 while ((n
= read(loop_master
, inbuf
, sizeof(inbuf
))) >= 0) {
677 if (loop_chars(inbuf
, n
))
682 fatal("eof on loopback");
683 if (errno
!= EWOULDBLOCK
)
684 fatal("read from loopback: %m");
691 * ppp_send_config - configure the transmit characteristics of
695 ppp_send_config(unit
, mtu
, asyncmap
, pcomp
, accomp
)
703 strlcpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
705 if (ioctl(sockfd
, SIOCSIFMTU
, (caddr_t
) &ifr
) < 0)
706 fatal("ioctl(SIOCSIFMTU): %m");
708 if (ioctl(ppp_fd
, PPPIOCSASYNCMAP
, (caddr_t
) &asyncmap
) < 0)
709 fatal("ioctl(PPPIOCSASYNCMAP): %m");
711 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0)
712 fatal("ioctl (PPPIOCGFLAGS): %m");
713 x
= pcomp
? x
| SC_COMP_PROT
: x
&~ SC_COMP_PROT
;
714 x
= accomp
? x
| SC_COMP_AC
: x
&~ SC_COMP_AC
;
715 x
= sync_serial
? x
| SC_SYNC
: x
& ~SC_SYNC
;
716 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0)
717 fatal("ioctl(PPPIOCSFLAGS): %m");
722 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
725 ppp_set_xaccm(unit
, accm
)
729 if (ioctl(ppp_fd
, PPPIOCSXASYNCMAP
, accm
) < 0 && errno
!= ENOTTY
)
730 warn("ioctl(set extended ACCM): %m");
735 * ppp_recv_config - configure the receive-side characteristics of
739 ppp_recv_config(unit
, mru
, asyncmap
, pcomp
, accomp
)
746 if (ioctl(ppp_fd
, PPPIOCSMRU
, (caddr_t
) &mru
) < 0)
747 fatal("ioctl(PPPIOCSMRU): %m");
748 if (ioctl(ppp_fd
, PPPIOCSRASYNCMAP
, (caddr_t
) &asyncmap
) < 0)
749 fatal("ioctl(PPPIOCSRASYNCMAP): %m");
750 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0)
751 fatal("ioctl (PPPIOCGFLAGS): %m");
752 x
= !accomp
? x
| SC_REJ_COMP_AC
: x
&~ SC_REJ_COMP_AC
;
753 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0)
754 fatal("ioctl(PPPIOCSFLAGS): %m");
758 * ccp_test - ask kernel whether a given compression method
759 * is acceptable for use. Returns 1 if the method and parameters
760 * are OK, 0 if the method is known but the parameters are not OK
761 * (e.g. code size should be reduced), or -1 if the method is unknown.
764 ccp_test(unit
, opt_ptr
, opt_len
, for_transmit
)
765 int unit
, opt_len
, for_transmit
;
768 struct ppp_option_data data
;
771 data
.length
= opt_len
;
772 data
.transmit
= for_transmit
;
773 if (ioctl(ttyfd
, PPPIOCSCOMPRESS
, (caddr_t
) &data
) >= 0)
775 return (errno
== ENOBUFS
)? 0: -1;
779 * ccp_flags_set - inform kernel about the current state of CCP.
782 ccp_flags_set(unit
, isopen
, isup
)
783 int unit
, isopen
, isup
;
787 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
788 error("ioctl (PPPIOCGFLAGS): %m");
791 x
= isopen
? x
| SC_CCP_OPEN
: x
&~ SC_CCP_OPEN
;
792 x
= isup
? x
| SC_CCP_UP
: x
&~ SC_CCP_UP
;
793 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0)
794 error("ioctl(PPPIOCSFLAGS): %m");
798 * ccp_fatal_error - returns 1 if decompression was disabled as a
799 * result of an error detected after decompression of a packet,
800 * 0 otherwise. This is necessary because of patent nonsense.
803 ccp_fatal_error(unit
)
808 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
809 error("ioctl(PPPIOCGFLAGS): %m");
812 return x
& SC_DC_FERROR
;
816 * get_idle_time - return how long the link has been idle.
823 return ioctl(ppp_fd
, PPPIOCGIDLE
, ip
) >= 0;
827 * get_ppp_stats - return statistics for the link.
830 get_ppp_stats(u
, stats
)
832 struct pppd_stats
*stats
;
834 struct ifpppstatsreq req
;
836 memset (&req
, 0, sizeof (req
));
837 strlcpy(req
.ifr_name
, ifname
, sizeof(req
.ifr_name
));
838 if (ioctl(sockfd
, SIOCGPPPSTATS
, &req
) < 0) {
839 error("Couldn't get PPP statistics: %m");
842 stats
->bytes_in
= req
.stats
.p
.ppp_ibytes
;
843 stats
->bytes_out
= req
.stats
.p
.ppp_obytes
;
850 * set_filters - transfer the pass and active filters to the kernel.
853 set_filters(pass
, active
)
854 struct bpf_program
*pass
, *active
;
858 if (pass
->bf_len
> 0) {
859 if (ioctl(ppp_fd
, PPPIOCSPASS
, pass
) < 0) {
860 error("Couldn't set pass-filter in kernel: %m");
864 if (active
->bf_len
> 0) {
865 if (ioctl(ppp_fd
, PPPIOCSACTIVE
, active
) < 0) {
866 error("Couldn't set active-filter in kernel: %m");
875 * sifvjcomp - config tcp header compression
878 sifvjcomp(u
, vjcomp
, cidcomp
, maxcid
)
879 int u
, vjcomp
, cidcomp
, maxcid
;
883 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
884 error("ioctl (PPPIOCGFLAGS): %m");
887 x
= vjcomp
? x
| SC_COMP_TCP
: x
&~ SC_COMP_TCP
;
888 x
= cidcomp
? x
& ~SC_NO_TCP_CCID
: x
| SC_NO_TCP_CCID
;
889 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0) {
890 error("ioctl(PPPIOCSFLAGS): %m");
893 if (vjcomp
&& ioctl(ppp_fd
, PPPIOCSMAXCID
, (caddr_t
) &maxcid
) < 0) {
894 error("ioctl(PPPIOCSFLAGS): %m");
901 * sifup - Config the interface up and enable IP packets to pass.
909 strlcpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
910 if (ioctl(sockfd
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) < 0) {
911 error("ioctl (SIOCGIFFLAGS): %m");
914 ifr
.ifr_flags
|= IFF_UP
;
915 if (ioctl(sockfd
, SIOCSIFFLAGS
, (caddr_t
) &ifr
) < 0) {
916 error("ioctl(SIOCSIFFLAGS): %m");
924 * sifnpmode - Set the mode for handling packets for a given NP.
927 sifnpmode(u
, proto
, mode
)
934 npi
.protocol
= proto
;
936 if (ioctl(ppp_fd
, PPPIOCSNPMODE
, &npi
) < 0) {
937 error("ioctl(set NP %d mode to %d): %m", proto
, mode
);
944 * sifdown - Config the interface down and disable IP.
955 npi
.protocol
= PPP_IP
;
956 npi
.mode
= NPMODE_ERROR
;
957 ioctl(ppp_fd
, PPPIOCSNPMODE
, (caddr_t
) &npi
);
958 /* ignore errors, because ppp_fd might have been closed by now. */
960 strlcpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
961 if (ioctl(sockfd
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) < 0) {
962 error("ioctl (SIOCGIFFLAGS): %m");
965 ifr
.ifr_flags
&= ~IFF_UP
;
966 if (ioctl(sockfd
, SIOCSIFFLAGS
, (caddr_t
) &ifr
) < 0) {
967 error("ioctl(SIOCSIFFLAGS): %m");
976 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
979 #define SET_SA_FAMILY(addr, family) \
980 BZERO((char *) &(addr), sizeof(addr)); \
981 addr.sa_family = (family); \
982 addr.sa_len = sizeof(addr);
985 * sifaddr - Config the interface IP addresses and netmask.
992 struct ifaliasreq ifra
;
995 strlcpy(ifra
.ifra_name
, ifname
, sizeof(ifra
.ifra_name
));
996 SET_SA_FAMILY(ifra
.ifra_addr
, AF_INET
);
997 ((struct sockaddr_in
*) &ifra
.ifra_addr
)->sin_addr
.s_addr
= o
;
998 SET_SA_FAMILY(ifra
.ifra_broadaddr
, AF_INET
);
999 ((struct sockaddr_in
*) &ifra
.ifra_broadaddr
)->sin_addr
.s_addr
= h
;
1001 SET_SA_FAMILY(ifra
.ifra_mask
, AF_INET
);
1002 ((struct sockaddr_in
*) &ifra
.ifra_mask
)->sin_addr
.s_addr
= m
;
1004 BZERO(&ifra
.ifra_mask
, sizeof(ifra
.ifra_mask
));
1005 BZERO(&ifr
, sizeof(ifr
));
1006 strlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
1007 if (ioctl(sockfd
, SIOCDIFADDR
, (caddr_t
) &ifr
) < 0) {
1008 if (errno
!= EADDRNOTAVAIL
)
1009 warn("Couldn't remove interface address: %m");
1011 if (ioctl(sockfd
, SIOCAIFADDR
, (caddr_t
) &ifra
) < 0) {
1012 if (errno
!= EEXIST
) {
1013 error("Couldn't set interface address: %m");
1016 warn("Couldn't set interface address: Address %I already exists", o
);
1024 * cifaddr - Clear the interface IP addresses, and delete routes
1025 * through the interface if possible.
1032 struct ifaliasreq ifra
;
1035 strlcpy(ifra
.ifra_name
, ifname
, sizeof(ifra
.ifra_name
));
1036 SET_SA_FAMILY(ifra
.ifra_addr
, AF_INET
);
1037 ((struct sockaddr_in
*) &ifra
.ifra_addr
)->sin_addr
.s_addr
= o
;
1038 SET_SA_FAMILY(ifra
.ifra_broadaddr
, AF_INET
);
1039 ((struct sockaddr_in
*) &ifra
.ifra_broadaddr
)->sin_addr
.s_addr
= h
;
1040 BZERO(&ifra
.ifra_mask
, sizeof(ifra
.ifra_mask
));
1041 if (ioctl(sockfd
, SIOCDIFADDR
, (caddr_t
) &ifra
) < 0) {
1042 if (errno
!= EADDRNOTAVAIL
)
1043 warn("Couldn't delete interface address: %m");
1050 * sifdefaultroute - assign a default route through the address given.
1053 sifdefaultroute(u
, l
, g
)
1057 return dodefaultroute(g
, 's');
1061 * cifdefaultroute - delete a default route through the address given.
1064 cifdefaultroute(u
, l
, g
)
1068 return dodefaultroute(g
, 'c');
1072 * dodefaultroute - talk to a routing socket to add/delete a default route.
1075 dodefaultroute(g
, cmd
)
1081 struct rt_msghdr hdr
;
1082 struct sockaddr_in dst
;
1083 struct sockaddr_in gway
;
1084 struct sockaddr_in mask
;
1087 if ((routes
= socket(PF_ROUTE
, SOCK_RAW
, AF_INET
)) < 0) {
1088 error("Couldn't %s default route: socket: %m",
1089 cmd
=='s'? "add": "delete");
1093 memset(&rtmsg
, 0, sizeof(rtmsg
));
1094 rtmsg
.hdr
.rtm_type
= cmd
== 's'? RTM_ADD
: RTM_DELETE
;
1095 rtmsg
.hdr
.rtm_flags
= RTF_UP
| RTF_GATEWAY
| RTF_STATIC
;
1096 rtmsg
.hdr
.rtm_version
= RTM_VERSION
;
1097 rtmsg
.hdr
.rtm_seq
= ++rtm_seq
;
1098 rtmsg
.hdr
.rtm_addrs
= RTA_DST
| RTA_GATEWAY
| RTA_NETMASK
;
1099 rtmsg
.dst
.sin_len
= sizeof(rtmsg
.dst
);
1100 rtmsg
.dst
.sin_family
= AF_INET
;
1101 rtmsg
.gway
.sin_len
= sizeof(rtmsg
.gway
);
1102 rtmsg
.gway
.sin_family
= AF_INET
;
1103 rtmsg
.gway
.sin_addr
.s_addr
= g
;
1104 rtmsg
.mask
.sin_len
= sizeof(rtmsg
.dst
);
1105 rtmsg
.mask
.sin_family
= AF_INET
;
1107 rtmsg
.hdr
.rtm_msglen
= sizeof(rtmsg
);
1108 if (write(routes
, &rtmsg
, sizeof(rtmsg
)) < 0) {
1109 error("Couldn't %s default route: %m",
1110 cmd
=='s'? "add": "delete");
1116 default_route_gateway
= (cmd
== 's')? g
: 0;
1120 #if RTM_VERSION >= 3
1123 * sifproxyarp - Make a proxy ARP entry for the peer.
1126 struct rt_msghdr hdr
;
1127 struct sockaddr_inarp dst
;
1128 struct sockaddr_dl hwa
;
1132 static int arpmsg_valid
;
1135 sifproxyarp(unit
, hisaddr
)
1142 * Get the hardware address of an interface on the same subnet
1143 * as our local address.
1145 memset(&arpmsg
, 0, sizeof(arpmsg
));
1146 if (!get_ether_addr(hisaddr
, &arpmsg
.hwa
)) {
1147 error("Cannot determine ethernet address for proxy ARP");
1151 if ((routes
= socket(PF_ROUTE
, SOCK_RAW
, AF_INET
)) < 0) {
1152 error("Couldn't add proxy arp entry: socket: %m");
1156 arpmsg
.hdr
.rtm_type
= RTM_ADD
;
1157 arpmsg
.hdr
.rtm_flags
= RTF_ANNOUNCE
| RTF_HOST
| RTF_STATIC
;
1158 arpmsg
.hdr
.rtm_version
= RTM_VERSION
;
1159 arpmsg
.hdr
.rtm_seq
= ++rtm_seq
;
1160 arpmsg
.hdr
.rtm_addrs
= RTA_DST
| RTA_GATEWAY
;
1161 arpmsg
.hdr
.rtm_inits
= RTV_EXPIRE
;
1162 arpmsg
.dst
.sin_len
= sizeof(struct sockaddr_inarp
);
1163 arpmsg
.dst
.sin_family
= AF_INET
;
1164 arpmsg
.dst
.sin_addr
.s_addr
= hisaddr
;
1165 arpmsg
.dst
.sin_other
= SIN_PROXY
;
1167 arpmsg
.hdr
.rtm_msglen
= (char *) &arpmsg
.hwa
- (char *) &arpmsg
1168 + arpmsg
.hwa
.sdl_len
;
1169 if (write(routes
, &arpmsg
, arpmsg
.hdr
.rtm_msglen
) < 0) {
1170 error("Couldn't add proxy arp entry: %m");
1177 proxy_arp_addr
= hisaddr
;
1182 * cifproxyarp - Delete the proxy ARP entry for the peer.
1185 cifproxyarp(unit
, hisaddr
)
1195 arpmsg
.hdr
.rtm_type
= RTM_DELETE
;
1196 arpmsg
.hdr
.rtm_seq
= ++rtm_seq
;
1198 if ((routes
= socket(PF_ROUTE
, SOCK_RAW
, AF_INET
)) < 0) {
1199 error("Couldn't delete proxy arp entry: socket: %m");
1203 if (write(routes
, &arpmsg
, arpmsg
.hdr
.rtm_msglen
) < 0) {
1204 error("Couldn't delete proxy arp entry: %m");
1214 #else /* RTM_VERSION */
1217 * sifproxyarp - Make a proxy ARP entry for the peer.
1220 sifproxyarp(unit
, hisaddr
)
1224 struct arpreq arpreq
;
1226 struct sockaddr_dl sdl
;
1230 BZERO(&arpreq
, sizeof(arpreq
));
1233 * Get the hardware address of an interface on the same subnet
1234 * as our local address.
1236 if (!get_ether_addr(hisaddr
, &dls
.sdl
)) {
1237 error("Cannot determine ethernet address for proxy ARP");
1241 arpreq
.arp_ha
.sa_len
= sizeof(struct sockaddr
);
1242 arpreq
.arp_ha
.sa_family
= AF_UNSPEC
;
1243 BCOPY(LLADDR(&dls
.sdl
), arpreq
.arp_ha
.sa_data
, dls
.sdl
.sdl_alen
);
1244 SET_SA_FAMILY(arpreq
.arp_pa
, AF_INET
);
1245 ((struct sockaddr_in
*) &arpreq
.arp_pa
)->sin_addr
.s_addr
= hisaddr
;
1246 arpreq
.arp_flags
= ATF_PERM
| ATF_PUBL
;
1247 if (ioctl(sockfd
, SIOCSARP
, (caddr_t
)&arpreq
) < 0) {
1248 error("Couldn't add proxy arp entry: %m");
1252 proxy_arp_addr
= hisaddr
;
1257 * cifproxyarp - Delete the proxy ARP entry for the peer.
1260 cifproxyarp(unit
, hisaddr
)
1264 struct arpreq arpreq
;
1266 BZERO(&arpreq
, sizeof(arpreq
));
1267 SET_SA_FAMILY(arpreq
.arp_pa
, AF_INET
);
1268 ((struct sockaddr_in
*) &arpreq
.arp_pa
)->sin_addr
.s_addr
= hisaddr
;
1269 if (ioctl(sockfd
, SIOCDARP
, (caddr_t
)&arpreq
) < 0) {
1270 warn("Couldn't delete proxy arp entry: %m");
1276 #endif /* RTM_VERSION */
1280 * get_ether_addr - get the hardware address of an interface on the
1281 * the same subnet as ipaddr.
1286 get_ether_addr(ipaddr
, hwaddr
)
1288 struct sockaddr_dl
*hwaddr
;
1290 struct ifreq
*ifr
, *ifend
, *ifp
;
1291 u_int32_t ina
, mask
;
1292 struct sockaddr_dl
*dla
;
1295 struct ifreq ifs
[MAX_IFS
];
1297 ifc
.ifc_len
= sizeof(ifs
);
1299 if (ioctl(sockfd
, SIOCGIFCONF
, &ifc
) < 0) {
1300 error("ioctl(SIOCGIFCONF): %m");
1305 * Scan through looking for an interface with an Internet
1306 * address on the same subnet as `ipaddr'.
1308 ifend
= (struct ifreq
*) (ifc
.ifc_buf
+ ifc
.ifc_len
);
1309 for (ifr
= ifc
.ifc_req
; ifr
< ifend
; ifr
= (struct ifreq
*)
1310 ((char *)&ifr
->ifr_addr
+ ifr
->ifr_addr
.sa_len
)) {
1311 if (ifr
->ifr_addr
.sa_family
== AF_INET
) {
1312 ina
= ((struct sockaddr_in
*) &ifr
->ifr_addr
)->sin_addr
.s_addr
;
1313 strlcpy(ifreq
.ifr_name
, ifr
->ifr_name
, sizeof(ifreq
.ifr_name
));
1315 * Check that the interface is up, and not point-to-point
1318 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifreq
) < 0)
1320 if ((ifreq
.ifr_flags
&
1321 (IFF_UP
|IFF_BROADCAST
|IFF_POINTOPOINT
|IFF_LOOPBACK
|IFF_NOARP
))
1322 != (IFF_UP
|IFF_BROADCAST
))
1325 * Get its netmask and check that it's on the right subnet.
1327 if (ioctl(sockfd
, SIOCGIFNETMASK
, &ifreq
) < 0)
1329 mask
= ((struct sockaddr_in
*) &ifreq
.ifr_addr
)->sin_addr
.s_addr
;
1330 if ((ipaddr
& mask
) != (ina
& mask
))
1339 info("found interface %s for proxy arp", ifr
->ifr_name
);
1342 * Now scan through again looking for a link-level address
1343 * for this interface.
1346 for (ifr
= ifc
.ifc_req
; ifr
< ifend
; ) {
1347 if (strcmp(ifp
->ifr_name
, ifr
->ifr_name
) == 0
1348 && ifr
->ifr_addr
.sa_family
== AF_LINK
) {
1350 * Found the link-level address - copy it out
1352 dla
= (struct sockaddr_dl
*) &ifr
->ifr_addr
;
1353 BCOPY(dla
, hwaddr
, dla
->sdl_len
);
1356 ifr
= (struct ifreq
*) ((char *)&ifr
->ifr_addr
+ ifr
->ifr_addr
.sa_len
);
1363 * Return user specified netmask, modified by any mask we might determine
1364 * for address `addr' (in network byte order).
1365 * Here we scan through the system's list of interfaces, looking for
1366 * any non-point-to-point interfaces which might appear to be on the same
1367 * network as `addr'. If we find any, we OR in their netmask to the
1368 * user-specified netmask.
1374 u_int32_t mask
, nmask
, ina
;
1375 struct ifreq
*ifr
, *ifend
, ifreq
;
1377 struct ifreq ifs
[MAX_IFS
];
1380 if (IN_CLASSA(addr
)) /* determine network mask for address class */
1381 nmask
= IN_CLASSA_NET
;
1382 else if (IN_CLASSB(addr
))
1383 nmask
= IN_CLASSB_NET
;
1385 nmask
= IN_CLASSC_NET
;
1386 /* class D nets are disallowed by bad_ip_adrs */
1387 mask
= netmask
| htonl(nmask
);
1390 * Scan through the system's network interfaces.
1392 ifc
.ifc_len
= sizeof(ifs
);
1394 if (ioctl(sockfd
, SIOCGIFCONF
, &ifc
) < 0) {
1395 warn("ioctl(SIOCGIFCONF): %m");
1398 ifend
= (struct ifreq
*) (ifc
.ifc_buf
+ ifc
.ifc_len
);
1399 for (ifr
= ifc
.ifc_req
; ifr
< ifend
; ifr
= (struct ifreq
*)
1400 ((char *)&ifr
->ifr_addr
+ ifr
->ifr_addr
.sa_len
)) {
1402 * Check the interface's internet address.
1404 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
1406 ina
= ((struct sockaddr_in
*) &ifr
->ifr_addr
)->sin_addr
.s_addr
;
1407 if ((ntohl(ina
) & nmask
) != (addr
& nmask
))
1410 * Check that the interface is up, and not point-to-point or loopback.
1412 strlcpy(ifreq
.ifr_name
, ifr
->ifr_name
, sizeof(ifreq
.ifr_name
));
1413 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifreq
) < 0)
1415 if ((ifreq
.ifr_flags
& (IFF_UP
|IFF_POINTOPOINT
|IFF_LOOPBACK
))
1419 * Get its netmask and OR it into our mask.
1421 if (ioctl(sockfd
, SIOCGIFNETMASK
, &ifreq
) < 0)
1423 mask
|= ((struct sockaddr_in
*)&ifreq
.ifr_addr
)->sin_addr
.s_addr
;
1430 * have_route_to - determine if the system has any route to
1431 * a given IP address.
1432 * For demand mode to work properly, we have to ignore routes
1433 * through our own interface.
1435 int have_route_to(u_int32_t addr
)
1441 * Use the hostid as part of the random number seed.
1451 * lock - create a lock file for the named lock device
1453 #define LOCK_PREFIX "/var/spool/lock/LCK.."
1455 static char *lock_file
; /* name of lock file created */
1461 char hdb_lock_buffer
[12];
1466 if ((p
= strrchr(dev
, '/')) != NULL
)
1468 l
= strlen(LOCK_PREFIX
) + strlen(dev
) + 1;
1469 lock_file
= malloc(l
);
1470 if (lock_file
== NULL
)
1471 novm("lock file name");
1472 slprintf(lock_file
, l
, "%s%s", LOCK_PREFIX
, dev
);
1474 while ((fd
= open(lock_file
, O_EXCL
| O_CREAT
| O_RDWR
, 0644)) < 0) {
1476 && (fd
= open(lock_file
, O_RDONLY
, 0)) >= 0) {
1477 /* Read the lock file to find out who has the device locked */
1478 n
= read(fd
, hdb_lock_buffer
, 11);
1480 error("Can't read pid from lock file %s", lock_file
);
1483 hdb_lock_buffer
[n
] = 0;
1484 pid
= atoi(hdb_lock_buffer
);
1485 if (kill(pid
, 0) == -1 && errno
== ESRCH
) {
1486 /* pid no longer exists - remove the lock file */
1487 if (unlink(lock_file
) == 0) {
1489 notice("Removed stale lock on %s (pid %d)",
1493 warn("Couldn't remove stale lock on %s",
1496 notice("Device %s is locked by pid %d",
1501 error("Can't create lock file %s: %m", lock_file
);
1507 slprintf(hdb_lock_buffer
, sizeof(hdb_lock_buffer
), "%10d\n", getpid());
1508 write(fd
, hdb_lock_buffer
, 11);
1515 * unlock - remove our lockfile