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 $
23 * $DragonFly: src/usr.sbin/pppd/sys-bsd.c,v 1.6 2005/11/24 23:42:54 swildner Exp $
26 /* $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 <netipx/ipx.h>
66 #include <sys/param.h>
67 #if defined(NetBSD) && (NetBSD >= 199703)
68 #include <netinet/if_inarp.h>
69 #else /* NetBSD 1.2D or later */
71 #include <netinet/if_ether.h>
73 #include <net/if_ether.h>
82 static int initdisc
= -1; /* Initial TTY discipline for ppp_fd */
83 static int initfdflags
= -1; /* Initial file descriptor flags for ppp_fd */
84 static int ppp_fd
= -1; /* fd which is set to PPP discipline */
87 static int restore_term
; /* 1 => we've munged the terminal */
88 static struct termios inittermios
; /* Initial TTY termios */
89 static struct winsize wsinfo
; /* Initial window size info */
91 static char *lock_file
; /* name of lock file created */
93 static int loop_slave
= -1;
94 static int loop_master
;
95 static char loop_name
[20];
97 static unsigned char inbuf
[512]; /* buffer for chars read from loopback */
99 static int sockfd
; /* socket for doing interface ioctls */
101 static int if_is_up
; /* the interface is currently up */
102 static u_int32_t ifaddrs
[2]; /* local and remote addresses we set */
103 static u_int32_t default_route_gateway
; /* gateway addr for default route */
104 static u_int32_t proxy_arp_addr
; /* remote addr for proxy arp */
106 /* Prototypes for procedures local to this file. */
107 static int dodefaultroute(u_int32_t
, int);
108 static int get_ether_addr(u_int32_t
, struct sockaddr_dl
*);
112 * sys_init - System-dependent initialization.
117 /* Get an internet socket for doing socket ioctl's on. */
118 if ((sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
119 syslog(LOG_ERR
, "Couldn't create IP socket: %m");
125 * sys_cleanup - restore any system state we modified before exiting:
126 * mark the interface down, delete default route and/or proxy arp entry.
127 * This should call die() because it's called from die().
135 strncpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
136 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifr
) >= 0
137 && ((ifr
.ifr_flags
& IFF_UP
) != 0)) {
138 ifr
.ifr_flags
&= ~IFF_UP
;
139 ioctl(sockfd
, SIOCSIFFLAGS
, &ifr
);
143 cifaddr(0, ifaddrs
[0], ifaddrs
[1]);
144 if (default_route_gateway
)
145 cifdefaultroute(0, 0, default_route_gateway
);
147 cifproxyarp(0, proxy_arp_addr
);
151 * sys_close - Clean up in a child process before execing.
157 if (loop_slave
>= 0) {
164 * sys_check_options - check the options that the user specified
167 sys_check_options(void)
172 * ppp_available - check whether the system has any ppp interfaces
173 * (in fact we check whether we can do an ioctl on ppp0).
180 extern char *no_ppp_msg
;
182 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
183 return 1; /* can't tell */
185 strncpy(ifr
.ifr_name
, "ppp0", sizeof (ifr
.ifr_name
));
186 ok
= ioctl(s
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) >= 0;
190 This system lacks kernel support for PPP. To include PPP support\n\
191 in the kernel, please follow the steps detailed in the README.bsd\n\
192 file in the ppp-2.2 distribution.\n";
197 * establish_ppp - Turn the serial port into a ppp interface.
200 establish_ppp(int fd
)
202 int pppdisc
= PPPDISC
;
207 * Demand mode - prime the old ppp device to relinquish the unit.
209 if (ioctl(ppp_fd
, PPPIOCXFERUNIT
, 0) < 0) {
210 syslog(LOG_ERR
, "ioctl(transfer ppp unit): %m");
216 * Save the old line discipline of fd, and set it to PPP.
218 if (ioctl(fd
, TIOCGETD
, &initdisc
) < 0) {
219 syslog(LOG_ERR
, "ioctl(TIOCGETD): %m");
222 if (ioctl(fd
, TIOCSETD
, &pppdisc
) < 0) {
223 syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
229 * Find out which interface we were given.
231 if (ioctl(fd
, PPPIOCGUNIT
, &ifunit
) < 0) {
232 syslog(LOG_ERR
, "ioctl(PPPIOCGUNIT): %m");
237 * Check that we got the same unit again.
239 if (ioctl(fd
, PPPIOCGUNIT
, &x
) < 0) {
240 syslog(LOG_ERR
, "ioctl(PPPIOCGUNIT): %m");
244 syslog(LOG_ERR
, "transfer_ppp failed: wanted unit %d, got %d",
249 ioctl(loop_slave
, TIOCSETD
, &x
);
255 * Enable debug in the driver if requested.
258 if (ioctl(fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
259 syslog(LOG_WARNING
, "ioctl (PPPIOCGFLAGS): %m");
261 x
|= (kdebugflag
& 0xFF) * SC_DEBUG
;
262 if (ioctl(fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0)
263 syslog(LOG_WARNING
, "ioctl(PPPIOCSFLAGS): %m");
268 * Set device for non-blocking reads.
270 if ((initfdflags
= fcntl(fd
, F_GETFL
)) == -1
271 || fcntl(fd
, F_SETFL
, initfdflags
| O_NONBLOCK
) == -1) {
272 syslog(LOG_WARNING
, "Couldn't set device to non-blocking mode: %m");
277 * restore_loop - reattach the ppp unit to the loopback.
285 * Transfer the ppp interface back to the loopback.
287 if (ioctl(ppp_fd
, PPPIOCXFERUNIT
, 0) < 0) {
288 syslog(LOG_ERR
, "ioctl(transfer ppp unit): %m");
292 if (ioctl(loop_slave
, TIOCSETD
, &x
) < 0) {
293 syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
298 * Check that we got the same unit again.
300 if (ioctl(loop_slave
, PPPIOCGUNIT
, &x
) < 0) {
301 syslog(LOG_ERR
, "ioctl(PPPIOCGUNIT): %m");
305 syslog(LOG_ERR
, "transfer_ppp failed: wanted unit %d, got %d",
314 * disestablish_ppp - Restore the serial port to normal operation.
315 * This shouldn't call die() because it's called from die().
318 disestablish_ppp(int fd
)
320 /* Reset non-blocking mode on fd. */
321 if (initfdflags
!= -1 && fcntl(fd
, F_SETFL
, initfdflags
) < 0)
322 syslog(LOG_WARNING
, "Couldn't restore device fd flags: %m");
325 /* Restore old line discipline. */
326 if (initdisc
>= 0 && ioctl(fd
, TIOCSETD
, &initdisc
) < 0)
327 syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
335 * Check whether the link seems not to be 8-bit clean.
343 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) == 0) {
345 switch (~x
& (SC_RCV_B7_0
|SC_RCV_B7_1
|SC_RCV_EVNP
|SC_RCV_ODDP
)) {
347 s
= "bit 7 set to 1";
350 s
= "bit 7 set to 0";
360 syslog(LOG_WARNING
, "Serial link is not 8-bit clean:");
361 syslog(LOG_WARNING
, "All received characters had %s", s
);
367 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
368 * at the requested speed, etc. If `local' is true, set CLOCAL
369 * regardless of whether the modem option was specified.
371 * For *BSD, we assume that speed_t values numerically equal bits/second.
374 set_up_tty(int fd
, int local
)
378 if (tcgetattr(fd
, &tios
) < 0) {
379 syslog(LOG_ERR
, "tcgetattr: %m");
385 ioctl(fd
, TIOCGWINSZ
, &wsinfo
);
388 tios
.c_cflag
&= ~(CSIZE
| CSTOPB
| PARENB
| CLOCAL
);
389 if (crtscts
> 0 && !local
)
390 tios
.c_cflag
|= CRTSCTS
;
391 else if (crtscts
< 0)
392 tios
.c_cflag
&= ~CRTSCTS
;
394 tios
.c_cflag
|= CS8
| CREAD
| HUPCL
;
396 tios
.c_cflag
|= CLOCAL
;
397 tios
.c_iflag
= IGNBRK
| IGNPAR
;
401 tios
.c_cc
[VTIME
] = 0;
404 tios
.c_iflag
|= IXON
| IXOFF
;
405 tios
.c_cc
[VSTOP
] = 0x13; /* DC3 = XOFF = ^S */
406 tios
.c_cc
[VSTART
] = 0x11; /* DC1 = XON = ^Q */
410 cfsetospeed(&tios
, inspeed
);
411 cfsetispeed(&tios
, inspeed
);
413 inspeed
= cfgetospeed(&tios
);
415 * We can't proceed if the serial port speed is 0,
416 * since that implies that the serial port is disabled.
419 syslog(LOG_ERR
, "Baud rate for %s is 0; need explicit baud rate",
426 if (tcsetattr(fd
, TCSAFLUSH
, &tios
) < 0) {
427 syslog(LOG_ERR
, "tcsetattr: %m");
435 * restore_tty - restore the terminal to the saved settings.
441 if (!default_device
) {
443 * Turn off echoing, because otherwise we can get into
444 * a loop with the tty and the modem echoing to each other.
445 * We presume we are the sole user of this tty device, so
446 * when we close it, it will revert to its defaults anyway.
448 inittermios
.c_lflag
&= ~(ECHO
| ECHONL
);
450 if (tcsetattr(fd
, TCSAFLUSH
, &inittermios
) < 0)
452 syslog(LOG_WARNING
, "tcsetattr: %m");
453 ioctl(fd
, TIOCSWINSZ
, &wsinfo
);
459 * setdtr - control the DTR line on the serial port.
460 * This is called from die(), so it shouldn't call die().
463 setdtr(int fd
, int on
)
465 int modembits
= TIOCM_DTR
;
467 ioctl(fd
, (on
? TIOCMBIS
: TIOCMBIC
), &modembits
);
472 * open_ppp_loopback - open the device we use for getting
473 * packets in demand mode, and connect it to a ppp interface.
477 open_ppp_loopback(void)
481 int pppdisc
= PPPDISC
;
483 if (openpty(&loop_master
, &loop_slave
, loop_name
, NULL
, NULL
) < 0) {
484 syslog(LOG_ERR
, "No free pty for loopback");
487 SYSDEBUG((LOG_DEBUG
, "using %s for loopback", loop_name
));
489 if (tcgetattr(loop_slave
, &tios
) == 0) {
490 tios
.c_cflag
&= ~(CSIZE
| CSTOPB
| PARENB
);
491 tios
.c_cflag
|= CS8
| CREAD
;
492 tios
.c_iflag
= IGNPAR
;
495 if (tcsetattr(loop_slave
, TCSAFLUSH
, &tios
) < 0)
496 syslog(LOG_WARNING
, "couldn't set attributes on loopback: %m");
499 if ((flags
= fcntl(loop_master
, F_GETFL
)) != -1)
500 if (fcntl(loop_master
, F_SETFL
, flags
| O_NONBLOCK
) == -1)
501 syslog(LOG_WARNING
, "couldn't set loopback to nonblock: %m");
504 if (ioctl(ppp_fd
, TIOCSETD
, &pppdisc
) < 0) {
505 syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
510 * Find out which interface we were given.
512 if (ioctl(ppp_fd
, PPPIOCGUNIT
, &ifunit
) < 0) {
513 syslog(LOG_ERR
, "ioctl(PPPIOCGUNIT): %m");
518 * Enable debug in the driver if requested.
521 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &flags
) < 0) {
522 syslog(LOG_WARNING
, "ioctl (PPPIOCGFLAGS): %m");
524 flags
|= (kdebugflag
& 0xFF) * SC_DEBUG
;
525 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &flags
) < 0)
526 syslog(LOG_WARNING
, "ioctl(PPPIOCSFLAGS): %m");
534 * output - Output PPP packet.
537 output(int unit
, u_char
*p
, int len
)
540 log_packet(p
, len
, "sent ", LOG_DEBUG
);
542 if (write(ttyfd
, p
, len
) < 0) {
544 syslog(LOG_ERR
, "write: %m");
550 * wait_input - wait until there is data available on ttyfd,
551 * for the length of time specified by *timo (indefinite
555 wait_input(struct timeval
*timo
)
560 if (ttyfd
>= FD_SETSIZE
) {
561 syslog(LOG_ERR
, "descriptor too big");
565 FD_SET(ttyfd
, &ready
);
566 n
= select(ttyfd
+1, &ready
, NULL
, &ready
, timo
);
567 if (n
< 0 && errno
!= EINTR
) {
568 syslog(LOG_ERR
, "select: %m");
575 * wait_loop_output - wait until there is data available on the
576 * loopback, for the length of time specified by *timo (indefinite
580 wait_loop_output(struct timeval
*timo
)
585 if (loop_master
>= FD_SETSIZE
) {
586 syslog(LOG_ERR
, "descriptor too big");
590 FD_SET(loop_master
, &ready
);
591 n
= select(loop_master
+ 1, &ready
, NULL
, &ready
, timo
);
592 if (n
< 0 && errno
!= EINTR
) {
593 syslog(LOG_ERR
, "select: %m");
600 * wait_time - wait for a given length of time or until a
601 * signal is received.
604 wait_time(struct timeval
*timo
)
608 n
= select(0, NULL
, NULL
, NULL
, timo
);
609 if (n
< 0 && errno
!= EINTR
) {
610 syslog(LOG_ERR
, "select: %m");
617 * read_packet - get a PPP packet from the serial device.
620 read_packet(u_char
*buf
)
624 if ((len
= read(ttyfd
, buf
, PPP_MTU
+ PPP_HDRLEN
)) < 0) {
625 if (errno
== EWOULDBLOCK
|| errno
== EINTR
)
627 syslog(LOG_ERR
, "read: %m");
635 * get_loop_output - read characters from the loopback, form them
636 * into frames, and detect when we want to bring the real link up.
637 * Return value is 1 if we need to bring up the link, 0 otherwise.
640 get_loop_output(void)
645 while ((n
= read(loop_master
, inbuf
, sizeof(inbuf
))) >= 0) {
646 if (loop_chars(inbuf
, n
))
651 syslog(LOG_ERR
, "eof on loopback");
653 } else if (errno
!= EWOULDBLOCK
){
654 syslog(LOG_ERR
, "read from loopback: %m");
663 * ppp_send_config - configure the transmit characteristics of
667 ppp_send_config(int unit
, int mtu
, u_int32_t asyncmap
, int pcomp
, int accomp
)
672 strncpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
674 if (ioctl(sockfd
, SIOCSIFMTU
, (caddr_t
) &ifr
) < 0) {
675 syslog(LOG_ERR
, "ioctl(SIOCSIFMTU): %m");
679 if (ioctl(ppp_fd
, PPPIOCSASYNCMAP
, (caddr_t
) &asyncmap
) < 0) {
680 syslog(LOG_ERR
, "ioctl(PPPIOCSASYNCMAP): %m");
684 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
685 syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
688 x
= pcomp
? x
| SC_COMP_PROT
: x
&~ SC_COMP_PROT
;
689 x
= accomp
? x
| SC_COMP_AC
: x
&~ SC_COMP_AC
;
690 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0) {
691 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
698 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
701 ppp_set_xaccm(int unit
, ext_accm accm
)
703 if (ioctl(ppp_fd
, PPPIOCSXASYNCMAP
, accm
) < 0 && errno
!= ENOTTY
)
704 syslog(LOG_WARNING
, "ioctl(set extended ACCM): %m");
709 * ppp_recv_config - configure the receive-side characteristics of
713 ppp_recv_config(int unit
, int mru
, u_int32_t asyncmap
, int pcomp
, int accomp
)
717 if (ioctl(ppp_fd
, PPPIOCSMRU
, (caddr_t
) &mru
) < 0) {
718 syslog(LOG_ERR
, "ioctl(PPPIOCSMRU): %m");
721 if (ioctl(ppp_fd
, PPPIOCSRASYNCMAP
, (caddr_t
) &asyncmap
) < 0) {
722 syslog(LOG_ERR
, "ioctl(PPPIOCSRASYNCMAP): %m");
725 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
726 syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
729 x
= !accomp
? x
| SC_REJ_COMP_AC
: x
&~ SC_REJ_COMP_AC
;
730 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0) {
731 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
737 * ccp_test - ask kernel whether a given compression method
738 * is acceptable for use. Returns 1 if the method and parameters
739 * are OK, 0 if the method is known but the parameters are not OK
740 * (e.g. code size should be reduced), or -1 if the method is unknown.
743 ccp_test(int unit
, u_char
*opt_ptr
, int opt_len
, int for_transmit
)
745 struct ppp_option_data data
;
748 data
.length
= opt_len
;
749 data
.transmit
= for_transmit
;
750 if (ioctl(ttyfd
, PPPIOCSCOMPRESS
, (caddr_t
) &data
) >= 0)
752 return (errno
== ENOBUFS
)? 0: -1;
756 * ccp_flags_set - inform kernel about the current state of CCP.
759 ccp_flags_set(int unit
, int isopen
, int isup
)
763 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
764 syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
767 x
= isopen
? x
| SC_CCP_OPEN
: x
&~ SC_CCP_OPEN
;
768 x
= isup
? x
| SC_CCP_UP
: x
&~ SC_CCP_UP
;
769 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0)
770 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
774 * ccp_fatal_error - returns 1 if decompression was disabled as a
775 * result of an error detected after decompression of a packet,
776 * 0 otherwise. This is necessary because of patent nonsense.
779 ccp_fatal_error(int unit
)
783 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
784 syslog(LOG_ERR
, "ioctl(PPPIOCGFLAGS): %m");
787 return x
& SC_DC_FERROR
;
791 * get_idle_time - return how long the link has been idle.
794 get_idle_time(int u
, struct ppp_idle
*ip
)
796 return ioctl(ppp_fd
, PPPIOCGIDLE
, ip
) >= 0;
802 * set_filters - transfer the pass and active filters to the kernel.
805 set_filters(struct bpf_program
*pass
, struct bpf_program
*active
)
809 if (pass
->bf_len
> 0) {
810 if (ioctl(ppp_fd
, PPPIOCSPASS
, pass
) < 0) {
811 syslog(LOG_ERR
, "Couldn't set pass-filter in kernel: %m");
815 if (active
->bf_len
> 0) {
816 if (ioctl(ppp_fd
, PPPIOCSACTIVE
, active
) < 0) {
817 syslog(LOG_ERR
, "Couldn't set active-filter in kernel: %m");
826 * sifvjcomp - config tcp header compression
829 sifvjcomp(int u
, int vjcomp
, int cidcomp
, int maxcid
)
833 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
834 syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
837 x
= vjcomp
? x
| SC_COMP_TCP
: x
&~ SC_COMP_TCP
;
838 x
= cidcomp
? x
& ~SC_NO_TCP_CCID
: x
| SC_NO_TCP_CCID
;
839 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0) {
840 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
843 if (vjcomp
&& ioctl(ppp_fd
, PPPIOCSMAXCID
, (caddr_t
) &maxcid
) < 0) {
844 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
851 * sifup - Config the interface up and enable IP packets to pass.
858 strncpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
859 if (ioctl(sockfd
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) < 0) {
860 syslog(LOG_ERR
, "ioctl (SIOCGIFFLAGS): %m");
863 ifr
.ifr_flags
|= IFF_UP
;
864 if (ioctl(sockfd
, SIOCSIFFLAGS
, (caddr_t
) &ifr
) < 0) {
865 syslog(LOG_ERR
, "ioctl(SIOCSIFFLAGS): %m");
873 * sifnpmode - Set the mode for handling packets for a given NP.
876 sifnpmode(int u
, int proto
, enum NPmode mode
)
880 npi
.protocol
= proto
;
882 if (ioctl(ppp_fd
, PPPIOCSNPMODE
, &npi
) < 0) {
883 syslog(LOG_ERR
, "ioctl(set NP %d mode to %d): %m", proto
, mode
);
890 * sifdown - Config the interface down and disable IP.
900 npi
.protocol
= PPP_IP
;
901 npi
.mode
= NPMODE_ERROR
;
902 ioctl(ppp_fd
, PPPIOCSNPMODE
, (caddr_t
) &npi
);
903 /* ignore errors, because ppp_fd might have been closed by now. */
905 strncpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
906 if (ioctl(sockfd
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) < 0) {
907 syslog(LOG_ERR
, "ioctl (SIOCGIFFLAGS): %m");
910 ifr
.ifr_flags
&= ~IFF_UP
;
911 if (ioctl(sockfd
, SIOCSIFFLAGS
, (caddr_t
) &ifr
) < 0) {
912 syslog(LOG_ERR
, "ioctl(SIOCSIFFLAGS): %m");
921 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
924 #define SET_SA_FAMILY(addr, family) \
925 BZERO((char *) &(addr), sizeof(addr)); \
926 addr.sa_family = (family); \
927 addr.sa_len = sizeof(addr);
930 * sifaddr - Config the interface IP addresses and netmask.
933 sifaddr(int u
, u_int32_t o
, u_int32_t h
, u_int32_t m
)
935 struct ifaliasreq ifra
;
938 strncpy(ifra
.ifra_name
, ifname
, sizeof(ifra
.ifra_name
));
939 SET_SA_FAMILY(ifra
.ifra_addr
, AF_INET
);
940 ((struct sockaddr_in
*) &ifra
.ifra_addr
)->sin_addr
.s_addr
= o
;
941 SET_SA_FAMILY(ifra
.ifra_broadaddr
, AF_INET
);
942 ((struct sockaddr_in
*) &ifra
.ifra_broadaddr
)->sin_addr
.s_addr
= h
;
944 SET_SA_FAMILY(ifra
.ifra_mask
, AF_INET
);
945 ((struct sockaddr_in
*) &ifra
.ifra_mask
)->sin_addr
.s_addr
= m
;
947 BZERO(&ifra
.ifra_mask
, sizeof(ifra
.ifra_mask
));
948 BZERO(&ifr
, sizeof(ifr
));
949 strncpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
950 if (ioctl(sockfd
, SIOCDIFADDR
, (caddr_t
) &ifr
) < 0) {
951 if (errno
!= EADDRNOTAVAIL
)
952 syslog(LOG_WARNING
, "Couldn't remove interface address: %m");
954 if (ioctl(sockfd
, SIOCAIFADDR
, (caddr_t
) &ifra
) < 0) {
955 if (errno
!= EEXIST
) {
956 syslog(LOG_ERR
, "Couldn't set interface address: %m");
960 "Couldn't set interface address: Address %s already exists",
969 * cifaddr - Clear the interface IP addresses, and delete routes
970 * through the interface if possible.
973 cifaddr(int u
, u_int32_t o
, u_int32_t h
)
975 struct ifaliasreq ifra
;
978 strncpy(ifra
.ifra_name
, ifname
, sizeof(ifra
.ifra_name
));
979 SET_SA_FAMILY(ifra
.ifra_addr
, AF_INET
);
980 ((struct sockaddr_in
*) &ifra
.ifra_addr
)->sin_addr
.s_addr
= o
;
981 SET_SA_FAMILY(ifra
.ifra_broadaddr
, AF_INET
);
982 ((struct sockaddr_in
*) &ifra
.ifra_broadaddr
)->sin_addr
.s_addr
= h
;
983 BZERO(&ifra
.ifra_mask
, sizeof(ifra
.ifra_mask
));
984 if (ioctl(sockfd
, SIOCDIFADDR
, (caddr_t
) &ifra
) < 0) {
985 if (errno
!= EADDRNOTAVAIL
)
986 syslog(LOG_WARNING
, "Couldn't delete interface address: %m");
993 * sifdefaultroute - assign a default route through the address given.
996 sifdefaultroute(int u
, u_int32_t l
, u_int32_t g
)
998 return dodefaultroute(g
, 's');
1002 * cifdefaultroute - delete a default route through the address given.
1005 cifdefaultroute(int u
, u_int32_t l
, u_int32_t g
)
1007 return dodefaultroute(g
, 'c');
1011 * dodefaultroute - talk to a routing socket to add/delete a default route.
1014 dodefaultroute(u_int32_t g
, int cmd
)
1018 struct rt_msghdr hdr
;
1019 struct sockaddr_in dst
;
1020 struct sockaddr_in gway
;
1021 struct sockaddr_in mask
;
1024 if ((routes
= socket(PF_ROUTE
, SOCK_RAW
, AF_INET
)) < 0) {
1025 syslog(LOG_ERR
, "Couldn't %s default route: socket: %m",
1026 cmd
=='s'? "add": "delete");
1030 memset(&rtmsg
, 0, sizeof(rtmsg
));
1031 rtmsg
.hdr
.rtm_type
= cmd
== 's'? RTM_ADD
: RTM_DELETE
;
1032 rtmsg
.hdr
.rtm_flags
= RTF_UP
| RTF_GATEWAY
| RTF_STATIC
;
1033 rtmsg
.hdr
.rtm_version
= RTM_VERSION
;
1034 rtmsg
.hdr
.rtm_seq
= ++rtm_seq
;
1035 rtmsg
.hdr
.rtm_addrs
= RTA_DST
| RTA_GATEWAY
| RTA_NETMASK
;
1036 rtmsg
.dst
.sin_len
= sizeof(rtmsg
.dst
);
1037 rtmsg
.dst
.sin_family
= AF_INET
;
1038 rtmsg
.gway
.sin_len
= sizeof(rtmsg
.gway
);
1039 rtmsg
.gway
.sin_family
= AF_INET
;
1040 rtmsg
.gway
.sin_addr
.s_addr
= g
;
1041 rtmsg
.mask
.sin_len
= sizeof(rtmsg
.dst
);
1042 rtmsg
.mask
.sin_family
= AF_INET
;
1044 rtmsg
.hdr
.rtm_msglen
= sizeof(rtmsg
);
1045 if (write(routes
, &rtmsg
, sizeof(rtmsg
)) < 0) {
1046 syslog(LOG_ERR
, "Couldn't %s default route: %m",
1047 cmd
=='s'? "add": "delete");
1053 default_route_gateway
= (cmd
== 's')? g
: 0;
1057 #if RTM_VERSION >= 3
1060 * sifproxyarp - Make a proxy ARP entry for the peer.
1063 struct rt_msghdr hdr
;
1064 struct sockaddr_inarp dst
;
1065 struct sockaddr_dl hwa
;
1069 static int arpmsg_valid
;
1072 sifproxyarp(int unit
, u_int32_t hisaddr
)
1077 * Get the hardware address of an interface on the same subnet
1078 * as our local address.
1080 memset(&arpmsg
, 0, sizeof(arpmsg
));
1081 if (!get_ether_addr(hisaddr
, &arpmsg
.hwa
)) {
1082 syslog(LOG_ERR
, "Cannot determine ethernet address for proxy ARP");
1086 if ((routes
= socket(PF_ROUTE
, SOCK_RAW
, AF_INET
)) < 0) {
1087 syslog(LOG_ERR
, "Couldn't add proxy arp entry: socket: %m");
1091 arpmsg
.hdr
.rtm_type
= RTM_ADD
;
1092 arpmsg
.hdr
.rtm_flags
= RTF_ANNOUNCE
| RTF_HOST
| RTF_STATIC
;
1093 arpmsg
.hdr
.rtm_version
= RTM_VERSION
;
1094 arpmsg
.hdr
.rtm_seq
= ++rtm_seq
;
1095 arpmsg
.hdr
.rtm_addrs
= RTA_DST
| RTA_GATEWAY
;
1096 arpmsg
.hdr
.rtm_inits
= RTV_EXPIRE
;
1097 arpmsg
.dst
.sin_len
= sizeof(struct sockaddr_inarp
);
1098 arpmsg
.dst
.sin_family
= AF_INET
;
1099 arpmsg
.dst
.sin_addr
.s_addr
= hisaddr
;
1100 arpmsg
.dst
.sin_other
= SIN_PROXY
;
1102 arpmsg
.hdr
.rtm_msglen
= (char *) &arpmsg
.hwa
- (char *) &arpmsg
1103 + arpmsg
.hwa
.sdl_len
;
1104 if (write(routes
, &arpmsg
, arpmsg
.hdr
.rtm_msglen
) < 0) {
1105 syslog(LOG_ERR
, "Couldn't add proxy arp entry: %m");
1112 proxy_arp_addr
= hisaddr
;
1117 * cifproxyarp - Delete the proxy ARP entry for the peer.
1120 cifproxyarp(int unit
, u_int32_t hisaddr
)
1128 arpmsg
.hdr
.rtm_type
= RTM_DELETE
;
1129 arpmsg
.hdr
.rtm_seq
= ++rtm_seq
;
1131 if ((routes
= socket(PF_ROUTE
, SOCK_RAW
, AF_INET
)) < 0) {
1132 syslog(LOG_ERR
, "Couldn't delete proxy arp entry: socket: %m");
1136 if (write(routes
, &arpmsg
, arpmsg
.hdr
.rtm_msglen
) < 0) {
1137 syslog(LOG_ERR
, "Couldn't delete proxy arp entry: %m");
1147 #else /* RTM_VERSION */
1150 * sifproxyarp - Make a proxy ARP entry for the peer.
1153 sifproxyarp(int unit
, u_int32_t hisaddr
)
1155 struct arpreq arpreq
;
1157 struct sockaddr_dl sdl
;
1161 BZERO(&arpreq
, sizeof(arpreq
));
1164 * Get the hardware address of an interface on the same subnet
1165 * as our local address.
1167 if (!get_ether_addr(hisaddr
, &dls
.sdl
)) {
1168 syslog(LOG_ERR
, "Cannot determine ethernet address for proxy ARP");
1172 arpreq
.arp_ha
.sa_len
= sizeof(struct sockaddr
);
1173 arpreq
.arp_ha
.sa_family
= AF_UNSPEC
;
1174 BCOPY(LLADDR(&dls
.sdl
), arpreq
.arp_ha
.sa_data
, dls
.sdl
.sdl_alen
);
1175 SET_SA_FAMILY(arpreq
.arp_pa
, AF_INET
);
1176 ((struct sockaddr_in
*) &arpreq
.arp_pa
)->sin_addr
.s_addr
= hisaddr
;
1177 arpreq
.arp_flags
= ATF_PERM
| ATF_PUBL
;
1178 if (ioctl(sockfd
, SIOCSARP
, (caddr_t
)&arpreq
) < 0) {
1179 syslog(LOG_ERR
, "Couldn't add proxy arp entry: %m");
1183 proxy_arp_addr
= hisaddr
;
1188 * cifproxyarp - Delete the proxy ARP entry for the peer.
1191 cifproxyarp(int unit
, u_int32_t hisaddr
)
1193 struct arpreq arpreq
;
1195 BZERO(&arpreq
, sizeof(arpreq
));
1196 SET_SA_FAMILY(arpreq
.arp_pa
, AF_INET
);
1197 ((struct sockaddr_in
*) &arpreq
.arp_pa
)->sin_addr
.s_addr
= hisaddr
;
1198 if (ioctl(sockfd
, SIOCDARP
, (caddr_t
)&arpreq
) < 0) {
1199 syslog(LOG_WARNING
, "Couldn't delete proxy arp entry: %m");
1205 #endif /* RTM_VERSION */
1208 /********************************************************************
1210 * sipxfaddr - Config the interface IPX networknumber
1214 sipxfaddr(int unit
, unsigned long int network
, unsigned char *node
)
1219 struct sockaddr_ipx ipx_addr
;
1221 struct sockaddr_ipx
*sipx
= (struct sockaddr_ipx
*) &ifr
.ifr_addr
;
1222 union ipx_net_u net
;
1224 skfd
= socket (AF_IPX
, SOCK_DGRAM
, 0);
1227 syslog (LOG_DEBUG
, "socket(AF_IPX): %m(%d)", errno
);
1232 memset (&ifr
, '\0', sizeof (ifr
));
1233 strcpy (ifr
.ifr_name
, ifname
);
1235 memcpy (sipx
->sipx_addr
.x_host
.c_host
, node
, 6);
1236 sipx
->sipx_len
= sizeof(sipx
);
1237 sipx
->sipx_family
= AF_IPX
;
1238 sipx
->sipx_port
= 0;
1239 memset(&net
, 0, sizeof(net
));
1240 net
.long_e
= htonl (network
);
1241 sipx
->sipx_addr
.x_net
= net
.net_e
;
1243 * Set the IPX device
1245 if (ioctl(skfd
, SIOCSIFADDR
, (caddr_t
) &ifr
) < 0)
1248 if (errno
!= EEXIST
)
1251 "ioctl(SIOCAIFADDR, CRTITF): %m(%d)", errno
);
1255 syslog (LOG_WARNING
,
1256 "ioctl(SIOCAIFADDR, CRTITF): Address already exists");
1264 /********************************************************************
1266 * cipxfaddr - Clear the information for the IPX network. The IPX routes
1267 * are removed and the device is no longer able to pass IPX
1271 int cipxfaddr(int unit
)
1276 struct sockaddr_ipx ipx_addr
;
1278 struct sockaddr_ipx
*sipx
= (struct sockaddr_ipx
*) &ifr
.ifr_addr
;
1280 skfd
= socket (AF_IPX
, SOCK_DGRAM
, 0);
1283 syslog (LOG_DEBUG
, "socket(AF_IPX): %m(%d)", errno
);
1288 memset (&ifr
, '\0', sizeof (ifr
));
1289 strcpy (ifr
.ifr_name
, ifname
);
1291 sipx
->sipx_len
= sizeof(sipx
);
1292 sipx
->sipx_family
= AF_IPX
;
1294 * Set the IPX device
1296 if (ioctl(skfd
, SIOCSIFADDR
, (caddr_t
) &ifr
) < 0)
1299 "ioctl(SIOCAIFADDR, IPX_DLTITF): %m(%d)", errno
);
1309 * get_ether_addr - get the hardware address of an interface on the
1310 * the same subnet as ipaddr.
1315 get_ether_addr(u_int32_t ipaddr
, struct sockaddr_dl
*hwaddr
)
1317 struct ifreq
*ifr
, *ifend
, *ifp
;
1318 u_int32_t ina
, mask
;
1319 struct sockaddr_dl
*dla
;
1322 struct ifreq ifs
[MAX_IFS
];
1324 ifc
.ifc_len
= sizeof(ifs
);
1326 if (ioctl(sockfd
, SIOCGIFCONF
, &ifc
) < 0) {
1327 syslog(LOG_ERR
, "ioctl(SIOCGIFCONF): %m");
1332 * Scan through looking for an interface with an Internet
1333 * address on the same subnet as `ipaddr'.
1335 ifend
= (struct ifreq
*) (ifc
.ifc_buf
+ ifc
.ifc_len
);
1336 for (ifr
= ifc
.ifc_req
; ifr
< ifend
;
1337 ifr
= (struct ifreq
*) ((char *)&ifr
->ifr_addr
1338 + MAX(ifr
->ifr_addr
.sa_len
, sizeof(ifr
->ifr_addr
)))) {
1339 if (ifr
->ifr_addr
.sa_family
== AF_INET
) {
1340 ina
= ((struct sockaddr_in
*) &ifr
->ifr_addr
)->sin_addr
.s_addr
;
1341 strncpy(ifreq
.ifr_name
, ifr
->ifr_name
, sizeof(ifreq
.ifr_name
));
1343 * Check that the interface is up, and not point-to-point
1346 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifreq
) < 0)
1348 if ((ifreq
.ifr_flags
&
1349 (IFF_UP
|IFF_BROADCAST
|IFF_POINTOPOINT
|IFF_LOOPBACK
|IFF_NOARP
))
1350 != (IFF_UP
|IFF_BROADCAST
))
1353 * Get its netmask and check that it's on the right subnet.
1355 if (ioctl(sockfd
, SIOCGIFNETMASK
, &ifreq
) < 0)
1357 mask
= ((struct sockaddr_in
*) &ifreq
.ifr_addr
)->sin_addr
.s_addr
;
1358 if ((ipaddr
& mask
) != (ina
& mask
))
1367 syslog(LOG_INFO
, "found interface %s for proxy arp", ifr
->ifr_name
);
1370 * Now scan through again looking for a link-level address
1371 * for this interface.
1374 for (ifr
= ifc
.ifc_req
; ifr
< ifend
; ) {
1375 if (strcmp(ifp
->ifr_name
, ifr
->ifr_name
) == 0
1376 && ifr
->ifr_addr
.sa_family
== AF_LINK
) {
1378 * Found the link-level address - copy it out
1380 dla
= (struct sockaddr_dl
*) &ifr
->ifr_addr
;
1381 BCOPY(dla
, hwaddr
, dla
->sdl_len
);
1384 ifr
= (struct ifreq
*) ((char *)&ifr
->ifr_addr
1385 + MAX(ifr
->ifr_addr
.sa_len
, sizeof(ifr
->ifr_addr
)));
1392 * Return user specified netmask, modified by any mask we might determine
1393 * for address `addr' (in network byte order).
1394 * Here we scan through the system's list of interfaces, looking for
1395 * any non-point-to-point interfaces which might appear to be on the same
1396 * network as `addr'. If we find any, we OR in their netmask to the
1397 * user-specified netmask.
1400 GetMask(u_int32_t addr
)
1402 u_int32_t mask
, nmask
, ina
;
1403 struct ifreq
*ifr
, *ifend
, ifreq
;
1405 struct ifreq ifs
[MAX_IFS
];
1408 if (IN_CLASSA(addr
)) /* determine network mask for address class */
1409 nmask
= IN_CLASSA_NET
;
1410 else if (IN_CLASSB(addr
))
1411 nmask
= IN_CLASSB_NET
;
1413 nmask
= IN_CLASSC_NET
;
1414 /* class D nets are disallowed by bad_ip_adrs */
1415 mask
= netmask
| htonl(nmask
);
1418 * Scan through the system's network interfaces.
1420 ifc
.ifc_len
= sizeof(ifs
);
1422 if (ioctl(sockfd
, SIOCGIFCONF
, &ifc
) < 0) {
1423 syslog(LOG_WARNING
, "ioctl(SIOCGIFCONF): %m");
1426 ifend
= (struct ifreq
*) (ifc
.ifc_buf
+ ifc
.ifc_len
);
1427 for (ifr
= ifc
.ifc_req
; ifr
< ifend
;
1428 ifr
= (struct ifreq
*) ((char *)&ifr
->ifr_addr
1429 + MAX(ifr
->ifr_addr
.sa_len
, sizeof(ifr
->ifr_addr
)))) {
1431 * Check the interface's internet address.
1433 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
1435 ina
= ((struct sockaddr_in
*) &ifr
->ifr_addr
)->sin_addr
.s_addr
;
1436 if ((ntohl(ina
) & nmask
) != (addr
& nmask
))
1439 * Check that the interface is up, and not point-to-point or loopback.
1441 strncpy(ifreq
.ifr_name
, ifr
->ifr_name
, sizeof(ifreq
.ifr_name
));
1442 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifreq
) < 0)
1444 if ((ifreq
.ifr_flags
& (IFF_UP
|IFF_POINTOPOINT
|IFF_LOOPBACK
))
1448 * Get its netmask and OR it into our mask.
1450 if (ioctl(sockfd
, SIOCGIFNETMASK
, &ifreq
) < 0)
1452 mask
|= ((struct sockaddr_in
*)&ifreq
.ifr_addr
)->sin_addr
.s_addr
;
1459 * Use the hostid as part of the random number seed.
1468 * lock - create a lock file for the named lock device
1470 #define LOCK_PREFIX "/var/spool/lock/LCK.."
1475 char hdb_lock_buffer
[12];
1479 if ((p
= strrchr(dev
, '/')) != NULL
)
1481 lock_file
= malloc(strlen(LOCK_PREFIX
) + strlen(dev
) + 1);
1482 if (lock_file
== NULL
)
1483 novm("lock file name");
1484 strcat(strcpy(lock_file
, LOCK_PREFIX
), dev
);
1486 while ((fd
= open(lock_file
, O_EXCL
| O_CREAT
| O_RDWR
, 0644)) < 0) {
1488 && (fd
= open(lock_file
, O_RDONLY
, 0)) >= 0) {
1489 /* Read the lock file to find out who has the device locked */
1490 n
= read(fd
, hdb_lock_buffer
, 11);
1492 syslog(LOG_ERR
, "Can't read pid from lock file %s", lock_file
);
1495 hdb_lock_buffer
[n
] = 0;
1496 pid
= atoi(hdb_lock_buffer
);
1497 if (kill(pid
, 0) == -1 && errno
== ESRCH
) {
1498 /* pid no longer exists - remove the lock file */
1499 if (unlink(lock_file
) == 0) {
1501 syslog(LOG_NOTICE
, "Removed stale lock on %s (pid %d)",
1505 syslog(LOG_WARNING
, "Couldn't remove stale lock on %s",
1508 syslog(LOG_NOTICE
, "Device %s is locked by pid %d",
1513 syslog(LOG_ERR
, "Can't create lock file %s: %m", lock_file
);
1519 sprintf(hdb_lock_buffer
, "%10d\n", getpid());
1520 write(fd
, hdb_lock_buffer
, 11);
1527 * unlock - remove our lockfile