X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fsys-linux.c;h=effb63854a3be94b1f730bdece21ce782b4f5dec;hp=f391dac082ad1993042c853ec604514e497baf4c;hb=7292aba5fee34d251b7caa488e02db1c48e75b2d;hpb=14768a012e45353cde5b60896ccc6b7528d90c69 diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c index f391dac..effb638 100644 --- a/pppd/sys-linux.c +++ b/pppd/sys-linux.c @@ -2,20 +2,76 @@ * sys-linux.c - System-dependent procedures for setting up * PPP interfaces on Linux systems * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Derived from main.c and pppd.h, which are: + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include @@ -127,7 +183,14 @@ static int master_fd = -1; #ifdef INET6 static int sock6_fd = -1; #endif /* INET6 */ -static int ppp_dev_fd = -1; /* fd for /dev/ppp (new style driver) */ + +/* + * For the old-style kernel driver, this is the same as ppp_fd. + * For the new-style driver, it is the fd of an instance of /dev/ppp + * which is attached to the ppp unit and is used for controlling it. + */ +int ppp_dev_fd = -1; /* fd for /dev/ppp (new style driver) */ + static int chindex; /* channel index (new style driver) */ static fd_set in_fds; /* set of fds that wait_input waits for */ @@ -168,8 +231,7 @@ static int kernel_version; #define SIN_ADDR(x) (((struct sockaddr_in *) (&(x)))->sin_addr.s_addr) /* Prototypes for procedures local to this file. */ -static int get_flags (int fd); -static void set_flags (int fd, int flags); +static int modify_flags(int fd, int clear_bits, int set_bits); static int translate_speed (int bps); static int baud_rate_of (int speed); static void close_route_table (void); @@ -222,36 +284,26 @@ static int still_ppp(void) return 0; } -/******************************************************************** - * - * Functions to read and set the flags value in the device driver +/* + * modify_flags - set and clear flag bits controlling the kernel + * PPP driver. */ - -static int get_flags (int fd) +static int modify_flags(int fd, int clear_bits, int set_bits) { - int flags; - - if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0) { - if ( ok_error (errno) ) - flags = 0; - else - fatal("ioctl(PPPIOCGFLAGS): %m (line %d)", __LINE__); - } - - SYSDEBUG ((LOG_DEBUG, "get flags = %x\n", flags)); - return flags; -} + int flags; -/********************************************************************/ + if (ioctl(fd, PPPIOCGFLAGS, &flags) == -1) + goto err; + flags = (flags & ~clear_bits) | set_bits; + if (ioctl(fd, PPPIOCSFLAGS, &flags) == -1) + goto err; -static void set_flags (int fd, int flags) -{ - SYSDEBUG ((LOG_DEBUG, "set flags = %x\n", flags)); + return 0; - if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0) { - if (! ok_error (errno) ) - fatal("ioctl(PPPIOCSFLAGS, %x): %m (line %d)", flags, errno, __LINE__); - } + err: + if (errno != EIO) + error("Failed to set PPP kernel option flags: %m"); + return -1; } /******************************************************************** @@ -261,18 +313,6 @@ static void set_flags (int fd, int flags) void sys_init(void) { - int flags; - - if (new_style_driver) { - ppp_dev_fd = open("/dev/ppp", O_RDWR); - if (ppp_dev_fd < 0) - fatal("Couldn't open /dev/ppp: %m"); - flags = fcntl(ppp_dev_fd, F_GETFL); - if (flags == -1 - || fcntl(ppp_dev_fd, F_SETFL, flags | O_NONBLOCK) == -1) - warn("Couldn't set /dev/ppp to nonblock: %m"); - } - /* Get an internet socket for doing socket ioctls. */ sock_fd = socket(AF_INET, SOCK_DGRAM, 0); if (sock_fd < 0) @@ -321,15 +361,18 @@ void sys_cleanup(void) void sys_close(void) { - if (new_style_driver) + if (new_style_driver && ppp_dev_fd >= 0) close(ppp_dev_fd); if (sock_fd >= 0) close(sock_fd); +#ifdef INET6 + if (sock6_fd >= 0) + close(sock6_fd); +#endif if (slave_fd >= 0) close(slave_fd); if (master_fd >= 0) close(master_fd); - closelog(); } /******************************************************************** @@ -339,7 +382,7 @@ sys_close(void) static int set_kdebugflag (int requested_level) { - if (new_style_driver && ifunit < 0) + if (ppp_dev_fd < 0) return 1; if (ioctl(ppp_dev_fd, PPPIOCSDEBUG, &requested_level) < 0) { if ( ! ok_error (errno) ) @@ -397,8 +440,8 @@ int tty_establish_ppp (int tty_fd) | SC_LOG_FLUSH) if (ret_fd >= 0) { - set_flags(ppp_fd, ((get_flags(ppp_fd) & ~(SC_RCVB | SC_LOGB)) - | ((kdebugflag * SC_DEBUG) & SC_LOGB))); + modify_flags(ppp_fd, SC_RCVB | SC_LOGB, + (kdebugflag * SC_DEBUG) & SC_LOGB); } else { if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0 && !ok_error(errno)) warn("Couldn't reset tty to normal line discipline: %m"); @@ -416,9 +459,9 @@ int generic_establish_ppp (int fd) int x; if (new_style_driver) { - /* Open another instance of /dev/ppp and connect the channel to it */ int flags; + /* Open an instance of /dev/ppp and connect the channel to it */ if (ioctl(fd, PPPIOCGCHAN, &chindex) == -1) { error("Couldn't get channel number: %m"); goto err; @@ -429,6 +472,7 @@ int generic_establish_ppp (int fd) error("Couldn't reopen /dev/ppp: %m"); goto err; } + (void) fcntl(fd, F_SETFD, FD_CLOEXEC); if (ioctl(fd, PPPIOCATTCHAN, &chindex) < 0) { error("Couldn't attach to channel %d: %m", chindex); goto err_close; @@ -449,7 +493,7 @@ int generic_establish_ppp (int fd) } if (looped) - set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) & ~SC_LOOP_TRAFFIC); + modify_flags(ppp_dev_fd, SC_LOOP_TRAFFIC, 0); if (!multilink) { add_fd(ppp_dev_fd); @@ -485,14 +529,14 @@ int generic_establish_ppp (int fd) } } - looped = 0; - /* * Enable debug in the driver if requested. */ if (!looped) set_kdebugflag (kdebugflag); + looped = 0; + SYSDEBUG ((LOG_NOTICE, "Using version %d.%d.%d of PPP driver", driver_version, driver_modification, driver_patch)); @@ -517,7 +561,10 @@ void tty_disestablish_ppp(int tty_fd) * Flush the tty output buffer so that the TIOCSETD doesn't hang. */ if (tcflush(tty_fd, TCIOFLUSH) < 0) + { warn("tcflush failed: %m"); + goto flushfailed; + } /* * Restore the previous line discipline */ @@ -537,6 +584,7 @@ void tty_disestablish_ppp(int tty_fd) warn("Couldn't restore device fd flags: %m"); } } +flushfailed: initfdflags = -1; generic_disestablish_ppp(tty_fd); @@ -554,16 +602,19 @@ void generic_disestablish_ppp(int dev_fd) close(ppp_fd); ppp_fd = -1; if (demand) { - set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) | SC_LOOP_TRAFFIC); + modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC); looped = 1; - } else if (ifunit >= 0 && ioctl(ppp_dev_fd, PPPIOCDETACH) < 0) - error("Couldn't release PPP unit: %m"); - if (!multilink) + } else if (ppp_dev_fd >= 0) { + close(ppp_dev_fd); remove_fd(ppp_dev_fd); + ppp_dev_fd = -1; + } } else { /* old-style driver */ if (demand) set_ppp_fd(slave_fd); + else + ppp_dev_fd = -1; } } @@ -573,12 +624,24 @@ void generic_disestablish_ppp(int dev_fd) */ static int make_ppp_unit() { - int x; + int x, flags; + + if (ppp_dev_fd >= 0) { + dbglog("in make_ppp_unit, already had /dev/ppp open?"); + close(ppp_dev_fd); + } + ppp_dev_fd = open("/dev/ppp", O_RDWR); + if (ppp_dev_fd < 0) + fatal("Couldn't open /dev/ppp: %m"); + flags = fcntl(ppp_dev_fd, F_GETFL); + if (flags == -1 + || fcntl(ppp_dev_fd, F_SETFL, flags | O_NONBLOCK) == -1) + warn("Couldn't set /dev/ppp to nonblock: %m"); ifunit = req_unit; x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit); if (x < 0 && req_unit >= 0 && errno == EEXIST) { - warn("Couldn't allocate PPP unit %d as it is already in use"); + warn("Couldn't allocate PPP unit %d as it is already in use", req_unit); ifunit = -1; x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit); } @@ -593,20 +656,16 @@ static int make_ppp_unit() */ void cfg_bundle(int mrru, int mtru, int rssn, int tssn) { - int flags; - if (!new_style_driver) return; /* set the mrru, mtu and flags */ if (ioctl(ppp_dev_fd, PPPIOCSMRRU, &mrru) < 0) error("Couldn't set MRRU: %m"); - flags = get_flags(ppp_dev_fd); - flags &= ~(SC_MP_SHORTSEQ | SC_MP_XSHORTSEQ); - flags |= (rssn? SC_MP_SHORTSEQ: 0) | (tssn? SC_MP_XSHORTSEQ: 0) - | (mrru? SC_MULTILINK: 0); - set_flags(ppp_dev_fd, flags); + modify_flags(ppp_dev_fd, SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ|SC_MULTILINK, + ((rssn? SC_MP_SHORTSEQ: 0) | (tssn? SC_MP_XSHORTSEQ: 0) + | (mrru? SC_MULTILINK: 0))); /* connect up the channel */ if (ioctl(ppp_fd, PPPIOCCONNECT, &ifunit) < 0) @@ -640,17 +699,25 @@ void make_new_bundle(int mrru, int mtru, int rssn, int tssn) */ int bundle_attach(int ifnum) { + int master_fd; + if (!new_style_driver) return -1; - if (ioctl(ppp_dev_fd, PPPIOCATTACH, &ifnum) < 0) { - if (errno == ENXIO) + master_fd = open("/dev/ppp", O_RDWR); + if (master_fd < 0) + fatal("Couldn't open /dev/ppp: %m"); + if (ioctl(master_fd, PPPIOCATTACH, &ifnum) < 0) { + if (errno == ENXIO) { + close(master_fd); return 0; /* doesn't still exist */ + } fatal("Couldn't attach to interface unit %d: %m\n", ifnum); } if (ioctl(ppp_fd, PPPIOCCONNECT, &ifnum) < 0) fatal("Couldn't connect to interface unit %d: %m", ifnum); - set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) | SC_MULTILINK); + modify_flags(master_fd, 0, SC_MULTILINK); + close(master_fd); ifunit = ifnum; return 1; @@ -946,6 +1013,7 @@ void output (int unit, unsigned char *p, int len) int proto; dump_packet("sent", p, len); + if (snoop_send_hook) snoop_send_hook(p, len); if (len < PPP_HDRLEN) return; @@ -953,7 +1021,7 @@ void output (int unit, unsigned char *p, int len) p += 2; len -= 2; proto = (p[0] << 8) + p[1]; - if (ifunit >= 0 && !(proto >= 0xc000 || proto == PPP_CCPFRAG)) + if (ppp_dev_fd >= 0 && !(proto >= 0xc000 || proto == PPP_CCPFRAG)) fd = ppp_dev_fd; } if (write(fd, p, len) < 0) { @@ -989,6 +1057,8 @@ void wait_input(struct timeval *timo) */ void add_fd(int fd) { + if (fd >= FD_SETSIZE) + fatal("internal error: file descriptor too large (%d)", fd); FD_SET(fd, &in_fds); if (fd > max_in_fd) max_in_fd = fd; @@ -1026,7 +1096,7 @@ int read_packet (unsigned char *buf) if (nr < 0 && errno == ENXIO) return 0; } - if (nr < 0 && new_style_driver && ifunit >= 0) { + if (nr < 0 && new_style_driver && ppp_dev_fd >= 0) { /* N.B. we read ppp_fd first since LCP packets come in there. */ nr = read(ppp_dev_fd, buf, len); if (nr < 0 && errno != EWOULDBLOCK && errno != EIO && errno != EINTR) @@ -1087,34 +1157,47 @@ netif_set_mtu(int unit, int mtu) error("ioctl(SIOCSIFMTU): %m (line %d)", __LINE__); } +/* + * netif_get_mtu - get the MTU on the PPP network interface. + */ +int +netif_get_mtu(int unit) +{ + struct ifreq ifr; + + memset (&ifr, '\0', sizeof (ifr)); + strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); + + if (ifunit >= 0 && ioctl(sock_fd, SIOCGIFMTU, (caddr_t) &ifr) < 0) { + error("ioctl(SIOCGIFMTU): %m (line %d)", __LINE__); + return 0; + } + return ifr.ifr_mtu; +} + /******************************************************************** * * tty_send_config - configure the transmit characteristics of * the ppp interface. */ -void tty_send_config (int mtu,u_int32_t asyncmap,int pcomp,int accomp) +void tty_send_config(int mtu, u_int32_t asyncmap, int pcomp, int accomp) { - u_int x; + int x; -/* - * Set the asyncmap and other parameters for the ppp device - */ - if (!still_ppp()) - return; - link_mtu = mtu; - SYSDEBUG ((LOG_DEBUG, "send_config: asyncmap = %lx\n", asyncmap)); - if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) { - if (!ok_error(errno)) - fatal("ioctl(PPPIOCSASYNCMAP): %m (line %d)", __LINE__); - return; - } + if (!still_ppp()) + return; + link_mtu = mtu; + if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) { + if (errno != EIO && errno != ENOTTY) + error("Couldn't set transmit async character map: %m"); + ++error_count; + return; + } - x = get_flags(ppp_fd); - x = pcomp ? x | SC_COMP_PROT : x & ~SC_COMP_PROT; - x = accomp ? x | SC_COMP_AC : x & ~SC_COMP_AC; - x = sync_serial ? x | SC_SYNC : x & ~SC_SYNC; - set_flags(ppp_fd, x); + x = (pcomp? SC_COMP_PROT: 0) | (accomp? SC_COMP_AC: 0) + | (sync_serial? SC_SYNC: 0); + modify_flags(ppp_fd, SC_COMP_PROT|SC_COMP_AC|SC_SYNC, x); } /******************************************************************** @@ -1141,31 +1224,29 @@ void tty_set_xaccm (ext_accm accm) * the ppp interface. */ -void tty_recv_config (int mru,u_int32_t asyncmap,int pcomp,int accomp) +void tty_recv_config(int mru, u_int32_t asyncmap, int pcomp, int accomp) { - SYSDEBUG ((LOG_DEBUG, "recv_config: mru = %d\n", mru)); /* * If we were called because the link has gone down then there is nothing * which may be done. Just return without incident. */ - if (!still_ppp()) - return; + if (!still_ppp()) + return; /* * Set the receiver parameters */ - if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) { - if ( ! ok_error (errno)) - error("ioctl(PPPIOCSMRU): %m (line %d)", __LINE__); - } - if (new_style_driver && ifunit >= 0 - && ioctl(ppp_dev_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) - error("Couldn't set MRU in generic PPP layer: %m"); + if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) { + if (errno != EIO && errno != ENOTTY) + error("Couldn't set channel receive MRU: %m"); + } + if (new_style_driver && ppp_dev_fd >= 0 + && ioctl(ppp_dev_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) + error("Couldn't set MRU in generic PPP layer: %m"); - SYSDEBUG ((LOG_DEBUG, "recv_config: asyncmap = %lx\n", asyncmap)); - if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) { - if (!ok_error(errno)) - error("ioctl(PPPIOCSRASYNCMAP): %m (line %d)", __LINE__); - } + if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) { + if (errno != EIO && errno != ENOTTY) + error("Couldn't set channel receive asyncmap: %m"); + } } /******************************************************************** @@ -1174,7 +1255,8 @@ void tty_recv_config (int mru,u_int32_t asyncmap,int pcomp,int accomp) * is acceptable for use. */ -int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit) +int +ccp_test(int unit, u_char *opt_ptr, int opt_len, int for_transmit) { struct ppp_option_data data; @@ -1196,12 +1278,11 @@ int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit) void ccp_flags_set (int unit, int isopen, int isup) { - if (still_ppp() && ifunit >= 0) { - int x = get_flags(ppp_dev_fd); - x = isopen? x | SC_CCP_OPEN : x &~ SC_CCP_OPEN; - x = isup? x | SC_CCP_UP : x &~ SC_CCP_UP; - set_flags (ppp_dev_fd, x); - } + int x; + + x = (isopen? SC_CCP_OPEN: 0) | (isup? SC_CCP_UP: 0); + if (still_ppp() && ppp_dev_fd >= 0) + modify_flags(ppp_dev_fd, SC_CCP_OPEN|SC_CCP_UP, x); } #ifdef PPP_FILTER @@ -1278,9 +1359,13 @@ get_ppp_stats(u, stats) int ccp_fatal_error (int unit) { - int x = get_flags(ppp_dev_fd); + int flags; - return x & SC_DC_FERROR; + if (ioctl(ppp_dev_fd, PPPIOCGFLAGS, &flags) < 0) { + error("Couldn't read compression error flags: %m"); + flags = 0; + } + return flags & SC_DC_FERROR; } /******************************************************************** @@ -1512,6 +1597,8 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway) SET_SA_FAMILY (rt.rt_dst, AF_INET); SET_SA_FAMILY (rt.rt_gateway, AF_INET); + rt.rt_dev = ifname; + if (kernel_version > KVERSION(2,1,0)) { SET_SA_FAMILY (rt.rt_genmask, AF_INET); SIN_ADDR(rt.rt_genmask) = 0L; @@ -2142,21 +2229,18 @@ void logwtmp (const char *line, const char *name, const char *host) int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid) { - u_int x = get_flags(ppp_dev_fd); + u_int x; - if (vjcomp) { - if (ioctl (ppp_dev_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) { - if (! ok_error (errno)) - error("ioctl(PPPIOCSMAXCID): %m (line %d)", __LINE__); - vjcomp = 0; + if (vjcomp) { + if (ioctl(ppp_dev_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) + error("Couldn't set up TCP header compression: %m"); + vjcomp = 0; } - } - x = vjcomp ? x | SC_COMP_TCP : x &~ SC_COMP_TCP; - x = cidcomp ? x & ~SC_NO_TCP_CCID : x | SC_NO_TCP_CCID; - set_flags (ppp_dev_fd, x); + x = (vjcomp? SC_COMP_TCP: 0) | (cidcomp? 0: SC_NO_TCP_CCID); + modify_flags(ppp_dev_fd, SC_COMP_TCP|SC_NO_TCP_CCID, x); - return 1; + return 1; } /******************************************************************** @@ -2553,7 +2637,7 @@ open_ppp_loopback(void) /* allocate ourselves a ppp unit */ if (make_ppp_unit() < 0) die(1); - set_flags(ppp_dev_fd, SC_LOOP_TRAFFIC); + modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC); set_kdebugflag(kdebugflag); ppp_fd = -1; return ppp_dev_fd; @@ -2756,3 +2840,51 @@ sys_check_options(void) } return 1; } + +#ifdef INET6 +/* + * ether_to_eui64 - Convert 48-bit Ethernet address into 64-bit EUI + * + * convert the 48-bit MAC address of eth0 into EUI 64. caller also assumes + * that the system has a properly configured Ethernet interface for this + * function to return non-zero. + */ +int +ether_to_eui64(eui64_t *p_eui64) +{ + struct ifreq ifr; + int skfd; + const unsigned char *ptr; + + skfd = socket(PF_INET6, SOCK_DGRAM, 0); + if(skfd == -1) + { + warn("could not open IPv6 socket"); + return 0; + } + + strcpy(ifr.ifr_name, "eth0"); + if(ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) + { + close(skfd); + warn("could not obtain hardware address for eth0"); + return 0; + } + close(skfd); + + /* + * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1] + */ + ptr = ifr.ifr_hwaddr.sa_data; + p_eui64->e8[0] = ptr[0] | 0x02; + p_eui64->e8[1] = ptr[1]; + p_eui64->e8[2] = ptr[2]; + p_eui64->e8[3] = 0xFF; + p_eui64->e8[4] = 0xFE; + p_eui64->e8[5] = ptr[3]; + p_eui64->e8[6] = ptr[4]; + p_eui64->e8[7] = ptr[5]; + + return 1; +} +#endif