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 $ */
42 #include <sys/ioctl.h>
43 #include <sys/types.h>
44 #include <sys/socket.h>
47 #include <sys/param.h>
56 #include <net/ppp_layer/ppp_defs.h>
57 #include <net/ppp/if_ppp.h>
58 #include <net/route.h>
59 #include <net/if_dl.h>
60 #include <netinet/in.h>
63 #include <netipx/ipx.h>
67 #include <sys/param.h>
68 #if defined(NetBSD) && (NetBSD >= 199703)
69 #include <netinet/if_inarp.h>
70 #else /* NetBSD 1.2D or later */
72 #include <netinet/if_ether.h>
74 #include <net/if_ether.h>
83 static int initdisc
= -1; /* Initial TTY discipline for ppp_fd */
84 static int initfdflags
= -1; /* Initial file descriptor flags for ppp_fd */
85 static int ppp_fd
= -1; /* fd which is set to PPP discipline */
88 static int restore_term
; /* 1 => we've munged the terminal */
89 static struct termios inittermios
; /* Initial TTY termios */
90 static struct winsize wsinfo
; /* Initial window size info */
92 static char *lock_file
; /* name of lock file created */
94 static int loop_slave
= -1;
95 static int loop_master
;
96 static char loop_name
[20];
98 static unsigned char inbuf
[512]; /* buffer for chars read from loopback */
100 static int sockfd
; /* socket for doing interface ioctls */
102 static int if_is_up
; /* the interface is currently up */
103 static u_int32_t ifaddrs
[2]; /* local and remote addresses we set */
104 static u_int32_t default_route_gateway
; /* gateway addr for default route */
105 static u_int32_t proxy_arp_addr
; /* remote addr for proxy arp */
107 /* Prototypes for procedures local to this file. */
108 static int dodefaultroute(u_int32_t
, int);
109 static int get_ether_addr(u_int32_t
, struct sockaddr_dl
*);
113 * sys_init - System-dependent initialization.
118 /* Get an internet socket for doing socket ioctl's on. */
119 if ((sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
120 syslog(LOG_ERR
, "Couldn't create IP socket: %m");
126 * sys_cleanup - restore any system state we modified before exiting:
127 * mark the interface down, delete default route and/or proxy arp entry.
128 * This should call die() because it's called from die().
136 strncpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
137 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifr
) >= 0
138 && ((ifr
.ifr_flags
& IFF_UP
) != 0)) {
139 ifr
.ifr_flags
&= ~IFF_UP
;
140 ioctl(sockfd
, SIOCSIFFLAGS
, &ifr
);
144 cifaddr(0, ifaddrs
[0], ifaddrs
[1]);
145 if (default_route_gateway
)
146 cifdefaultroute(0, 0, default_route_gateway
);
148 cifproxyarp(0, proxy_arp_addr
);
152 * sys_close - Clean up in a child process before execing.
158 if (loop_slave
>= 0) {
165 * sys_check_options - check the options that the user specified
168 sys_check_options(void)
173 * ppp_available - check whether the system has any ppp interfaces
174 * (in fact we check whether we can do an ioctl on ppp0).
181 extern char *no_ppp_msg
;
183 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
184 return 1; /* can't tell */
186 strncpy(ifr
.ifr_name
, "ppp0", sizeof (ifr
.ifr_name
));
187 ok
= ioctl(s
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) >= 0;
191 This system lacks kernel support for PPP. To include PPP support\n\
192 in the kernel, please follow the steps detailed in the README.bsd\n\
193 file in the ppp-2.2 distribution.\n";
198 * establish_ppp - Turn the serial port into a ppp interface.
201 establish_ppp(int fd
)
203 int pppdisc
= PPPDISC
;
208 * Demand mode - prime the old ppp device to relinquish the unit.
210 if (ioctl(ppp_fd
, PPPIOCXFERUNIT
, 0) < 0) {
211 syslog(LOG_ERR
, "ioctl(transfer ppp unit): %m");
217 * Save the old line discipline of fd, and set it to PPP.
219 if (ioctl(fd
, TIOCGETD
, &initdisc
) < 0) {
220 syslog(LOG_ERR
, "ioctl(TIOCGETD): %m");
223 if (ioctl(fd
, TIOCSETD
, &pppdisc
) < 0) {
224 syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
230 * Find out which interface we were given.
232 if (ioctl(fd
, PPPIOCGUNIT
, &ifunit
) < 0) {
233 syslog(LOG_ERR
, "ioctl(PPPIOCGUNIT): %m");
238 * Check that we got the same unit again.
240 if (ioctl(fd
, PPPIOCGUNIT
, &x
) < 0) {
241 syslog(LOG_ERR
, "ioctl(PPPIOCGUNIT): %m");
245 syslog(LOG_ERR
, "transfer_ppp failed: wanted unit %d, got %d",
250 ioctl(loop_slave
, TIOCSETD
, &x
);
256 * Enable debug in the driver if requested.
259 if (ioctl(fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
260 syslog(LOG_WARNING
, "ioctl (PPPIOCGFLAGS): %m");
262 x
|= (kdebugflag
& 0xFF) * SC_DEBUG
;
263 if (ioctl(fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0)
264 syslog(LOG_WARNING
, "ioctl(PPPIOCSFLAGS): %m");
269 * Set device for non-blocking reads.
271 if ((initfdflags
= fcntl(fd
, F_GETFL
)) == -1
272 || fcntl(fd
, F_SETFL
, initfdflags
| O_NONBLOCK
) == -1) {
273 syslog(LOG_WARNING
, "Couldn't set device to non-blocking mode: %m");
278 * restore_loop - reattach the ppp unit to the loopback.
286 * Transfer the ppp interface back to the loopback.
288 if (ioctl(ppp_fd
, PPPIOCXFERUNIT
, 0) < 0) {
289 syslog(LOG_ERR
, "ioctl(transfer ppp unit): %m");
293 if (ioctl(loop_slave
, TIOCSETD
, &x
) < 0) {
294 syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
299 * Check that we got the same unit again.
301 if (ioctl(loop_slave
, PPPIOCGUNIT
, &x
) < 0) {
302 syslog(LOG_ERR
, "ioctl(PPPIOCGUNIT): %m");
306 syslog(LOG_ERR
, "transfer_ppp failed: wanted unit %d, got %d",
315 * disestablish_ppp - Restore the serial port to normal operation.
316 * This shouldn't call die() because it's called from die().
319 disestablish_ppp(int fd
)
321 /* Reset non-blocking mode on fd. */
322 if (initfdflags
!= -1 && fcntl(fd
, F_SETFL
, initfdflags
) < 0)
323 syslog(LOG_WARNING
, "Couldn't restore device fd flags: %m");
326 /* Restore old line discipline. */
327 if (initdisc
>= 0 && ioctl(fd
, TIOCSETD
, &initdisc
) < 0)
328 syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
336 * Check whether the link seems not to be 8-bit clean.
344 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) == 0) {
346 switch (~x
& (SC_RCV_B7_0
|SC_RCV_B7_1
|SC_RCV_EVNP
|SC_RCV_ODDP
)) {
348 s
= "bit 7 set to 1";
351 s
= "bit 7 set to 0";
361 syslog(LOG_WARNING
, "Serial link is not 8-bit clean:");
362 syslog(LOG_WARNING
, "All received characters had %s", s
);
368 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
369 * at the requested speed, etc. If `local' is true, set CLOCAL
370 * regardless of whether the modem option was specified.
372 * For *BSD, we assume that speed_t values numerically equal bits/second.
375 set_up_tty(int fd
, int local
)
379 if (tcgetattr(fd
, &tios
) < 0) {
380 syslog(LOG_ERR
, "tcgetattr: %m");
386 ioctl(fd
, TIOCGWINSZ
, &wsinfo
);
389 tios
.c_cflag
&= ~(CSIZE
| CSTOPB
| PARENB
| CLOCAL
);
390 if (crtscts
> 0 && !local
)
391 tios
.c_cflag
|= CRTSCTS
;
392 else if (crtscts
< 0)
393 tios
.c_cflag
&= ~CRTSCTS
;
395 tios
.c_cflag
|= CS8
| CREAD
| HUPCL
;
397 tios
.c_cflag
|= CLOCAL
;
398 tios
.c_iflag
= IGNBRK
| IGNPAR
;
402 tios
.c_cc
[VTIME
] = 0;
405 tios
.c_iflag
|= IXON
| IXOFF
;
406 tios
.c_cc
[VSTOP
] = 0x13; /* DC3 = XOFF = ^S */
407 tios
.c_cc
[VSTART
] = 0x11; /* DC1 = XON = ^Q */
411 cfsetospeed(&tios
, inspeed
);
412 cfsetispeed(&tios
, inspeed
);
414 inspeed
= cfgetospeed(&tios
);
416 * We can't proceed if the serial port speed is 0,
417 * since that implies that the serial port is disabled.
420 syslog(LOG_ERR
, "Baud rate for %s is 0; need explicit baud rate",
427 if (tcsetattr(fd
, TCSAFLUSH
, &tios
) < 0) {
428 syslog(LOG_ERR
, "tcsetattr: %m");
436 * restore_tty - restore the terminal to the saved settings.
442 if (!default_device
) {
444 * Turn off echoing, because otherwise we can get into
445 * a loop with the tty and the modem echoing to each other.
446 * We presume we are the sole user of this tty device, so
447 * when we close it, it will revert to its defaults anyway.
449 inittermios
.c_lflag
&= ~(ECHO
| ECHONL
);
451 if (tcsetattr(fd
, TCSAFLUSH
, &inittermios
) < 0)
453 syslog(LOG_WARNING
, "tcsetattr: %m");
454 ioctl(fd
, TIOCSWINSZ
, &wsinfo
);
460 * setdtr - control the DTR line on the serial port.
461 * This is called from die(), so it shouldn't call die().
464 setdtr(int fd
, int on
)
466 int modembits
= TIOCM_DTR
;
468 ioctl(fd
, (on
? TIOCMBIS
: TIOCMBIC
), &modembits
);
473 * open_ppp_loopback - open the device we use for getting
474 * packets in demand mode, and connect it to a ppp interface.
478 open_ppp_loopback(void)
482 int pppdisc
= PPPDISC
;
484 if (openpty(&loop_master
, &loop_slave
, loop_name
, NULL
, NULL
) < 0) {
485 syslog(LOG_ERR
, "No free pty for loopback");
488 SYSDEBUG((LOG_DEBUG
, "using %s for loopback", loop_name
));
490 if (tcgetattr(loop_slave
, &tios
) == 0) {
491 tios
.c_cflag
&= ~(CSIZE
| CSTOPB
| PARENB
);
492 tios
.c_cflag
|= CS8
| CREAD
;
493 tios
.c_iflag
= IGNPAR
;
496 if (tcsetattr(loop_slave
, TCSAFLUSH
, &tios
) < 0)
497 syslog(LOG_WARNING
, "couldn't set attributes on loopback: %m");
500 if ((flags
= fcntl(loop_master
, F_GETFL
)) != -1)
501 if (fcntl(loop_master
, F_SETFL
, flags
| O_NONBLOCK
) == -1)
502 syslog(LOG_WARNING
, "couldn't set loopback to nonblock: %m");
505 if (ioctl(ppp_fd
, TIOCSETD
, &pppdisc
) < 0) {
506 syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
511 * Find out which interface we were given.
513 if (ioctl(ppp_fd
, PPPIOCGUNIT
, &ifunit
) < 0) {
514 syslog(LOG_ERR
, "ioctl(PPPIOCGUNIT): %m");
519 * Enable debug in the driver if requested.
522 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &flags
) < 0) {
523 syslog(LOG_WARNING
, "ioctl (PPPIOCGFLAGS): %m");
525 flags
|= (kdebugflag
& 0xFF) * SC_DEBUG
;
526 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &flags
) < 0)
527 syslog(LOG_WARNING
, "ioctl(PPPIOCSFLAGS): %m");
535 * output - Output PPP packet.
538 output(int unit
, u_char
*p
, int len
)
541 log_packet(p
, len
, "sent ", LOG_DEBUG
);
543 if (write(ttyfd
, p
, len
) < 0) {
545 syslog(LOG_ERR
, "write: %m");
551 * wait_input - wait until there is data available on ttyfd,
552 * for the length of time specified by *timo (indefinite
556 wait_input(struct timeval
*timo
)
561 if (ttyfd
>= FD_SETSIZE
) {
562 syslog(LOG_ERR
, "descriptor too big");
566 FD_SET(ttyfd
, &ready
);
567 n
= select(ttyfd
+1, &ready
, NULL
, &ready
, timo
);
568 if (n
< 0 && errno
!= EINTR
) {
569 syslog(LOG_ERR
, "select: %m");
576 * wait_loop_output - wait until there is data available on the
577 * loopback, for the length of time specified by *timo (indefinite
581 wait_loop_output(struct timeval
*timo
)
586 if (loop_master
>= FD_SETSIZE
) {
587 syslog(LOG_ERR
, "descriptor too big");
591 FD_SET(loop_master
, &ready
);
592 n
= select(loop_master
+ 1, &ready
, NULL
, &ready
, timo
);
593 if (n
< 0 && errno
!= EINTR
) {
594 syslog(LOG_ERR
, "select: %m");
601 * wait_time - wait for a given length of time or until a
602 * signal is received.
605 wait_time(struct timeval
*timo
)
609 n
= select(0, NULL
, NULL
, NULL
, timo
);
610 if (n
< 0 && errno
!= EINTR
) {
611 syslog(LOG_ERR
, "select: %m");
618 * read_packet - get a PPP packet from the serial device.
621 read_packet(u_char
*buf
)
625 if ((len
= read(ttyfd
, buf
, PPP_MTU
+ PPP_HDRLEN
)) < 0) {
626 if (errno
== EWOULDBLOCK
|| errno
== EINTR
)
628 syslog(LOG_ERR
, "read: %m");
636 * get_loop_output - read characters from the loopback, form them
637 * into frames, and detect when we want to bring the real link up.
638 * Return value is 1 if we need to bring up the link, 0 otherwise.
641 get_loop_output(void)
646 while ((n
= read(loop_master
, inbuf
, sizeof(inbuf
))) >= 0) {
647 if (loop_chars(inbuf
, n
))
652 syslog(LOG_ERR
, "eof on loopback");
654 } else if (errno
!= EWOULDBLOCK
){
655 syslog(LOG_ERR
, "read from loopback: %m");
664 * ppp_send_config - configure the transmit characteristics of
668 ppp_send_config(int unit
, int mtu
, u_int32_t asyncmap
, int pcomp
, int accomp
)
673 strncpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
675 if (ioctl(sockfd
, SIOCSIFMTU
, (caddr_t
) &ifr
) < 0) {
676 syslog(LOG_ERR
, "ioctl(SIOCSIFMTU): %m");
680 if (ioctl(ppp_fd
, PPPIOCSASYNCMAP
, (caddr_t
) &asyncmap
) < 0) {
681 syslog(LOG_ERR
, "ioctl(PPPIOCSASYNCMAP): %m");
685 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
686 syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
689 x
= pcomp
? x
| SC_COMP_PROT
: x
&~ SC_COMP_PROT
;
690 x
= accomp
? x
| SC_COMP_AC
: x
&~ SC_COMP_AC
;
691 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0) {
692 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
699 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
702 ppp_set_xaccm(int unit
, ext_accm accm
)
704 if (ioctl(ppp_fd
, PPPIOCSXASYNCMAP
, accm
) < 0 && errno
!= ENOTTY
)
705 syslog(LOG_WARNING
, "ioctl(set extended ACCM): %m");
710 * ppp_recv_config - configure the receive-side characteristics of
714 ppp_recv_config(int unit
, int mru
, u_int32_t asyncmap
, int pcomp
, int accomp
)
718 if (ioctl(ppp_fd
, PPPIOCSMRU
, (caddr_t
) &mru
) < 0) {
719 syslog(LOG_ERR
, "ioctl(PPPIOCSMRU): %m");
722 if (ioctl(ppp_fd
, PPPIOCSRASYNCMAP
, (caddr_t
) &asyncmap
) < 0) {
723 syslog(LOG_ERR
, "ioctl(PPPIOCSRASYNCMAP): %m");
726 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
727 syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
730 x
= !accomp
? x
| SC_REJ_COMP_AC
: x
&~ SC_REJ_COMP_AC
;
731 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0) {
732 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
738 * ccp_test - ask kernel whether a given compression method
739 * is acceptable for use. Returns 1 if the method and parameters
740 * are OK, 0 if the method is known but the parameters are not OK
741 * (e.g. code size should be reduced), or -1 if the method is unknown.
744 ccp_test(int unit
, u_char
*opt_ptr
, int opt_len
, int for_transmit
)
746 struct ppp_option_data data
;
749 data
.length
= opt_len
;
750 data
.transmit
= for_transmit
;
751 if (ioctl(ttyfd
, PPPIOCSCOMPRESS
, (caddr_t
) &data
) >= 0)
753 return (errno
== ENOBUFS
)? 0: -1;
757 * ccp_flags_set - inform kernel about the current state of CCP.
760 ccp_flags_set(int unit
, int isopen
, int isup
)
764 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
765 syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
768 x
= isopen
? x
| SC_CCP_OPEN
: x
&~ SC_CCP_OPEN
;
769 x
= isup
? x
| SC_CCP_UP
: x
&~ SC_CCP_UP
;
770 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0)
771 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
775 * ccp_fatal_error - returns 1 if decompression was disabled as a
776 * result of an error detected after decompression of a packet,
777 * 0 otherwise. This is necessary because of patent nonsense.
780 ccp_fatal_error(int unit
)
784 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
785 syslog(LOG_ERR
, "ioctl(PPPIOCGFLAGS): %m");
788 return x
& SC_DC_FERROR
;
792 * get_idle_time - return how long the link has been idle.
795 get_idle_time(int u
, struct ppp_idle
*ip
)
797 return ioctl(ppp_fd
, PPPIOCGIDLE
, ip
) >= 0;
803 * set_filters - transfer the pass and active filters to the kernel.
806 set_filters(struct bpf_program
*pass
, struct bpf_program
*active
)
810 if (pass
->bf_len
> 0) {
811 if (ioctl(ppp_fd
, PPPIOCSPASS
, pass
) < 0) {
812 syslog(LOG_ERR
, "Couldn't set pass-filter in kernel: %m");
816 if (active
->bf_len
> 0) {
817 if (ioctl(ppp_fd
, PPPIOCSACTIVE
, active
) < 0) {
818 syslog(LOG_ERR
, "Couldn't set active-filter in kernel: %m");
827 * sifvjcomp - config tcp header compression
830 sifvjcomp(int u
, int vjcomp
, int cidcomp
, int maxcid
)
834 if (ioctl(ppp_fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
835 syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
838 x
= vjcomp
? x
| SC_COMP_TCP
: x
&~ SC_COMP_TCP
;
839 x
= cidcomp
? x
& ~SC_NO_TCP_CCID
: x
| SC_NO_TCP_CCID
;
840 if (ioctl(ppp_fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0) {
841 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
844 if (vjcomp
&& ioctl(ppp_fd
, PPPIOCSMAXCID
, (caddr_t
) &maxcid
) < 0) {
845 syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
852 * sifup - Config the interface up and enable IP packets to pass.
859 strncpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
860 if (ioctl(sockfd
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) < 0) {
861 syslog(LOG_ERR
, "ioctl (SIOCGIFFLAGS): %m");
864 ifr
.ifr_flags
|= IFF_UP
;
865 if (ioctl(sockfd
, SIOCSIFFLAGS
, (caddr_t
) &ifr
) < 0) {
866 syslog(LOG_ERR
, "ioctl(SIOCSIFFLAGS): %m");
874 * sifnpmode - Set the mode for handling packets for a given NP.
877 sifnpmode(int u
, int proto
, enum NPmode mode
)
881 npi
.protocol
= proto
;
883 if (ioctl(ppp_fd
, PPPIOCSNPMODE
, &npi
) < 0) {
884 syslog(LOG_ERR
, "ioctl(set NP %d mode to %d): %m", proto
, mode
);
891 * sifdown - Config the interface down and disable IP.
901 npi
.protocol
= PPP_IP
;
902 npi
.mode
= NPMODE_ERROR
;
903 ioctl(ppp_fd
, PPPIOCSNPMODE
, (caddr_t
) &npi
);
904 /* ignore errors, because ppp_fd might have been closed by now. */
906 strncpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
907 if (ioctl(sockfd
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) < 0) {
908 syslog(LOG_ERR
, "ioctl (SIOCGIFFLAGS): %m");
911 ifr
.ifr_flags
&= ~IFF_UP
;
912 if (ioctl(sockfd
, SIOCSIFFLAGS
, (caddr_t
) &ifr
) < 0) {
913 syslog(LOG_ERR
, "ioctl(SIOCSIFFLAGS): %m");
922 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
925 #define SET_SA_FAMILY(addr, family) \
926 BZERO((char *) &(addr), sizeof(addr)); \
927 addr.sa_family = (family); \
928 addr.sa_len = sizeof(addr);
931 * sifaddr - Config the interface IP addresses and netmask.
934 sifaddr(int u
, u_int32_t o
, u_int32_t h
, u_int32_t m
)
936 struct ifaliasreq ifra
;
939 strncpy(ifra
.ifra_name
, ifname
, sizeof(ifra
.ifra_name
));
940 SET_SA_FAMILY(ifra
.ifra_addr
, AF_INET
);
941 ((struct sockaddr_in
*) &ifra
.ifra_addr
)->sin_addr
.s_addr
= o
;
942 SET_SA_FAMILY(ifra
.ifra_broadaddr
, AF_INET
);
943 ((struct sockaddr_in
*) &ifra
.ifra_broadaddr
)->sin_addr
.s_addr
= h
;
945 SET_SA_FAMILY(ifra
.ifra_mask
, AF_INET
);
946 ((struct sockaddr_in
*) &ifra
.ifra_mask
)->sin_addr
.s_addr
= m
;
948 BZERO(&ifra
.ifra_mask
, sizeof(ifra
.ifra_mask
));
949 BZERO(&ifr
, sizeof(ifr
));
950 strncpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
951 if (ioctl(sockfd
, SIOCDIFADDR
, (caddr_t
) &ifr
) < 0) {
952 if (errno
!= EADDRNOTAVAIL
)
953 syslog(LOG_WARNING
, "Couldn't remove interface address: %m");
955 if (ioctl(sockfd
, SIOCAIFADDR
, (caddr_t
) &ifra
) < 0) {
956 if (errno
!= EEXIST
) {
957 syslog(LOG_ERR
, "Couldn't set interface address: %m");
961 "Couldn't set interface address: Address %s already exists",
970 * cifaddr - Clear the interface IP addresses, and delete routes
971 * through the interface if possible.
974 cifaddr(int u
, u_int32_t o
, u_int32_t h
)
976 struct ifaliasreq ifra
;
979 strncpy(ifra
.ifra_name
, ifname
, sizeof(ifra
.ifra_name
));
980 SET_SA_FAMILY(ifra
.ifra_addr
, AF_INET
);
981 ((struct sockaddr_in
*) &ifra
.ifra_addr
)->sin_addr
.s_addr
= o
;
982 SET_SA_FAMILY(ifra
.ifra_broadaddr
, AF_INET
);
983 ((struct sockaddr_in
*) &ifra
.ifra_broadaddr
)->sin_addr
.s_addr
= h
;
984 BZERO(&ifra
.ifra_mask
, sizeof(ifra
.ifra_mask
));
985 if (ioctl(sockfd
, SIOCDIFADDR
, (caddr_t
) &ifra
) < 0) {
986 if (errno
!= EADDRNOTAVAIL
)
987 syslog(LOG_WARNING
, "Couldn't delete interface address: %m");
994 * sifdefaultroute - assign a default route through the address given.
997 sifdefaultroute(int u
, u_int32_t l
, u_int32_t g
)
999 return dodefaultroute(g
, 's');
1003 * cifdefaultroute - delete a default route through the address given.
1006 cifdefaultroute(int u
, u_int32_t l
, u_int32_t g
)
1008 return dodefaultroute(g
, 'c');
1012 * dodefaultroute - talk to a routing socket to add/delete a default route.
1015 dodefaultroute(u_int32_t g
, int cmd
)
1019 struct rt_msghdr hdr
;
1020 struct sockaddr_in dst
;
1021 struct sockaddr_in gway
;
1022 struct sockaddr_in mask
;
1025 if ((routes
= socket(PF_ROUTE
, SOCK_RAW
, AF_INET
)) < 0) {
1026 syslog(LOG_ERR
, "Couldn't %s default route: socket: %m",
1027 cmd
=='s'? "add": "delete");
1031 memset(&rtmsg
, 0, sizeof(rtmsg
));
1032 rtmsg
.hdr
.rtm_type
= cmd
== 's'? RTM_ADD
: RTM_DELETE
;
1033 rtmsg
.hdr
.rtm_flags
= RTF_UP
| RTF_GATEWAY
| RTF_STATIC
;
1034 rtmsg
.hdr
.rtm_version
= RTM_VERSION
;
1035 rtmsg
.hdr
.rtm_seq
= ++rtm_seq
;
1036 rtmsg
.hdr
.rtm_addrs
= RTA_DST
| RTA_GATEWAY
| RTA_NETMASK
;
1037 rtmsg
.dst
.sin_len
= sizeof(rtmsg
.dst
);
1038 rtmsg
.dst
.sin_family
= AF_INET
;
1039 rtmsg
.gway
.sin_len
= sizeof(rtmsg
.gway
);
1040 rtmsg
.gway
.sin_family
= AF_INET
;
1041 rtmsg
.gway
.sin_addr
.s_addr
= g
;
1042 rtmsg
.mask
.sin_len
= sizeof(rtmsg
.dst
);
1043 rtmsg
.mask
.sin_family
= AF_INET
;
1045 rtmsg
.hdr
.rtm_msglen
= sizeof(rtmsg
);
1046 if (write(routes
, &rtmsg
, sizeof(rtmsg
)) < 0) {
1047 syslog(LOG_ERR
, "Couldn't %s default route: %m",
1048 cmd
=='s'? "add": "delete");
1054 default_route_gateway
= (cmd
== 's')? g
: 0;
1058 #if RTM_VERSION >= 3
1061 * sifproxyarp - Make a proxy ARP entry for the peer.
1064 struct rt_msghdr hdr
;
1065 struct sockaddr_inarp dst
;
1066 struct sockaddr_dl hwa
;
1070 static int arpmsg_valid
;
1073 sifproxyarp(int unit
, u_int32_t hisaddr
)
1078 * Get the hardware address of an interface on the same subnet
1079 * as our local address.
1081 memset(&arpmsg
, 0, sizeof(arpmsg
));
1082 if (!get_ether_addr(hisaddr
, &arpmsg
.hwa
)) {
1083 syslog(LOG_ERR
, "Cannot determine ethernet address for proxy ARP");
1087 if ((routes
= socket(PF_ROUTE
, SOCK_RAW
, AF_INET
)) < 0) {
1088 syslog(LOG_ERR
, "Couldn't add proxy arp entry: socket: %m");
1092 arpmsg
.hdr
.rtm_type
= RTM_ADD
;
1093 arpmsg
.hdr
.rtm_flags
= RTF_ANNOUNCE
| RTF_HOST
| RTF_STATIC
;
1094 arpmsg
.hdr
.rtm_version
= RTM_VERSION
;
1095 arpmsg
.hdr
.rtm_seq
= ++rtm_seq
;
1096 arpmsg
.hdr
.rtm_addrs
= RTA_DST
| RTA_GATEWAY
;
1097 arpmsg
.hdr
.rtm_inits
= RTV_EXPIRE
;
1098 arpmsg
.dst
.sin_len
= sizeof(struct sockaddr_inarp
);
1099 arpmsg
.dst
.sin_family
= AF_INET
;
1100 arpmsg
.dst
.sin_addr
.s_addr
= hisaddr
;
1101 arpmsg
.dst
.sin_other
= SIN_PROXY
;
1103 arpmsg
.hdr
.rtm_msglen
= (char *) &arpmsg
.hwa
- (char *) &arpmsg
1104 + arpmsg
.hwa
.sdl_len
;
1105 if (write(routes
, &arpmsg
, arpmsg
.hdr
.rtm_msglen
) < 0) {
1106 syslog(LOG_ERR
, "Couldn't add proxy arp entry: %m");
1113 proxy_arp_addr
= hisaddr
;
1118 * cifproxyarp - Delete the proxy ARP entry for the peer.
1121 cifproxyarp(int unit
, u_int32_t hisaddr
)
1129 arpmsg
.hdr
.rtm_type
= RTM_DELETE
;
1130 arpmsg
.hdr
.rtm_seq
= ++rtm_seq
;
1132 if ((routes
= socket(PF_ROUTE
, SOCK_RAW
, AF_INET
)) < 0) {
1133 syslog(LOG_ERR
, "Couldn't delete proxy arp entry: socket: %m");
1137 if (write(routes
, &arpmsg
, arpmsg
.hdr
.rtm_msglen
) < 0) {
1138 syslog(LOG_ERR
, "Couldn't delete proxy arp entry: %m");
1148 #else /* RTM_VERSION */
1151 * sifproxyarp - Make a proxy ARP entry for the peer.
1154 sifproxyarp(int unit
, u_int32_t hisaddr
)
1156 struct arpreq arpreq
;
1158 struct sockaddr_dl sdl
;
1162 BZERO(&arpreq
, sizeof(arpreq
));
1165 * Get the hardware address of an interface on the same subnet
1166 * as our local address.
1168 if (!get_ether_addr(hisaddr
, &dls
.sdl
)) {
1169 syslog(LOG_ERR
, "Cannot determine ethernet address for proxy ARP");
1173 arpreq
.arp_ha
.sa_len
= sizeof(struct sockaddr
);
1174 arpreq
.arp_ha
.sa_family
= AF_UNSPEC
;
1175 BCOPY(LLADDR(&dls
.sdl
), arpreq
.arp_ha
.sa_data
, dls
.sdl
.sdl_alen
);
1176 SET_SA_FAMILY(arpreq
.arp_pa
, AF_INET
);
1177 ((struct sockaddr_in
*) &arpreq
.arp_pa
)->sin_addr
.s_addr
= hisaddr
;
1178 arpreq
.arp_flags
= ATF_PERM
| ATF_PUBL
;
1179 if (ioctl(sockfd
, SIOCSARP
, (caddr_t
)&arpreq
) < 0) {
1180 syslog(LOG_ERR
, "Couldn't add proxy arp entry: %m");
1184 proxy_arp_addr
= hisaddr
;
1189 * cifproxyarp - Delete the proxy ARP entry for the peer.
1192 cifproxyarp(int unit
, u_int32_t hisaddr
)
1194 struct arpreq arpreq
;
1196 BZERO(&arpreq
, sizeof(arpreq
));
1197 SET_SA_FAMILY(arpreq
.arp_pa
, AF_INET
);
1198 ((struct sockaddr_in
*) &arpreq
.arp_pa
)->sin_addr
.s_addr
= hisaddr
;
1199 if (ioctl(sockfd
, SIOCDARP
, (caddr_t
)&arpreq
) < 0) {
1200 syslog(LOG_WARNING
, "Couldn't delete proxy arp entry: %m");
1206 #endif /* RTM_VERSION */
1209 /********************************************************************
1211 * sipxfaddr - Config the interface IPX networknumber
1215 sipxfaddr(int unit
, unsigned long int network
, unsigned char *node
)
1220 struct sockaddr_ipx ipx_addr
;
1222 struct sockaddr_ipx
*sipx
= (struct sockaddr_ipx
*) &ifr
.ifr_addr
;
1223 union ipx_net_u net
;
1225 skfd
= socket (AF_IPX
, SOCK_DGRAM
, 0);
1228 syslog (LOG_DEBUG
, "socket(AF_IPX): %m(%d)", errno
);
1233 memset (&ifr
, '\0', sizeof (ifr
));
1234 strcpy (ifr
.ifr_name
, ifname
);
1236 memcpy (sipx
->sipx_addr
.x_host
.c_host
, node
, 6);
1237 sipx
->sipx_len
= sizeof(sipx
);
1238 sipx
->sipx_family
= AF_IPX
;
1239 sipx
->sipx_port
= 0;
1240 memset(&net
, 0, sizeof(net
));
1241 net
.long_e
= htonl (network
);
1242 sipx
->sipx_addr
.x_net
= net
.net_e
;
1244 * Set the IPX device
1246 if (ioctl(skfd
, SIOCSIFADDR
, (caddr_t
) &ifr
) < 0)
1249 if (errno
!= EEXIST
)
1252 "ioctl(SIOCAIFADDR, CRTITF): %m(%d)", errno
);
1256 syslog (LOG_WARNING
,
1257 "ioctl(SIOCAIFADDR, CRTITF): Address already exists");
1265 /********************************************************************
1267 * cipxfaddr - Clear the information for the IPX network. The IPX routes
1268 * are removed and the device is no longer able to pass IPX
1272 int cipxfaddr(int unit
)
1277 struct sockaddr_ipx ipx_addr
;
1279 struct sockaddr_ipx
*sipx
= (struct sockaddr_ipx
*) &ifr
.ifr_addr
;
1281 skfd
= socket (AF_IPX
, SOCK_DGRAM
, 0);
1284 syslog (LOG_DEBUG
, "socket(AF_IPX): %m(%d)", errno
);
1289 memset (&ifr
, '\0', sizeof (ifr
));
1290 strcpy (ifr
.ifr_name
, ifname
);
1292 sipx
->sipx_len
= sizeof(sipx
);
1293 sipx
->sipx_family
= AF_IPX
;
1295 * Set the IPX device
1297 if (ioctl(skfd
, SIOCSIFADDR
, (caddr_t
) &ifr
) < 0)
1300 "ioctl(SIOCAIFADDR, IPX_DLTITF): %m(%d)", errno
);
1310 * get_ether_addr - get the hardware address of an interface on the
1311 * the same subnet as ipaddr.
1316 get_ether_addr(u_int32_t ipaddr
, struct sockaddr_dl
*hwaddr
)
1318 struct ifreq
*ifr
, *ifend
, *ifp
;
1319 u_int32_t ina
, mask
;
1320 struct sockaddr_dl
*dla
;
1323 struct ifreq ifs
[MAX_IFS
];
1325 ifc
.ifc_len
= sizeof(ifs
);
1327 if (ioctl(sockfd
, SIOCGIFCONF
, &ifc
) < 0) {
1328 syslog(LOG_ERR
, "ioctl(SIOCGIFCONF): %m");
1333 * Scan through looking for an interface with an Internet
1334 * address on the same subnet as `ipaddr'.
1336 ifend
= (struct ifreq
*) (ifc
.ifc_buf
+ ifc
.ifc_len
);
1337 for (ifr
= ifc
.ifc_req
; ifr
< ifend
;
1338 ifr
= (struct ifreq
*) ((char *)&ifr
->ifr_addr
1339 + MAX(ifr
->ifr_addr
.sa_len
, sizeof(ifr
->ifr_addr
)))) {
1340 if (ifr
->ifr_addr
.sa_family
== AF_INET
) {
1341 ina
= ((struct sockaddr_in
*) &ifr
->ifr_addr
)->sin_addr
.s_addr
;
1342 strncpy(ifreq
.ifr_name
, ifr
->ifr_name
, sizeof(ifreq
.ifr_name
));
1344 * Check that the interface is up, and not point-to-point
1347 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifreq
) < 0)
1349 if ((ifreq
.ifr_flags
&
1350 (IFF_UP
|IFF_BROADCAST
|IFF_POINTOPOINT
|IFF_LOOPBACK
|IFF_NOARP
))
1351 != (IFF_UP
|IFF_BROADCAST
))
1354 * Get its netmask and check that it's on the right subnet.
1356 if (ioctl(sockfd
, SIOCGIFNETMASK
, &ifreq
) < 0)
1358 mask
= ((struct sockaddr_in
*) &ifreq
.ifr_addr
)->sin_addr
.s_addr
;
1359 if ((ipaddr
& mask
) != (ina
& mask
))
1368 syslog(LOG_INFO
, "found interface %s for proxy arp", ifr
->ifr_name
);
1371 * Now scan through again looking for a link-level address
1372 * for this interface.
1375 for (ifr
= ifc
.ifc_req
; ifr
< ifend
; ) {
1376 if (strcmp(ifp
->ifr_name
, ifr
->ifr_name
) == 0
1377 && ifr
->ifr_addr
.sa_family
== AF_LINK
) {
1379 * Found the link-level address - copy it out
1381 dla
= (struct sockaddr_dl
*) &ifr
->ifr_addr
;
1382 BCOPY(dla
, hwaddr
, dla
->sdl_len
);
1385 ifr
= (struct ifreq
*) ((char *)&ifr
->ifr_addr
1386 + MAX(ifr
->ifr_addr
.sa_len
, sizeof(ifr
->ifr_addr
)));
1393 * Return user specified netmask, modified by any mask we might determine
1394 * for address `addr' (in network byte order).
1395 * Here we scan through the system's list of interfaces, looking for
1396 * any non-point-to-point interfaces which might appear to be on the same
1397 * network as `addr'. If we find any, we OR in their netmask to the
1398 * user-specified netmask.
1401 GetMask(u_int32_t addr
)
1403 u_int32_t mask
, nmask
, ina
;
1404 struct ifreq
*ifr
, *ifend
, ifreq
;
1406 struct ifreq ifs
[MAX_IFS
];
1409 if (IN_CLASSA(addr
)) /* determine network mask for address class */
1410 nmask
= IN_CLASSA_NET
;
1411 else if (IN_CLASSB(addr
))
1412 nmask
= IN_CLASSB_NET
;
1414 nmask
= IN_CLASSC_NET
;
1415 /* class D nets are disallowed by bad_ip_adrs */
1416 mask
= netmask
| htonl(nmask
);
1419 * Scan through the system's network interfaces.
1421 ifc
.ifc_len
= sizeof(ifs
);
1423 if (ioctl(sockfd
, SIOCGIFCONF
, &ifc
) < 0) {
1424 syslog(LOG_WARNING
, "ioctl(SIOCGIFCONF): %m");
1427 ifend
= (struct ifreq
*) (ifc
.ifc_buf
+ ifc
.ifc_len
);
1428 for (ifr
= ifc
.ifc_req
; ifr
< ifend
;
1429 ifr
= (struct ifreq
*) ((char *)&ifr
->ifr_addr
1430 + MAX(ifr
->ifr_addr
.sa_len
, sizeof(ifr
->ifr_addr
)))) {
1432 * Check the interface's internet address.
1434 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
1436 ina
= ((struct sockaddr_in
*) &ifr
->ifr_addr
)->sin_addr
.s_addr
;
1437 if ((ntohl(ina
) & nmask
) != (addr
& nmask
))
1440 * Check that the interface is up, and not point-to-point or loopback.
1442 strncpy(ifreq
.ifr_name
, ifr
->ifr_name
, sizeof(ifreq
.ifr_name
));
1443 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifreq
) < 0)
1445 if ((ifreq
.ifr_flags
& (IFF_UP
|IFF_POINTOPOINT
|IFF_LOOPBACK
))
1449 * Get its netmask and OR it into our mask.
1451 if (ioctl(sockfd
, SIOCGIFNETMASK
, &ifreq
) < 0)
1453 mask
|= ((struct sockaddr_in
*)&ifreq
.ifr_addr
)->sin_addr
.s_addr
;
1460 * Use the hostid as part of the random number seed.
1469 * lock - create a lock file for the named lock device
1471 #define LOCK_PREFIX "/var/spool/lock/LCK.."
1476 char hdb_lock_buffer
[12];
1480 if ((p
= strrchr(dev
, '/')) != NULL
)
1482 lock_file
= malloc(strlen(LOCK_PREFIX
) + strlen(dev
) + 1);
1483 if (lock_file
== NULL
)
1484 novm("lock file name");
1485 strcat(strcpy(lock_file
, LOCK_PREFIX
), dev
);
1487 while ((fd
= open(lock_file
, O_EXCL
| O_CREAT
| O_RDWR
, 0644)) < 0) {
1489 && (fd
= open(lock_file
, O_RDONLY
, 0)) >= 0) {
1490 /* Read the lock file to find out who has the device locked */
1491 n
= read(fd
, hdb_lock_buffer
, 11);
1493 syslog(LOG_ERR
, "Can't read pid from lock file %s", lock_file
);
1496 hdb_lock_buffer
[n
] = 0;
1497 pid
= atoi(hdb_lock_buffer
);
1498 if (kill(pid
, 0) == -1 && errno
== ESRCH
) {
1499 /* pid no longer exists - remove the lock file */
1500 if (unlink(lock_file
) == 0) {
1502 syslog(LOG_NOTICE
, "Removed stale lock on %s (pid %d)",
1506 syslog(LOG_WARNING
, "Couldn't remove stale lock on %s",
1509 syslog(LOG_NOTICE
, "Device %s is locked by pid %d",
1514 syslog(LOG_ERR
, "Can't create lock file %s: %m", lock_file
);
1520 sprintf(hdb_lock_buffer
, "%10d\n", getpid());
1521 write(fd
, hdb_lock_buffer
, 11);
1528 * unlock - remove our lockfile