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)
* Gateway could be an address or interface name.
*
*/
static int
libwinet_dump_ipv6_route_table(struct kernel_route *routes,
libwinet_dump_ipv6_route_table(struct cyginet_route *routes,
int maxroutes)
{
#define MAX_LINE_SIZE 80
......@@ -216,13 +215,19 @@ libwinet_dump_ipv6_route_table(struct kernel_route *routes,
int count = 0;
int ignored = 0;
IN6_ADDR *sin6;
struct kernel_route * proute = routes;
struct sockaddr_in6 *dest;
struct sockaddr_in6 *gate;
struct cyginet_route route;
struct cyginet_route * proute = routes;
output = popen (command, "r");
if (!output)
return -1;
dest = (struct sockaddr_in6*)&(route.prefix);
gate = (struct sockaddr_in6*)&(route.gateway);
/* Ignore the first line */
fgets(buffer, MAX_LINE_SIZE, output);
......@@ -240,41 +245,43 @@ libwinet_dump_ipv6_route_table(struct kernel_route *routes,
/* The first field of route entry */
if (strncmp(buffer, "Prefix", 6) == 0) {
sin6 = (IN6_ADDR*)&(proute -> prefix);
memset(&route, 0, sizeof(struct cyginet_route));
if (NULL == (p = strchr(s, '/')))
break;
*p ++ = 0;
/*
* 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;
proute -> plen = strtol(p, NULL, 10);
dest -> sin6_family = AF_INET6;
route.plen = strtol(p, NULL, 10);
}
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) {
sin6 = (IN6_ADDR*)&(proute -> gw);
if (inet_pton(AF_INET6, s, sin6) != 1)
memset(sin6, 0, sizeof(IN6_ADDR));
if (inet_pton(AF_INET6, s, &(gate -> sin6_addr)) == 1)
gate -> sin6_family = AF_INET6;
}
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 */
else if (strncmp(buffer, "Site Prefix Length", 18) == 0) {
if (ignored)
ignored = 0;
else if (!ignored) {
proute -> proto = MIB_IPPROTO_OTHER; /* ?? */
count ++;
route.proto = MIB_IPPROTO_OTHER; /* ?? */
if ((maxroutes > count) && (proute != NULL)) {
memcpy(proute, &route, sizeof(struct cyginet_route));
proute ++;
if (count > maxroutes)
break;
}
count ++;
}
}
......@@ -1015,31 +1022,6 @@ cyginet_loopback_index(int 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:
*
......@@ -1057,11 +1039,11 @@ libwinet_get_ipforward_table(int forder)
*
*/
int
cyginet_dump_route_table(struct kernel_route *routes, int maxroutes)
cyginet_dump_route_table(struct cyginet_route *routes, int maxroutes)
{
ULONG NumEntries = -1;
struct kernel_route *proute;
struct cyginet_route *proute;
int i;
#if _WIN32_WINNT < _WIN32_WINNT_VISTA
......@@ -1076,21 +1058,38 @@ cyginet_dump_route_table(struct kernel_route *routes, int maxroutes)
SOCKADDR_IN * paddr;
PMIB_IPFORWARDTABLE pIpForwardTable;
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;
{
proute = routes + NumEntries;
NumEntries += pIpForwardTable->dwNumEntries;
if (NumEntries > maxroutes) {
if ((routes == NULL) || (NumEntries > maxroutes)) {
FREE(pIpForwardTable);
return -1;
return NumEntries;
}
pRow = pIpForwardTable->table;
for (i = 0;
i < (int) pIpForwardTable->dwNumEntries;
i++, proute ++, pRow ++) {
/* libwinet_map_ifindex_to_ipv6ifindex */
proute -> ifindex = pRow -> dwForwardIfIndex;
proute -> metric = pRow -> dwForwardMetric1;
......@@ -1100,16 +1099,15 @@ cyginet_dump_route_table(struct kernel_route *routes, int maxroutes)
/* Note that the IPv4 addresses returned in GetIpForwardTable
* entries are in network byte order
*/
paddr = (SOCKADDR_IN*)proute -> prefix;
paddr = (struct sockaddr_in*)&(proute -> prefix);
paddr -> sin_family = AF_INET;
(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_addr).S_un.S_addr = pRow -> dwForwardNextHop;
}
FREE(pIpForwardTable);
}
#else
PMIB_IPFORWARD_TABLE2 pIpForwardTable2;
......@@ -1120,9 +1118,13 @@ cyginet_dump_route_table(struct kernel_route *routes, int maxroutes)
pIpForwardTable2
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;
pRow2 = pIpForwardTable2 -> Table;
......@@ -1135,13 +1137,11 @@ cyginet_dump_route_table(struct kernel_route *routes, int maxroutes)
(pRow2 -> DestinationPrefix).DestinationPrefix,
sizeof(SOCKADDR_INET)
);
memcpy(proute -> gw,
memcpy(proute -> gateway,
pRow2 -> NextHop,
sizeof(SOCKADDR_INET)
);
}
}
FreeMibTable(pIpForwardTable2);
}
#endif
......@@ -1209,6 +1209,31 @@ void cyginet_cleanup()
/* The following functions are reserved. */
#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
convert_ipv6_route_table2()
{
......@@ -1969,8 +1994,8 @@ runTestCases()
printf("\n\nTest libwinet_dump_ipv6_route_table:\n\n");
{
struct kernel_route routes[100];
memset(routes, 0, sizeof(struct kernel_route) * 100);
struct cyginet_route routes[100];
memset(routes, 0, sizeof(struct cyginet_route) * 100);
int n = libwinet_dump_ipv6_route_table(routes, 100);
printf("Get route numbers: %d\n", n);
}
......@@ -2182,8 +2207,8 @@ runTestCases()
printf("\n\nTest cyginet_dump_route_table:\n\n");
do {
#define MAX_ROUTES 120
struct kernel_route routes[MAX_ROUTES];
memset(routes, 0, sizeof(struct kernel_route) * MAX_ROUTES);
struct cyginet_route routes[MAX_ROUTES];
memset(routes, 0, sizeof(struct cyginet_route) * MAX_ROUTES);
int n = cyginet_dump_route_table(routes, MAX_ROUTES);
printf("Get route numbers: %d\n", n);
} while (0);
......
......@@ -75,20 +75,16 @@ struct sockaddr_dl {
contains both if name and ll address */
};
#if defined(INSIDE_CYGINET)
/* Copy from babeld/kernel.h */
#define RTPROT_BABEL_LOCAL -2
#define KERNEL_INFINITY 0xFFFF
struct kernel_route {
unsigned char prefix[16];
struct cyginet_route {
struct sockaddr prefix;
int plen;
int metric;
unsigned int ifindex;
int proto;
unsigned char gw[16];
struct sockaddr gateway;
};
/* End of Copy */
#if defined(INSIDE_CYGINET)
struct ifaddrs {
struct ifaddrs *ifa_next;
......@@ -156,7 +152,7 @@ int cyginet_interface_mtu(const char *, int);
int cyginet_interface_operational(const char *, int);
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_add_route_entry(const struct sockaddr *, unsigned short,
......
......@@ -519,7 +519,7 @@ print_kernel_route(int add, struct kernel_route *route)
}
static int
parse_kernel_route(struct kernel_route *route)
parse_kernel_route(struct cyginet_route *src, struct kernel_route *route)
{
struct sockaddr *sa;
......@@ -535,9 +535,16 @@ parse_kernel_route(struct kernel_route *route)
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) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
memcpy(route->prefix, &sin6->sin6_addr, 16);
if(IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
|| IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
return -1;
......@@ -555,9 +562,10 @@ parse_kernel_route(struct kernel_route *route)
}
/* Gateway */
sa = (struct sockaddr *)route -> gw;
sa = &(src -> gateway);
if(sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
memcpy(route->gw, &sin6->sin6_addr, 16);
if(IN6_IS_ADDR_LINKLOCAL (&sin6->sin6_addr)) {
route->ifindex = IN6_LINKLOCAL_IFINDEX(sin6->sin6_addr);
SET_IN6_LINKLOCAL_IFINDEX(sin6->sin6_addr, 0);
......@@ -583,30 +591,40 @@ kernel_routes(struct kernel_route *routes, int maxroutes)
{
int rc, i;
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)
return -1;
if (rc == 0)
return 0;
rc += 10;
if (NULL == (ptable = calloc(rc, sizeof(struct cyginet_route))))
return -1;
count = 0;
for (i = 0; i < rc; i++, proute++) {
rc = cyginet_dump_route_table(ptable, rc);
if (rc < 0) {
free(ptable);
return -1;
}
if (parse_kernel_route(proute) != 0)
continue;
for (i = 0, count = 0; i < rc; i++) {
if (proute != pdest)
memcpy(pdest, proute, sizeof(struct kernel_route));
if (parse_kernel_route(ptable + i, proute) != 0)
continue;
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
......
......@@ -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
THE SOFTWARE.
*/
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
......@@ -50,9 +49,11 @@ babel_socket(int port)
if(s < 0)
return -1;
#if !defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x0600
rc = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
if(rc < 0)
goto fail;
#endif
rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
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