2 * sys-linux.c - System-dependent procedures for setting up
3 * PPP interfaces on Linux systems
5 * Copyright (c) 1994-2004 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 #include <sys/ioctl.h>
73 #include <sys/types.h>
74 #include <sys/socket.h>
76 #include <sys/errno.h>
79 #include <sys/utsname.h>
80 #include <sys/sysmacros.h>
96 /* This is in netdevice.h. However, this compile will fail miserably if
97 you attempt to include netdevice.h because it has so many references
98 to __memcpy functions which it should not attempt to do. So, since I
99 really don't use it, but it must be defined, define it now. */
102 #define MAX_ADDR_LEN 7
106 #include <asm/types.h> /* glibc 2 conflicts with linux/types.h */
108 #include <net/if_arp.h>
109 #include <net/route.h>
110 #include <netinet/if_ether.h>
112 #include <linux/types.h>
113 #include <linux/if.h>
114 #include <linux/if_arp.h>
115 #include <linux/route.h>
116 #include <linux/if_ether.h>
118 #include <netinet/in.h>
119 #include <arpa/inet.h>
121 #include <linux/ppp_defs.h>
122 #include <linux/if_ppp.h>
130 #if __GLIBC__ >= 2 && \
131 !(defined(__powerpc__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
132 #include <netipx/ipx.h>
134 #include <linux/ipx.h>
136 #endif /* IPX_CHANGE */
139 #include <pcap-bpf.h>
140 #include <linux/filter.h>
141 #endif /* PPP_FILTER */
144 #include <sys/locks.h>
150 * This is in linux/include/net/ipv6.h.
154 struct in6_addr ifr6_addr;
155 __u32 ifr6_prefixlen;
156 unsigned int ifr6_ifindex;
160 #define IN6_LLADDR_FROM_EUI64(sin6, eui64) do { \
161 memset(&sin6.s6_addr, 0, sizeof(struct in6_addr)); \
162 sin6.s6_addr16[0] = htons(0xfe80); \
163 eui64_copy(eui64, sin6.s6_addr32[2]); \
168 /* We can get an EIO error on an ioctl if the modem has hung up */
169 #define ok_error(num) ((num)==EIO)
171 static int tty_disc = N_TTY; /* The TTY discipline */
172 static int ppp_disc = N_PPP; /* The PPP discpline */
173 static int initfdflags = -1; /* Initial file descriptor flags for fd */
174 static int ppp_fd = -1; /* fd which is set to PPP discipline */
175 static int sock_fd = -1; /* socket for doing interface ioctls */
176 static int slave_fd = -1; /* pty for old-style demand mode, slave */
177 static int master_fd = -1; /* pty for old-style demand mode, master */
179 static int sock6_fd = -1;
183 * For the old-style kernel driver, this is the same as ppp_fd.
184 * For the new-style driver, it is the fd of an instance of /dev/ppp
185 * which is attached to the ppp unit and is used for controlling it.
187 int ppp_dev_fd = -1; /* fd for /dev/ppp (new style driver) */
189 static int chindex; /* channel index (new style driver) */
191 static fd_set in_fds; /* set of fds that wait_input waits for */
192 static int max_in_fd; /* highest fd set in in_fds */
194 static int has_proxy_arp = 0;
195 static int driver_version = 0;
196 static int driver_modification = 0;
197 static int driver_patch = 0;
198 static int driver_is_old = 0;
199 static int restore_term = 0; /* 1 => we've munged the terminal */
200 static struct termios inittermios; /* Initial TTY termios */
202 int new_style_driver = 0;
204 static char loop_name[20];
205 static unsigned char inbuf[512]; /* buffer for chars read from loopback */
207 static int if_is_up; /* Interface has been marked up */
208 static int if6_is_up; /* Interface has been marked up for IPv6, to help differentiate */
209 static int have_default_route; /* Gateway for default route added */
210 static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */
211 static char proxy_arp_dev[16]; /* Device for proxy arp entry */
212 static u_int32_t our_old_addr; /* for detecting address changes */
213 static int dynaddr_set; /* 1 if ip_dynaddr set */
214 static int looped; /* 1 if using loop */
215 static int link_mtu; /* mtu for the link (not bundle) */
217 static struct utsname utsname; /* for the kernel version */
218 static int kernel_version;
219 #define KVERSION(j,n,p) ((j)*1000000 + (n)*1000 + (p))
223 #define FLAGS_GOOD (IFF_UP | IFF_BROADCAST)
224 #define FLAGS_MASK (IFF_UP | IFF_BROADCAST | \
225 IFF_POINTOPOINT | IFF_LOOPBACK | IFF_NOARP)
227 #define SIN_ADDR(x) (((struct sockaddr_in *) (&(x)))->sin_addr.s_addr)
229 /* Prototypes for procedures local to this file. */
230 static int modify_flags(int fd, int clear_bits, int set_bits);
231 static int translate_speed (int bps);
232 static int baud_rate_of (int speed);
233 static void close_route_table (void);
234 static int open_route_table (void);
235 static int read_route_table (struct rtentry *rt);
236 static int defaultroute_exists (struct rtentry *rt);
237 static int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr,
238 char *name, int namelen);
239 static void decode_version (char *buf, int *version, int *mod, int *patch);
240 static int set_kdebugflag(int level);
241 static int ppp_registered(void);
242 static int make_ppp_unit(void);
243 static int setifstate (int u, int state);
245 extern u_char inpacket_buf[]; /* borrowed from main.c */
248 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
252 #define SET_SA_FAMILY(addr, family) \
253 memset ((char *) &(addr), '\0', sizeof(addr)); \
254 addr.sa_family = (family);
257 * Determine if the PPP connection should still be present.
262 /* new_fd is the fd of a tty */
263 static void set_ppp_fd (int new_fd)
266 if (!new_style_driver)
270 static int still_ppp(void)
272 if (new_style_driver)
273 return !hungup && ppp_fd >= 0;
274 if (!hungup || ppp_fd == slave_fd)
277 set_ppp_fd(slave_fd);
284 * modify_flags - set and clear flag bits controlling the kernel
287 static int modify_flags(int fd, int clear_bits, int set_bits)
291 if (ioctl(fd, PPPIOCGFLAGS, &flags) == -1)
293 flags = (flags & ~clear_bits) | set_bits;
294 if (ioctl(fd, PPPIOCSFLAGS, &flags) == -1)
301 error("Failed to set PPP kernel option flags: %m");
305 /********************************************************************
307 * sys_init - System-dependent initialization.
312 /* Get an internet socket for doing socket ioctls. */
313 sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
315 fatal("Couldn't create IP socket: %m(%d)", errno);
318 sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0);
320 sock6_fd = -errno; /* save errno for later */
327 /********************************************************************
329 * sys_cleanup - restore any system state we modified before exiting:
330 * mark the interface down, delete default route and/or proxy arp entry.
331 * This shouldn't call die() because it's called from die().
334 void sys_cleanup(void)
337 * Take down the device
347 * Delete any routes through the device.
349 if (have_default_route)
350 cifdefaultroute(0, 0, 0);
353 cifproxyarp(0, proxy_arp_addr);
356 /********************************************************************
358 * sys_close - Clean up in a child process before execing.
363 if (new_style_driver && ppp_dev_fd >= 0)
377 /********************************************************************
379 * set_kdebugflag - Define the debugging level for the kernel
382 static int set_kdebugflag (int requested_level)
386 if (ioctl(ppp_dev_fd, PPPIOCSDEBUG, &requested_level) < 0) {
387 if ( ! ok_error (errno) )
388 error("ioctl(PPPIOCSDEBUG): %m (line %d)", __LINE__);
394 /********************************************************************
396 * tty_establish_ppp - Turn the serial port into a ppp interface.
399 int tty_establish_ppp (int tty_fd)
404 * Ensure that the tty device is in exclusive mode.
406 if (ioctl(tty_fd, TIOCEXCL, 0) < 0) {
407 if ( ! ok_error ( errno ))
408 warn("Couldn't make tty exclusive: %m");
411 * Demand mode - prime the old ppp device to relinquish the unit.
413 if (!new_style_driver && looped
414 && ioctl(slave_fd, PPPIOCXFERUNIT, 0) < 0) {
415 error("ioctl(transfer ppp unit): %m, line %d", __LINE__);
419 * Set the current tty to the PPP discpline
423 #define N_SYNC_PPP 14
425 ppp_disc = (new_style_driver && sync_serial)? N_SYNC_PPP: N_PPP;
426 if (ioctl(tty_fd, TIOCSETD, &ppp_disc) < 0) {
427 if ( ! ok_error (errno) ) {
428 error("Couldn't set tty to PPP discipline: %m");
433 ret_fd = generic_establish_ppp(tty_fd);
435 #define SC_RCVB (SC_RCV_B7_0 | SC_RCV_B7_1 | SC_RCV_EVNP | SC_RCV_ODDP)
436 #define SC_LOGB (SC_DEBUG | SC_LOG_INPKT | SC_LOG_OUTPKT | SC_LOG_RAWIN \
440 modify_flags(ppp_fd, SC_RCVB | SC_LOGB,
441 (kdebugflag * SC_DEBUG) & SC_LOGB);
443 if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0 && !ok_error(errno))
444 warn("Couldn't reset tty to normal line discipline: %m");
450 /********************************************************************
452 * generic_establish_ppp - Turn the fd into a ppp interface.
454 int generic_establish_ppp (int fd)
458 if (new_style_driver) {
461 /* Open an instance of /dev/ppp and connect the channel to it */
462 if (ioctl(fd, PPPIOCGCHAN, &chindex) == -1) {
463 error("Couldn't get channel number: %m");
466 dbglog("using channel %d", chindex);
467 fd = open("/dev/ppp", O_RDWR);
469 error("Couldn't reopen /dev/ppp: %m");
472 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
473 if (ioctl(fd, PPPIOCATTCHAN, &chindex) < 0) {
474 error("Couldn't attach to channel %d: %m", chindex);
477 flags = fcntl(fd, F_GETFL);
478 if (flags == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
479 warn("Couldn't set /dev/ppp (channel) to nonblock: %m");
484 if (!looped && !multilink) {
486 * Create a new PPP unit.
488 if (make_ppp_unit() < 0)
493 modify_flags(ppp_dev_fd, SC_LOOP_TRAFFIC, 0);
497 if (ioctl(fd, PPPIOCCONNECT, &ifunit) < 0) {
498 error("Couldn't attach to PPP unit %d: %m", ifunit);
505 * Old-style driver: find out which interface we were given.
508 if (ioctl(fd, PPPIOCGUNIT, &x) < 0) {
509 if (ok_error (errno))
511 fatal("ioctl(PPPIOCGUNIT): %m (line %d)", __LINE__);
513 /* Check that we got the same unit again. */
514 if (looped && x != ifunit)
515 fatal("transfer_ppp failed: wanted unit %d, got %d", ifunit, x);
519 * Fetch the initial file flags and reset blocking mode on the file.
521 initfdflags = fcntl(fd, F_GETFL);
522 if (initfdflags == -1 ||
523 fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
524 if ( ! ok_error (errno))
525 warn("Couldn't set device to non-blocking mode: %m");
530 * Enable debug in the driver if requested.
533 set_kdebugflag (kdebugflag);
545 /********************************************************************
547 * tty_disestablish_ppp - Restore the serial port to normal operation.
548 * This shouldn't call die() because it's called from die().
551 void tty_disestablish_ppp(int tty_fd)
555 * Flush the tty output buffer so that the TIOCSETD doesn't hang.
557 if (tcflush(tty_fd, TCIOFLUSH) < 0)
559 warn("tcflush failed: %m");
563 * Restore the previous line discipline
565 if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0) {
566 if ( ! ok_error (errno))
567 error("ioctl(TIOCSETD, N_TTY): %m (line %d)", __LINE__);
570 if (ioctl(tty_fd, TIOCNXCL, 0) < 0) {
571 if ( ! ok_error (errno))
572 warn("ioctl(TIOCNXCL): %m (line %d)", __LINE__);
575 /* Reset non-blocking mode on fd. */
576 if (initfdflags != -1 && fcntl(tty_fd, F_SETFL, initfdflags) < 0) {
577 if ( ! ok_error (errno))
578 warn("Couldn't restore device fd flags: %m");
584 generic_disestablish_ppp(tty_fd);
587 /********************************************************************
589 * generic_disestablish_ppp - Restore device components to normal
590 * operation, and reconnect the ppp unit to the loopback if in demand
591 * mode. This shouldn't call die() because it's called from die().
593 void generic_disestablish_ppp(int dev_fd)
595 if (new_style_driver) {
599 modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC);
601 } else if (!doing_multilink && ppp_dev_fd >= 0) {
603 remove_fd(ppp_dev_fd);
607 /* old-style driver */
609 set_ppp_fd(slave_fd);
616 * make_ppp_unit - make a new ppp unit for ppp_dev_fd.
617 * Assumes new_style_driver.
619 static int make_ppp_unit()
623 if (ppp_dev_fd >= 0) {
624 dbglog("in make_ppp_unit, already had /dev/ppp open?");
627 ppp_dev_fd = open("/dev/ppp", O_RDWR);
629 fatal("Couldn't open /dev/ppp: %m");
630 flags = fcntl(ppp_dev_fd, F_GETFL);
632 || fcntl(ppp_dev_fd, F_SETFL, flags | O_NONBLOCK) == -1)
633 warn("Couldn't set /dev/ppp to nonblock: %m");
636 x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
637 if (x < 0 && req_unit >= 0 && errno == EEXIST) {
638 warn("Couldn't allocate PPP unit %d as it is already in use", req_unit);
640 x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
643 error("Couldn't create new ppp unit: %m");
648 * cfg_bundle - configure the existing bundle.
649 * Used in demand mode.
651 void cfg_bundle(int mrru, int mtru, int rssn, int tssn)
653 if (!new_style_driver)
656 /* set the mrru, mtu and flags */
657 if (ioctl(ppp_dev_fd, PPPIOCSMRRU, &mrru) < 0)
658 error("Couldn't set MRRU: %m");
660 modify_flags(ppp_dev_fd, SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ|SC_MULTILINK,
661 ((rssn? SC_MP_SHORTSEQ: 0) | (tssn? SC_MP_XSHORTSEQ: 0)
662 | (mrru? SC_MULTILINK: 0)));
664 /* connect up the channel */
665 if (ioctl(ppp_fd, PPPIOCCONNECT, &ifunit) < 0)
666 fatal("Couldn't attach to PPP unit %d: %m", ifunit);
671 * make_new_bundle - create a new PPP unit (i.e. a bundle)
672 * and connect our channel to it. This should only get called
673 * if `multilink' was set at the time establish_ppp was called.
674 * In demand mode this uses our existing bundle instead of making
677 void make_new_bundle(int mrru, int mtru, int rssn, int tssn)
679 if (!new_style_driver)
682 /* make us a ppp unit */
683 if (make_ppp_unit() < 0)
686 /* set the mrru and flags */
687 cfg_bundle(mrru, mtru, rssn, tssn);
691 * bundle_attach - attach our link to a given PPP unit.
692 * We assume the unit is controlled by another pppd.
694 int bundle_attach(int ifnum)
698 if (!new_style_driver)
701 master_fd = open("/dev/ppp", O_RDWR);
703 fatal("Couldn't open /dev/ppp: %m");
704 if (ioctl(master_fd, PPPIOCATTACH, &ifnum) < 0) {
705 if (errno == ENXIO) {
707 return 0; /* doesn't still exist */
709 fatal("Couldn't attach to interface unit %d: %m\n", ifnum);
711 if (ioctl(ppp_fd, PPPIOCCONNECT, &ifnum) < 0)
712 fatal("Couldn't connect to interface unit %d: %m", ifnum);
713 modify_flags(master_fd, 0, SC_MULTILINK);
721 * destroy_bundle - tell the driver to destroy our bundle.
723 void destroy_bundle(void)
725 if (ppp_dev_fd >= 0) {
727 remove_fd(ppp_dev_fd);
732 /********************************************************************
734 * clean_check - Fetch the flags for the device and generate
735 * appropriate error messages.
737 void clean_check(void)
743 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
745 switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
747 s = "all had bit 7 set to 1";
751 s = "all had bit 7 set to 0";
755 s = "all had odd parity";
759 s = "all had even parity";
764 warn("Receive serial link is not 8-bit clean:");
765 warn("Problem: %s", s);
773 * List of valid speeds.
777 int speed_int, speed_val;
858 { 1000000, B1000000 },
861 { 1152000, B1152000 },
864 { 1500000, B1500000 },
867 { 2000000, B2000000 },
870 { 2500000, B2500000 },
873 { 3000000, B3000000 },
876 { 3500000, B3500000 },
879 { 4000000, B4000000 },
884 /********************************************************************
886 * Translate from bits/second to a speed_t.
889 static int translate_speed (int bps)
891 struct speed *speedp;
894 for (speedp = speeds; speedp->speed_int; speedp++) {
895 if (bps == speedp->speed_int)
896 return speedp->speed_val;
898 warn("speed %d not supported", bps);
903 /********************************************************************
905 * Translate from a speed_t to bits/second.
908 static int baud_rate_of (int speed)
910 struct speed *speedp;
913 for (speedp = speeds; speedp->speed_int; speedp++) {
914 if (speed == speedp->speed_val)
915 return speedp->speed_int;
921 /********************************************************************
923 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
924 * at the requested speed, etc. If `local' is true, set CLOCAL
925 * regardless of whether the modem option was specified.
928 void set_up_tty(int tty_fd, int local)
934 if (tcgetattr(tty_fd, &tios) < 0) {
935 if (!ok_error(errno))
936 fatal("tcgetattr: %m (line %d)", __LINE__);
943 tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
944 tios.c_cflag |= CS8 | CREAD | HUPCL;
946 tios.c_iflag = IGNBRK | IGNPAR;
950 tios.c_cc[VTIME] = 0;
953 tios.c_cflag ^= (CLOCAL | HUPCL);
957 tios.c_cflag |= CRTSCTS;
961 tios.c_iflag |= IXON | IXOFF;
962 tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */
963 tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */
967 tios.c_cflag &= ~CRTSCTS;
974 speed = translate_speed(inspeed);
976 cfsetospeed (&tios, speed);
977 cfsetispeed (&tios, speed);
980 * We can't proceed if the serial port speed is B0,
981 * since that implies that the serial port is disabled.
984 speed = cfgetospeed(&tios);
986 fatal("Baud rate for %s is 0; need explicit baud rate", devnam);
989 while (tcsetattr(tty_fd, TCSAFLUSH, &tios) < 0 && !ok_error(errno))
991 fatal("tcsetattr: %m (line %d)", __LINE__);
993 baud_rate = baud_rate_of(speed);
997 /********************************************************************
999 * setdtr - control the DTR line on the serial port.
1000 * This is called from die(), so it shouldn't call die().
1003 void setdtr (int tty_fd, int on)
1005 int modembits = TIOCM_DTR;
1007 ioctl(tty_fd, (on ? TIOCMBIS : TIOCMBIC), &modembits);
1010 /********************************************************************
1012 * restore_tty - restore the terminal to the saved settings.
1015 void restore_tty (int tty_fd)
1020 * Turn off echoing, because otherwise we can get into
1021 * a loop with the tty and the modem echoing to each other.
1022 * We presume we are the sole user of this tty device, so
1023 * when we close it, it will revert to its defaults anyway.
1025 if (!default_device)
1026 inittermios.c_lflag &= ~(ECHO | ECHONL);
1028 if (tcsetattr(tty_fd, TCSAFLUSH, &inittermios) < 0) {
1029 if (! ok_error (errno))
1030 warn("tcsetattr: %m (line %d)", __LINE__);
1035 /********************************************************************
1037 * output - Output PPP packet.
1040 void output (int unit, unsigned char *p, int len)
1045 dump_packet("sent", p, len);
1046 if (snoop_send_hook) snoop_send_hook(p, len);
1048 if (len < PPP_HDRLEN)
1050 if (new_style_driver) {
1053 proto = (p[0] << 8) + p[1];
1054 if (ppp_dev_fd >= 0 && !(proto >= 0xc000 || proto == PPP_CCPFRAG))
1057 if (write(fd, p, len) < 0) {
1058 if (errno == EWOULDBLOCK || errno == EAGAIN || errno == ENOBUFS
1059 || errno == ENXIO || errno == EIO || errno == EINTR)
1060 warn("write: warning: %m (%d)", errno);
1062 error("write: %m (%d)", errno);
1066 /********************************************************************
1068 * wait_input - wait until there is data available,
1069 * for the length of time specified by *timo (indefinite
1073 void wait_input(struct timeval *timo)
1080 n = select(max_in_fd + 1, &ready, NULL, &exc, timo);
1081 if (n < 0 && errno != EINTR)
1082 fatal("select: %m");
1086 * add_fd - add an fd to the set that wait_input waits for.
1090 if (fd >= FD_SETSIZE)
1091 fatal("internal error: file descriptor too large (%d)", fd);
1092 FD_SET(fd, &in_fds);
1098 * remove_fd - remove an fd from the set that wait_input waits for.
1100 void remove_fd(int fd)
1102 FD_CLR(fd, &in_fds);
1106 /********************************************************************
1108 * read_packet - get a PPP packet from the serial device.
1111 int read_packet (unsigned char *buf)
1115 len = PPP_MRU + PPP_HDRLEN;
1116 if (new_style_driver) {
1117 *buf++ = PPP_ALLSTATIONS;
1123 nr = read(ppp_fd, buf, len);
1124 if (nr < 0 && errno != EWOULDBLOCK && errno != EAGAIN
1125 && errno != EIO && errno != EINTR)
1127 if (nr < 0 && errno == ENXIO)
1130 if (nr < 0 && new_style_driver && ppp_dev_fd >= 0 && !bundle_eof) {
1131 /* N.B. we read ppp_fd first since LCP packets come in there. */
1132 nr = read(ppp_dev_fd, buf, len);
1133 if (nr < 0 && errno != EWOULDBLOCK && errno != EAGAIN
1134 && errno != EIO && errno != EINTR)
1135 error("read /dev/ppp: %m");
1136 if (nr < 0 && errno == ENXIO)
1138 if (nr == 0 && doing_multilink) {
1139 remove_fd(ppp_dev_fd);
1143 if (new_style_driver && ppp_fd < 0 && ppp_dev_fd < 0)
1145 return (new_style_driver && nr > 0)? nr+2: nr;
1148 /********************************************************************
1150 * get_loop_output - get outgoing packets from the ppp device,
1151 * and detect when we want to bring the real link up.
1152 * Return value is 1 if we need to bring up the link, 0 otherwise.
1155 get_loop_output(void)
1160 if (new_style_driver) {
1161 while ((n = read_packet(inpacket_buf)) > 0)
1162 if (loop_frame(inpacket_buf, n))
1167 while ((n = read(master_fd, inbuf, sizeof(inbuf))) > 0)
1168 if (loop_chars(inbuf, n))
1172 fatal("eof on loopback");
1174 if (errno != EWOULDBLOCK && errno != EAGAIN)
1175 fatal("read from loopback: %m(%d)", errno);
1181 * netif_set_mtu - set the MTU on the PPP network interface.
1184 netif_set_mtu(int unit, int mtu)
1188 memset (&ifr, '\0', sizeof (ifr));
1189 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1192 if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
1193 error("ioctl(SIOCSIFMTU): %m (line %d)", __LINE__);
1197 * netif_get_mtu - get the MTU on the PPP network interface.
1200 netif_get_mtu(int unit)
1204 memset (&ifr, '\0', sizeof (ifr));
1205 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1207 if (ifunit >= 0 && ioctl(sock_fd, SIOCGIFMTU, (caddr_t) &ifr) < 0) {
1208 error("ioctl(SIOCGIFMTU): %m (line %d)", __LINE__);
1214 /********************************************************************
1216 * tty_send_config - configure the transmit characteristics of
1217 * the ppp interface.
1220 void tty_send_config(int mtu, u_int32_t asyncmap, int pcomp, int accomp)
1227 if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
1228 if (errno != EIO && errno != ENOTTY)
1229 error("Couldn't set transmit async character map: %m");
1234 x = (pcomp? SC_COMP_PROT: 0) | (accomp? SC_COMP_AC: 0)
1235 | (sync_serial? SC_SYNC: 0);
1236 modify_flags(ppp_fd, SC_COMP_PROT|SC_COMP_AC|SC_SYNC, x);
1239 /********************************************************************
1241 * tty_set_xaccm - set the extended transmit ACCM for the interface.
1244 void tty_set_xaccm (ext_accm accm)
1248 if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY) {
1249 if ( ! ok_error (errno))
1250 warn("ioctl(set extended ACCM): %m (line %d)", __LINE__);
1254 /********************************************************************
1256 * tty_recv_config - configure the receive-side characteristics of
1257 * the ppp interface.
1260 void tty_recv_config(int mru, u_int32_t asyncmap, int pcomp, int accomp)
1263 * If we were called because the link has gone down then there is nothing
1264 * which may be done. Just return without incident.
1269 * Set the receiver parameters
1271 if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
1272 if (errno != EIO && errno != ENOTTY)
1273 error("Couldn't set channel receive MRU: %m");
1275 if (new_style_driver && ppp_dev_fd >= 0
1276 && ioctl(ppp_dev_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
1277 error("Couldn't set MRU in generic PPP layer: %m");
1279 if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
1280 if (errno != EIO && errno != ENOTTY)
1281 error("Couldn't set channel receive asyncmap: %m");
1285 /********************************************************************
1287 * ccp_test - ask kernel whether a given compression method
1288 * is acceptable for use.
1292 ccp_test(int unit, u_char *opt_ptr, int opt_len, int for_transmit)
1294 struct ppp_option_data data;
1296 memset (&data, '\0', sizeof (data));
1298 data.length = opt_len;
1299 data.transmit = for_transmit;
1301 if (ioctl(ppp_dev_fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
1304 return (errno == ENOBUFS)? 0: -1;
1307 /********************************************************************
1309 * ccp_flags_set - inform kernel about the current state of CCP.
1312 void ccp_flags_set (int unit, int isopen, int isup)
1316 x = (isopen? SC_CCP_OPEN: 0) | (isup? SC_CCP_UP: 0);
1317 if (still_ppp() && ppp_dev_fd >= 0)
1318 modify_flags(ppp_dev_fd, SC_CCP_OPEN|SC_CCP_UP, x);
1323 * set_filters - set the active and pass filters in the kernel driver.
1325 int set_filters(struct bpf_program *pass, struct bpf_program *active)
1327 struct sock_fprog fp;
1329 fp.len = pass->bf_len;
1330 fp.filter = (struct sock_filter *) pass->bf_insns;
1331 if (ioctl(ppp_dev_fd, PPPIOCSPASS, &fp) < 0) {
1332 if (errno == ENOTTY)
1333 warn("kernel does not support PPP filtering");
1335 error("Couldn't set pass-filter in kernel: %m");
1338 fp.len = active->bf_len;
1339 fp.filter = (struct sock_filter *) active->bf_insns;
1340 if (ioctl(ppp_dev_fd, PPPIOCSACTIVE, &fp) < 0) {
1341 error("Couldn't set active-filter in kernel: %m");
1346 #endif /* PPP_FILTER */
1348 /********************************************************************
1350 * get_idle_time - return how long the link has been idle.
1353 get_idle_time(u, ip)
1355 struct ppp_idle *ip;
1357 return ioctl(ppp_dev_fd, PPPIOCGIDLE, ip) >= 0;
1360 /********************************************************************
1362 * get_ppp_stats - return statistics for the link.
1365 get_ppp_stats(u, stats)
1367 struct pppd_stats *stats;
1369 struct ifpppstatsreq req;
1371 memset (&req, 0, sizeof (req));
1373 req.stats_ptr = (caddr_t) &req.stats;
1374 strlcpy(req.ifr__name, ifname, sizeof(req.ifr__name));
1375 if (ioctl(sock_fd, SIOCGPPPSTATS, &req) < 0) {
1376 error("Couldn't get PPP statistics: %m");
1379 stats->bytes_in = req.stats.p.ppp_ibytes;
1380 stats->bytes_out = req.stats.p.ppp_obytes;
1381 stats->pkts_in = req.stats.p.ppp_ipackets;
1382 stats->pkts_out = req.stats.p.ppp_opackets;
1386 /********************************************************************
1388 * ccp_fatal_error - returns 1 if decompression was disabled as a
1389 * result of an error detected after decompression of a packet,
1390 * 0 otherwise. This is necessary because of patent nonsense.
1393 int ccp_fatal_error (int unit)
1397 if (ioctl(ppp_dev_fd, PPPIOCGFLAGS, &flags) < 0) {
1398 error("Couldn't read compression error flags: %m");
1401 return flags & SC_DC_FERROR;
1404 /********************************************************************
1406 * path_to_procfs - find the path to the proc file system mount point
1408 static char proc_path[MAXPATHLEN];
1409 static int proc_path_len;
1411 static char *path_to_procfs(const char *tail)
1413 struct mntent *mntent;
1416 if (proc_path_len == 0) {
1417 /* Default the mount location of /proc */
1418 strlcpy (proc_path, "/proc", sizeof(proc_path));
1420 fp = fopen(MOUNTED, "r");
1422 while ((mntent = getmntent(fp)) != NULL) {
1423 if (strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0)
1425 if (strcmp(mntent->mnt_type, "proc") == 0) {
1426 strlcpy(proc_path, mntent->mnt_dir, sizeof(proc_path));
1427 proc_path_len = strlen(proc_path);
1435 strlcpy(proc_path + proc_path_len, tail,
1436 sizeof(proc_path) - proc_path_len);
1441 * /proc/net/route parsing stuff.
1443 #define ROUTE_MAX_COLS 12
1444 FILE *route_fd = (FILE *) 0;
1445 static char route_buffer[512];
1446 static int route_dev_col, route_dest_col, route_gw_col;
1447 static int route_flags_col, route_mask_col;
1448 static int route_num_cols;
1450 static int open_route_table (void);
1451 static void close_route_table (void);
1452 static int read_route_table (struct rtentry *rt);
1454 /********************************************************************
1456 * close_route_table - close the interface to the route table
1459 static void close_route_table (void)
1461 if (route_fd != (FILE *) 0) {
1463 route_fd = (FILE *) 0;
1467 /********************************************************************
1469 * open_route_table - open the interface to the route table
1471 static char route_delims[] = " \t\n";
1473 static int open_route_table (void)
1477 close_route_table();
1479 path = path_to_procfs("/net/route");
1480 route_fd = fopen (path, "r");
1481 if (route_fd == NULL) {
1482 error("can't open routing table %s: %m", path);
1486 route_dev_col = 0; /* default to usual columns */
1489 route_flags_col = 3;
1493 /* parse header line */
1494 if (fgets(route_buffer, sizeof(route_buffer), route_fd) != 0) {
1495 char *p = route_buffer, *q;
1497 for (col = 0; col < ROUTE_MAX_COLS; ++col) {
1499 if ((q = strtok(p, route_delims)) == 0)
1501 if (strcasecmp(q, "iface") == 0)
1502 route_dev_col = col;
1503 else if (strcasecmp(q, "destination") == 0)
1504 route_dest_col = col;
1505 else if (strcasecmp(q, "gateway") == 0)
1507 else if (strcasecmp(q, "flags") == 0)
1508 route_flags_col = col;
1509 else if (strcasecmp(q, "mask") == 0)
1510 route_mask_col = col;
1513 if (used && col >= route_num_cols)
1514 route_num_cols = col + 1;
1522 /********************************************************************
1524 * read_route_table - read the next entry from the route table
1527 static int read_route_table(struct rtentry *rt)
1529 char *cols[ROUTE_MAX_COLS], *p;
1532 memset (rt, '\0', sizeof (struct rtentry));
1534 if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
1538 for (col = 0; col < route_num_cols; ++col) {
1539 cols[col] = strtok(p, route_delims);
1540 if (cols[col] == NULL)
1541 return 0; /* didn't get enough columns */
1545 SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16);
1546 SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16);
1547 SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
1549 rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16);
1550 rt->rt_dev = cols[route_dev_col];
1555 /********************************************************************
1557 * defaultroute_exists - determine if there is a default route
1560 static int defaultroute_exists (struct rtentry *rt)
1564 if (!open_route_table())
1567 while (read_route_table(rt) != 0) {
1568 if ((rt->rt_flags & RTF_UP) == 0)
1571 if (kernel_version > KVERSION(2,1,0) && SIN_ADDR(rt->rt_genmask) != 0)
1573 if (SIN_ADDR(rt->rt_dst) == 0L) {
1579 close_route_table();
1584 * have_route_to - determine if the system has any route to
1585 * a given IP address. `addr' is in network byte order.
1586 * Return value is 1 if yes, 0 if no, -1 if don't know.
1587 * For demand mode to work properly, we have to ignore routes
1588 * through our own interface.
1590 int have_route_to(u_int32_t addr)
1595 if (!open_route_table())
1596 return -1; /* don't know */
1598 while (read_route_table(&rt)) {
1599 if ((rt.rt_flags & RTF_UP) == 0 || strcmp(rt.rt_dev, ifname) == 0)
1601 if ((addr & SIN_ADDR(rt.rt_genmask)) == SIN_ADDR(rt.rt_dst)) {
1607 close_route_table();
1611 /********************************************************************
1613 * sifdefaultroute - assign a default route through the address given.
1616 int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
1620 if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {
1621 if (rt.rt_flags & RTF_GATEWAY)
1622 error("not replacing existing default route via %I",
1623 SIN_ADDR(rt.rt_gateway));
1625 error("not replacing existing default route through %s",
1630 memset (&rt, 0, sizeof (rt));
1631 SET_SA_FAMILY (rt.rt_dst, AF_INET);
1635 if (kernel_version > KVERSION(2,1,0)) {
1636 SET_SA_FAMILY (rt.rt_genmask, AF_INET);
1637 SIN_ADDR(rt.rt_genmask) = 0L;
1640 rt.rt_flags = RTF_UP;
1641 if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
1642 if ( ! ok_error ( errno ))
1643 error("default route ioctl(SIOCADDRT): %m");
1647 have_default_route = 1;
1651 /********************************************************************
1653 * cifdefaultroute - delete a default route through the address given.
1656 int cifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
1660 have_default_route = 0;
1662 memset (&rt, '\0', sizeof (rt));
1663 SET_SA_FAMILY (rt.rt_dst, AF_INET);
1664 SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1668 if (kernel_version > KVERSION(2,1,0)) {
1669 SET_SA_FAMILY (rt.rt_genmask, AF_INET);
1670 SIN_ADDR(rt.rt_genmask) = 0L;
1673 rt.rt_flags = RTF_UP;
1674 if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
1676 if ( ! ok_error ( errno ))
1677 error("default route ioctl(SIOCDELRT): %m");
1685 /********************************************************************
1687 * sifproxyarp - Make a proxy ARP entry for the peer.
1690 int sifproxyarp (int unit, u_int32_t his_adr)
1692 struct arpreq arpreq;
1695 if (has_proxy_arp == 0) {
1696 memset (&arpreq, '\0', sizeof(arpreq));
1698 SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1699 SIN_ADDR(arpreq.arp_pa) = his_adr;
1700 arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1702 * Get the hardware address of an interface on the same subnet
1703 * as our local address.
1705 if (!get_ether_addr(his_adr, &arpreq.arp_ha, proxy_arp_dev,
1706 sizeof(proxy_arp_dev))) {
1707 error("Cannot determine ethernet address for proxy ARP");
1710 strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
1712 if (ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq) < 0) {
1713 if ( ! ok_error ( errno ))
1714 error("ioctl(SIOCSARP): %m");
1717 proxy_arp_addr = his_adr;
1721 forw_path = path_to_procfs("/sys/net/ipv4/ip_forward");
1722 if (forw_path != 0) {
1723 int fd = open(forw_path, O_WRONLY);
1725 if (write(fd, "1", 1) != 1)
1726 error("Couldn't enable IP forwarding: %m");
1736 /********************************************************************
1738 * cifproxyarp - Delete the proxy ARP entry for the peer.
1741 int cifproxyarp (int unit, u_int32_t his_adr)
1743 struct arpreq arpreq;
1745 if (has_proxy_arp) {
1747 memset (&arpreq, '\0', sizeof(arpreq));
1748 SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1749 SIN_ADDR(arpreq.arp_pa) = his_adr;
1750 arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1751 strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
1753 if (ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1754 if ( ! ok_error ( errno ))
1755 warn("ioctl(SIOCDARP): %m");
1762 /********************************************************************
1764 * get_ether_addr - get the hardware address of an interface on the
1765 * the same subnet as ipaddr.
1768 static int get_ether_addr (u_int32_t ipaddr,
1769 struct sockaddr *hwaddr,
1770 char *name, int namelen)
1772 struct ifreq *ifr, *ifend;
1773 u_int32_t ina, mask;
1775 struct ifreq ifreq, bestifreq;
1777 struct ifreq ifs[MAX_IFS];
1779 u_int32_t bestmask=0;
1780 int found_interface = 0;
1782 ifc.ifc_len = sizeof(ifs);
1784 if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {
1785 if ( ! ok_error ( errno ))
1786 error("ioctl(SIOCGIFCONF): %m (line %d)", __LINE__);
1791 * Scan through looking for an interface with an Internet
1792 * address on the same subnet as `ipaddr'.
1794 ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
1795 for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
1796 if (ifr->ifr_addr.sa_family == AF_INET) {
1797 ina = SIN_ADDR(ifr->ifr_addr);
1798 strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1800 * Check that the interface is up, and not point-to-point
1803 if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
1806 if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1809 * Get its netmask and check that it's on the right subnet.
1811 if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
1814 mask = SIN_ADDR(ifreq.ifr_addr);
1816 if (((ipaddr ^ ina) & mask) != 0)
1817 continue; /* no match */
1819 if (mask >= bestmask) {
1820 /* Compare using >= instead of > -- it is possible for
1821 an interface to have a netmask of 0.0.0.0 */
1822 found_interface = 1;
1829 if (!found_interface) return 0;
1831 strlcpy(name, bestifreq.ifr_name, namelen);
1833 /* trim off the :1 in eth0:1 */
1834 aliasp = strchr(name, ':');
1838 info("found interface %s for proxy arp", name);
1840 * Now get the hardware address.
1842 memset (&bestifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
1843 if (ioctl (sock_fd, SIOCGIFHWADDR, &bestifreq) < 0) {
1844 error("SIOCGIFHWADDR(%s): %m", bestifreq.ifr_name);
1849 &bestifreq.ifr_hwaddr,
1850 sizeof (struct sockaddr));
1856 * get_if_hwaddr - get the hardware address for the specified
1857 * network interface device.
1860 get_if_hwaddr(u_char *addr, char *name)
1865 sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
1868 memset(&ifreq.ifr_hwaddr, 0, sizeof(struct sockaddr));
1869 strlcpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name));
1870 ret = ioctl(sock_fd, SIOCGIFHWADDR, &ifreq);
1873 memcpy(addr, ifreq.ifr_hwaddr.sa_data, 6);
1878 * get_first_ethernet - return the name of the first ethernet-style
1879 * interface on this system.
1882 get_first_ethernet()
1887 /********************************************************************
1889 * Return user specified netmask, modified by any mask we might determine
1890 * for address `addr' (in network byte order).
1891 * Here we scan through the system's list of interfaces, looking for
1892 * any non-point-to-point interfaces which might appear to be on the same
1893 * network as `addr'. If we find any, we OR in their netmask to the
1894 * user-specified netmask.
1897 u_int32_t GetMask (u_int32_t addr)
1899 u_int32_t mask, nmask, ina;
1900 struct ifreq *ifr, *ifend, ifreq;
1902 struct ifreq ifs[MAX_IFS];
1906 if (IN_CLASSA(addr)) /* determine network mask for address class */
1907 nmask = IN_CLASSA_NET;
1908 else if (IN_CLASSB(addr))
1909 nmask = IN_CLASSB_NET;
1911 nmask = IN_CLASSC_NET;
1913 /* class D nets are disallowed by bad_ip_adrs */
1914 mask = netmask | htonl(nmask);
1916 * Scan through the system's network interfaces.
1918 ifc.ifc_len = sizeof(ifs);
1920 if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {
1921 if ( ! ok_error ( errno ))
1922 warn("ioctl(SIOCGIFCONF): %m (line %d)", __LINE__);
1926 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1927 for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
1929 * Check the interface's internet address.
1931 if (ifr->ifr_addr.sa_family != AF_INET)
1933 ina = SIN_ADDR(ifr->ifr_addr);
1934 if (((ntohl(ina) ^ addr) & nmask) != 0)
1937 * Check that the interface is up, and not point-to-point nor loopback.
1939 strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1940 if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
1943 if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1946 * Get its netmask and OR it into our mask.
1948 if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
1950 mask |= SIN_ADDR(ifreq.ifr_addr);
1956 /********************************************************************
1958 * Internal routine to decode the version.modification.patch level
1961 static void decode_version (char *buf, int *version,
1962 int *modification, int *patch)
1966 *version = (int) strtoul (buf, &endp, 10);
1970 if (endp != buf && *endp == '.') {
1972 *modification = (int) strtoul (buf, &endp, 10);
1973 if (endp != buf && *endp == '.') {
1975 *patch = (int) strtoul (buf, &buf, 10);
1980 /********************************************************************
1982 * Procedure to determine if the PPP line discipline is registered.
1986 ppp_registered(void)
1994 * We used to open the serial device and set it to the ppp line
1995 * discipline here, in order to create a ppp unit. But that is
1996 * not a good idea - the user might have specified a device that
1997 * they can't open (permission, or maybe it doesn't really exist).
1998 * So we grab a pty master/slave pair and use that.
2000 if (!get_pty(&mfd, &local_fd, slave, 0)) {
2001 no_ppp_msg = "Couldn't determine if PPP is supported (no free ptys)";
2006 * Try to put the device into the PPP discipline.
2008 if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0) {
2009 error("ioctl(TIOCSETD(PPP)): %m (line %d)", __LINE__);
2018 /********************************************************************
2020 * ppp_available - check whether the system has any ppp interfaces
2021 * (in fact we check whether we can do an ioctl on ppp0).
2024 int ppp_available(void)
2029 int my_version, my_modification, my_patch;
2030 int osmaj, osmin, ospatch;
2032 /* get the kernel version now, since we are called before sys_init */
2034 osmaj = osmin = ospatch = 0;
2035 sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch);
2036 kernel_version = KVERSION(osmaj, osmin, ospatch);
2038 fd = open("/dev/ppp", O_RDWR);
2040 new_style_driver = 1;
2042 /* XXX should get from driver */
2044 driver_modification = 4;
2050 if (kernel_version >= KVERSION(2,3,13)) {
2051 error("Couldn't open the /dev/ppp device: %m");
2052 if (errno == ENOENT)
2054 "You need to create the /dev/ppp device node by\n"
2055 "executing the following command as root:\n"
2056 " mknod /dev/ppp c 108 0\n";
2057 else if (errno == ENODEV || errno == ENXIO)
2059 "Please load the ppp_generic kernel module.\n";
2063 /* we are running on a really really old kernel */
2065 "This system lacks kernel support for PPP. This could be because\n"
2066 "the PPP kernel module could not be loaded, or because PPP was not\n"
2067 "included in the kernel configuration. If PPP was included as a\n"
2068 "module, try `/sbin/modprobe -v ppp'. If that fails, check that\n"
2069 "ppp.o exists in /lib/modules/`uname -r`/net.\n"
2070 "See README.linux file in the ppp distribution for more details.\n";
2073 * Open a socket for doing the ioctl operations.
2075 s = socket(AF_INET, SOCK_DGRAM, 0);
2079 strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
2080 ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
2082 * If the device did not exist then attempt to create one by putting the
2083 * current tty into the PPP discipline. If this works then obtain the
2084 * flags for the device again.
2087 if (ppp_registered()) {
2088 strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
2089 ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
2093 * Ensure that the hardware address is for PPP and not something else
2096 ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
2098 if (ok && ((ifr.ifr_hwaddr.sa_family & ~0xFF) != ARPHRD_PPP))
2102 * This is the PPP device. Validate the version of the driver at this
2103 * point to ensure that this program will work with the driver.
2106 char abBuffer [1024];
2108 ifr.ifr_data = abBuffer;
2109 size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
2111 error("Couldn't read driver version: %m");
2113 no_ppp_msg = "Sorry, couldn't verify kernel driver version\n";
2116 decode_version(abBuffer,
2118 &driver_modification,
2121 * Validate the version of the driver against the version that we used.
2123 decode_version(VERSION,
2128 /* The version numbers must match */
2129 if (driver_version != my_version)
2132 /* The modification levels must be legal */
2133 if (driver_modification < 3) {
2134 if (driver_modification >= 2) {
2135 /* we can cope with 2.2.0 and above */
2144 slprintf(route_buffer, sizeof(route_buffer),
2145 "Sorry - PPP driver version %d.%d.%d is out of date\n",
2146 driver_version, driver_modification, driver_patch);
2148 no_ppp_msg = route_buffer;
2155 #ifndef HAVE_LOGWTMP
2156 /********************************************************************
2158 * Update the wtmp file with the appropriate user name and tty device.
2161 void logwtmp (const char *line, const char *name, const char *host)
2163 struct utmp ut, *utp;
2164 pid_t mypid = getpid();
2170 * Update the signon database for users.
2171 * Christoph Lameter: Copied from poeigl-1.36 Jan 3, 1996
2173 utmpname(_PATH_UTMP);
2175 while ((utp = getutent()) && (utp->ut_pid != mypid))
2179 memcpy(&ut, utp, sizeof(ut));
2181 /* some gettys/telnetds don't initialize utmp... */
2182 memset(&ut, 0, sizeof(ut));
2184 if (ut.ut_id[0] == 0)
2185 strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
2187 strncpy(ut.ut_user, name, sizeof(ut.ut_user));
2188 strncpy(ut.ut_line, line, sizeof(ut.ut_line));
2192 ut.ut_type = USER_PROCESS;
2195 /* Insert the host name if one is supplied */
2197 strncpy (ut.ut_host, host, sizeof(ut.ut_host));
2199 /* Insert the IP address of the remote system if IP is enabled */
2200 if (ipcp_protent.enabled_flag && ipcp_hisoptions[0].neg_addr)
2201 memcpy(&ut.ut_addr, (char *) &ipcp_hisoptions[0].hisaddr,
2202 sizeof(ut.ut_addr));
2204 /* CL: Makes sure that the logout works */
2205 if (*host == 0 && *name==0)
2211 * Update the wtmp file.
2214 updwtmp(_PATH_WTMP, &ut);
2216 wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY);
2218 flock(wtmp, LOCK_EX);
2220 if (write (wtmp, (char *)&ut, sizeof(ut)) != sizeof(ut))
2221 warn("error writing %s: %m", _PATH_WTMP);
2223 flock(wtmp, LOCK_UN);
2229 #endif /* HAVE_LOGWTMP */
2231 /********************************************************************
2233 * sifvjcomp - config tcp header compression
2236 int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
2241 if (ioctl(ppp_dev_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
2242 error("Couldn't set up TCP header compression: %m");
2247 x = (vjcomp? SC_COMP_TCP: 0) | (cidcomp? 0: SC_NO_TCP_CCID);
2248 modify_flags(ppp_dev_fd, SC_COMP_TCP|SC_NO_TCP_CCID, x);
2253 /********************************************************************
2255 * sifup - Config the interface up and enable IP packets to pass.
2262 if ((ret = setifstate(u, 1)))
2268 /********************************************************************
2270 * sifdown - Disable the indicated protocol and config the interface
2271 * down if there are no remaining protocols.
2276 if (if_is_up && --if_is_up > 0)
2284 return setifstate(u, 0);
2288 /********************************************************************
2290 * sif6up - Config the interface up for IPv6
2297 if ((ret = setifstate(u, 1)))
2303 /********************************************************************
2305 * sif6down - Disable the IPv6CP protocol and config the interface
2306 * down if there are no remaining protocols.
2309 int sif6down (int u)
2316 return setifstate(u, 0);
2320 /********************************************************************
2322 * setifstate - Config the interface up or down
2325 static int setifstate (int u, int state)
2329 memset (&ifr, '\0', sizeof (ifr));
2330 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2331 if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
2332 if (! ok_error (errno))
2333 error("ioctl (SIOCGIFFLAGS): %m (line %d)", __LINE__);
2338 ifr.ifr_flags |= IFF_UP;
2340 ifr.ifr_flags &= ~IFF_UP;
2341 ifr.ifr_flags |= IFF_POINTOPOINT;
2342 if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
2343 if (! ok_error (errno))
2344 error("ioctl(SIOCSIFFLAGS): %m (line %d)", __LINE__);
2350 /********************************************************************
2352 * sifaddr - Config the interface IP addresses and netmask.
2355 int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
2361 memset (&ifr, '\0', sizeof (ifr));
2362 memset (&rt, '\0', sizeof (rt));
2364 SET_SA_FAMILY (ifr.ifr_addr, AF_INET);
2365 SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET);
2366 SET_SA_FAMILY (ifr.ifr_netmask, AF_INET);
2368 strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2370 * Set our IP address
2372 SIN_ADDR(ifr.ifr_addr) = our_adr;
2373 if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
2374 if (errno != EEXIST) {
2375 if (! ok_error (errno))
2376 error("ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
2379 warn("ioctl(SIOCSIFADDR): Address already exists");
2384 * Set the gateway address
2387 SIN_ADDR(ifr.ifr_dstaddr) = his_adr;
2388 if (ioctl(sock_fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
2389 if (! ok_error (errno))
2390 error("ioctl(SIOCSIFDSTADDR): %m (line %d)", __LINE__);
2396 * For recent kernels, force the netmask to 255.255.255.255.
2398 if (kernel_version >= KVERSION(2,1,16))
2400 if (net_mask != 0) {
2401 SIN_ADDR(ifr.ifr_netmask) = net_mask;
2402 if (ioctl(sock_fd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
2403 if (! ok_error (errno))
2404 error("ioctl(SIOCSIFNETMASK): %m (line %d)", __LINE__);
2409 * Add the device route
2411 if (kernel_version < KVERSION(2,1,16)) {
2412 SET_SA_FAMILY (rt.rt_dst, AF_INET);
2413 SET_SA_FAMILY (rt.rt_gateway, AF_INET);
2416 SIN_ADDR(rt.rt_gateway) = 0L;
2417 SIN_ADDR(rt.rt_dst) = his_adr;
2418 rt.rt_flags = RTF_UP | RTF_HOST;
2420 if (kernel_version > KVERSION(2,1,0)) {
2421 SET_SA_FAMILY (rt.rt_genmask, AF_INET);
2422 SIN_ADDR(rt.rt_genmask) = -1L;
2425 if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
2426 if (! ok_error (errno))
2427 error("ioctl(SIOCADDRT) device route: %m (line %d)", __LINE__);
2432 /* set ip_dynaddr in demand mode if address changes */
2433 if (demand && tune_kernel && !dynaddr_set
2434 && our_old_addr && our_old_addr != our_adr) {
2435 /* set ip_dynaddr if possible */
2439 path = path_to_procfs("/sys/net/ipv4/ip_dynaddr");
2440 if (path != 0 && (fd = open(path, O_WRONLY)) >= 0) {
2441 if (write(fd, "1", 1) != 1)
2442 error("Couldn't enable dynamic IP addressing: %m");
2445 dynaddr_set = 1; /* only 1 attempt */
2452 /********************************************************************
2454 * cifaddr - Clear the interface IP addresses, and delete routes
2455 * through the interface if possible.
2458 int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
2462 if (kernel_version < KVERSION(2,1,16)) {
2464 * Delete the route through the device
2467 memset (&rt, '\0', sizeof (rt));
2469 SET_SA_FAMILY (rt.rt_dst, AF_INET);
2470 SET_SA_FAMILY (rt.rt_gateway, AF_INET);
2473 SIN_ADDR(rt.rt_gateway) = 0;
2474 SIN_ADDR(rt.rt_dst) = his_adr;
2475 rt.rt_flags = RTF_UP | RTF_HOST;
2477 if (kernel_version > KVERSION(2,1,0)) {
2478 SET_SA_FAMILY (rt.rt_genmask, AF_INET);
2479 SIN_ADDR(rt.rt_genmask) = -1L;
2482 if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
2483 if (still_ppp() && ! ok_error (errno))
2484 error("ioctl(SIOCDELRT) device route: %m (line %d)", __LINE__);
2489 /* This way it is possible to have an IPX-only or IPv6-only interface */
2490 memset(&ifr, 0, sizeof(ifr));
2491 SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
2492 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2494 if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
2495 if (! ok_error (errno)) {
2496 error("ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
2501 our_old_addr = our_adr;
2507 /********************************************************************
2509 * sif6addr - Config the interface with an IPv6 link-local address
2511 int sif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
2513 struct in6_ifreq ifr6;
2515 struct in6_rtmsg rt6;
2519 error("IPv6 socket creation failed: %m");
2522 memset(&ifr, 0, sizeof (ifr));
2523 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2524 if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
2525 error("sif6addr: ioctl(SIOCGIFINDEX): %m (line %d)", __LINE__);
2529 /* Local interface */
2530 memset(&ifr6, 0, sizeof(ifr6));
2531 IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
2532 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
2533 ifr6.ifr6_prefixlen = 10;
2535 if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6) < 0) {
2536 error("sif6addr: ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
2540 /* Route to remote host */
2541 memset(&rt6, 0, sizeof(rt6));
2542 IN6_LLADDR_FROM_EUI64(rt6.rtmsg_dst, his_eui64);
2543 rt6.rtmsg_flags = RTF_UP;
2544 rt6.rtmsg_dst_len = 10;
2545 rt6.rtmsg_ifindex = ifr.ifr_ifindex;
2546 rt6.rtmsg_metric = 1;
2548 if (ioctl(sock6_fd, SIOCADDRT, &rt6) < 0) {
2549 error("sif6addr: ioctl(SIOCADDRT): %m (line %d)", __LINE__);
2557 /********************************************************************
2559 * cif6addr - Remove IPv6 address from interface
2561 int cif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
2564 struct in6_ifreq ifr6;
2568 error("IPv6 socket creation failed: %m");
2571 memset(&ifr, 0, sizeof(ifr));
2572 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2573 if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
2574 error("cif6addr: ioctl(SIOCGIFINDEX): %m (line %d)", __LINE__);
2578 memset(&ifr6, 0, sizeof(ifr6));
2579 IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
2580 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
2581 ifr6.ifr6_prefixlen = 10;
2583 if (ioctl(sock6_fd, SIOCDIFADDR, &ifr6) < 0) {
2584 if (errno != EADDRNOTAVAIL) {
2585 if (! ok_error (errno))
2586 error("cif6addr: ioctl(SIOCDIFADDR): %m (line %d)", __LINE__);
2589 warn("cif6addr: ioctl(SIOCDIFADDR): No such address");
2598 * get_pty - get a pty master/slave pair and chown the slave side
2599 * to the uid given. Assumes slave_name points to >= 16 bytes of space.
2602 get_pty(master_fdp, slave_fdp, slave_name, uid)
2608 int i, mfd, sfd = -1;
2610 struct termios tios;
2614 * Try the unix98 way first.
2616 mfd = open("/dev/ptmx", O_RDWR);
2619 if (ioctl(mfd, TIOCGPTN, &ptn) >= 0) {
2620 slprintf(pty_name, sizeof(pty_name), "/dev/pts/%d", ptn);
2621 chmod(pty_name, S_IRUSR | S_IWUSR);
2624 if (ioctl(mfd, TIOCSPTLCK, &ptn) < 0)
2625 warn("Couldn't unlock pty slave %s: %m", pty_name);
2627 if ((sfd = open(pty_name, O_RDWR | O_NOCTTY)) < 0)
2628 warn("Couldn't open pty slave %s: %m", pty_name);
2631 #endif /* TIOCGPTN */
2634 /* the old way - scan through the pty name space */
2635 for (i = 0; i < 64; ++i) {
2636 slprintf(pty_name, sizeof(pty_name), "/dev/pty%c%x",
2637 'p' + i / 16, i % 16);
2638 mfd = open(pty_name, O_RDWR, 0);
2641 sfd = open(pty_name, O_RDWR | O_NOCTTY, 0);
2643 fchown(sfd, uid, -1);
2644 fchmod(sfd, S_IRUSR | S_IWUSR);
2655 strlcpy(slave_name, pty_name, 16);
2658 if (tcgetattr(sfd, &tios) == 0) {
2659 tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
2660 tios.c_cflag |= CS8 | CREAD | CLOCAL;
2661 tios.c_iflag = IGNPAR;
2664 if (tcsetattr(sfd, TCSAFLUSH, &tios) < 0)
2665 warn("couldn't set attributes on pty: %m");
2667 warn("couldn't get attributes on pty: %m");
2672 /********************************************************************
2674 * open_loopback - open the device we use for getting packets
2675 * in demand mode. Under Linux, we use a pty master/slave pair.
2678 open_ppp_loopback(void)
2683 if (new_style_driver) {
2684 /* allocate ourselves a ppp unit */
2685 if (make_ppp_unit() < 0)
2687 modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC);
2688 set_kdebugflag(kdebugflag);
2693 if (!get_pty(&master_fd, &slave_fd, loop_name, 0))
2694 fatal("No free pty for loopback");
2696 set_ppp_fd(slave_fd);
2698 flags = fcntl(master_fd, F_GETFL);
2700 fcntl(master_fd, F_SETFL, flags | O_NONBLOCK) == -1)
2701 warn("couldn't set master loopback to nonblock: %m");
2703 flags = fcntl(ppp_fd, F_GETFL);
2705 fcntl(ppp_fd, F_SETFL, flags | O_NONBLOCK) == -1)
2706 warn("couldn't set slave loopback to nonblock: %m");
2708 if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0)
2709 fatal("ioctl(TIOCSETD): %m (line %d)", __LINE__);
2711 * Find out which interface we were given.
2713 if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
2714 fatal("ioctl(PPPIOCGUNIT): %m (line %d)", __LINE__);
2716 * Enable debug in the driver if requested.
2718 set_kdebugflag (kdebugflag);
2723 /********************************************************************
2725 * sifnpmode - Set the mode for handling packets for a given NP.
2729 sifnpmode(u, proto, mode)
2736 npi.protocol = proto;
2738 if (ioctl(ppp_dev_fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) {
2739 if (! ok_error (errno))
2740 error("ioctl(PPPIOCSNPMODE, %d, %d): %m", proto, mode);
2747 /********************************************************************
2749 * sipxfaddr - Config the interface IPX networknumber
2752 int sipxfaddr (int unit, unsigned long int network, unsigned char * node )
2759 struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
2761 skfd = socket (AF_IPX, SOCK_DGRAM, 0);
2763 if (! ok_error (errno))
2764 dbglog("socket(AF_IPX): %m (line %d)", __LINE__);
2768 memset (&ifr, '\0', sizeof (ifr));
2769 strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2771 memcpy (sipx->sipx_node, node, IPX_NODE_LEN);
2772 sipx->sipx_family = AF_IPX;
2773 sipx->sipx_port = 0;
2774 sipx->sipx_network = htonl (network);
2775 sipx->sipx_type = IPX_FRAME_ETHERII;
2776 sipx->sipx_action = IPX_CRTITF;
2778 * Set the IPX device
2780 if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
2782 if (errno != EEXIST) {
2783 if (! ok_error (errno))
2784 dbglog("ioctl(SIOCSIFADDR, CRTITF): %m (line %d)", __LINE__);
2787 warn("ioctl(SIOCSIFADDR, CRTITF): Address already exists");
2796 /********************************************************************
2798 * cipxfaddr - Clear the information for the IPX network. The IPX routes
2799 * are removed and the device is no longer able to pass IPX
2803 int cipxfaddr (int unit)
2810 struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
2812 skfd = socket (AF_IPX, SOCK_DGRAM, 0);
2814 if (! ok_error (errno))
2815 dbglog("socket(AF_IPX): %m (line %d)", __LINE__);
2819 memset (&ifr, '\0', sizeof (ifr));
2820 strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2822 sipx->sipx_type = IPX_FRAME_ETHERII;
2823 sipx->sipx_action = IPX_DLTITF;
2824 sipx->sipx_family = AF_IPX;
2826 * Set the IPX device
2828 if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
2829 if (! ok_error (errno))
2830 info("ioctl(SIOCSIFADDR, IPX_DLTITF): %m (line %d)", __LINE__);
2840 * Use the hostname as part of the random number seed.
2849 for (p = hostname; *p != 0; ++p)
2854 /********************************************************************
2856 * sys_check_options - check the options that the user specified
2860 sys_check_options(void)
2864 * Disable the IPX protocol if the support is not present in the kernel.
2868 if (ipxcp_protent.enabled_flag) {
2869 struct stat stat_buf;
2870 if ( ((path = path_to_procfs("/net/ipx/interface")) == NULL
2871 && (path = path_to_procfs("/net/ipx_interface")) == NULL)
2872 || lstat(path, &stat_buf) < 0) {
2873 error("IPX support is not present in the kernel\n");
2874 ipxcp_protent.enabled_flag = 0;
2878 if (demand && driver_is_old) {
2879 option_error("demand dialling is not supported by kernel driver "
2880 "version %d.%d.%d", driver_version, driver_modification,
2884 if (multilink && !new_style_driver) {
2885 warn("Warning: multilink is not supported by the kernel driver");
2893 * ether_to_eui64 - Convert 48-bit Ethernet address into 64-bit EUI
2895 * convert the 48-bit MAC address of eth0 into EUI 64. caller also assumes
2896 * that the system has a properly configured Ethernet interface for this
2897 * function to return non-zero.
2900 ether_to_eui64(eui64_t *p_eui64)
2904 const unsigned char *ptr;
2906 skfd = socket(PF_INET6, SOCK_DGRAM, 0);
2909 warn("could not open IPv6 socket");
2913 strcpy(ifr.ifr_name, "eth0");
2914 if(ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
2917 warn("could not obtain hardware address for eth0");
2923 * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1]
2925 ptr = (unsigned char *) ifr.ifr_hwaddr.sa_data;
2926 p_eui64->e8[0] = ptr[0] | 0x02;
2927 p_eui64->e8[1] = ptr[1];
2928 p_eui64->e8[2] = ptr[2];
2929 p_eui64->e8[3] = 0xFF;
2930 p_eui64->e8[4] = 0xFE;
2931 p_eui64->e8[5] = ptr[3];
2932 p_eui64->e8[6] = ptr[4];
2933 p_eui64->e8[7] = ptr[5];