From da525eb2e7be828a240c72655fa8827f6d74329b Mon Sep 17 00:00:00 2001 From: Hajimu UMEMOTO Date: Sun, 12 Nov 2006 17:36:58 +0000 Subject: [PATCH] Teach an IPV6CP to pppd(8). The eui64.[ch] and ipv6cp.[ch] were taken from ppp-2.3.11. However, our stock pppd(8) doesn't provide option_t nor some utility functions. So, I made some hacks to adjust to our stock pppd(8). The sys_bsd.c part was taken from NetBSD with some modifications to adjust to our stock pppd(8). MFC after: 1 week --- usr.sbin/pppd/Makefile | 5 ++ usr.sbin/pppd/eui64.c | 6 ++ usr.sbin/pppd/ipv6cp.c | 99 ++++++----------------------- usr.sbin/pppd/ipv6cp.h | 3 + usr.sbin/pppd/main.c | 6 ++ usr.sbin/pppd/options.c | 113 +++++++++++++++++++++++++++++++++ usr.sbin/pppd/pathnames.h | 5 ++ usr.sbin/pppd/pppd.8 | 49 +++++++++++++- usr.sbin/pppd/pppd.h | 16 +++++ usr.sbin/pppd/sys-bsd.c | 130 +++++++++++++++++++++++++++++++++++++- 10 files changed, 351 insertions(+), 81 deletions(-) diff --git a/usr.sbin/pppd/Makefile b/usr.sbin/pppd/Makefile index 3a09d271a720..2df0330337cd 100644 --- a/usr.sbin/pppd/Makefile +++ b/usr.sbin/pppd/Makefile @@ -39,6 +39,11 @@ LDADD+= -lcrypto DPADD+= ${LIBCRYPTO} .endif +.if ${MK_INET6_SUPPORT} != "no" +CFLAGS+=-DINET6 +SRCS+= eui64.c ipv6cp.c +.endif + .if defined(RELEASE_CRUNCH) # We must create these objects because crunchgen will link them, # and we don't want any unused symbols to spoil the final link. diff --git a/usr.sbin/pppd/eui64.c b/usr.sbin/pppd/eui64.c index a59186d8d565..28335a3797ff 100644 --- a/usr.sbin/pppd/eui64.c +++ b/usr.sbin/pppd/eui64.c @@ -18,11 +18,17 @@ $Id: eui64.c,v 1.3 1999/08/25 04:15:51 paulus Exp $ */ +#ifndef lint #define RCSID "$Id: eui64.c,v 1.3 1999/08/25 04:15:51 paulus Exp $" +#endif +#include +__FBSDID("$FreeBSD$"); #include "pppd.h" +#ifdef RCSID static const char rcsid[] = RCSID; +#endif /* * eui64_ntoa - Make an ascii representation of an interface identifier diff --git a/usr.sbin/pppd/ipv6cp.c b/usr.sbin/pppd/ipv6cp.c index 326ff65d572c..0be6dc4e116e 100644 --- a/usr.sbin/pppd/ipv6cp.c +++ b/usr.sbin/pppd/ipv6cp.c @@ -93,7 +93,11 @@ * $Id: ipv6cp.c,v 1.7 1999/10/08 01:08:18 masputra Exp $ */ +#ifndef lint #define RCSID "$Id: ipv6cp.c,v 1.7 1999/10/08 01:08:18 masputra Exp $" +#endif +#include +__FBSDID("$FreeBSD$"); /* * TODO: @@ -107,6 +111,7 @@ #include #include +#include #include #include #include @@ -122,7 +127,11 @@ #include "magic.h" #include "pathnames.h" +#define s6_addr32 __u6_addr.__u6_addr32 + +#ifdef RCSID static const char rcsid[] = RCSID; +#endif /* global vars */ ipv6cp_options ipv6cp_wantoptions[NUM_PPP]; /* Options that we want to request */ @@ -168,41 +177,6 @@ static fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */ "IPV6CP" /* String name of protocol */ }; -/* - * Command-line options. - */ -static int setifaceid __P((char **arg)); - -static option_t ipv6cp_option_list[] = { - { "ipv6", o_special, setifaceid, - "Set interface identifiers for IPV6" }, - { "noipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Disable IPv6 and IPv6CP" }, - { "-ipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Disable IPv6 and IPv6CP" }, - { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Enable IPv6 and IPv6CP", 1 }, - - { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local, - "Accept peer's interface identifier for us", 1 }, - { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip, - "Use (default) IPv4 address as interface identifier", 0 }, -#if defined(SOL2) - { "ipv6cp-use-persistent", o_bool, &ipv6cp_wantoptions[0].use_persistent, - "Use uniquely-available persistent value for link local address", 1 }, -#endif /* defined(SOL2) */ - { "ipv6cp-restart", o_int, &ipv6cp_fsm[0].timeouttime, - "Set timeout for IPv6CP" }, - { "ipv6cp-max-terminate", o_int, &ipv6cp_fsm[0].maxtermtransmits, - "Set max #xmits for term-reqs" }, - { "ipv6cp-max-configure", o_int, &ipv6cp_fsm[0].maxconfreqtransmits, - "Set max #xmits for conf-reqs" }, - { "ipv6cp-max-failure", o_int, &ipv6cp_fsm[0].maxnakloops, - "Set max #conf-naks for IPv6CP" }, - - { NULL } -}; - /* * Protocol entry points from main code. @@ -233,8 +207,6 @@ struct protent ipv6cp_protent = { NULL, 0, "IPV6CP", - "IPV6", - ipv6cp_option_list, ipv6_check_options, ipv6_demand_conf, ipv6_active_pkt @@ -242,7 +214,6 @@ struct protent ipv6cp_protent = { static void ipv6cp_clear_addrs __P((int, eui64_t, eui64_t)); static void ipv6cp_script __P((char *)); -static void ipv6cp_script_done __P((void *)); /* * Lengths of configuration options. @@ -262,12 +233,11 @@ static enum script_state { s_down, s_up, } ipv6cp_script_state; -static pid_t ipv6cp_script_pid; /* * setifaceid - set the interface identifiers manually */ -static int +int setifaceid(argv) char **argv; { @@ -1069,9 +1039,9 @@ ipv6_demand_conf(u) if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE)) return 0; - notice("ipv6_demand_conf"); - notice("local LL address %s", llv6_ntoa(wo->ourid)); - notice("remote LL address %s", llv6_ntoa(wo->hisid)); + syslog(LOG_NOTICE, "ipv6_demand_conf"); + syslog(LOG_NOTICE, "local LL address %s", llv6_ntoa(wo->ourid)); + syslog(LOG_NOTICE, "remote LL address %s", llv6_ntoa(wo->hisid)); return 1; } @@ -1100,17 +1070,17 @@ ipv6cp_up(f) if(!no_ifaceid_neg) { if (eui64_iszero(ho->hisid)) { - error("Could not determine remote LL address"); + syslog(LOG_ERR, "Could not determine remote LL address"); ipv6cp_close(f->unit, "Could not determine remote LL address"); return; } if (eui64_iszero(go->ourid)) { - error("Could not determine local LL address"); + syslog(LOG_ERR, "Could not determine local LL address"); ipv6cp_close(f->unit, "Could not determine local LL address"); return; } if (eui64_equals(go->ourid, ho->hisid)) { - error("local and remote LL addresses are equal"); + syslog(LOG_ERR, "local and remote LL addresses are equal"); ipv6cp_close(f->unit, "local and remote LL addresses are equal"); return; } @@ -1191,8 +1161,8 @@ ipv6cp_up(f) #endif sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS); - notice("local LL address %s", llv6_ntoa(go->ourid)); - notice("remote LL address %s", llv6_ntoa(ho->hisid)); + syslog(LOG_NOTICE, "local LL address %s", llv6_ntoa(go->ourid)); + syslog(LOG_NOTICE, "remote LL address %s", llv6_ntoa(ho->hisid)); } np_up(f->unit, PPP_IPV6); @@ -1202,7 +1172,7 @@ ipv6cp_up(f) * Execute the ipv6-up script, like this: * /etc/ppp/ipv6-up interface tty speed local-LL remote-LL */ - if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) { + if (ipv6cp_script_state == s_down) { ipv6cp_script_state = s_up; ipv6cp_script(_PATH_IPV6UP); } @@ -1220,7 +1190,6 @@ ipv6cp_down(f) fsm *f; { IPV6CPDEBUG(("ipv6cp: down")); - update_link_stats(f->unit); if (ipv6cp_is_up) { ipv6cp_is_up = 0; np_down(f->unit, PPP_IPV6); @@ -1253,7 +1222,7 @@ ipv6cp_down(f) } /* Execute the ipv6-down script */ - if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) { + if (ipv6cp_script_state == s_up) { ipv6cp_script_state = s_down; ipv6cp_script(_PATH_IPV6DOWN); } @@ -1285,32 +1254,6 @@ ipv6cp_finished(f) } -/* - * ipv6cp_script_done - called when the ipv6-up or ipv6-down script - * has finished. - */ -static void -ipv6cp_script_done(arg) - void *arg; -{ - ipv6cp_script_pid = 0; - switch (ipv6cp_script_state) { - case s_up: - if (ipv6cp_fsm[0].state != OPENED) { - ipv6cp_script_state = s_down; - ipv6cp_script(_PATH_IPV6DOWN); - } - break; - case s_down: - if (ipv6cp_fsm[0].state == OPENED) { - ipv6cp_script_state = s_up; - ipv6cp_script(_PATH_IPV6UP); - } - break; - } -} - - /* * ipv6cp_script - Execute a script with arguments * interface-name tty-name speed local-LL remote-LL. @@ -1335,7 +1278,7 @@ ipv6cp_script(script) argv[6] = ipparam; argv[7] = NULL; - ipv6cp_script_pid = run_program(script, argv, 0, ipv6cp_script_done, NULL); + run_program(script, argv, 0); } /* diff --git a/usr.sbin/pppd/ipv6cp.h b/usr.sbin/pppd/ipv6cp.h index d800d5d5da4b..2641008e99ad 100644 --- a/usr.sbin/pppd/ipv6cp.h +++ b/usr.sbin/pppd/ipv6cp.h @@ -91,6 +91,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * $Id: ipv6cp.h,v 1.3 1999/09/30 19:57:45 masputra Exp $ + * $FreeBSD$ */ /* @@ -124,3 +125,5 @@ extern ipv6cp_options ipv6cp_allowoptions[]; extern ipv6cp_options ipv6cp_hisoptions[]; extern struct protent ipv6cp_protent; + +extern int setifaceid __P((char **arg)); diff --git a/usr.sbin/pppd/main.c b/usr.sbin/pppd/main.c index c2d0abfbc3c4..7bb104dde65a 100644 --- a/usr.sbin/pppd/main.c +++ b/usr.sbin/pppd/main.c @@ -46,6 +46,9 @@ static char rcsid[] = "$FreeBSD$"; #include "fsm.h" #include "lcp.h" #include "ipcp.h" +#ifdef INET6 +#include "ipv6cp.h" +#endif #include "upap.h" #include "chap.h" #include "ccp.h" @@ -152,6 +155,9 @@ struct protent *protocols[] = { &cbcp_protent, #endif &ipcp_protent, +#ifdef INET6 + &ipv6cp_protent, +#endif &ccp_protent, #ifdef IPX_CHANGE &ipxcp_protent, diff --git a/usr.sbin/pppd/options.c b/usr.sbin/pppd/options.c index d1e679b2aa43..00ad006ef4d1 100644 --- a/usr.sbin/pppd/options.c +++ b/usr.sbin/pppd/options.c @@ -55,6 +55,10 @@ static char rcsid[] = "$FreeBSD$"; #include "cbcp.h" #endif +#ifdef INET6 +#include "ipv6cp.h" +#endif + #ifdef IPX_CHANGE #include "ipxcp.h" #endif /* IPX_CHANGE */ @@ -227,6 +231,7 @@ static int setpapcrypt __P((char **)); static int setidle __P((char **)); static int setholdoff __P((char **)); static int setdnsaddr __P((char **)); +static int resetipv6proto __P((char **)); static int resetipxproto __P((char **)); static int setwinsaddr __P((char **)); static int showversion __P((char **)); @@ -238,6 +243,19 @@ static int setpassfilter __P((char **)); static int setactivefilter __P((char **)); #endif +#ifdef INET6 +static int setipv6cp_accept_local __P((char **)); +static int setipv6cp_use_ip __P((char **)); +#if defined(SOL2) +static int setipv6cp_use_persistent __P((char **)); +#endif +static int setipv6cptimeout __P((char **)); +static int setipv6cpterm __P((char **)); +static int setipv6cpconf __P((char **)); +static int setipv6cpfails __P((char **)); +static int setipv6proto __P((char **)); +#endif /* INET6 */ + #ifdef IPX_CHANGE static int setipxproto __P((char **)); static int setipxanet __P((char **)); @@ -388,6 +406,8 @@ static struct cmd { /* end compat hack */ {"ms-dns", 1, setdnsaddr}, /* DNS address for the peer's use */ {"ms-wins", 1, setwinsaddr}, /* Nameserver for SMB over TCP/IP for peer */ + {"noipv6", 0, resetipv6proto}, /* Disable IPv6 and IPv6CP */ + {"-ipv6", 0, resetipv6proto}, /* Disable IPv6 and IPv6CP */ {"noipx", 0, resetipxproto}, /* Disable IPXCP (and IPX) */ {"-ipx", 0, resetipxproto}, /* Disable IPXCP (and IPX) */ {"--version", 0, showversion}, /* Show version number */ @@ -400,6 +420,20 @@ static struct cmd { {"active-filter", 1, setactivefilter}, /* set filter for active pkts */ #endif +#ifdef INET6 + {"ipv6", 1, setifaceid}, /* Set interface id for IPV6" */ + {"+ipv6", 0, setipv6proto}, /* Enable IPv6 and IPv6CP */ + {"ipv6cp-accept-local", 0, setipv6cp_accept_local}, /* Accept peer's iface id for us */ + {"ipv6cp-use-ipaddr", 0, setipv6cp_use_ip}, /* Use IPv4 addr as iface id */ +#if defined(SOL2) + {"ipv6cp-use-persistent", 0, setipv6cp_use_persistent}, /* Use uniquely-available persistent value for link local addr */ +#endif + {"ipv6cp-restart", 1, setipv6cptimeout}, /* Set timeout for IPv6CP */ + {"ipv6cp-max-terminate", 1, setipv6cpterm}, /* max #xmits for term-reqs */ + {"ipv6cp-max-configure", 1, setipv6cpconf}, /* max #xmits for conf-reqs */ + {"ipv6cp-max-failure", 1, setipv6cpfails}, /* max #conf-naks for IPv6CP */ +#endif + #ifdef IPX_CHANGE {"ipx-network", 1, setipxnetwork}, /* IPX network number */ {"ipxcp-accept-network", 0, setipxanet}, /* Accept peer netowrk */ @@ -2374,6 +2408,85 @@ setwinsaddr(argv) return (1); } +#ifdef INET6 +static int +setipv6cp_accept_local(argv) + char **argv; +{ + ipv6cp_allowoptions[0].accept_local = 1; + return 1; +} + +static int +setipv6cp_use_ip(argv) + char **argv; +{ + ipv6cp_allowoptions[0].use_ip = 1; + return 1; +} + +#if defined(SOL2) +static int +setipv6cp_use_persistent(argv) + char **argv; +{ + ipv6cp_wantoptions[0].use_persistent = 1; + return 1; +} +#endif + +static int +setipv6cptimeout(argv) + char **argv; +{ + return int_option(*argv, &ipv6cp_fsm[0].timeouttime); +} + +static int +setipv6cpterm(argv) + char **argv; +{ + return int_option(*argv, &ipv6cp_fsm[0].maxtermtransmits); +} + +static int +setipv6cpconf(argv) + char **argv; +{ + return int_option(*argv, &ipv6cp_fsm[0].maxconfreqtransmits); +} + +static int +setipv6cpfails(argv) + char **argv; +{ + return int_option(*argv, &ipv6cp_fsm[0].maxnakloops); +} + +static int +setipv6proto(argv) + char **argv; +{ + ipv6cp_protent.enabled_flag = 1; + return 1; +} + +static int +resetipv6proto(argv) + char **argv; +{ + ipv6cp_protent.enabled_flag = 0; + return 1; +} +#else +static int +resetipv6proto(argv) + char **argv; +{ + return 1; +} +#endif /* INET6 */ + #ifdef IPX_CHANGE static int setipxrouter (argv) diff --git a/usr.sbin/pppd/pathnames.h b/usr.sbin/pppd/pathnames.h index 147ae38ab40f..5d09b0b2fa18 100644 --- a/usr.sbin/pppd/pathnames.h +++ b/usr.sbin/pppd/pathnames.h @@ -26,6 +26,11 @@ #define _PATH_PPPDENY "/etc/ppp/ppp.deny" #define _PATH_PPPSHELLS "/etc/ppp/ppp.shells" +#ifdef INET6 +#define _PATH_IPV6UP "/etc/ppp/ipv6-up" +#define _PATH_IPV6DOWN "/etc/ppp/ipv6-down" +#endif + #ifdef IPX_CHANGE #define _PATH_IPXUP "/etc/ppp/ipx-up" #define _PATH_IPXDOWN "/etc/ppp/ipx-down" diff --git a/usr.sbin/pppd/pppd.8 b/usr.sbin/pppd/pppd.8 index 6becff62cdfa..ba55f2119d1f 100644 --- a/usr.sbin/pppd/pppd.8 +++ b/usr.sbin/pppd/pppd.8 @@ -142,13 +142,14 @@ Pppd will ask the peer to send packets of no more than \fIn\fR bytes. The minimum MRU value is 128. The default MRU value is 1500. A value of 296 is recommended for slow links (40 bytes for TCP/IP header + 256 -bytes of data). +bytes of data). (Note that for IPv6 MRU must be at least 1280) .TP .B mtu \fIn Set the MTU [Maximum Transmit Unit] value to \fIn\fR. Unless the peer requests a smaller value via MRU negotiation, pppd will request that the kernel networking code send data packets of no more -than \fIn\fR bytes through the PPP network interface. +than \fIn\fR bytes through the PPP network interface. (Note that for +IPv6 MTU must be at least 1280) .TP .B passive Enables the "passive" option in the LCP. With this option, pppd will @@ -171,6 +172,17 @@ will not accept a different value from the peer in the IPCP negotiation, unless the \fIipcp-accept-local\fR and/or \fIipcp-accept-remote\fR options are given, respectively. .TP +.B ipv6 \fI\fR,\fI +Set the local and/or remote 64-bit interface identifier. Either one may be +omitted. The identifier must be specified in standard ascii notation of +IPv6 addresses (e.g. ::dead:beef). If the +\fIipv6cp-use-ipaddr\fR +option is given, the local identifier is the local IPv4 address (see above). +On systems which supports a unique persistent id, such as EUI-48 derived +from the Ethernet MAC address, \fIipv6cp-use-persistent\fR option can be +used to replace the \fIipv6 ,\fR option. Otherwise the +identifier is randomized. +.TP .B bsdcomp \fInr,nt Request that the peer compress packets that it sends, using the BSD-Compress scheme, with a maximum code size of \fInr\fR bits, and @@ -300,6 +312,22 @@ Provides an extra parameter to the ip-up and ip-down scripts. If this option is given, the \fIstring\fR supplied is given as the 6th parameter to those scripts. .TP +.B ipv6cp-max-configure \fIn +Set the maximum number of IPv6CP configure-request transmissions to +\fIn\fR (default 10). +.TP +.B ipv6cp-max-failure \fIn +Set the maximum number of IPv6CP configure-NAKs returned before starting +to send configure-Rejects instead to \fIn\fR (default 10). +.TP +.B ipv6cp-max-terminate \fIn +Set the maximum number of IPv6CP terminate-request transmissions to +\fIn\fR (default 3). +.TP +.B ipv6cp-restart \fIn +Set the IPv6CP restart interval (retransmission timeout) to \fIn\fR +seconds (default 3). +.TP .B ipx Enable the IPXCP and IPX protocols. This option is presently only supported under Linux, and only if your kernel has been configured to @@ -526,6 +554,11 @@ Disable IPCP negotiation and IP communication. This option should only be required if the peer is buggy and gets confused by requests from pppd for IPCP negotiation. .TP +.B noipv6 +Disable IPv6CP negotiation and IPv6 communication. This option should +only be required if the peer is buggy and gets confused by requests +from pppd for IPv6CP negotiation. +.TP .B noipdefault Disables the default behaviour when no local IP address is specified, which is to determine (if possible) the local IP address from the @@ -1063,6 +1096,18 @@ used for undoing the effects of the /etc/ppp/ip-up script. It is invoked in the same manner and with the same parameters as the ip-up script. .TP +.B /etc/ppp/ipv6-up +Like /etc/ppp/ip-up, except that it is executed when the link is available +for sending and receiving IPv6 packets. It is executed with the parameters +.IP +\fIinterface-name tty-device speed local-link-local-address +remote-link-local-address ipparam\fR +.TP +.B /etc/ppp/ipv6-down +Similar to /etc/ppp/ip-down, but it is executed when IPv6 packets can no +longer be transmitted on the link. It is executed with the same parameters +as the ipv6-up script. +.TP .B /etc/ppp/ipx-up A program or script which is executed when the link is available for sending and receiving IPX packets (that is, IPXCP has come up). It is diff --git a/usr.sbin/pppd/pppd.h b/usr.sbin/pppd/pppd.h index 248556d381e8..48e2eb01eacc 100644 --- a/usr.sbin/pppd/pppd.h +++ b/usr.sbin/pppd/pppd.h @@ -41,6 +41,10 @@ #define const #endif +#ifdef INET6 +#include "eui64.h" +#endif + /* * Limits. */ @@ -285,6 +289,12 @@ int sifaddr __P((int, u_int32_t, u_int32_t, u_int32_t)); /* Configure IP addresses for i/f */ int cifaddr __P((int, u_int32_t, u_int32_t)); /* Reset i/f IP addresses */ +#ifdef INET6 +int sif6addr __P((int, eui64_t, eui64_t)); + /* Configure IPv6 addresses for i/f */ +int cif6addr __P((int, eui64_t, eui64_t)); + /* Remove an IPv6 address from i/f */ +#endif int sifdefaultroute __P((int, u_int32_t, u_int32_t)); /* Create default route through i/f */ int cifdefaultroute __P((int, u_int32_t, u_int32_t)); @@ -457,6 +467,12 @@ extern struct option_info devnam_info; #define IPCPDEBUG(x) #endif +#ifdef DEBUGIPV6CP +#define IPV6CPDEBUG(x) if (debug) syslog x +#else +#define IPV6CPDEBUG(x) +#endif + #ifdef DEBUGUPAP #define UPAPDEBUG(x) if (debug) syslog x #else diff --git a/usr.sbin/pppd/sys-bsd.c b/usr.sbin/pppd/sys-bsd.c index 3ca43c0cb2ed..ccb13c8cc001 100644 --- a/usr.sbin/pppd/sys-bsd.c +++ b/usr.sbin/pppd/sys-bsd.c @@ -58,6 +58,10 @@ static char rcsid[] = "$FreeBSD$"; #include #include #include +#include +#include +#include +#include #ifdef IPX_CHANGE #include @@ -100,6 +104,9 @@ static char loop_name[20]; static unsigned char inbuf[512]; /* buffer for chars read from loopback */ static int sockfd; /* socket for doing interface ioctls */ +#ifdef INET6 +static int sock6_fd = -1; /* socket for doing ipv6 interface ioctls */ +#endif /* INET6 */ static int if_is_up; /* the interface is currently up */ static u_int32_t ifaddrs[2]; /* local and remote addresses we set */ @@ -122,6 +129,13 @@ sys_init() syslog(LOG_ERR, "Couldn't create IP socket: %m"); die(1); } + +#ifdef INET6 + if ((sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { + /* check it at runtime */ + sock6_fd = -1; + } +#endif } /* @@ -156,7 +170,12 @@ sys_cleanup() void sys_close() { - close(sockfd); + if (sockfd >= 0) + close(sockfd); +#ifdef INET6 + if (sock6_fd >= 0) + close(sock6_fd); +#endif if (loop_slave >= 0) { close(loop_slave); close(loop_master); @@ -476,6 +495,115 @@ int fd, on; ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); } +#ifdef INET6 +/* + * sif6addr - Config the interface with an IPv6 link-local address + */ +int +sif6addr(int unit, eui64_t our_eui64, eui64_t his_eui64) +{ + int ifindex; + struct in6_aliasreq addreq6; + + if (sock6_fd < 0) { + syslog(LOG_ERR, "No IPv6 socket available"); + die(1); + /*NOTREACHED*/ + } + + /* actually, this part is not kame local - RFC2553 conformant */ + ifindex = if_nametoindex(ifname); + if (ifindex == 0) { + syslog(LOG_ERR, "sifaddr6: no interface %s", ifname); + return 0; + } + + memset(&addreq6, 0, sizeof(addreq6)); + strlcpy(addreq6.ifra_name, ifname, sizeof(addreq6.ifra_name)); + + /* my addr */ + addreq6.ifra_addr.sin6_family = AF_INET6; + addreq6.ifra_addr.sin6_len = sizeof(struct sockaddr_in6); + addreq6.ifra_addr.sin6_addr.s6_addr[0] = 0xfe; + addreq6.ifra_addr.sin6_addr.s6_addr[1] = 0x80; + memcpy(&addreq6.ifra_addr.sin6_addr.s6_addr[8], &our_eui64, + sizeof(our_eui64)); + /* KAME ifindex hack */ + *(u_int16_t *)&addreq6.ifra_addr.sin6_addr.s6_addr[2] = htons(ifindex); + + /* his addr */ + addreq6.ifra_dstaddr.sin6_family = AF_INET6; + addreq6.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6); + addreq6.ifra_dstaddr.sin6_addr.s6_addr[0] = 0xfe; + addreq6.ifra_dstaddr.sin6_addr.s6_addr[1] = 0x80; + memcpy(&addreq6.ifra_dstaddr.sin6_addr.s6_addr[8], &his_eui64, + sizeof(our_eui64)); + /* KAME ifindex hack */ + *(u_int16_t *)&addreq6.ifra_dstaddr.sin6_addr.s6_addr[2] = htons(ifindex); + + /* prefix mask: 128bit */ + addreq6.ifra_prefixmask.sin6_family = AF_INET6; + addreq6.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6); + memset(&addreq6.ifra_prefixmask.sin6_addr, 0xff, + sizeof(addreq6.ifra_prefixmask.sin6_addr)); + + /* address lifetime (infty) */ + addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; + addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; + + if (ioctl(sock6_fd, SIOCAIFADDR_IN6, &addreq6) < 0) { + syslog(LOG_ERR, "sif6addr: ioctl(SIOCAIFADDR_IN6): %m"); + return 0; + } + + return 1; +} + + +/* + * cif6addr - Remove IPv6 address from interface + */ +int +cif6addr(int unit, eui64_t our_eui64, eui64_t his_eui64) +{ + int ifindex; + struct in6_ifreq delreq6; + + if (sock6_fd < 0) { + syslog(LOG_ERR, "No IPv6 socket available"); + die(1); + /*NOTREACHED*/ + } + + /* actually, this part is not kame local - RFC2553 conformant */ + ifindex = if_nametoindex(ifname); + if (ifindex == 0) { + syslog(LOG_ERR, "cifaddr6: no interface %s", ifname); + return 0; + } + + memset(&delreq6, 0, sizeof(delreq6)); + strlcpy(delreq6.ifr_name, ifname, sizeof(delreq6.ifr_name)); + + /* my addr */ + delreq6.ifr_ifru.ifru_addr.sin6_family = AF_INET6; + delreq6.ifr_ifru.ifru_addr.sin6_len = sizeof(struct sockaddr_in6); + delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[0] = 0xfe; + delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[1] = 0x80; + memcpy(&delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[8], &our_eui64, + sizeof(our_eui64)); + /* KAME ifindex hack */ + *(u_int16_t *)&delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[2] = + htons(ifindex); + + if (ioctl(sock6_fd, SIOCDIFADDR_IN6, &delreq6) < 0) { + syslog(LOG_ERR, "cif6addr: ioctl(SIOCDIFADDR_IN6): %m"); + return 0; + } + + return 1; +} +#endif /* INET6 */ /* * open_ppp_loopback - open the device we use for getting