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.
22 * $FreeBSD: src/usr.sbin/pppd/sys-bsd.c,v 1.17.2.1 2002/09/17 16:53:55 nectar Exp $
25 /* $NetBSD: sys-bsd.c,v 1.1.1.3 1997/09/26 18:53:04 christos Exp $ */
41 #include <sys/ioctl.h>
42 #include <sys/types.h>
43 #include <sys/socket.h>
46 #include <sys/param.h>
55 #include <net/ppp_layer/ppp_defs.h>
56 #include <net/ppp/if_ppp.h>
57 #include <net/route.h>
58 #include <net/if_dl.h>
59 #include <netinet/in.h>
62 #include <sys/param.h>
63 #if defined(NetBSD) && (NetBSD >= 199703)
64 #include <netinet/if_inarp.h>
65 #else /* NetBSD 1.2D or later */
67 #include <netinet/if_ether.h>
69 #include <net/if_ether.h>
78 static int initdisc
= -1; /* Initial TTY discipline for ppp_fd */
79 static int initfdflags
= -1; /* Initial file descriptor flags for ppp_fd */
80 static int ppp_fd
= -1; /* fd which is set to PPP discipline */
83 static int restore_term
; /* 1 => we've munged the terminal */
84 static struct termios inittermios
; /* Initial TTY termios */
85 static struct winsize wsinfo
; /* Initial window size info */
87 static char *lock_file
; /* name of lock file created */
89 static int loop_slave
= -1;
90 static int loop_master
;
91 static char loop_name
[20];
93 static unsigned char inbuf
[512]; /* buffer for chars read from loopback */
95 static int sockfd
; /* socket for doing interface ioctls */
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(u_int32_t
, int);
104 static int get_ether_addr(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 syslog(LOG_ERR
, "Couldn't create IP socket: %m");
121 * sys_cleanup - restore any system state we modified before exiting:
122 * mark the interface down, delete default route and/or proxy arp entry.
123 * This should call die() because it's called from die().
131 strncpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
132 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifr
) >= 0
133 && ((ifr
.ifr_flags
& IFF_UP
) != 0)) {
134 ifr
.ifr_flags
&= ~IFF_UP
;
135 ioctl(sockfd
, SIOCSIFFLAGS
, &ifr
);
139 cifaddr(0, ifaddrs
[0], ifaddrs
[1]);
140 if (default_route_gateway
)
141 cifdefaultroute(0, 0, default_route_gateway
);
143 cifproxyarp(0, proxy_arp_addr
);
147 * sys_close - Clean up in a child process before execing.
153 if (loop_slave
>= 0) {
160 * sys_check_options - check the options that the user specified
163 sys_check_options(void)
168 * ppp_available - check whether the system has any ppp interfaces
169 * (in fact we check whether we can do an ioctl on ppp0).
176 extern char *no_ppp_msg
;
178 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
179 return 1; /* can't tell */
181 strncpy(ifr
.ifr_name
, "ppp0", sizeof (ifr
.ifr_name
));
182 ok
= ioctl(s
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) >= 0;
186 This system lacks kernel support for PPP. To include PPP support\n\
187 in the kernel, please follow the steps detailed in the README.bsd\n\
188 file in the ppp-2.2 distribution.\n";
193 * establish_ppp - Turn the serial port into a ppp interface.
196 establish_ppp(int fd
)
198 int pppdisc
= PPPDISC
;
203 * Demand mode - prime the old ppp device to relinquish the unit.
205 if (ioctl(ppp_fd
, PPPIOCXFERUNIT
, 0) < 0) {
206 syslog(LOG_ERR
, "ioctl(transfer ppp unit): %m");
212 * Save the old line discipline of fd, and set it to PPP.
214 if (ioctl(fd
, TIOCGETD
, &initdisc
) < 0) {
215 syslog(LOG_ERR
, "ioctl(TIOCGETD): %m");
218 if (ioctl(fd
, TIOCSETD
, &pppdisc
) < 0) {
219 syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
225 * Find out which interface we were given.
227 if (ioctl(fd
, PPPIOCGUNIT
, &ifunit
) < 0) {
228 syslog(LOG_ERR
, "ioctl(PPPIOCGUNIT): %m");
233 * Check that we got the same unit again.
235 if (ioctl(fd
, PPPIOCGUNIT
, &x
) < 0) {
236 syslog(LOG_ERR
, "ioctl(PPPIOCGUNIT): %m");
240 syslog(LOG_ERR
, "transfer_ppp failed: wanted unit %d, got %d",
245 ioctl(loop_slave
, TIOCSETD
, &x
);
251 * Enable debug in the driver if requested.
254 if (ioctl(fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
255 syslog(LOG_WARNING
, "ioctl (PPPIOCGFLAGS): %m");
257 x
|= (kdebugflag
& 0xFF) * SC_DEBUG
;
258 if (ioctl(fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0)
259 syslog(LOG_WARNING
, "ioctl(PPPIOCSFLAGS): %m");
264 * Set device for non-blocking reads.
266 if ((initfdflags
= fcntl(fd
, F_GETFL
)) == -1
267 || fcntl(fd
, F_SETFL
, initfdflags
| O_NONBLOCK
) == -1) {
268 syslog(LOG_WARNING
, "Couldn't set device to non-blocking mode: %m");
273 * restore_loop - reattach the ppp unit to the loopback.
281 * Transfer the ppp interface back to the loopback.
283 if (ioctl(ppp_fd
, PPPIOCXFERUNIT
, 0) < 0) {
284 syslog(LOG_ERR
, "ioctl(transfer ppp unit): %m");
288 if (ioctl(loop_slave
, TIOCSETD
, &x
) < 0) {
289 syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
294 * Check that we got the same unit again.
296 if (ioctl(loop_slave
, PPPIOCGUNIT
, &x
) < 0) {
297 syslog(LOG_ERR
, "ioctl(PPPIOCGUNIT): %m");
301 syslog(LOG_ERR
, "transfer_ppp failed: wanted unit %d, got %d",
310 * disestablish_ppp - Restore the serial port to normal operation.
311 * This shouldn't call die() because it's called from die().
314 disestablish_ppp(int fd
)
316 /* Reset non-blocking mode on fd. */
317 if (initfdflags
!= -1 && fcntl(fd
, F_SETFL
, initfdflags
) < 0)
318 syslog(LOG_WARNING
, "Couldn't restore device fd flags: %m");
321 /* Restore old line discipline. */
322 if (initdisc
>= 0 && ioctl(fd
, TIOCSETD
, &initdisc
) < 0)
323 syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
331 * Check whether the link seems not to be 8-bit clean.
339 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) == 0) {
341 switch (~x
& (SC_RCV_B7_0
|SC_RCV_B7_1
|SC_RCV_EVNP
|SC_RCV_ODDP
)) {
343 s
= "bit 7 set to 1";
346 s
= "bit 7 set to 0";
356 syslog(LOG_WARNING
, "Serial link is not 8-bit clean:");
357 syslog(LOG_WARNING
, "All received characters had %s", s
);
363 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
364 * at the requested speed, etc. If `local' is true, set CLOCAL
365 * regardless of whether the modem option was specified.
367 * For *BSD, we assume that speed_t values numerically equal bits/second.
370 set_up_tty(int fd
, int local
)
374 if (tcgetattr(fd
, &tios
) < 0) {
375 syslog(LOG_ERR
, "tcgetattr: %m");
381 ioctl(fd
, TIOCGWINSZ
, &wsinfo
);
384 tios
.c_cflag
&= ~(CSIZE
| CSTOPB
| PARENB
| CLOCAL
);
385 if (crtscts
> 0 && !local
)
386 tios
.c_cflag
|= CRTSCTS
;
387 else if (crtscts
< 0)
388 tios
.c_cflag
&= ~CRTSCTS
;
390 tios
.c_cflag
|= CS8
| CREAD
| HUPCL
;
392 tios
.c_cflag
|= CLOCAL
;
393 tios
.c_iflag
= IGNBRK
| IGNPAR
;
397 tios
.c_cc
[VTIME
] = 0;
400 tios
.c_iflag
|= IXON
| IXOFF
;
401 tios
.c_cc
[VSTOP
] = 0x13; /* DC3 = XOFF = ^S */
402 tios
.c_cc
[VSTART
] = 0x11; /* DC1 = XON = ^Q */
406 cfsetospeed(&tios
, inspeed
);
407 cfsetispeed(&tios
, inspeed
);
409 inspeed
= cfgetospeed(&tios
);
411 * We can't proceed if the serial port speed is 0,
412 * since that implies that the serial port is disabled.
415 syslog(LOG_ERR
, "Baud rate for %s is 0; need explicit baud rate",
422 if (tcsetattr(fd
, TCSAFLUSH
, &tios
) < 0) {
423 syslog(LOG_ERR
, "tcsetattr: %m");
431 * restore_tty - restore the terminal to the saved settings.
437 if (!default_device
) {
439 * Turn off echoing, because otherwise we can get into
440 * a loop with the tty and the modem echoing to each other.
441 * We presume we are the sole user of this tty device, so
442 * when we close it, it will revert to its defaults anyway.
444 inittermios
.c_lflag
&= ~(ECHO
| ECHONL
);
446 if (tcsetattr(fd
, TCSAFLUSH
, &inittermios
) < 0)
448 syslog(LOG_WARNING
, "tcsetattr: %m");
449 ioctl(fd
, TIOCSWINSZ
, &wsinfo
);
455 * setdtr - control the DTR line on the serial port.
456 * This is called from die(), so it shouldn't call die().
459 setdtr(int fd
, int on
)
461 int modembits
= TIOCM_DTR
;
463 ioctl(fd
, (on
? TIOCMBIS
: TIOCMBIC
), &modembits
);
468 * open_ppp_loopback - open the device we use for getting
469 * packets in demand mode, and connect it to a ppp interface.
473 open_ppp_loopback(void)
477 int pppdisc
= PPPDISC
;
479 if (openpty(&loop_master
, &loop_slave
, loop_name
, NULL
, NULL
) < 0) {
480 syslog(LOG_ERR
, "No free pty for loopback");
483 SYSDEBUG((LOG_DEBUG
, "using %s for loopback", loop_name
));
485 if (tcgetattr(loop_slave
, &tios
) == 0) {
486 tios
.c_cflag
&= ~(CSIZE
| CSTOPB
| PARENB
);
487 tios
.c_cflag
|= CS8
| CREAD
;
488 tios
.c_iflag
= IGNPAR
;
491 if (tcsetattr(loop_slave
, TCSAFLUSH
, &tios
) < 0)
492 syslog(LOG_WARNING
, "couldn't set attributes on loopback: %m");
495 if ((flags
= fcntl(loop_master
, F_GETFL
)) != -1)
496 if (fcntl(loop_master
, F_SETFL
, flags
| O_NONBLOCK
) == -1)
497 syslog(LOG_WARNING
, "couldn't set loopback to nonblock: %m");
500 if (ioctl(ppp_fd
, TIOCSETD
, &pppdisc
) < 0) {
501 syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
506 * Find out which interface we were given.
508 if (ioctl(ppp_fd
, PPPIOCGUNIT
, &ifunit
) < 0) {
509 syslog(LOG_ERR
, "ioctl(PPPIOCGUNIT): %m");
514 * Enable debug in the driver if requested.
517 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &flags
) < 0) {
518 syslog(LOG_WARNING
, "ioctl (PPPIOCGFLAGS): %m");
520 flags
|= (kdebugflag
& 0xFF) * SC_DEBUG
;
521 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &flags
) < 0)
522 syslog(LOG_WARNING
, "ioctl(PPPIOCSFLAGS): %m");
530 * output - Output PPP packet.
533 output(int unit
, u_char
*p
, int len
)
536 log_packet(p
, len
, "sent ", LOG_DEBUG
);
538 if (write(ttyfd
, p
, len
) < 0) {
540 syslog(LOG_ERR
, "write: %m");
546 * wait_input - wait until there is data available on ttyfd,
547 * for the length of time specified by *timo (indefinite
551 wait_input(struct timeval
*timo
)
556 if (ttyfd
>= FD_SETSIZE
) {
557 syslog(LOG_ERR
, "descriptor too big");
561 FD_SET(ttyfd
, &ready
);
562 n
= select(ttyfd
+1, &ready
, NULL
, &ready
, timo
);
563 if (n
< 0 && errno
!= EINTR
) {
564 syslog(LOG_ERR
, "select: %m");
571 * wait_loop_output - wait until there is data available on the
572 * loopback, for the length of time specified by *timo (indefinite
576 wait_loop_output(struct timeval
*timo
)
581 if (loop_master
>= FD_SETSIZE
) {
582 syslog(LOG_ERR
, "descriptor too big");
586 FD_SET(loop_master
, &ready
);
587 n
= select(loop_master
+ 1, &ready
, NULL
, &ready
, timo
);
588 if (n
< 0 && errno
!= EINTR
) {
589 syslog(LOG_ERR
, "select: %m");
596 * wait_time - wait for a given length of time or until a
597 * signal is received.
600 wait_time(struct timeval
*timo
)
604 n
= select(0, NULL
, NULL
, NULL
, timo
);
605 if (n
< 0 && errno
!= EINTR
) {
606 syslog(LOG_ERR
, "select: %m");
613 * read_packet - get a PPP packet from the serial device.
616 read_packet(u_char
*buf
)
620 if ((len
= read(ttyfd
, buf
, PPP_MTU
+ PPP_HDRLEN
)) < 0) {
621 if (errno
== EWOULDBLOCK
|| errno
== EINTR
)
623 syslog(LOG_ERR
, "read: %m");
631 * get_loop_output - read characters from the loopback, form them
632 * into frames, and detect when we want to bring the real link up.
633 * Return value is 1 if we need to bring up the link, 0 otherwise.
636 get_loop_output(void)
641 while ((n
= read(loop_master
, inbuf
, sizeof(inbuf
))) >= 0) {
642 if (loop_chars(inbuf
, n
))
647 syslog(LOG_ERR
, "eof on loopback");
649 } else if (errno
!= EWOULDBLOCK
){
650 syslog(LOG_ERR
, "read from loopback: %m");
659 * ppp_send_config - configure the transmit characteristics of
663 ppp_send_config(int unit
, int mtu
, u_int32_t asyncmap
, int pcomp
, int accomp
)
668 strncpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
670 if (ioctl(sockfd
, SIOCSIFMTU
, (caddr_t
) &ifr
) < 0) {
671 syslog(LOG_ERR
, "ioctl(SIOCSIFMTU): %m");
675 if (ioctl(ppp_fd
, PPPIOCSASYNCMAP
, (caddr_t
) &asyncmap
) < 0) {
676 syslog(LOG_ERR
, "ioctl(PPPIOCSASYNCMAP): %m");
680 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
681 syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
684 x
= pcomp
? x
| SC_COMP_PROT
: x
&~ SC_COMP_PROT
;
685 x
= accomp
? x
| SC_COMP_AC
: x
&~ SC_COMP_AC
;
686 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0) {
687 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
694 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
697 ppp_set_xaccm(int unit
, ext_accm accm
)
699 if (ioctl(ppp_fd
, PPPIOCSXASYNCMAP
, accm
) < 0 && errno
!= ENOTTY
)
700 syslog(LOG_WARNING
, "ioctl(set extended ACCM): %m");
705 * ppp_recv_config - configure the receive-side characteristics of
709 ppp_recv_config(int unit
, int mru
, u_int32_t asyncmap
, int pcomp
, int accomp
)
713 if (ioctl(ppp_fd
, PPPIOCSMRU
, (caddr_t
) &mru
) < 0) {
714 syslog(LOG_ERR
, "ioctl(PPPIOCSMRU): %m");
717 if (ioctl(ppp_fd
, PPPIOCSRASYNCMAP
, (caddr_t
) &asyncmap
) < 0) {
718 syslog(LOG_ERR
, "ioctl(PPPIOCSRASYNCMAP): %m");
721 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
722 syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
725 x
= !accomp
? x
| SC_REJ_COMP_AC
: x
&~ SC_REJ_COMP_AC
;
726 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0) {
727 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
733 * ccp_test - ask kernel whether a given compression method
734 * is acceptable for use. Returns 1 if the method and parameters
735 * are OK, 0 if the method is known but the parameters are not OK
736 * (e.g. code size should be reduced), or -1 if the method is unknown.
739 ccp_test(int unit
, u_char
*opt_ptr
, int opt_len
, int for_transmit
)
741 struct ppp_option_data data
;
744 data
.length
= opt_len
;
745 data
.transmit
= for_transmit
;
746 if (ioctl(ttyfd
, PPPIOCSCOMPRESS
, (caddr_t
) &data
) >= 0)
748 return (errno
== ENOBUFS
)? 0: -1;
752 * ccp_flags_set - inform kernel about the current state of CCP.
755 ccp_flags_set(int unit
, int isopen
, int isup
)
759 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
760 syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
763 x
= isopen
? x
| SC_CCP_OPEN
: x
&~ SC_CCP_OPEN
;
764 x
= isup
? x
| SC_CCP_UP
: x
&~ SC_CCP_UP
;
765 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0)
766 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
770 * ccp_fatal_error - returns 1 if decompression was disabled as a
771 * result of an error detected after decompression of a packet,
772 * 0 otherwise. This is necessary because of patent nonsense.
775 ccp_fatal_error(int unit
)
779 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
780 syslog(LOG_ERR
, "ioctl(PPPIOCGFLAGS): %m");
783 return x
& SC_DC_FERROR
;
787 * get_idle_time - return how long the link has been idle.
790 get_idle_time(int u
, struct ppp_idle
*ip
)
792 return ioctl(ppp_fd
, PPPIOCGIDLE
, ip
) >= 0;
798 * set_filters - transfer the pass and active filters to the kernel.
801 set_filters(struct bpf_program
*pass
, struct bpf_program
*active
)
805 if (pass
->bf_len
> 0) {
806 if (ioctl(ppp_fd
, PPPIOCSPASS
, pass
) < 0) {
807 syslog(LOG_ERR
, "Couldn't set pass-filter in kernel: %m");
811 if (active
->bf_len
> 0) {
812 if (ioctl(ppp_fd
, PPPIOCSACTIVE
, active
) < 0) {
813 syslog(LOG_ERR
, "Couldn't set active-filter in kernel: %m");
822 * sifvjcomp - config tcp header compression
825 sifvjcomp(int u
, int vjcomp
, int cidcomp
, int maxcid
)
829 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
830 syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
833 x
= vjcomp
? x
| SC_COMP_TCP
: x
&~ SC_COMP_TCP
;
834 x
= cidcomp
? x
& ~SC_NO_TCP_CCID
: x
| SC_NO_TCP_CCID
;
835 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0) {
836 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
839 if (vjcomp
&& ioctl(ppp_fd
, PPPIOCSMAXCID
, (caddr_t
) &maxcid
) < 0) {
840 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
847 * sifup - Config the interface up and enable IP packets to pass.
854 strncpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
855 if (ioctl(sockfd
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) < 0) {
856 syslog(LOG_ERR
, "ioctl (SIOCGIFFLAGS): %m");
859 ifr
.ifr_flags
|= IFF_UP
;
860 if (ioctl(sockfd
, SIOCSIFFLAGS
, (caddr_t
) &ifr
) < 0) {
861 syslog(LOG_ERR
, "ioctl(SIOCSIFFLAGS): %m");
869 * sifnpmode - Set the mode for handling packets for a given NP.
872 sifnpmode(int u
, int proto
, enum NPmode mode
)
876 npi
.protocol
= proto
;
878 if (ioctl(ppp_fd
, PPPIOCSNPMODE
, &npi
) < 0) {
879 syslog(LOG_ERR
, "ioctl(set NP %d mode to %d): %m", proto
, mode
);
886 * sifdown - Config the interface down and disable IP.
896 npi
.protocol
= PPP_IP
;
897 npi
.mode
= NPMODE_ERROR
;
898 ioctl(ppp_fd
, PPPIOCSNPMODE
, (caddr_t
) &npi
);
899 /* ignore errors, because ppp_fd might have been closed by now. */
901 strncpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
902 if (ioctl(sockfd
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) < 0) {
903 syslog(LOG_ERR
, "ioctl (SIOCGIFFLAGS): %m");
906 ifr
.ifr_flags
&= ~IFF_UP
;
907 if (ioctl(sockfd
, SIOCSIFFLAGS
, (caddr_t
) &ifr
) < 0) {
908 syslog(LOG_ERR
, "ioctl(SIOCSIFFLAGS): %m");
917 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
920 #define SET_SA_FAMILY(addr, family) \
921 BZERO((char *) &(addr), sizeof(addr)); \
922 addr.sa_family = (family); \
923 addr.sa_len = sizeof(addr);
926 * sifaddr - Config the interface IP addresses and netmask.
929 sifaddr(int u
, u_int32_t o
, u_int32_t h
, u_int32_t m
)
931 struct ifaliasreq ifra
;
934 strncpy(ifra
.ifra_name
, ifname
, sizeof(ifra
.ifra_name
));
935 SET_SA_FAMILY(ifra
.ifra_addr
, AF_INET
);
936 ((struct sockaddr_in
*) &ifra
.ifra_addr
)->sin_addr
.s_addr
= o
;
937 SET_SA_FAMILY(ifra
.ifra_broadaddr
, AF_INET
);
938 ((struct sockaddr_in
*) &ifra
.ifra_broadaddr
)->sin_addr
.s_addr
= h
;
940 SET_SA_FAMILY(ifra
.ifra_mask
, AF_INET
);
941 ((struct sockaddr_in
*) &ifra
.ifra_mask
)->sin_addr
.s_addr
= m
;
943 BZERO(&ifra
.ifra_mask
, sizeof(ifra
.ifra_mask
));
944 BZERO(&ifr
, sizeof(ifr
));
945 strncpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
946 if (ioctl(sockfd
, SIOCDIFADDR
, (caddr_t
) &ifr
) < 0) {
947 if (errno
!= EADDRNOTAVAIL
)
948 syslog(LOG_WARNING
, "Couldn't remove interface address: %m");
950 if (ioctl(sockfd
, SIOCAIFADDR
, (caddr_t
) &ifra
) < 0) {
951 if (errno
!= EEXIST
) {
952 syslog(LOG_ERR
, "Couldn't set interface address: %m");
956 "Couldn't set interface address: Address %s already exists",
965 * cifaddr - Clear the interface IP addresses, and delete routes
966 * through the interface if possible.
969 cifaddr(int u
, u_int32_t o
, u_int32_t h
)
971 struct ifaliasreq ifra
;
974 strncpy(ifra
.ifra_name
, ifname
, sizeof(ifra
.ifra_name
));
975 SET_SA_FAMILY(ifra
.ifra_addr
, AF_INET
);
976 ((struct sockaddr_in
*) &ifra
.ifra_addr
)->sin_addr
.s_addr
= o
;
977 SET_SA_FAMILY(ifra
.ifra_broadaddr
, AF_INET
);
978 ((struct sockaddr_in
*) &ifra
.ifra_broadaddr
)->sin_addr
.s_addr
= h
;
979 BZERO(&ifra
.ifra_mask
, sizeof(ifra
.ifra_mask
));
980 if (ioctl(sockfd
, SIOCDIFADDR
, (caddr_t
) &ifra
) < 0) {
981 if (errno
!= EADDRNOTAVAIL
)
982 syslog(LOG_WARNING
, "Couldn't delete interface address: %m");
989 * sifdefaultroute - assign a default route through the address given.
992 sifdefaultroute(int u
, u_int32_t l
, u_int32_t g
)
994 return dodefaultroute(g
, 's');
998 * cifdefaultroute - delete a default route through the address given.
1001 cifdefaultroute(int u
, u_int32_t l
, u_int32_t g
)
1003 return dodefaultroute(g
, 'c');
1007 * dodefaultroute - talk to a routing socket to add/delete a default route.
1010 dodefaultroute(u_int32_t g
, int cmd
)
1014 struct rt_msghdr hdr
;
1015 struct sockaddr_in dst
;
1016 struct sockaddr_in gway
;
1017 struct sockaddr_in mask
;
1020 if ((routes
= socket(PF_ROUTE
, SOCK_RAW
, AF_INET
)) < 0) {
1021 syslog(LOG_ERR
, "Couldn't %s default route: socket: %m",
1022 cmd
=='s'? "add": "delete");
1026 memset(&rtmsg
, 0, sizeof(rtmsg
));
1027 rtmsg
.hdr
.rtm_type
= cmd
== 's'? RTM_ADD
: RTM_DELETE
;
1028 rtmsg
.hdr
.rtm_flags
= RTF_UP
| RTF_GATEWAY
| RTF_STATIC
;
1029 rtmsg
.hdr
.rtm_version
= RTM_VERSION
;
1030 rtmsg
.hdr
.rtm_seq
= ++rtm_seq
;
1031 rtmsg
.hdr
.rtm_addrs
= RTA_DST
| RTA_GATEWAY
| RTA_NETMASK
;
1032 rtmsg
.dst
.sin_len
= sizeof(rtmsg
.dst
);
1033 rtmsg
.dst
.sin_family
= AF_INET
;
1034 rtmsg
.gway
.sin_len
= sizeof(rtmsg
.gway
);
1035 rtmsg
.gway
.sin_family
= AF_INET
;
1036 rtmsg
.gway
.sin_addr
.s_addr
= g
;
1037 rtmsg
.mask
.sin_len
= sizeof(rtmsg
.dst
);
1038 rtmsg
.mask
.sin_family
= AF_INET
;
1040 rtmsg
.hdr
.rtm_msglen
= sizeof(rtmsg
);
1041 if (write(routes
, &rtmsg
, sizeof(rtmsg
)) < 0) {
1042 syslog(LOG_ERR
, "Couldn't %s default route: %m",
1043 cmd
=='s'? "add": "delete");
1049 default_route_gateway
= (cmd
== 's')? g
: 0;
1053 #if RTM_VERSION >= 3
1056 * sifproxyarp - Make a proxy ARP entry for the peer.
1059 struct rt_msghdr hdr
;
1060 struct sockaddr_inarp dst
;
1061 struct sockaddr_dl hwa
;
1065 static int arpmsg_valid
;
1068 sifproxyarp(int unit
, u_int32_t hisaddr
)
1073 * Get the hardware address of an interface on the same subnet
1074 * as our local address.
1076 memset(&arpmsg
, 0, sizeof(arpmsg
));
1077 if (!get_ether_addr(hisaddr
, &arpmsg
.hwa
)) {
1078 syslog(LOG_ERR
, "Cannot determine ethernet address for proxy ARP");
1082 if ((routes
= socket(PF_ROUTE
, SOCK_RAW
, AF_INET
)) < 0) {
1083 syslog(LOG_ERR
, "Couldn't add proxy arp entry: socket: %m");
1087 arpmsg
.hdr
.rtm_type
= RTM_ADD
;
1088 arpmsg
.hdr
.rtm_flags
= RTF_ANNOUNCE
| RTF_HOST
| RTF_STATIC
;
1089 arpmsg
.hdr
.rtm_version
= RTM_VERSION
;
1090 arpmsg
.hdr
.rtm_seq
= ++rtm_seq
;
1091 arpmsg
.hdr
.rtm_addrs
= RTA_DST
| RTA_GATEWAY
;
1092 arpmsg
.hdr
.rtm_inits
= RTV_EXPIRE
;
1093 arpmsg
.dst
.sin_len
= sizeof(struct sockaddr_inarp
);
1094 arpmsg
.dst
.sin_family
= AF_INET
;
1095 arpmsg
.dst
.sin_addr
.s_addr
= hisaddr
;
1096 arpmsg
.dst
.sin_other
= SIN_PROXY
;
1098 arpmsg
.hdr
.rtm_msglen
= (char *) &arpmsg
.hwa
- (char *) &arpmsg
1099 + arpmsg
.hwa
.sdl_len
;
1100 if (write(routes
, &arpmsg
, arpmsg
.hdr
.rtm_msglen
) < 0) {
1101 syslog(LOG_ERR
, "Couldn't add proxy arp entry: %m");
1108 proxy_arp_addr
= hisaddr
;
1113 * cifproxyarp - Delete the proxy ARP entry for the peer.
1116 cifproxyarp(int unit
, u_int32_t hisaddr
)
1124 arpmsg
.hdr
.rtm_type
= RTM_DELETE
;
1125 arpmsg
.hdr
.rtm_seq
= ++rtm_seq
;
1127 if ((routes
= socket(PF_ROUTE
, SOCK_RAW
, AF_INET
)) < 0) {
1128 syslog(LOG_ERR
, "Couldn't delete proxy arp entry: socket: %m");
1132 if (write(routes
, &arpmsg
, arpmsg
.hdr
.rtm_msglen
) < 0) {
1133 syslog(LOG_ERR
, "Couldn't delete proxy arp entry: %m");
1143 #else /* RTM_VERSION */
1146 * sifproxyarp - Make a proxy ARP entry for the peer.
1149 sifproxyarp(int unit
, u_int32_t hisaddr
)
1151 struct arpreq arpreq
;
1153 struct sockaddr_dl sdl
;
1157 BZERO(&arpreq
, sizeof(arpreq
));
1160 * Get the hardware address of an interface on the same subnet
1161 * as our local address.
1163 if (!get_ether_addr(hisaddr
, &dls
.sdl
)) {
1164 syslog(LOG_ERR
, "Cannot determine ethernet address for proxy ARP");
1168 arpreq
.arp_ha
.sa_len
= sizeof(struct sockaddr
);
1169 arpreq
.arp_ha
.sa_family
= AF_UNSPEC
;
1170 BCOPY(LLADDR(&dls
.sdl
), arpreq
.arp_ha
.sa_data
, dls
.sdl
.sdl_alen
);
1171 SET_SA_FAMILY(arpreq
.arp_pa
, AF_INET
);
1172 ((struct sockaddr_in
*) &arpreq
.arp_pa
)->sin_addr
.s_addr
= hisaddr
;
1173 arpreq
.arp_flags
= ATF_PERM
| ATF_PUBL
;
1174 if (ioctl(sockfd
, SIOCSARP
, (caddr_t
)&arpreq
) < 0) {
1175 syslog(LOG_ERR
, "Couldn't add proxy arp entry: %m");
1179 proxy_arp_addr
= hisaddr
;
1184 * cifproxyarp - Delete the proxy ARP entry for the peer.
1187 cifproxyarp(int unit
, u_int32_t hisaddr
)
1189 struct arpreq arpreq
;
1191 BZERO(&arpreq
, sizeof(arpreq
));
1192 SET_SA_FAMILY(arpreq
.arp_pa
, AF_INET
);
1193 ((struct sockaddr_in
*) &arpreq
.arp_pa
)->sin_addr
.s_addr
= hisaddr
;
1194 if (ioctl(sockfd
, SIOCDARP
, (caddr_t
)&arpreq
) < 0) {
1195 syslog(LOG_WARNING
, "Couldn't delete proxy arp entry: %m");
1201 #endif /* RTM_VERSION */
1204 * get_ether_addr - get the hardware address of an interface on the
1205 * the same subnet as ipaddr.
1210 get_ether_addr(u_int32_t ipaddr
, struct sockaddr_dl
*hwaddr
)
1212 struct ifreq
*ifr
, *ifend
, *ifp
;
1213 u_int32_t ina
, mask
;
1214 struct sockaddr_dl
*dla
;
1217 struct ifreq ifs
[MAX_IFS
];
1219 ifc
.ifc_len
= sizeof(ifs
);
1221 if (ioctl(sockfd
, SIOCGIFCONF
, &ifc
) < 0) {
1222 syslog(LOG_ERR
, "ioctl(SIOCGIFCONF): %m");
1227 * Scan through looking for an interface with an Internet
1228 * address on the same subnet as `ipaddr'.
1230 ifend
= (struct ifreq
*) (ifc
.ifc_buf
+ ifc
.ifc_len
);
1231 for (ifr
= ifc
.ifc_req
; ifr
< ifend
;
1232 ifr
= (struct ifreq
*) ((char *)&ifr
->ifr_addr
1233 + MAX(ifr
->ifr_addr
.sa_len
, sizeof(ifr
->ifr_addr
)))) {
1234 if (ifr
->ifr_addr
.sa_family
== AF_INET
) {
1235 ina
= ((struct sockaddr_in
*) &ifr
->ifr_addr
)->sin_addr
.s_addr
;
1236 strncpy(ifreq
.ifr_name
, ifr
->ifr_name
, sizeof(ifreq
.ifr_name
));
1238 * Check that the interface is up, and not point-to-point
1241 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifreq
) < 0)
1243 if ((ifreq
.ifr_flags
&
1244 (IFF_UP
|IFF_BROADCAST
|IFF_POINTOPOINT
|IFF_LOOPBACK
|IFF_NOARP
))
1245 != (IFF_UP
|IFF_BROADCAST
))
1248 * Get its netmask and check that it's on the right subnet.
1250 if (ioctl(sockfd
, SIOCGIFNETMASK
, &ifreq
) < 0)
1252 mask
= ((struct sockaddr_in
*) &ifreq
.ifr_addr
)->sin_addr
.s_addr
;
1253 if ((ipaddr
& mask
) != (ina
& mask
))
1262 syslog(LOG_INFO
, "found interface %s for proxy arp", ifr
->ifr_name
);
1265 * Now scan through again looking for a link-level address
1266 * for this interface.
1269 for (ifr
= ifc
.ifc_req
; ifr
< ifend
; ) {
1270 if (strcmp(ifp
->ifr_name
, ifr
->ifr_name
) == 0
1271 && ifr
->ifr_addr
.sa_family
== AF_LINK
) {
1273 * Found the link-level address - copy it out
1275 dla
= (struct sockaddr_dl
*) &ifr
->ifr_addr
;
1276 BCOPY(dla
, hwaddr
, dla
->sdl_len
);
1279 ifr
= (struct ifreq
*) ((char *)&ifr
->ifr_addr
1280 + MAX(ifr
->ifr_addr
.sa_len
, sizeof(ifr
->ifr_addr
)));
1287 * Return user specified netmask, modified by any mask we might determine
1288 * for address `addr' (in network byte order).
1289 * Here we scan through the system's list of interfaces, looking for
1290 * any non-point-to-point interfaces which might appear to be on the same
1291 * network as `addr'. If we find any, we OR in their netmask to the
1292 * user-specified netmask.
1295 GetMask(u_int32_t addr
)
1297 u_int32_t mask
, nmask
, ina
;
1298 struct ifreq
*ifr
, *ifend
, ifreq
;
1300 struct ifreq ifs
[MAX_IFS
];
1303 if (IN_CLASSA(addr
)) /* determine network mask for address class */
1304 nmask
= IN_CLASSA_NET
;
1305 else if (IN_CLASSB(addr
))
1306 nmask
= IN_CLASSB_NET
;
1308 nmask
= IN_CLASSC_NET
;
1309 /* class D nets are disallowed by bad_ip_adrs */
1310 mask
= netmask
| htonl(nmask
);
1313 * Scan through the system's network interfaces.
1315 ifc
.ifc_len
= sizeof(ifs
);
1317 if (ioctl(sockfd
, SIOCGIFCONF
, &ifc
) < 0) {
1318 syslog(LOG_WARNING
, "ioctl(SIOCGIFCONF): %m");
1321 ifend
= (struct ifreq
*) (ifc
.ifc_buf
+ ifc
.ifc_len
);
1322 for (ifr
= ifc
.ifc_req
; ifr
< ifend
;
1323 ifr
= (struct ifreq
*) ((char *)&ifr
->ifr_addr
1324 + MAX(ifr
->ifr_addr
.sa_len
, sizeof(ifr
->ifr_addr
)))) {
1326 * Check the interface's internet address.
1328 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
1330 ina
= ((struct sockaddr_in
*) &ifr
->ifr_addr
)->sin_addr
.s_addr
;
1331 if ((ntohl(ina
) & nmask
) != (addr
& nmask
))
1334 * Check that the interface is up, and not point-to-point or loopback.
1336 strncpy(ifreq
.ifr_name
, ifr
->ifr_name
, sizeof(ifreq
.ifr_name
));
1337 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifreq
) < 0)
1339 if ((ifreq
.ifr_flags
& (IFF_UP
|IFF_POINTOPOINT
|IFF_LOOPBACK
))
1343 * Get its netmask and OR it into our mask.
1345 if (ioctl(sockfd
, SIOCGIFNETMASK
, &ifreq
) < 0)
1347 mask
|= ((struct sockaddr_in
*)&ifreq
.ifr_addr
)->sin_addr
.s_addr
;
1354 * Use the hostid as part of the random number seed.
1363 * lock - create a lock file for the named lock device
1365 #define LOCK_PREFIX "/var/spool/lock/LCK.."
1370 char hdb_lock_buffer
[12];
1374 if ((p
= strrchr(dev
, '/')) != NULL
)
1376 lock_file
= malloc(strlen(LOCK_PREFIX
) + strlen(dev
) + 1);
1377 if (lock_file
== NULL
)
1378 novm("lock file name");
1379 strcat(strcpy(lock_file
, LOCK_PREFIX
), dev
);
1381 while ((fd
= open(lock_file
, O_EXCL
| O_CREAT
| O_RDWR
, 0644)) < 0) {
1383 && (fd
= open(lock_file
, O_RDONLY
, 0)) >= 0) {
1384 /* Read the lock file to find out who has the device locked */
1385 n
= read(fd
, hdb_lock_buffer
, 11);
1387 syslog(LOG_ERR
, "Can't read pid from lock file %s", lock_file
);
1390 hdb_lock_buffer
[n
] = 0;
1391 pid
= atoi(hdb_lock_buffer
);
1392 if (kill(pid
, 0) == -1 && errno
== ESRCH
) {
1393 /* pid no longer exists - remove the lock file */
1394 if (unlink(lock_file
) == 0) {
1396 syslog(LOG_NOTICE
, "Removed stale lock on %s (pid %d)",
1400 syslog(LOG_WARNING
, "Couldn't remove stale lock on %s",
1403 syslog(LOG_NOTICE
, "Device %s is locked by pid %d",
1408 syslog(LOG_ERR
, "Can't create lock file %s: %m", lock_file
);
1414 sprintf(hdb_lock_buffer
, "%10d\n", getpid());
1415 write(fd
, hdb_lock_buffer
, 11);
1422 * unlock - remove our lockfile