Commit 7ca8acee authored by Jondy Zhao's avatar Jondy Zhao

Windows XP doesn't support IPV6_V6ONLY options (net.c)

Fix issues to get the route table.
Add README.cygwin
parent 5fe4e2ab
Introduction
============
Babeld for windows can work in the Cygwin 1.7 and later.
Changed files
-------------
Makefile
net.c
kernel.c
New files
---------
kernel_cygwin.c
cyginet.h
cyginet.c
README.cygwin
Building in the cygwin
======================
Required packages:
Cygwin 1.7
gcc 4.5.3 for cygwin
In the Windows XP,
$ PLATFORM_DEFINES="-D_WIN32_WINNT=0x0503" make
Later Windows Vista,
$ PLATFORM_DEFINES="-D_WIN32_WINNT=0x0600" make
Interface Names
===============
In the Windows, GUID is used as unique interface names. You can list
all the interfaces by the following command:
$ ipv6 if | grep "^Interface" -A 1
--
Interface 2: Automatic Tunneling Pseudo-Interface
Guid {48FCE3FC-EC30-E50E-F1A7-71172AEEE3AE}
--
Interface 1: Loopback Pseudo-Interface
Guid {6BD113CC-5EC2-7638-B953-0B889DA72014}
...
When call babled, use GUID as interface name:
$ ./babeld.exe {6BD113CC-5EC2-7638-B953-0B889DA72014}
This diff is collapsed.
...@@ -75,20 +75,16 @@ struct sockaddr_dl { ...@@ -75,20 +75,16 @@ struct sockaddr_dl {
contains both if name and ll address */ contains both if name and ll address */
}; };
#if defined(INSIDE_CYGINET) struct cyginet_route {
struct sockaddr prefix;
/* Copy from babeld/kernel.h */
#define RTPROT_BABEL_LOCAL -2
#define KERNEL_INFINITY 0xFFFF
struct kernel_route {
unsigned char prefix[16];
int plen; int plen;
int metric; int metric;
unsigned int ifindex; unsigned int ifindex;
int proto; int proto;
unsigned char gw[16]; struct sockaddr gateway;
}; };
/* End of Copy */
#if defined(INSIDE_CYGINET)
struct ifaddrs { struct ifaddrs {
struct ifaddrs *ifa_next; struct ifaddrs *ifa_next;
...@@ -156,7 +152,7 @@ int cyginet_interface_mtu(const char *, int); ...@@ -156,7 +152,7 @@ int cyginet_interface_mtu(const char *, int);
int cyginet_interface_operational(const char *, int); int cyginet_interface_operational(const char *, int);
int cyginet_interface_ipv4(const char *, int, unsigned char *); int cyginet_interface_ipv4(const char *, int, unsigned char *);
int cyginet_dump_route_table(struct kernel_route *, int); int cyginet_dump_route_table(struct cyginet_route *, int);
int cyginet_loopback_index(int); int cyginet_loopback_index(int);
int cyginet_add_route_entry(const struct sockaddr *, unsigned short, int cyginet_add_route_entry(const struct sockaddr *, unsigned short,
......
...@@ -59,7 +59,7 @@ THE SOFTWARE. ...@@ -59,7 +59,7 @@ THE SOFTWARE.
* 3. kernel_interface_ipv4 * 3. kernel_interface_ipv4
* *
* ? interface name, ipv4, ifindex, Oh, they're mass. * ? interface name, ipv4, ifindex, Oh, they're mass.
* *
*/ */
static int get_sdl(struct sockaddr_dl *sdl, char *ifname); static int get_sdl(struct sockaddr_dl *sdl, char *ifname);
...@@ -125,10 +125,10 @@ kernel_setup(int setup) ...@@ -125,10 +125,10 @@ kernel_setup(int setup)
int accept_redirects = 0; int accept_redirects = 0;
int reboot = 0; int reboot = 0;
/* It enables ip6.forwarding and disable ip6.redirect. /* It enables ip6.forwarding and disable ip6.redirect.
* *
* Option 1: * Option 1:
* *
* IPV6CTL_FORWARDING (ip6.forwarding) Boolean: enable/disable * IPV6CTL_FORWARDING (ip6.forwarding) Boolean: enable/disable
* forward- ing of IPv6 packets. Also, identify if the node is * forward- ing of IPv6 packets. Also, identify if the node is
* acting as a router. Defaults to off. * acting as a router. Defaults to off.
...@@ -136,7 +136,7 @@ kernel_setup(int setup) ...@@ -136,7 +136,7 @@ kernel_setup(int setup)
* ==> command line: * ==> command line:
* *
* C:/> ipv6 ifc $If6Index forwards * C:/> ipv6 ifc $If6Index forwards
* *
* repeat this operation for all ipv6 interfaces * repeat this operation for all ipv6 interfaces
* *
* List all ipv6 interface by the command: * List all ipv6 interface by the command:
...@@ -155,13 +155,13 @@ kernel_setup(int setup) ...@@ -155,13 +155,13 @@ kernel_setup(int setup)
* *
* A value of 1 enables TCP/IP forwarding for all network * A value of 1 enables TCP/IP forwarding for all network
* connections that are installed and used by this computer. * connections that are installed and used by this computer.
* *
* Refer to: http://support.microsoft.com/kb/315236/en-us * Refer to: http://support.microsoft.com/kb/315236/en-us
* *
* Option 2: * Option 2:
* *
* ICMPV6CTL_REDIRACCEPT * ICMPV6CTL_REDIRACCEPT
* *
* IPV6CTL_SENDREDIRECTS (ip6.redirect) Boolean: enable/disable * IPV6CTL_SENDREDIRECTS (ip6.redirect) Boolean: enable/disable
* sending of ICMPv6 redirects in response to unforwardable IPv6 * sending of ICMPv6 redirects in response to unforwardable IPv6
* packets. This option is ignored unless the node is routing * packets. This option is ignored unless the node is routing
...@@ -171,26 +171,26 @@ kernel_setup(int setup) ...@@ -171,26 +171,26 @@ kernel_setup(int setup)
* ==> MSDN says in the registry * ==> MSDN says in the registry
* *
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
* *
* EnableICMPRedirect = 0 * EnableICMPRedirect = 0
* *
* Refer to: * Refer to:
* *
* http://technet.microsoft.com/en-us/library/cc766102(v=ws.10).aspx * http://technet.microsoft.com/en-us/library/cc766102(v=ws.10).aspx
* *
* After change them, need to reboot machine. * After change them, need to reboot machine.
* *
* Notice: * Notice:
* *
* MSDN says nothing about ipv6, it should use the following key * MSDN says nothing about ipv6, it should use the following key
* *
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters
* *
* Maybe later Window VISTA its corresponding APIs are * Maybe later Window VISTA its corresponding APIs are
* WSAEnumProtocols, WSCUpdateProvider. * WSAEnumProtocols, WSCUpdateProvider.
* *
*/ */
if (setup) { if (setup) {
int flags; int flags;
if (0 != cyginet_startup()) if (0 != cyginet_startup())
...@@ -207,7 +207,7 @@ kernel_setup(int setup) ...@@ -207,7 +207,7 @@ kernel_setup(int setup)
if (reboot) if (reboot)
cyginet_set_ipv6_forwards(old_forwarding); cyginet_set_ipv6_forwards(old_forwarding);
return -1; return -1;
} }
old_accept_redirects = rc; old_accept_redirects = rc;
reboot = (rc == accept_redirects) ? reboot : 1; reboot = (rc == accept_redirects) ? reboot : 1;
if (pipe(kernel_pipe_handles) == -1) if (pipe(kernel_pipe_handles) == -1)
...@@ -226,12 +226,12 @@ kernel_setup(int setup) ...@@ -226,12 +226,12 @@ kernel_setup(int setup)
return -1; return -1;
reboot = (rc == accept_redirects) ? reboot : 1; reboot = (rc == accept_redirects) ? reboot : 1;
close(kernel_pipe_handles[0]); close(kernel_pipe_handles[0]);
close(kernel_pipe_handles[1]); close(kernel_pipe_handles[1]);
cyginet_cleanup(); cyginet_cleanup();
} }
if (reboot) if (reboot)
fprintf(stderr, fprintf(stderr,
"%s IPv6 forwarding and %s ICMPv6 redirect successfully.\n" "%s IPv6 forwarding and %s ICMPv6 redirect successfully.\n"
"REBOOT NOW, so that these changes take effect.\n\n", "REBOOT NOW, so that these changes take effect.\n\n",
forwarding ? "Enable" : "Disable", forwarding ? "Enable" : "Disable",
...@@ -280,7 +280,7 @@ kernel_interface_operational(const char *ifname, int ifindex) ...@@ -280,7 +280,7 @@ kernel_interface_operational(const char *ifname, int ifindex)
{ {
int rc; int rc;
int flags = link_detect ? (IFF_UP | IFF_RUNNING) : IFF_UP; int flags = link_detect ? (IFF_UP | IFF_RUNNING) : IFF_UP;
rc = cyginet_interface_operational(ifname, ifindex); rc = cyginet_interface_operational(ifname, ifindex);
if (rc < 0) if (rc < 0)
return -1; return -1;
...@@ -312,22 +312,22 @@ kernel_interface_channel(const char *ifname, int ifindex) ...@@ -312,22 +312,22 @@ kernel_interface_channel(const char *ifname, int ifindex)
return -1; return -1;
} }
/* /*
* RTF_REJECT * RTF_REJECT
* *
* Instead of forwarding a packet like a normal route, routes with * Instead of forwarding a packet like a normal route, routes with
* RTF_REJECT cause packets to be dropped and unreachable messages * RTF_REJECT cause packets to be dropped and unreachable messages
* to be sent to the packet originators. This flag is only valid on * to be sent to the packet originators. This flag is only valid on
* routes pointing at the loopback interface. * routes pointing at the loopback interface.
* *
* RTF_BLACKHOLE * RTF_BLACKHOLE
* *
* Like the RTF_REJECT flag, routes with RTF_BLACKHOLE cause packets * Like the RTF_REJECT flag, routes with RTF_BLACKHOLE cause packets
* to be dropped, but unreachable messages are not sent. This flag * to be dropped, but unreachable messages are not sent. This flag
* is only valid on routes pointing at the loopback interface. * is only valid on routes pointing at the loopback interface.
* *
* Nullrouting on Windows * Nullrouting on Windows
* *
* Windows XP/Vista/7 does not support reject or blackhole arguments * Windows XP/Vista/7 does not support reject or blackhole arguments
* via route, thus an unused IP address (e.g. 192.168.0.205) must be * via route, thus an unused IP address (e.g. 192.168.0.205) must be
* used as the target gateway. * used as the target gateway.
...@@ -336,12 +336,12 @@ kernel_interface_channel(const char *ifname, int ifindex) ...@@ -336,12 +336,12 @@ kernel_interface_channel(const char *ifname, int ifindex)
* *
* RTF_HOST: host entry (net otherwise) * RTF_HOST: host entry (net otherwise)
* *
* It means all the netmask bits are 1. * It means all the netmask bits are 1.
* *
* RTF_CLONING: generate new routes on use * RTF_CLONING: generate new routes on use
* *
* No corresponding function in the Windows. * No corresponding function in the Windows.
* *
*/ */
int int
kernel_route(int operation, const unsigned char *dest, unsigned short plen, kernel_route(int operation, const unsigned char *dest, unsigned short plen,
...@@ -374,7 +374,7 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen, ...@@ -374,7 +374,7 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
ipv4 = 0; ipv4 = 0;
} }
if(operation == ROUTE_MODIFY && newmetric == metric && if(operation == ROUTE_MODIFY && newmetric == metric &&
memcmp(newgate, gate, 16) == 0 && newifindex == ifindex) memcmp(newgate, gate, 16) == 0 && newifindex == ifindex)
return 0; return 0;
...@@ -443,20 +443,20 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen, ...@@ -443,20 +443,20 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
if(IN6_IS_ADDR_LINKLOCAL (&sin6->sin6_addr)) \ if(IN6_IS_ADDR_LINKLOCAL (&sin6->sin6_addr)) \
SET_IN6_LINKLOCAL_IFINDEX (sin6->sin6_addr, ifindex); \ SET_IN6_LINKLOCAL_IFINDEX (sin6->sin6_addr, ifindex); \
} while (0) } while (0)
if(ipv4) { if(ipv4) {
PUSHADDR(destination, dest); PUSHADDR(destination, dest);
if (metric == KERNEL_INFINITY) if (metric == KERNEL_INFINITY)
PUSHADDR(gateway, **local4); PUSHADDR(gateway, **local4);
else else
PUSHADDR(gateway, gate); PUSHADDR(gateway, gate);
} else { } else {
PUSHADDR6(destination, dest); PUSHADDR6(destination, dest);
if (metric == KERNEL_INFINITY) if (metric == KERNEL_INFINITY)
PUSHADDR6(gateway, &local6); PUSHADDR6(gateway, &local6);
else else
PUSHADDR6(gateway, gate); PUSHADDR6(gateway, gate);
} }
#undef PUSHADDR #undef PUSHADDR
...@@ -519,7 +519,7 @@ print_kernel_route(int add, struct kernel_route *route) ...@@ -519,7 +519,7 @@ print_kernel_route(int add, struct kernel_route *route)
} }
static int static int
parse_kernel_route(struct kernel_route *route) parse_kernel_route(struct cyginet_route *src, struct kernel_route *route)
{ {
struct sockaddr *sa; struct sockaddr *sa;
...@@ -535,9 +535,16 @@ parse_kernel_route(struct kernel_route *route) ...@@ -535,9 +535,16 @@ parse_kernel_route(struct kernel_route *route)
return -1; return -1;
} }
sa = (struct sockaddr *)route -> prefix; memset(route, 0, sizeof(struct kernel_route));
route -> plen = src -> plen;
route -> metric = src -> metric;
route -> proto = src -> proto;
route -> ifindex = src -> ifindex;
sa = &(src -> prefix);
if(sa->sa_family == AF_INET6) { if(sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
memcpy(route->prefix, &sin6->sin6_addr, 16);
if(IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) if(IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
|| IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) || IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
return -1; return -1;
...@@ -555,9 +562,10 @@ parse_kernel_route(struct kernel_route *route) ...@@ -555,9 +562,10 @@ parse_kernel_route(struct kernel_route *route)
} }
/* Gateway */ /* Gateway */
sa = (struct sockaddr *)route -> gw; sa = &(src -> gateway);
if(sa->sa_family == AF_INET6) { if(sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
memcpy(route->gw, &sin6->sin6_addr, 16);
if(IN6_IS_ADDR_LINKLOCAL (&sin6->sin6_addr)) { if(IN6_IS_ADDR_LINKLOCAL (&sin6->sin6_addr)) {
route->ifindex = IN6_LINKLOCAL_IFINDEX(sin6->sin6_addr); route->ifindex = IN6_LINKLOCAL_IFINDEX(sin6->sin6_addr);
SET_IN6_LINKLOCAL_IFINDEX(sin6->sin6_addr, 0); SET_IN6_LINKLOCAL_IFINDEX(sin6->sin6_addr, 0);
...@@ -567,7 +575,7 @@ parse_kernel_route(struct kernel_route *route) ...@@ -567,7 +575,7 @@ parse_kernel_route(struct kernel_route *route)
v4tov6(route->gw, (unsigned char *)&sin->sin_addr); v4tov6(route->gw, (unsigned char *)&sin->sin_addr);
} }
if((sa->sa_family == AF_INET6) && (route->ifindex == if6index_lo)) if((sa->sa_family == AF_INET6) && (route->ifindex == if6index_lo))
return -1; return -1;
if((sa->sa_family == AF_INET) && (route->ifindex == ifindex_lo)) if((sa->sa_family == AF_INET) && (route->ifindex == ifindex_lo))
return -1; return -1;
...@@ -583,30 +591,40 @@ kernel_routes(struct kernel_route *routes, int maxroutes) ...@@ -583,30 +591,40 @@ kernel_routes(struct kernel_route *routes, int maxroutes)
{ {
int rc, i; int rc, i;
int count; int count;
struct kernel_route * proute = routes; struct kernel_route * proute = routes;
struct kernel_route * pdest = proute; struct cyginet_route * ptable;
memset(routes, 0, sizeof(struct kernel_route) * maxroutes);
rc = cyginet_dump_route_table(routes, maxroutes); rc = cyginet_dump_route_table(NULL, 0);
if (rc < 0) if (rc < 0)
return -1; return -1;
if (rc == 0)
return 0;
rc += 10;
if (NULL == (ptable = calloc(rc, sizeof(struct cyginet_route))))
return -1;
rc = cyginet_dump_route_table(ptable, rc);
if (rc < 0) {
free(ptable);
return -1;
}
count = 0; for (i = 0, count = 0; i < rc; i++) {
for (i = 0; i < rc; i++, proute++) {
if (parse_kernel_route(proute) != 0) if (parse_kernel_route(ptable + i, proute) != 0)
continue; continue;
if (proute != pdest)
memcpy(pdest, proute, sizeof(struct kernel_route));
if(debug > 2) if(debug > 2)
print_kernel_route(RTM_ADD, pdest); print_kernel_route(RTM_ADD, proute);
pdest++; if (maxroutes > rc)
proute++;
count ++;
} }
return (pdest - routes); free(ptable);
return count;
} }
int int
......
...@@ -19,7 +19,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ...@@ -19,7 +19,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <fcntl.h> #include <fcntl.h>
...@@ -50,9 +49,11 @@ babel_socket(int port) ...@@ -50,9 +49,11 @@ babel_socket(int port)
if(s < 0) if(s < 0)
return -1; return -1;
#if !defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x0600
rc = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); rc = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
if(rc < 0) if(rc < 0)
goto fail; goto fail;
#endif
rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if(rc < 0) if(rc < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment