2 * sys-aix4.c - System-dependent procedures for setting up
3 * PPP interfaces on AIX systems which use the STREAMS ppp interface.
5 * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. The name(s) of the authors of this software must not be used to
15 * endorse or promote products derived from this software without
16 * prior written permission.
18 * 3. Redistributions of any form whatsoever must retain the following
20 * "This product includes software developed by Paul Mackerras
21 * <paulus@samba.org>".
23 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
24 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
25 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
26 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
28 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
29 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 * Derived from main.c and pppd.h, which are:
33 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in
44 * the documentation and/or other materials provided with the
47 * 3. The name "Carnegie Mellon University" must not be used to
48 * endorse or promote products derived from this software without
49 * prior written permission. For permission or any legal
50 * details, please contact
51 * Office of Technology Transfer
52 * Carnegie Mellon University
54 * Pittsburgh, PA 15213-3890
55 * (412) 268-4387, fax: (412) 268-7395
56 * tech-transfer@andrew.cmu.edu
58 * 4. Redistributions of any form whatsoever must retain the following
60 * "This product includes software developed by Computing Services
61 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
63 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
64 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
65 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
66 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
67 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
68 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
69 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
72 #define RCSID "$Id: sys-aix4.c,v 1.24 2004/11/04 10:02:26 paulus Exp $"
84 #include <sys/termiox.h>
90 #include <sys/types.h>
91 #include <sys/socket.h>
93 #include <sys/stream.h>
94 #include <sys/stropts.h>
97 #include <net/ppp_defs.h>
98 #include <net/route.h>
99 #include <net/if_arp.h>
100 #include <netinet/in.h>
104 static const char rcsid
[] = RCSID
;
107 #define ifr_mtu ifr_metric
110 #define MAXMODULES 10 /* max number of module names to save */
111 static struct modlist
{
112 char modname
[FMNAMESZ
+1];
113 } str_modules
[MAXMODULES
];
114 static int str_module_count
= 0;
115 static int pushed_ppp
;
116 static int closed_stdio
;
118 static int restore_term
; /* 1 => we've munged the terminal */
119 static struct termios inittermios
; /* Initial TTY termios */
120 static int initfdflags
= -1; /* Initial file descriptor flags for fd */
122 static int sockfd
; /* socket for doing interface ioctls */
124 static int if_is_up
; /* Interface has been marked up */
125 static u_int32_t ifaddrs
[2]; /* local and remote addresses */
126 static u_int32_t default_route_gateway
; /* Gateway for default route added */
127 static u_int32_t proxy_arp_addr
; /* Addr for proxy arp entry added */
129 #define MAX_POLLFDS 32
130 static struct pollfd pollfds
[MAX_POLLFDS
];
131 static int n_pollfds
;
133 /* Prototypes for procedures local to this file. */
134 static int translate_speed
__P((int));
135 static int baud_rate_of
__P((int));
136 static int get_ether_addr
__P((u_int32_t
, struct sockaddr
*));
140 * sys_init - System-dependent initialization.
145 /* Get an internet socket for doing socket ioctl's on. */
146 if ((sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
147 fatal("Couldn't create IP socket: %m");
153 * sys_cleanup - restore any system state we modified before exiting:
154 * mark the interface down, delete default route and/or proxy arp entry.
155 * This should call die() because it's called from die().
163 strlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
164 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifr
) >= 0
165 && ((ifr
.ifr_flags
& IFF_UP
) != 0)) {
166 ifr
.ifr_flags
&= ~IFF_UP
;
167 ioctl(sockfd
, SIOCSIFFLAGS
, &ifr
);
171 cifaddr(0, ifaddrs
[0], ifaddrs
[1]);
172 if (default_route_gateway
)
173 cifdefaultroute(0, 0, default_route_gateway
);
175 cifproxyarp(0, proxy_arp_addr
);
179 * have_route_to - determine if the system has any route to
180 * a given IP address.
181 * For demand mode to work properly, we have to ignore routes
182 * through our own interface.
184 int have_route_to(u_int32_t addr
)
191 * daemon - Detach us from the terminal session.
194 daemon(nochdir
, noclose
)
195 int nochdir
, noclose
;
199 if ((pid
= fork()) < 0)
202 exit(0); /* parent dies */
207 fclose(stdin
); /* don't need stdin, stdout, stderr */
216 * ppp_available - check if this kernel supports PPP.
223 fd
= open("/dev/tty", O_RDONLY
, 0);
225 return 1; /* can't find out - assume we have ppp */
226 ret
= ioctl(fd
, I_FIND
, "pppasync") >= 0;
233 * establish_ppp - Turn the serial port into a ppp interface.
239 /* go through and save the name of all the modules, then pop em */
241 if (ioctl(fd
, I_LOOK
, str_modules
[str_module_count
].modname
) < 0 ||
242 ioctl(fd
, I_POP
, 0) < 0)
244 SYSDEBUG(("popped stream module : %s",
245 str_modules
[str_module_count
].modname
));
249 /* now push the async/fcs module */
250 if (ioctl(fd
, I_PUSH
, "pppasync") < 0)
251 fatal("ioctl(I_PUSH, ppp_async): %m");
252 /* push the compress module */
253 if (ioctl(fd
, I_PUSH
, "pppcomp") < 0) {
254 warn("ioctl(I_PUSH, ppp_comp): %m");
256 /* finally, push the ppp_if module that actually handles the */
257 /* network interface */
258 if (ioctl(fd
, I_PUSH
, "pppif") < 0)
259 fatal("ioctl(I_PUSH, ppp_if): %m");
261 /* read mode, message non-discard mode
262 if (ioctl(fd, I_SRDOPT, RMSGN) < 0)
263 fatal("ioctl(I_SRDOPT, RMSGN): %m");
266 * Find out which interface we were given.
267 * (ppp_if handles this ioctl)
269 if (ioctl(fd
, SIOCGETU
, &ifunit
) < 0)
270 fatal("ioctl(SIOCGETU): %m");
272 /* Set debug flags in driver */
273 if (ioctl(fd
, SIOCSIFDEBUG
, kdebugflag
) < 0) {
274 error("ioctl(SIOCSIFDEBUG): %m");
277 /* close stdin, stdout, stderr if they might refer to the device */
278 if (default_device
&& !closed_stdio
) {
281 for (i
= 0; i
<= 2; ++i
)
282 if (i
!= fd
&& i
!= sockfd
)
288 * Set device for non-blocking reads.
290 if ((initfdflags
= fcntl(fd
, F_GETFL
)) == -1
291 || fcntl(fd
, F_SETFL
, initfdflags
| O_NONBLOCK
) == -1) {
292 warn("Couldn't set device to non-blocking mode: %m");
299 * disestablish_ppp - Restore the serial port to normal operation.
300 * It attempts to reconstruct the stream with the previously popped
301 * modules. This shouldn't call die() because it's called from die().
310 /* Reset non-blocking mode on the file descriptor. */
311 if (initfdflags
!= -1 && fcntl(fd
, F_SETFL
, initfdflags
) < 0)
312 warn("Couldn't restore device fd flags: %m");
316 /* we can't push or pop modules after the stream has hung up */
317 str_module_count
= 0;
318 restore_term
= 0; /* nor can we fix up terminal settings */
324 * Check whether the link seems not to be 8-bit clean.
326 if (ioctl(fd
, SIOCGIFDEBUG
, (caddr_t
) &flags
) == 0) {
328 switch (~flags
& PAI_FLAGS_HIBITS
) {
330 s
= "bit 7 set to 1";
333 s
= "bit 7 set to 0";
335 case PAI_FLAGS_PAR_EVEN
:
338 case PAI_FLAGS_PAR_ODD
:
343 warn("Serial link is not 8-bit clean:");
344 warn("All received characters had %s", s
);
349 while (ioctl(fd
, I_POP
, 0) == 0) /* pop any we pushed */
353 for (; str_module_count
> 0; str_module_count
--) {
354 if (ioctl(fd
, I_PUSH
, str_modules
[str_module_count
-1].modname
)) {
356 warn("str_restore: couldn't push module %s: %m",
357 str_modules
[str_module_count
-1].modname
);
359 SYSDEBUG(("str_restore: pushed module %s",
360 str_modules
[str_module_count
-1].modname
));
367 * List of valid speeds.
370 int speed_int
, speed_val
;
442 * Translate from bits/second to a speed_t.
448 struct speed
*speedp
;
452 for (speedp
= speeds
; speedp
->speed_int
; speedp
++)
453 if (bps
== speedp
->speed_int
)
454 return speedp
->speed_val
;
455 warn("speed %d not supported", bps
);
460 * Translate from a speed_t to bits/second.
466 struct speed
*speedp
;
470 for (speedp
= speeds
; speedp
->speed_int
; speedp
++)
471 if (speed
== speedp
->speed_val
)
472 return speedp
->speed_int
;
477 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
478 * at the requested speed, etc. If `local' is true, set CLOCAL
479 * regardless of whether the modem option was specified.
482 set_up_tty(fd
, local
)
489 if (tcgetattr(fd
, &tios
) < 0)
490 fatal("tcgetattr: %m");
496 tios
.c_cflag
&= ~(CSIZE
| CSTOPB
| PARENB
| CLOCAL
);
498 bzero(&tiox
, sizeof(tiox
));
499 ioctl(fd
, TCGETX
, &tiox
);
500 tiox
.x_hflag
= RTSXOFF
;
501 ioctl(fd
, TCSETX
, &tiox
);
502 tios
.c_cflag
&= ~(IXON
| IXOFF
);
503 } else if (crtscts
< 0) {
504 bzero(&tiox
, sizeof(tiox
));
505 ioctl(fd
, TCGETX
, &tiox
);
506 tiox
.x_hflag
&= ~RTSXOFF
;
507 ioctl(fd
, TCSETX
, &tiox
);
511 tios
.c_cflag
|= CS8
| CREAD
| HUPCL
;
513 tios
.c_cflag
|= CLOCAL
;
514 tios
.c_iflag
= IGNBRK
| IGNPAR
;
518 tios
.c_cc
[VTIME
] = 0;
521 tios
.c_iflag
|= IXON
| IXOFF
;
522 tios
.c_cc
[VSTOP
] = 0x13; /* DC3 = XOFF = ^S */
523 tios
.c_cc
[VSTART
] = 0x11; /* DC1 = XON = ^Q */
526 speed
= translate_speed(inspeed
);
528 cfsetospeed(&tios
, speed
);
529 cfsetispeed(&tios
, speed
);
531 speed
= cfgetospeed(&tios
);
533 * We can't proceed if the serial port speed is B0,
534 * since that implies that the serial port is disabled.
537 fatal("Baud rate for %s is 0; need explicit baud rate", devnam
);
540 if (tcsetattr(fd
, TCSAFLUSH
, &tios
) < 0)
541 fatal("tcsetattr: %m");
543 baud_rate
= inspeed
= baud_rate_of(speed
);
548 * restore_tty - restore the terminal to the saved settings.
555 if (!default_device
) {
557 * Turn off echoing, because otherwise we can get into
558 * a loop with the tty and the modem echoing to each other.
559 * We presume we are the sole user of this tty device, so
560 * when we close it, it will revert to its defaults anyway.
562 inittermios
.c_lflag
&= ~(ECHO
| ECHONL
);
564 if (tcsetattr(fd
, TCSAFLUSH
, &inittermios
) < 0)
566 warn("tcsetattr: %m");
572 * setdtr - control the DTR line on the serial port.
573 * This is called from die(), so it shouldn't call die().
579 int modembits
= TIOCM_DTR
;
581 ioctl(fd
, (on
? TIOCMBIS
: TIOCMBIC
), &modembits
);
586 * output - Output PPP packet.
599 dbglog("sent %P", p
, len
);
602 str
.buf
= (caddr_t
) p
;
604 while (putmsg(ttyfd
, NULL
, &str
, 0) < 0) {
605 if (--retries
< 0 || (errno
!= EWOULDBLOCK
&& errno
!= EAGAIN
)) {
607 error("Couldn't send packet: %m");
611 pfd
.events
= POLLOUT
;
612 poll(&pfd
, 1, 250); /* wait for up to 0.25 seconds */
617 * wait_input - wait for input, for a length of time specified in *timo.
621 struct timeval
*timo
;
625 t
= timo
== NULL
? -1: timo
->tv_sec
* 1000 + timo
->tv_usec
/ 1000;
626 if (poll(pollfds
, n_pollfds
, t
) < 0 && errno
!= EINTR
)
631 * add_fd - add an fd to the set that wait_input waits for.
638 for (n
= 0; n
< n_pollfds
; ++n
)
639 if (pollfds
[n
].fd
== fd
)
641 if (n_pollfds
< MAX_POLLFDS
) {
642 pollfds
[n_pollfds
].fd
= fd
;
643 pollfds
[n_pollfds
].events
= POLLIN
| POLLPRI
| POLLHUP
;
646 error("Too many inputs!");
650 * remove_fd - remove an fd from the set that wait_input waits for.
657 for (n
= 0; n
< n_pollfds
; ++n
) {
658 if (pollfds
[n
].fd
== fd
) {
659 while (++n
< n_pollfds
)
660 pollfds
[n
-1] = pollfds
[n
];
669 * read_packet - get a PPP packet from the serial device.
675 struct strbuf str
, ctl
;
677 unsigned char ctlbuf
[16];
679 str
.maxlen
= PPP_MTU
+ PPP_HDRLEN
;
680 str
.buf
= (caddr_t
) buf
;
681 ctl
.maxlen
= sizeof(ctlbuf
);
682 ctl
.buf
= (caddr_t
) ctlbuf
;
684 len
= getmsg(ttyfd
, &ctl
, &str
, &i
);
686 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
|| errno
== EINTR
) {
692 SYSDEBUG(("getmsg returned 0x%x", len
));
694 notice("got ctrl msg len %d %x %x\n", ctl
.len
, ctlbuf
[0], ctlbuf
[1]);
697 SYSDEBUG(("getmsg short return length %d", str
.len
));
706 * ppp_send_config - configure the transmit characteristics of
710 ppp_send_config(unit
, mtu
, asyncmap
, pcomp
, accomp
)
718 strlcpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
720 if (ioctl(sockfd
, SIOCSIFMTU
, (caddr_t
) &ifr
) < 0)
721 fatal("ioctl(SIOCSIFMTU): %m");
723 if(ioctl(ttyfd
, SIOCSIFASYNCMAP
, asyncmap
) < 0)
724 fatal("ioctl(SIOCSIFASYNCMAP): %m");
727 if(ioctl(ttyfd
, SIOCSIFCOMPPROT
, c
) < 0)
728 fatal("ioctl(SIOCSIFCOMPPROT): %m");
731 if(ioctl(ttyfd
, SIOCSIFCOMPAC
, c
) < 0)
732 fatal("ioctl(SIOCSIFCOMPAC): %m");
737 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
740 ppp_set_xaccm(unit
, accm
)
744 if (ioctl(ttyfd
, SIOCSIFXASYNCMAP
, accm
) < 0 && errno
!= ENOTTY
)
745 warn("ioctl(set extended ACCM): %m");
750 * ppp_recv_config - configure the receive-side characteristics of
754 ppp_recv_config(unit
, mru
, asyncmap
, pcomp
, accomp
)
761 if (ioctl(ttyfd
, SIOCSIFMRU
, mru
) < 0) {
762 error("ioctl(SIOCSIFMRU): %m");
765 if (ioctl(ttyfd
, SIOCSIFRASYNCMAP
, (caddr_t
) asyncmap
) < 0) {
766 error("ioctl(SIOCSIFRASYNCMAP): %m");
769 c
= 2 + (pcomp
? 1: 0);
770 if(ioctl(ttyfd
, SIOCSIFCOMPPROT
, c
) < 0) {
771 error("ioctl(SIOCSIFCOMPPROT): %m");
774 c
= 2 + (accomp
? 1: 0);
775 if (ioctl(ttyfd
, SIOCSIFCOMPAC
, c
) < 0) {
776 error("ioctl(SIOCSIFCOMPAC): %m");
781 * ccp_test - ask kernel whether a given compression method
782 * is acceptable for use.
785 ccp_test(unit
, opt_ptr
, opt_len
, for_transmit
)
786 int unit
, opt_len
, for_transmit
;
789 struct ppp_option_data data
;
791 if ((unsigned) opt_len
> MAX_PPP_OPTION
)
792 opt_len
= MAX_PPP_OPTION
;
793 data
.length
= opt_len
;
794 data
.transmit
= for_transmit
;
795 BCOPY(opt_ptr
, data
.opt_data
, opt_len
);
796 if (ioctl(ttyfd
, SIOCSCOMPRESS
, &data
) >= 0)
798 return (errno
== ENOSR
)? 0: -1;
802 * ccp_flags_set - inform kernel about the current state of CCP.
805 ccp_flags_set(unit
, isopen
, isup
)
806 int unit
, isopen
, isup
;
810 x
= (isopen
? 1: 0) + (isup
? 2: 0);
811 if (ioctl(ttyfd
, SIOCSIFCOMP
, x
) < 0 && errno
!= ENOTTY
)
812 error("ioctl (SIOCSIFCOMP): %m");
816 * ccp_fatal_error - returns 1 if decompression was disabled as a
817 * result of an error detected after decompression of a packet,
818 * 0 otherwise. This is necessary because of patent nonsense.
821 ccp_fatal_error(unit
)
826 if (ioctl(ttyfd
, SIOCGIFCOMP
, &x
) < 0) {
827 error("ioctl(SIOCGIFCOMP): %m");
830 return x
& CCP_FATALERROR
;
834 * sifvjcomp - config tcp header compression
837 sifvjcomp(u
, vjcomp
, cidcomp
, maxcid
)
838 int u
, vjcomp
, cidcomp
, maxcid
;
842 x
= (vjcomp
? 1: 0) + (cidcomp
? 0: 2) + (maxcid
<< 4);
843 if (ioctl(ttyfd
, SIOCSIFVJCOMP
, x
) < 0) {
844 error("ioctl(SIOCSIFVJCOMP): %m");
851 * sifup - Config the interface up and enable IP packets to pass.
859 strlcpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
860 if (ioctl(sockfd
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) < 0) {
861 error("ioctl (SIOCGIFFLAGS): %m");
864 ifr
.ifr_flags
|= IFF_UP
;
865 if (ioctl(sockfd
, SIOCSIFFLAGS
, (caddr_t
) &ifr
) < 0) {
866 error("ioctl(SIOCSIFFLAGS): %m");
875 * sifnpmode - Set the mode for handling packets for a given NP.
878 sifnpmode(u
, proto
, mode
)
885 npi
.protocol
= proto
;
887 if (ioctl(ppp_fd
, PPPIOCSNPMODE
, &npi
) < 0) {
888 error("ioctl(set NP %d mode to %d): %m", proto
, mode
);
895 * sifdown - Config the interface down.
906 npi
.protocol
= PPP_IP
;
907 npi
.mode
= NPMODE_ERROR
;
908 ioctl(ttyfd
, SIOCSETNPMODE
, &npi
);
909 /* ignore errors, because ttyfd might have been closed by now. */
911 strlcpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
912 if (ioctl(sockfd
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) < 0) {
913 error("ioctl (SIOCGIFFLAGS): %m");
916 ifr
.ifr_flags
&= ~IFF_UP
;
917 if (ioctl(sockfd
, SIOCSIFFLAGS
, (caddr_t
) &ifr
) < 0) {
918 error("ioctl(SIOCSIFFLAGS): %m");
927 * SET_SA_FAMILY - initialize a struct sockaddr, setting the sa_family field.
929 #define SET_SA_FAMILY(addr, family) \
930 BZERO((char *) &(addr), sizeof(addr)); \
931 addr.sa_family = (family);
934 * sifaddr - Config the interface IP addresses and netmask.
945 strlcpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
946 SET_SA_FAMILY(ifr
.ifr_addr
, AF_INET
);
948 info("Setting interface mask to %s\n", ip_ntoa(m
));
949 ((struct sockaddr_in
*) &ifr
.ifr_addr
)->sin_addr
.s_addr
= m
;
950 if (ioctl(sockfd
, SIOCSIFNETMASK
, (caddr_t
) &ifr
) < 0) {
951 error("ioctl(SIOCSIFNETMASK): %m");
956 ((struct sockaddr_in
*) &ifr
.ifr_addr
)->sin_addr
.s_addr
= o
;
957 if (ioctl(sockfd
, SIOCSIFADDR
, (caddr_t
) &ifr
) < 0) {
958 error("ioctl(SIOCSIFADDR): %m");
962 SET_SA_FAMILY(ifr
.ifr_dstaddr
, AF_INET
);
963 ((struct sockaddr_in
*) &ifr
.ifr_dstaddr
)->sin_addr
.s_addr
= h
;
964 if (ioctl(sockfd
, SIOCSIFDSTADDR
, (caddr_t
) &ifr
) < 0) {
965 error("ioctl(SIOCSIFDSTADDR): %m");
969 /* XXX is this necessary? */
970 ((struct sockaddr_in
*) &ifr
.ifr_addr
)->sin_addr
.s_addr
= o
;
971 if (ioctl(sockfd
, SIOCSIFADDR
, (caddr_t
) &ifr
) < 0) {
972 error("ioctl(SIOCSIFADDR): %m");
982 * cifaddr - Clear the interface IP addresses, and delete routes
983 * through the interface if possible.
993 BZERO(&rt
, sizeof(rt
));
994 SET_SA_FAMILY(rt
.rt_dst
, AF_INET
);
995 ((struct sockaddr_in
*) &rt
.rt_dst
)->sin_addr
.s_addr
= h
;
996 SET_SA_FAMILY(rt
.rt_gateway
, AF_INET
);
997 ((struct sockaddr_in
*) &rt
.rt_gateway
)->sin_addr
.s_addr
= o
;
998 rt
.rt_flags
= RTF_HOST
;
999 if (ioctl(sockfd
, SIOCDELRT
, (caddr_t
) &rt
) < 0) {
1000 error("ioctl(SIOCDELRT): %m");
1007 * sifdefaultroute - assign a default route through the address given.
1010 sifdefaultroute(u
, l
, g
)
1016 BZERO(&rt
, sizeof(rt
));
1017 SET_SA_FAMILY(rt
.rt_dst
, AF_INET
);
1018 SET_SA_FAMILY(rt
.rt_gateway
, AF_INET
);
1019 ((struct sockaddr_in
*) &rt
.rt_gateway
)->sin_addr
.s_addr
= g
;
1020 rt
.rt_flags
= RTF_GATEWAY
;
1021 if (ioctl(sockfd
, SIOCADDRT
, &rt
) < 0) {
1022 error("default route ioctl(SIOCADDRT): %m");
1025 default_route_gateway
= g
;
1030 * cifdefaultroute - delete a default route through the address given.
1033 cifdefaultroute(u
, l
, g
)
1039 BZERO(&rt
, sizeof(rt
));
1040 SET_SA_FAMILY(rt
.rt_dst
, AF_INET
);
1041 SET_SA_FAMILY(rt
.rt_gateway
, AF_INET
);
1042 ((struct sockaddr_in
*) &rt
.rt_gateway
)->sin_addr
.s_addr
= g
;
1043 rt
.rt_flags
= RTF_GATEWAY
;
1044 if (ioctl(sockfd
, SIOCDELRT
, &rt
) < 0) {
1045 error("default route ioctl(SIOCDELRT): %m");
1048 default_route_gateway
= 0;
1053 * sifproxyarp - Make a proxy ARP entry for the peer.
1056 sifproxyarp(unit
, hisaddr
)
1060 struct arpreq arpreq
;
1062 BZERO(&arpreq
, sizeof(arpreq
));
1065 * Get the hardware address of an interface on the same subnet
1066 * as our local address.
1068 if (!get_ether_addr(hisaddr
, &arpreq
.arp_ha
)) {
1069 warn("Cannot determine ethernet address for proxy ARP");
1073 SET_SA_FAMILY(arpreq
.arp_pa
, AF_INET
);
1074 ((struct sockaddr_in
*) &arpreq
.arp_pa
)->sin_addr
.s_addr
= hisaddr
;
1075 arpreq
.arp_flags
= ATF_PERM
| ATF_PUBL
;
1076 if (ioctl(sockfd
, SIOCSARP
, (caddr_t
)&arpreq
) < 0) {
1077 error("ioctl(SIOCSARP): %m");
1081 proxy_arp_addr
= hisaddr
;
1086 * cifproxyarp - Delete the proxy ARP entry for the peer.
1089 cifproxyarp(unit
, hisaddr
)
1093 struct arpreq arpreq
;
1095 BZERO(&arpreq
, sizeof(arpreq
));
1096 SET_SA_FAMILY(arpreq
.arp_pa
, AF_INET
);
1097 ((struct sockaddr_in
*) &arpreq
.arp_pa
)->sin_addr
.s_addr
= hisaddr
;
1098 if (ioctl(sockfd
, SIOCDARP
, (caddr_t
)&arpreq
) < 0) {
1099 error("ioctl(SIOCDARP): %m");
1107 * get_ether_addr - get the hardware address of an interface on the
1108 * the same subnet as ipaddr. Code borrowed from myetheraddr.c
1109 * in the cslip-2.6 distribution, which is subject to the following
1110 * copyright notice (which also applies to logwtmp below):
1112 * Copyright (c) 1990, 1992 The Regents of the University of California.
1113 * All rights reserved.
1115 * Redistribution and use in source and binary forms, with or without
1116 * modification, are permitted provided that: (1) source code distributions
1117 * retain the above copyright notice and this paragraph in its entirety, (2)
1118 * distributions including binary code include the above copyright notice and
1119 * this paragraph in its entirety in the documentation or other materials
1120 * provided with the distribution, and (3) all advertising materials mentioning
1121 * features or use of this software display the following acknowledgement:
1122 * ``This product includes software developed by the University of California,
1123 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1124 * the University nor the names of its contributors may be used to endorse
1125 * or promote products derived from this software without specific prior
1126 * written permission.
1127 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1128 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1129 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1133 #include <arpa/inet.h>
1134 #include <netinet/in_var.h>
1135 #include <net/if_dl.h>
1137 /* Cast a struct sockaddr to a structaddr_in */
1138 #define SATOSIN(sa) ((struct sockaddr_in *)(sa))
1140 /* Determine if "bits" is set in "flag" */
1141 #define ALLSET(flag, bits) (((flag) & (bits)) == (bits))
1143 static struct nlist nl
[] = {
1149 int kvm_read(int fd
, off_t offset
, void *buf
, int nbytes
)
1151 if (lseek(fd
, offset
, SEEK_SET
) != offset
) {
1152 error("lseek in kmem: %m");
1155 return(read(fd
, buf
, nbytes
));
1159 get_ether_addr(ipaddr
, hwaddr
)
1161 struct sockaddr
*hwaddr
;
1164 register struct ifnet
*ifp
;
1165 register struct arpcom
*ac
;
1166 struct arpcom arpcom
;
1167 struct in_addr
*inp
;
1168 register struct ifaddr
*ifa
;
1169 register struct in_ifaddr
*in
;
1172 struct in_ifaddr in
;
1174 struct ifaddr
*ifap
;
1175 struct sockaddr ifaddrsaddr
;
1176 struct sockaddr_in ifmasksaddr
;
1177 struct sockaddr_in
*ifinetptr
;
1178 struct sockaddr_dl
*iflinkptr
;
1179 u_long addr
, mask
, ifip
;
1182 /* Open kernel memory for reading */
1183 if ((kd
= open("/dev/kmem", O_RDONLY
)) < 0) {
1184 error("/dev/kmem: %m");
1188 /* Fetch namelist */
1189 if (nlist("/unix", nl
) != 0) {
1190 error("nlist(): %m");
1195 ifp
= &arpcom
.ac_if
;
1199 if (kvm_read(kd
, nl
[N_IFNET
].n_value
, (char *)&addr
, sizeof(addr
))
1201 error("error reading ifnet addr");
1204 for ( ; addr
&& !found
; addr
= (u_long
)ifp
->if_next
) {
1205 if (kvm_read(kd
, addr
, (char *)ac
, sizeof(*ac
)) != sizeof(*ac
)) {
1206 error("error reading ifnet");
1210 /* Only look at configured, broadcast interfaces */
1211 if (!ALLSET(ifp
->if_flags
, IFF_UP
| IFF_BROADCAST
))
1213 /* This probably can't happen... */
1214 if (ifp
->if_addrlist
== 0)
1217 /* Get interface ip address */
1218 for (ifap
= ifp
->if_addrlist
; ifap
; ifap
=ifaddr
.ifa
.ifa_next
) {
1219 if (kvm_read(kd
, (u_long
)ifap
, (char *)&ifaddr
,
1220 sizeof(ifaddr
)) != sizeof(ifaddr
)) {
1221 error("error reading ifaddr");
1224 if (kvm_read(kd
, (u_long
)ifaddr
.ifa
.ifa_addr
, &ifaddrsaddr
,
1225 sizeof(struct sockaddr_in
)) != sizeof(struct sockaddr_in
)) {
1226 error("error reading ifaddrsaddr");
1229 if (kvm_read(kd
, (u_long
)ifaddr
.ifa
.ifa_netmask
, &ifmasksaddr
,
1230 sizeof(struct sockaddr_in
)) != sizeof(struct sockaddr_in
)) {
1231 error("error reading ifmasksaddr");
1234 /* Check if this interface on the right subnet */
1235 switch (ifaddrsaddr
.sa_family
) {
1237 hwaddr
->sa_family
= AF_UNSPEC
;
1238 iflinkptr
= (struct sockaddr_dl
*) &ifaddrsaddr
;
1239 bcopy(LLADDR(iflinkptr
),hwaddr
->sa_data
,iflinkptr
->sdl_alen
);
1242 ifinetptr
= (struct sockaddr_in
*) &ifaddrsaddr
;
1243 ifip
= ifinetptr
->sin_addr
.s_addr
;
1244 if (kvm_read(kd
, (u_long
)ifaddr
.ifa
.ifa_netmask
, &ifmasksaddr
,
1245 sizeof(struct sockaddr_in
)) != sizeof(struct sockaddr_in
)) {
1246 error("error reading ifmasksaddr");
1249 mask
= ifmasksaddr
.sin_addr
.s_addr
;
1250 if ((ipaddr
& mask
) == (ifip
& mask
))
1263 * Return user specified netmask, modified by any mask we might determine
1264 * for address `addr' (in network byte order).
1265 * Here we scan through the system's list of interfaces, looking for
1266 * any non-point-to-point interfaces which might appear to be on the same
1267 * network as `addr'. If we find any, we OR in their netmask to the
1268 * user-specified netmask.
1276 u_int32_t mask
, nmask
, ina
;
1277 struct ifreq
*ifr
, *ifend
, ifreq
;
1279 struct ifreq ifs
[MAX_IFS
];
1282 if (IN_CLASSA(addr
)) /* determine network mask for address class */
1283 nmask
= IN_CLASSA_NET
;
1284 else if (IN_CLASSB(addr
))
1285 nmask
= IN_CLASSB_NET
;
1287 nmask
= IN_CLASSC_NET
;
1288 /* class D nets are disallowed by bad_ip_adrs */
1289 mask
= netmask
| htonl(nmask
);
1292 * Scan through the system's network interfaces.
1294 ifc
.ifc_len
= sizeof(ifs
);
1296 if (ioctl(sockfd
, SIOCGIFCONF
, &ifc
) < 0) {
1297 warn("ioctl(SIOCGIFCONF): %m");
1300 ifend
= (struct ifreq
*) (ifc
.ifc_buf
+ ifc
.ifc_len
);
1301 for (ifr
= ifc
.ifc_req
; ifr
< ifend
; ++ifr
) {
1303 * Check the interface's internet address.
1305 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
1307 ina
= ((struct sockaddr_in
*) &ifr
->ifr_addr
)->sin_addr
.s_addr
;
1308 if ((ntohl(ina
) & nmask
) != (addr
& nmask
))
1311 * Check that the interface is up, and not point-to-point or loopback.
1313 strlcpy(ifreq
.ifr_name
, ifr
->ifr_name
, sizeof(ifreq
.ifr_name
));
1314 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifreq
) < 0)
1316 if ((ifreq
.ifr_flags
& (IFF_UP
|IFF_POINTOPOINT
|IFF_LOOPBACK
))
1320 * Get its netmask and OR it into our mask.
1322 if (ioctl(sockfd
, SIOCGIFNETMASK
, &ifreq
) < 0)
1324 mask
|= ((struct sockaddr_in
*)&ifreq
.ifr_addr
)->sin_addr
.s_addr
;
1330 #define WTMPFILE "/var/adm/wtmp"
1333 logwtmp(line
, name
, host
)
1334 const char *line
, *name
, *host
;
1340 if ((fd
= open(WTMPFILE
, O_WRONLY
|O_APPEND
, 0)) < 0)
1342 if (!fstat(fd
, &buf
)) {
1343 strncpy(ut
.ut_line
, line
, sizeof(ut
.ut_line
));
1344 strncpy(ut
.ut_name
, name
, sizeof(ut
.ut_name
));
1345 strncpy(ut
.ut_host
, host
, sizeof(ut
.ut_host
));
1346 (void)time(&ut
.ut_time
);
1347 if (write(fd
, (char *)&ut
, sizeof(struct utmp
)) != sizeof(struct utmp
))
1348 (void)ftruncate(fd
, buf
.st_size
);
1354 * Use the hostid as part of the random number seed.
1363 * Code for locking/unlocking the serial device.
1366 static char *devlocked
= (char *) 0;
1368 int lock(char *device
)
1373 if (devname
= strrchr(device
,'/'))
1378 if ((rc
= ttylock(devname
)) == 0) {
1379 devlocked
= strdup(devname
);
1381 devlocked
= (char *) 0;
1391 rc
= ttyunlock(devlocked
);
1393 devlocked
= (char *) 0;