diff --git a/component/babeld/README.cygwin b/component/babeld/README.cygwin index 4eb8362deef154d4936a7d90fbd441cc46717085..143c710dd16742f039d4423c6fa0309d60400e1f 100644 --- a/component/babeld/README.cygwin +++ b/component/babeld/README.cygwin @@ -196,3 +196,6 @@ Notes format to specify interface index in the link local address: fe80::2ff:38ff:fed8:7d97%11 + +10. For ipv4, blackhole route doesn't work now. I can't find a simple + way to do it in the Windows. \ No newline at end of file diff --git a/component/babeld/cyginet.c b/component/babeld/cyginet.c index be4ef3ba57cc46316940b9c90a9a7871a3ff0c50..067f7b395717c1f4b7c48c77a371b762efd7af82 100644 --- a/component/babeld/cyginet.c +++ b/component/babeld/cyginet.c @@ -24,6 +24,7 @@ #include <stdio.h> #include <unistd.h> #include <wchar.h> +#include <assert.h> #define INSIDE_BABELD_CYGINET #include "cyginet.h" @@ -861,7 +862,6 @@ cyginet_blackhole_index(struct in6_addr* addr6, char * addr) } FREE(pAdaptAddr); } - return dwReturn; } @@ -958,8 +958,7 @@ libwinet_edit_route_entry(const struct sockaddr *dest, /* Add ipv4 route before Windows Vista, use IP Helper API */ else { MIB_IPFORWARDROW Row; - unsigned long Res; - + unsigned long Res; struct in_addr mask; plen2mask(plen, &mask); @@ -972,12 +971,12 @@ libwinet_edit_route_entry(const struct sockaddr *dest, Row.dwForwardMask = mask.S_un.S_addr; /* * MIB_IPROUTE_TYPE_DIRECT <==> dwForwardNextHop == dwForwardDest - * MIB_IPROUTE_TYPE_LOCAL <==> dwForwardNextHop in local interfaces * MIB_IPROUTE_TYPE_INDIRECT all the others + * Refer to: + * http://technet.microsoft.com/en-us/library/dd379495(v=ws.10).aspx */ - Row.dwForwardType = Row.dwForwardNextHop == Row.dwForwardDest ? \ - MIB_IPROUTE_TYPE_DIRECT : MIB_IPROUTE_TYPE_INDIRECT; - Row.dwForwardType = MIB_IPROUTE_TYPE_INDIRECT; + Row.dwForwardType = (Row.dwForwardNextHop == Row.dwForwardDest) ? + MIB_IPROUTE_TYPE_DIRECT : MIB_IPROUTE_TYPE_INDIRECT; Row.dwForwardProto = MIB_IPPROTO_NETMGMT; Row.dwForwardAge = 0; Row.dwForwardNextHopAS = 0; @@ -1004,7 +1003,7 @@ libwinet_edit_route_entry(const struct sockaddr *dest, return -1; } -#if 0 /* Use route command */ +#if 0 /* Use route command */ else { /* route ADD dest MASK mask gate METRIC n IF index */ /* route CHANGE dest MASK mask gate METRIC n IF index */ @@ -1533,7 +1532,6 @@ cyginet_dump_route_table(struct cyginet_route *routes, int maxroutes) proute -> metric = pRow -> dwForwardMetric1; proute -> proto = pRow -> dwForwardProto; proute -> plen = mask2len((unsigned char*)&(pRow -> dwForwardMask), 4); - /* Note that the IPv4 addresses returned in GetIpForwardTable * entries are in network byte order */ @@ -1629,7 +1627,7 @@ cyginet_read_route_socket(void *buffer, size_t size) return 0; } -int +int cyginet_refresh_interface_table() { return libwinet_refresh_interface_map_table(); @@ -1685,37 +1683,102 @@ cyginet_ifname(const char * guidname) return NULL; } -int -cyginet_add_ipentry(int ifindex, struct sockaddr *addr) +static int +libwinet_edit_netentry(int operation, + int ifindex, + struct sockaddr *addr, + int type) { - MIB_IPNETROW row; - PLIBWINET_INTERFACE_MAP_TABLE p; - if (!g_interface_map_table) - libwinet_refresh_interface_map_table(); - - p = g_interface_map_table; - while (p) { - if (p -> IfIndex == ifindex) { - row.dwPhysAddrLen = p -> PhysicalAddressLength; - if (row.dwPhysAddrLen > MAXLEN_PHYSADDR) + MIB_IPNETROW row = {0}; + DWORD dwRetVal = NO_ERROR; + DWORD dest = (((SOCKADDR_IN*)addr) -> sin_addr).S_un.S_addr; + + if (operation == 1) { + /* We need send an arp request to get mac address */ + /* TO DO: src should be address assigned to ifindex */ + DWORD src = 0; + if (type != MIB_IPNET_TYPE_INVALID) { + dwRetVal = SendARP(dest, src, (PULONG)row.bPhysAddr, &row.dwPhysAddrLen); + if (dwRetVal != NO_ERROR) return -1; - memcpy(row.bPhysAddr, p -> PhysicalAddress, row.dwPhysAddrLen); - break; } - p = p -> next; + row.dwIndex = ifindex; + row.dwAddr = dest; + row.dwType = MIB_IPNET_TYPE_DYNAMIC; + dwRetVal = CreateIpNetEntry ( &row ); } - if (row.dwPhysAddrLen) { - row.dwIndex = ifindex; - row.dwAddr = (((SOCKADDR_IN*)addr) -> sin_addr).S_un.S_addr; - row.dwType = MIB_IPNET_TYPE_DYNAMIC; - return CreateIpNetEntry ( &row ); + else if (operation == 0) { + row.dwIndex = ifindex; + row.dwAddr = dest; + dwRetVal = DeleteIpNetEntry(&row); } - return -1; + else assert(0); + + return 0 ? dwRetVal == NO_ERROR : dwRetVal; } /* The following functions are reserved. */ #if 0 +int +cyginet_search_netentry(int add, int ifindex, struct sockaddr *addr) +{ + MIB_IPNETROW row = {0}; + MIB_IPNETTABLE * ptable; + MIB_IPNETROW * prow = NULL; + DWORD dwSize; + DWORD dwRetVal = NO_ERROR; + DWORD dest = (((SOCKADDR_IN*)addr) -> sin_addr).S_un.S_addr; + DWORD n; + + ptable = (MIB_IPNETTABLE *) MALLOC(sizeof (MIB_IPNETTABLE)); + if (ptable == NULL) + return -1; + /* Make an initial call to get the necessary size into dwSize */ + dwSize = sizeof (MIB_IPNETTABLE); + if (GetIpNetTable(ptable, &dwSize, FALSE) == ERROR_INSUFFICIENT_BUFFER) { + FREE(ptable); + ptable = (MIB_IPNETTABLE *) MALLOC(dwSize); + if (ptable == NULL) + return -1; + } + /* Make a second call to get the actual data we want. */ + if ((dwRetVal = GetIpNetTable(ptable, &dwSize, FALSE)) != NO_ERROR) { + FREE(ptable); + return -1; + } + + /* Search entry in the table */ + prow = ptable -> table; + for (n = 0; n < ptable -> dwNumEntries; n++, prow++) + if ( prow -> dwAddr == dest) + break; + + if (add) { + if (!prow) { + /* We need send an arp request to get mac address */ + /* TO DO: src should be address assigned to ifindex */ + DWORD src = 0; + dwRetVal = SendARP(dest, src, (PULONG)row.bPhysAddr, &row.dwPhysAddrLen); + if (dwRetVal != NO_ERROR) { + FREE(ptable); + return -1; + } + row.dwIndex = ifindex; + row.dwAddr = dest; + row.dwType = MIB_IPNET_TYPE_DYNAMIC; + dwRetVal = CreateIpNetEntry ( &row ); + } + } + else { + if (prow) + dwRetVal = DeleteIpNetEntry(prow); + } + + FREE(ptable); + return 0 ? dwRetVal == NO_ERROR : dwRetVal; +} + char * cyginet_ipv4_index2ifname(int ifindex) { @@ -2432,52 +2495,6 @@ DWORD GetConnectedNetworks() /* ------------------------------------------------------------- */ #ifdef TEST_CYGINET -// The following #defines are from routprot.h in the Platform Software Develoment Kit (SDK) -#define PROTO_TYPE_UCAST 0 -#define PROTOCOL_ID(Type, VendorId, ProtocolId) \ - (((Type & 0x03)<<30)|((VendorId & 0x3FFF)<<16)|(ProtocolId & 0xFFFF)) -#define PROTO_VENDOR_ID 0x3FAA - -DWORD (WINAPI * fRtmRegisterEntity)(PRTM_ENTITY_INFO,PRTM_ENTITY_EXPORT_METHODS, - RTM_EVENT_CALLBACK,WINBOOL,PRTM_REGN_PROFILE,PRTM_ENTITY_HANDLE); -DWORD (WINAPI * fRtmDeregisterEntity)(RTM_ENTITY_HANDLE); - -int test_rtm2() -{ - HMODULE lib; - if ((lib = LoadLibraryW(L"rtm.dll"))) { - fRtmRegisterEntity = GetProcAddress(lib, (LPCSTR)"RtmRegisterEntity"); - fRtmDeregisterEntity = GetProcAddress(lib, (LPCSTR)"RtmDeregisterEntity"); - FreeLibrary(lib); - } - else - return -1; - - RTM_ENTITY_HANDLE RtmRegHandle; - RTM_ENTITY_INFO EntityInfo; - RTM_REGN_PROFILE RegnProfile; - DWORD dwRet = ERROR_SUCCESS; - - EntityInfo.RtmInstanceId = 0; - EntityInfo.AddressFamily = AF_INET; - EntityInfo.EntityId.EntityProtocolId = PROTO_IP_OTHER; - EntityInfo.EntityId.EntityInstanceId = PROTOCOL_ID(PROTO_TYPE_UCAST, PROTO_VENDOR_ID, PROTO_IP_OTHER); - - // Register the new entity - dwRet = fRtmRegisterEntity(&EntityInfo, NULL, NULL, FALSE, &RegnProfile, &RtmRegHandle); - if (dwRet != ERROR_SUCCESS){ - // Registration failed - Log an Error and Quit - return -1; - } - // Clean-up: Deregister the new entity - dwRet = fRtmDeregisterEntity(RtmRegHandle); - if (dwRet != ERROR_SUCCESS){ - // Registration failed - Log an Error and Quit - return -1; - } - return 0; -} - VOID PrintAllInterfaces() { IP_ADAPTER_ADDRESSES *pAdaptAddr = NULL; @@ -2755,6 +2772,15 @@ runTestCases() } } + printf("\n\nTest cyginet_dump_route_table:\n\n"); + do { + #define MAX_ROUTES 120 + 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); + printf("\n\nTest libwinet_monitor_route_thread_proc:\n\n"); do { int mypipes[2]; @@ -2923,6 +2949,7 @@ runTestCases() printf("Delete Ipv6 route return %d\n", n); } while(0); + } int main(int argc, char* argv[]) @@ -2976,6 +3003,27 @@ int main(int argc, char* argv[]) printf("libwinet_refresh_interface_map_table failed\n"); } + printf("\n\nTest ipv4 blackhole route:\n\n"); + do { + SOCKADDR_IN dest = { AF_INET, 0, {{{ INADDR_ANY }}}, {0} }; + SOCKADDR_IN gate = { AF_INET, 0, {{{ INADDR_ANY }}}, {0} }; + int ifindex = 1; + int n; + + if (inet_pton(AF_INET, "123.58.180.0", &dest.sin_addr) != 1) + break; + if (inet_pton(AF_INET, "127.0.0.1", &gate.sin_addr) != 1) + break; + n = libwinet_edit_route_entry((struct sockaddr*)&dest, + 24, + (struct sockaddr*)&gate, + ifindex, + 1, + RTM_ADD + ); + printf("Add blackhole route return: %d", n); + } while(0); + runTestCases(); /* printf("\n\nTest libwinet_init_ipv6_interface:\n\n"); */ diff --git a/component/babeld/cyginet.h b/component/babeld/cyginet.h index 9a8bf8b62cb10c7cc27d14eb21e78f148bfd7693..6c15fc83fba99d3b56a07480b87027387bcf727e 100755 --- a/component/babeld/cyginet.h +++ b/component/babeld/cyginet.h @@ -90,6 +90,10 @@ IPv6 Addresses, it explains the relation between link-local address and interface id http://msdn.microsoft.com/en-us/library/aa921042.aspx + + TCP/IP (v4 and v6) Technical Reference, it shows ipv4 and ipv6 how + to work in the windows. (Recommended) + http://technet.microsoft.com/en-us/library/dd379473(v=ws.10).aspx */ #ifndef __CYGIFNET_H__ @@ -220,8 +224,6 @@ int cyginet_delete_route_entry(const struct sockaddr *, unsigned short, int cyginet_update_route_entry(const struct sockaddr *, unsigned short, const struct sockaddr *, int , unsigned int); -int cyginet_add_ipentry(int, struct sockaddr*); - char * cyginet_ifname(const char *); char * cyginet_guidname(const char *); int cyginet_refresh_interface_table(); diff --git a/component/babeld/kernel_cygwin.c b/component/babeld/kernel_cygwin.c index 06102cc252be06d279863e6af66a9dd0adb32951..135c66986f6c652288716d284d50af9f38fd4574 100644 --- a/component/babeld/kernel_cygwin.c +++ b/component/babeld/kernel_cygwin.c @@ -116,7 +116,7 @@ static int kernel_pipe_handles[2]; * * For ipv6, no global options to enable forwarding, but for each * interface respectively. - * + * * Option 2: * * ICMPV6CTL_REDIRACCEPT @@ -140,7 +140,7 @@ static int kernel_pipe_handles[2]; * Refer to: * http://technet.microsoft.com/en-us/library/cc766102(v=ws.10).aspx * http://msdn.microsoft.com/en-us/library/aa915651.aspx - * + * * Notice the msdn page of Windows CE, value is "EnableICMPRedirects", * it's plural. But I'd rather use singluar form "EnableICMPRedirect". * @@ -158,7 +158,7 @@ kernel_setup(int setup) return -1; /* We don't disable ICMPv6 redirect in the Windows */ - /* + /* if ((rc = cyginet_set_icmp6_redirect_accept(0)) == -1) { fprintf(stderr, "Cannot disable ICMPv6 redirect.\n"); return -1; @@ -171,7 +171,7 @@ kernel_setup(int setup) ); return -1; } - */ + */ FOR_ALL_INTERFACES(ifp) { if (cyginet_set_interface_forwards(ifp->name, 1) == -1) { fprintf(stderr, "Cannot enable IPv6 forwarding.\n"); @@ -305,8 +305,10 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen, const unsigned char *newgate, int newifindex, unsigned int newmetric) { - char blackhole_addr6[1][1][16] = {{{0}}}; - char blackhole_addr[1][1][16] = {{{0}}}; + char local6[1][1][16] = {{IN6ADDR_ANY_INIT}}; + char local4[1][1][16] = + {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01 }}}; int rc, ipv4; int route_ifindex; int prefix_len; @@ -353,8 +355,6 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen, IN6_IS_ADDR_UNSPECIFIED(newgate)) return 0; - - kdebugf("kernel_route: %s %s/%d metric %d dev %d nexthop %s\n", operation == ROUTE_ADD ? "add" : operation == ROUTE_FLUSH ? "flush" : "change", @@ -390,27 +390,30 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen, if(ipv4) { PUSHADDR(destination, dest); - if (metric == KERNEL_INFINITY) - PUSHADDR(gateway, **blackhole_addr); + if (metric == KERNEL_INFINITY) { + /* blackhole route, now it doesn't work */ + kdebugf("Error: ipv4 blackhole route doesn't work.\n"); + return -1; + assert (operation != ROUTE_MODIFY); + PUSHADDR(gateway, **local4); + } else if(plen == 128 && memcmp(dest+12, gate+12, 4) == 0) { - /* It means add arp record, add dest ip to this interface */ - if (cyginet_add_ipentry(ifindex, - (struct sockaddr*)&destination) != 0) - return -1; + assert (operation != ROUTE_MODIFY); + PUSHADDR(gateway, gate); /* MIB_IPROUTE_TYPE_DIRECT */ } else - PUSHADDR(gateway, gate); + PUSHADDR(gateway, gate); /* MIB_IPROUTE_TYPE_INDIRECT */ } else { PUSHADDR6(destination, dest); if (metric == KERNEL_INFINITY) - PUSHADDR6(gateway, **blackhole_addr6); - else + PUSHADDR6(gateway, **local6); + else PUSHADDR6(gateway, gate); } #undef PUSHADDR #undef PUSHADDR6 - /* what if route_ifindex == 0 */ + /* what if route_ifindex == 0 */ switch(operation) { case ROUTE_FLUSH: rc = cyginet_delete_route_entry((struct sockaddr*)&destination, @@ -465,7 +468,7 @@ print_kernel_route(int add, struct kernel_route *route) ifname ? ifname : "unk", route->ifindex ); -} +} static int parse_kernel_route(struct cyginet_route *src, struct kernel_route *route) @@ -619,7 +622,7 @@ kernel_addresses(char *ifname, int ifindex, int ll, memcpy(routes[i].prefix, v4prefix, 12); memcpy(routes[i].prefix + 12, &sin->sin_addr, 4); routes[i].plen = 128; - routes[i].metric = 0; + routes[i].metric = 0; routes[i].ifindex = ifindex; routes[i].proto = RTPROT_BABEL_LOCAL; memset(routes[i].gw, 0, 16); @@ -643,7 +646,7 @@ kernel_callback(int (*fn)(int, void*), void *closure) kdebugf("Kernel table changed.\n"); cyginet_refresh_interface_table(); clear_kernel_socket_event(); - + return fn(~0, closure); }