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}
...@@ -202,9 +202,8 @@ libwinet_run_command(const char *command) ...@@ -202,9 +202,8 @@ libwinet_run_command(const char *command)
* Gateway could be an address or interface name. * Gateway could be an address or interface name.
* *
*/ */
static int static int
libwinet_dump_ipv6_route_table(struct kernel_route *routes, libwinet_dump_ipv6_route_table(struct cyginet_route *routes,
int maxroutes) int maxroutes)
{ {
#define MAX_LINE_SIZE 80 #define MAX_LINE_SIZE 80
...@@ -216,13 +215,19 @@ libwinet_dump_ipv6_route_table(struct kernel_route *routes, ...@@ -216,13 +215,19 @@ libwinet_dump_ipv6_route_table(struct kernel_route *routes,
int count = 0; int count = 0;
int ignored = 0; int ignored = 0;
IN6_ADDR *sin6; struct sockaddr_in6 *dest;
struct kernel_route * proute = routes; struct sockaddr_in6 *gate;
struct cyginet_route route;
struct cyginet_route * proute = routes;
output = popen (command, "r"); output = popen (command, "r");
if (!output) if (!output)
return -1; return -1;
dest = (struct sockaddr_in6*)&(route.prefix);
gate = (struct sockaddr_in6*)&(route.gateway);
/* Ignore the first line */ /* Ignore the first line */
fgets(buffer, MAX_LINE_SIZE, output); fgets(buffer, MAX_LINE_SIZE, output);
...@@ -240,41 +245,43 @@ libwinet_dump_ipv6_route_table(struct kernel_route *routes, ...@@ -240,41 +245,43 @@ libwinet_dump_ipv6_route_table(struct kernel_route *routes,
/* The first field of route entry */ /* The first field of route entry */
if (strncmp(buffer, "Prefix", 6) == 0) { if (strncmp(buffer, "Prefix", 6) == 0) {
sin6 = (IN6_ADDR*)&(proute -> prefix);
memset(&route, 0, sizeof(struct cyginet_route));
if (NULL == (p = strchr(s, '/'))) if (NULL == (p = strchr(s, '/')))
break; break;
*p ++ = 0; *p ++ = 0;
/* /*
* Maybe it will be "fe80::5efe:10.85.0.127", ignore it * Maybe it will be "fe80::5efe:10.85.0.127", ignore it
*/ */
if (inet_pton(AF_INET6, s, sin6) != 1) if (inet_pton(AF_INET6, s, &(dest -> sin6_addr)) != 1)
ignored = 1; ignored = 1;
proute -> plen = strtol(p, NULL, 10); dest -> sin6_family = AF_INET6;
route.plen = strtol(p, NULL, 10);
} }
else if (strncmp(buffer, "Interface", 9) == 0) else if (strncmp(buffer, "Interface", 9) == 0)
proute -> ifindex = strtol(buffer + 9, NULL, 10); route.ifindex = strtol(buffer + 9, NULL, 10);
else if (strncmp(buffer, "Gateway", 7) == 0) { else if (strncmp(buffer, "Gateway", 7) == 0) {
sin6 = (IN6_ADDR*)&(proute -> gw); if (inet_pton(AF_INET6, s, &(gate -> sin6_addr)) == 1)
if (inet_pton(AF_INET6, s, sin6) != 1) gate -> sin6_family = AF_INET6;
memset(sin6, 0, sizeof(IN6_ADDR));
} }
else if (strncmp(buffer, "Metric", 6) == 0) else if (strncmp(buffer, "Metric", 6) == 0)
proute -> metric = strtol(s, NULL, 10); route.metric = strtol(s, NULL, 10);
/* Last field of the route entry */ /* Last field of the route entry */
else if (strncmp(buffer, "Site Prefix Length", 18) == 0) { else if (strncmp(buffer, "Site Prefix Length", 18) == 0) {
if (ignored) if (ignored)
ignored = 0; ignored = 0;
else if (!ignored) { else if (!ignored) {
proute -> proto = MIB_IPPROTO_OTHER; /* ?? */ route.proto = MIB_IPPROTO_OTHER; /* ?? */
count ++; if ((maxroutes > count) && (proute != NULL)) {
memcpy(proute, &route, sizeof(struct cyginet_route));
proute ++; proute ++;
if (count > maxroutes) }
break; count ++;
} }
} }
...@@ -1015,31 +1022,6 @@ cyginet_loopback_index(int family) ...@@ -1015,31 +1022,6 @@ cyginet_loopback_index(int family)
return libwinet_get_loopback_index(family); return libwinet_get_loopback_index(family);
} }
static PMIB_IPFORWARDTABLE
libwinet_get_ipforward_table(int forder)
{
DWORD dwSize = 0;
PMIB_IPFORWARDTABLE pIpForwardTable;
pIpForwardTable = (PMIB_IPFORWARDTABLE)MALLOC(sizeof(MIB_IPFORWARDTABLE));
if (NULL == pIpForwardTable)
return NULL;
if (ERROR_INSUFFICIENT_BUFFER == GetIpForwardTable(pIpForwardTable,
&dwSize,
forder
)) {
FREE(pIpForwardTable);
pIpForwardTable = (PMIB_IPFORWARDTABLE) MALLOC(dwSize);
if (pIpForwardTable == NULL)
return NULL;
}
if (NO_ERROR == GetIpForwardTable(pIpForwardTable,
&dwSize,
forder))
return pIpForwardTable;
return NULL;
}
/* /*
* There are 3 ways to dump route table in the Windows: * There are 3 ways to dump route table in the Windows:
* *
...@@ -1057,11 +1039,11 @@ libwinet_get_ipforward_table(int forder) ...@@ -1057,11 +1039,11 @@ libwinet_get_ipforward_table(int forder)
* *
*/ */
int int
cyginet_dump_route_table(struct kernel_route *routes, int maxroutes) cyginet_dump_route_table(struct cyginet_route *routes, int maxroutes)
{ {
ULONG NumEntries = -1; ULONG NumEntries = -1;
struct kernel_route *proute; struct cyginet_route *proute;
int i; int i;
#if _WIN32_WINNT < _WIN32_WINNT_VISTA #if _WIN32_WINNT < _WIN32_WINNT_VISTA
...@@ -1076,21 +1058,38 @@ cyginet_dump_route_table(struct kernel_route *routes, int maxroutes) ...@@ -1076,21 +1058,38 @@ cyginet_dump_route_table(struct kernel_route *routes, int maxroutes)
SOCKADDR_IN * paddr; SOCKADDR_IN * paddr;
PMIB_IPFORWARDTABLE pIpForwardTable; PMIB_IPFORWARDTABLE pIpForwardTable;
PMIB_IPFORWARDROW pRow; PMIB_IPFORWARDROW pRow;
if (NULL == (pIpForwardTable = libwinet_get_ipforward_table(0))) DWORD dwSize = sizeof(MIB_IPFORWARDTABLE);
pIpForwardTable = (PMIB_IPFORWARDTABLE)MALLOC(dwSize);
if (NULL == pIpForwardTable)
return -1;
if (ERROR_INSUFFICIENT_BUFFER == GetIpForwardTable(pIpForwardTable,
&dwSize,
0
)) {
FREE(pIpForwardTable);
pIpForwardTable = (PMIB_IPFORWARDTABLE) MALLOC(dwSize);
if (pIpForwardTable == NULL)
return -1;
}
if (NO_ERROR != GetIpForwardTable(pIpForwardTable,
&dwSize,
0))
return -1; return -1;
{
proute = routes + NumEntries; proute = routes + NumEntries;
NumEntries += pIpForwardTable->dwNumEntries; NumEntries += pIpForwardTable->dwNumEntries;
if (NumEntries > maxroutes) { if ((routes == NULL) || (NumEntries > maxroutes)) {
FREE(pIpForwardTable); FREE(pIpForwardTable);
return -1; return NumEntries;
} }
pRow = pIpForwardTable->table; pRow = pIpForwardTable->table;
for (i = 0; for (i = 0;
i < (int) pIpForwardTable->dwNumEntries; i < (int) pIpForwardTable->dwNumEntries;
i++, proute ++, pRow ++) { i++, proute ++, pRow ++) {
/* libwinet_map_ifindex_to_ipv6ifindex */ /* libwinet_map_ifindex_to_ipv6ifindex */
proute -> ifindex = pRow -> dwForwardIfIndex; proute -> ifindex = pRow -> dwForwardIfIndex;
proute -> metric = pRow -> dwForwardMetric1; proute -> metric = pRow -> dwForwardMetric1;
...@@ -1100,16 +1099,15 @@ cyginet_dump_route_table(struct kernel_route *routes, int maxroutes) ...@@ -1100,16 +1099,15 @@ cyginet_dump_route_table(struct kernel_route *routes, int maxroutes)
/* Note that the IPv4 addresses returned in GetIpForwardTable /* Note that the IPv4 addresses returned in GetIpForwardTable
* entries are in network byte order * entries are in network byte order
*/ */
paddr = (SOCKADDR_IN*)proute -> prefix; paddr = (struct sockaddr_in*)&(proute -> prefix);
paddr -> sin_family = AF_INET; paddr -> sin_family = AF_INET;
(paddr -> sin_addr).S_un.S_addr = pRow -> dwForwardDest; (paddr -> sin_addr).S_un.S_addr = pRow -> dwForwardDest;
paddr = (SOCKADDR_IN*)proute -> gw; paddr = (struct sockaddr_in*)&(proute -> gateway);
paddr -> sin_family = AF_INET; paddr -> sin_family = AF_INET;
(paddr -> sin_addr).S_un.S_addr = pRow -> dwForwardNextHop; (paddr -> sin_addr).S_un.S_addr = pRow -> dwForwardNextHop;
} }
FREE(pIpForwardTable); FREE(pIpForwardTable);
}
#else #else
PMIB_IPFORWARD_TABLE2 pIpForwardTable2; PMIB_IPFORWARD_TABLE2 pIpForwardTable2;
...@@ -1120,9 +1118,13 @@ cyginet_dump_route_table(struct kernel_route *routes, int maxroutes) ...@@ -1120,9 +1118,13 @@ cyginet_dump_route_table(struct kernel_route *routes, int maxroutes)
pIpForwardTable2 pIpForwardTable2
0)) { 0)) {
if (pIpForwardTable2 -> NumEntries < maxroutes) { NumEntries = pIpForwardTable2->dwNumEntries;
if ((routes == NULL) || (NumEntries > maxroutes)) {
FreeMibTable(pIpForwardTable2);
return NumEntries;
}
proute = routes + NumEntries; proute = routes;
NumEntries = pIpForwardTable2->dwNumEntries; NumEntries = pIpForwardTable2->dwNumEntries;
pRow2 = pIpForwardTable2 -> Table; pRow2 = pIpForwardTable2 -> Table;
...@@ -1135,13 +1137,11 @@ cyginet_dump_route_table(struct kernel_route *routes, int maxroutes) ...@@ -1135,13 +1137,11 @@ cyginet_dump_route_table(struct kernel_route *routes, int maxroutes)
(pRow2 -> DestinationPrefix).DestinationPrefix, (pRow2 -> DestinationPrefix).DestinationPrefix,
sizeof(SOCKADDR_INET) sizeof(SOCKADDR_INET)
); );
memcpy(proute -> gw, memcpy(proute -> gateway,
pRow2 -> NextHop, pRow2 -> NextHop,
sizeof(SOCKADDR_INET) sizeof(SOCKADDR_INET)
); );
} }
}
FreeMibTable(pIpForwardTable2); FreeMibTable(pIpForwardTable2);
} }
#endif #endif
...@@ -1209,6 +1209,31 @@ void cyginet_cleanup() ...@@ -1209,6 +1209,31 @@ void cyginet_cleanup()
/* The following functions are reserved. */ /* The following functions are reserved. */
#if 0 #if 0
static PMIB_IPFORWARDTABLE
libwinet_get_ipforward_table(int forder)
{
DWORD dwSize = sizeof(MIB_IPFORWARDTABLE);
PMIB_IPFORWARDTABLE pIpForwardTable;
pIpForwardTable = (PMIB_IPFORWARDTABLE)MALLOC(dwSize);
if (NULL == pIpForwardTable)
return NULL;
if (ERROR_INSUFFICIENT_BUFFER == GetIpForwardTable(pIpForwardTable,
&dwSize,
forder
)) {
FREE(pIpForwardTable);
pIpForwardTable = (PMIB_IPFORWARDTABLE) MALLOC(dwSize);
if (pIpForwardTable == NULL)
return NULL;
}
if (NO_ERROR == GetIpForwardTable(pIpForwardTable,
&dwSize,
forder))
return pIpForwardTable;
return NULL;
}
static int static int
convert_ipv6_route_table2() convert_ipv6_route_table2()
{ {
...@@ -1969,8 +1994,8 @@ runTestCases() ...@@ -1969,8 +1994,8 @@ runTestCases()
printf("\n\nTest libwinet_dump_ipv6_route_table:\n\n"); printf("\n\nTest libwinet_dump_ipv6_route_table:\n\n");
{ {
struct kernel_route routes[100]; struct cyginet_route routes[100];
memset(routes, 0, sizeof(struct kernel_route) * 100); memset(routes, 0, sizeof(struct cyginet_route) * 100);
int n = libwinet_dump_ipv6_route_table(routes, 100); int n = libwinet_dump_ipv6_route_table(routes, 100);
printf("Get route numbers: %d\n", n); printf("Get route numbers: %d\n", n);
} }
...@@ -2182,8 +2207,8 @@ runTestCases() ...@@ -2182,8 +2207,8 @@ runTestCases()
printf("\n\nTest cyginet_dump_route_table:\n\n"); printf("\n\nTest cyginet_dump_route_table:\n\n");
do { do {
#define MAX_ROUTES 120 #define MAX_ROUTES 120
struct kernel_route routes[MAX_ROUTES]; struct cyginet_route routes[MAX_ROUTES];
memset(routes, 0, sizeof(struct kernel_route) * MAX_ROUTES); memset(routes, 0, sizeof(struct cyginet_route) * MAX_ROUTES);
int n = cyginet_dump_route_table(routes, MAX_ROUTES); int n = cyginet_dump_route_table(routes, MAX_ROUTES);
printf("Get route numbers: %d\n", n); printf("Get route numbers: %d\n", n);
} while (0); } while (0);
......
...@@ -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,
......
...@@ -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);
...@@ -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 * pdest = proute;
memset(routes, 0, sizeof(struct kernel_route) * maxroutes); struct kernel_route * proute = routes;
struct cyginet_route * ptable;
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;
count = 0; rc = cyginet_dump_route_table(ptable, rc);
for (i = 0; i < rc; i++, proute++) { if (rc < 0) {
free(ptable);
return -1;
}
if (parse_kernel_route(proute) != 0) for (i = 0, count = 0; i < rc; i++) {
continue;
if (proute != pdest) if (parse_kernel_route(ptable + i, proute) != 0)
memcpy(pdest, proute, sizeof(struct kernel_route)); continue;
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