Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
slapos
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Thomas Leymonerie
slapos
Commits
582eb114
Commit
582eb114
authored
Apr 06, 2013
by
Jondy Zhao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use API other than route command to add route entry for ipv4;
Refine the code; List issues in the README.cygwin;
parent
055ff708
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
617 additions
and
440 deletions
+617
-440
component/babeld/Makefile
component/babeld/Makefile
+2
-2
component/babeld/README.cygwin
component/babeld/README.cygwin
+114
-10
component/babeld/cyginet.c
component/babeld/cyginet.c
+335
-241
component/babeld/cyginet.h
component/babeld/cyginet.h
+48
-11
component/babeld/kernel_cygwin.c
component/babeld/kernel_cygwin.c
+113
-176
component/babeld/net.c
component/babeld/net.c
+5
-0
No files found.
component/babeld/Makefile
View file @
582eb114
...
...
@@ -64,7 +64,7 @@ clean:
kernel.o
:
kernel_netlink.c kernel_socket.c kernel_cygwin.c
# Usage: ./test
c
.exe
# Usage: ./test.exe
# Verify most of the functions in the cyginet.c
test
c
.exe
:
cyginet.c
test.exe
:
cyginet.c
$(CC)
$(CFLAGS)
$(LDFLAGS)
-DTEST_CYGINET
-o
$@
$<
$(LDLIBS)
component/babeld/README.cygwin
View file @
582eb114
...
...
@@ -46,7 +46,97 @@ Control Panel -> Network Connections.
You should see all the connections like "Local Area Connection
3". Right click and rename this to something shorter and without
embedded spaces such as "my-tap".
embedded spaces such as "tap1".
Or
$ netsh interface set interface name = "Local Area Connection 3" newname="tap1"
Test babeld in the Cygwin
=========================
We need 2 laptops, a wireless router, one laptop connects the router
by wireless netcard, another is wired.
Both of laptops install Openvpn for cygwin, enable ipv6 forwarding on
each tap interface
Laptop A:
lan Disconnect
wlan 192.168.121.100/24
2001::A1 (manual)
tap ifindex = 11, ipv6 forwarding=enabled
10.100.0.1/24
fe80::2ff:38ff:fed8:7d97 (auto link addr)
Laptop B:
lan 192.168.121.21/24
2001::B1 (manual)
tap ifindex = 7, ipv6 forwarding=enabled
10.200.0.1/24
fe80::2ff:17ff:fee4:8ed0 (auto link addr)
Router R:
192.168.121.1/24
In the laptop A, run the following command:
# Start openvpn server
$ cd C:/Program Files/OpenVPN/server
$ ../bin/openvpn.exe --config server.ovpn
# Startup babeld
$ babeld.exe -d 3 -h 15 -H 15 -s wlan tap
# Assign ipv6 unicast address to interfaces
# netsh interface ipv6 add address wlan 2001:A1
# netsh interface ipv6 set interface tap forwarding=enabled
In the laptop B, run the following command:
# Start openvpn client
$ cd C:/Program Files/OpenVPN/client
$ ../bin/openvpn.exe --config client.ovpn
# Startup babeld
$ babeld.exe -d 3 -h 15 -H 15 -s lan tap1
# Assign ipv6 unicast address to interfaces
# netsh interface ipv6 add address lan 2001:B1
# netsh interface ipv6 set interface tap forwarding=enabled
Then ping6 to each other ,
In laptop A,
$ ping6 2001::B1
In laptop B,
$ ping6 2001::A1
It should work.
Check kernel route:
$ netsh interface ipv6 show route
Example output of A
Publish Type Met Prefix Idx Gateway/Interface Name
------- -------- ---- ------------------------ --- ---------------------
no Manual 0 ::/0 11 fe80::2ff:17ff:fee4:8ed0
Example output of B
Publish Type Met Prefix Idx Gateway/Interface Name
------- -------- ---- ------------------------ --- ---------------------
no Manual 0 ::/0 7 fe80::2ff:38ff:fed8:7d97
Notes
=====
...
...
@@ -66,22 +156,31 @@ Notes
5. Ipv6 option "IPV6_V6ONLY" only works in the Windows Vista later.
6. If one connection is assigned more than one ipv4 address, babeld
returns the first one only, is it right? I'm not sure.
returns the first one only to check whether ipv4 address changed,
is it right? I'm not sure.
7. Regarding IPV6CTL_FORWARDING and IPV6CTL_SENDREDIRECTS, MSDN says
that you can set both of options for Ipv4 in the registry:
"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters",
but says nothing for Ipv6. Does it work for ipv6 in the registry:
"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters"
?
that you can set both of options in the registry:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters
IPEnableRouter, DWORD
EnableICMPRedirect, DWORD
Refers to:
http://support.microsoft.com/kb/315236/en-us
http://technet.microsoft.com/en-us/library/cc766102(v=ws.10).aspx
http://msdn.microsoft.com/en-us/library/aa915651.aspx
For Ipv6, FORWARDING is set per interface, not global setting.
8. There is no RTM_BLACKHOLE, RTM_REJECT, NULLROUTE in the windows, in
the kernel_cygwin.c!kernel_route, we only use local address as
gateway in the BLACKHOLE route entry. Is it OK?
A: It's not OK actually
. In the Windows, you can't use 127.0.0.1 as
gateway when add route entry. So the solution is find one
interface other than loopback interface, then use its
A: It's not OK actually
for ipv4. In the Windows, you can't use
127.0.0.1 as gateway when add route entry. So the solution is
find one
interface other than loopback interface, then use its
uni-address as gateway, it will be a blackhole route entry. For
example, if you have an interface which ip addr is
192.168.128.100, and ifindex is 5, then
...
...
@@ -92,3 +191,8 @@ Notes
9. IN6_LINKLOCAL_IFINDEX && SET_IN6_LINKLOCAL_IFINDEX, do both of them
work in the Windows?
A: We can ignore both of them. In the windows, it use the following
format to specify interface index in the link local address:
fe80::2ff:38ff:fed8:7d97%11
component/babeld/cyginet.c
View file @
582eb114
/*
* Some issues:
*
* 1. libwinet_dump_ipv6_route_table
*
* Before Windows Vista, we have to use command "netsh" to get ipv6
* route table. But the output misses the value of route protocol.
*
* 2. libwinet_edit_route_entry
*
* What should be the value of protocol? MIB_IPPROTO_NETMGMT or
* RTPROT_BABEL_LOCAL
*
*/
/* The Win32 select only worked on socket handles. The Cygwin
* implementation allows select to function normally when given
* different types of file descriptors (sockets, pipes, handles,
...
...
@@ -58,7 +43,7 @@ void do_debugf(int level, const char *format, ...);
static
HRESULT
(
WINAPI
*
ws_guidfromstring
)(
LPCTSTR
psz
,
LPGUID
pguid
)
=
NULL
;
static
HANDLE
event_notify_monitor_thread
=
WSA_INVALID_EVENT
;
static
PLIBWINET_INTERFACE_MAP_TABLE
interface_map_table
=
NULL
;
static
PLIBWINET_INTERFACE_MAP_TABLE
g_
interface_map_table
=
NULL
;
static
int
libwinet_run_command
(
const
char
*
);
static
void
...
...
@@ -111,39 +96,64 @@ mask2len(const unsigned char *p, const int size)
}
static
int
libwinet_
ipv6_interfaces_forwards
(
int
forward
)
libwinet_
set_registry_key
(
char
*
key
,
char
*
name
,
int
value
,
int
defvalue
)
{
const
int
MAX_BUFFER_SIZE
=
255
;
char
cmdbuf
[
MAX_BUFFER_SIZE
];
int
result
;
HKEY
hKey
;
unsigned
long
type
;
unsigned
long
size
;
unsigned
long
old
;
struct
if_nameindex
*
p
;
struct
if_nameindex
*
ptr
;
if
(
NULL
==
(
ptr
=
(
struct
if_nameindex
*
)
if_nameindex
()))
if
(
RegOpenKeyEx
(
HKEY_LOCAL_MACHINE
,
key
,
0
,
KEY_READ
|
KEY_WRITE
,
&
hKey
)
!=
ERROR_SUCCESS
)
return
-
1
;
p
=
ptr
;
while
(
p
->
if_index
)
{
if
(
snprintf
(
cmdbuf
,
MAX_BUFFER_SIZE
,
"netsh interface ipv6 set interface %d forwarding=%s"
,
p
->
if_index
,
forward
?
"enabled"
:
"disabled"
)
>=
MAX_BUFFER_SIZE
)
break
;
if
(
libwinet_run_command
(
cmdbuf
)
!=
0
)
break
;
p
++
;
size
=
sizeof
(
old
);
if
(
RegQueryValueEx
(
hKey
,
name
,
NULL
,
&
type
,
(
unsigned
char
*
)
&
old
,
&
size
)
!=
ERROR_SUCCESS
||
type
!=
REG_DWORD
)
old
=
defvalue
;
if
(
RegSetValueEx
(
hKey
,
name
,
0
,
REG_DWORD
,
(
unsigned
char
*
)
&
value
,
sizeof
(
value
)
))
{
RegCloseKey
(
hKey
);
return
-
1
;
}
result
=
!
(
p
->
if_index
);
if_freenameindex
(
ptr
);
return
result
;
RegCloseKey
(
hKey
);
return
old
;
}
/* return True if success */
static
int
libwinet_get_registry_key
(
char
*
key
,
char
*
name
,
long
*
value
)
{
HKEY
hKey
;
int
rc
;
unsigned
long
type
;
unsigned
long
size
;
if
(
RegOpenKeyEx
(
HKEY_LOCAL_MACHINE
,
key
,
0
,
KEY_READ
,
&
hKey
)
!=
ERROR_SUCCESS
)
return
-
1
;
size
=
sizeof
(
*
value
);
rc
=
(
RegQueryValueEx
(
hKey
,
name
,
NULL
,
&
type
,
(
unsigned
char
*
)
value
,
&
size
)
==
ERROR_SUCCESS
&&
type
==
REG_DWORD
);
RegCloseKey
(
hKey
);
return
rc
;
}
static
void
libwinet_free_interface_map_table
()
{
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
s
;
while
(
p
)
{
if
(
p
->
AdapterName
)
...
...
@@ -154,7 +164,22 @@ libwinet_free_interface_map_table()
p
=
p
->
next
;
FREE
(
s
);
}
interface_map_table
=
NULL
;
g_interface_map_table
=
NULL
;
}
static
int
get_interface_forwards
(
char
*
guid
)
{
long
value
=
0
;
/* Location in the Windows XP, not sure in Vista or Windows 7 */
char
*
key
=
"SYSTEM
\\
CurrentControlSet
\\
Services
\\
Tcpip6
\\
Parameters"
"
\\
Interfaces
\\
%s"
;
char
*
name
=
"Forwards"
;
char
buf
[
256
]
=
{
0
};
if
(
snprintf
(
buf
,
255
,
key
,
guid
)
>
0
)
if
(
libwinet_get_registry_key
(
buf
,
name
,
&
value
))
return
value
;
return
-
1
;
}
static
int
...
...
@@ -191,13 +216,13 @@ libwinet_refresh_interface_map_table()
if
(
NO_ERROR
==
dwRet
)
{
if
(
interface_map_table
)
if
(
g_
interface_map_table
)
libwinet_free_interface_map_table
();
PLIBWINET_INTERFACE_MAP_TABLE
p
;
size_t
len
;
interface_map_table
=
NULL
;
g_
interface_map_table
=
NULL
;
pTmpAdaptAddr
=
pAdaptAddr
;
while
(
pTmpAdaptAddr
)
{
...
...
@@ -206,8 +231,10 @@ libwinet_refresh_interface_map_table()
dwRet
=
ERROR_BUFFER_OVERFLOW
;
break
;
}
p
->
next
=
interface_map_table
;
p
->
next
=
g_interface_map_table
;
p
->
IfIndex
=
pTmpAdaptAddr
->
IfIndex
;
p
->
Ipv6IfIndex
=
pTmpAdaptAddr
->
Ipv6IfIndex
;
p
->
RouteFlags
=
get_interface_forwards
(
pTmpAdaptAddr
->
AdapterName
);
len
=
WideCharToMultiByte
(
CP_ACP
,
0
,
pTmpAdaptAddr
->
FriendlyName
,
...
...
@@ -250,9 +277,8 @@ libwinet_refresh_interface_map_table()
pTmpAdaptAddr
->
PhysicalAddress
,
p
->
PhysicalAddressLength
);
pTmpAdaptAddr
=
pTmpAdaptAddr
->
Next
;
interface_map_table
=
p
;
g_
interface_map_table
=
p
;
}
if
(
ERROR_BUFFER_OVERFLOW
==
dwRet
)
...
...
@@ -270,62 +296,32 @@ libwinet_refresh_interface_map_table()
Return 0, if the interface only binds one ip version.
Special case:
If the interface is loopback, it will always return 1.
If the interface is loopback, it will always return 1.
Notice the parameter family specify the familay of input ifindex,
not output family. Actually,
family == AF_INET, it will map ipv4 to ipv6,
family == AF_INET6, it will map ipv6 to ipv4,
*/
static
int
libwinet_map_ifindex
(
int
family
,
int
ifindex
)
{
IP_ADAPTER_ADDRESSES
*
pAdaptAddr
=
NULL
;
IP_ADAPTER_ADDRESSES
*
pTmpAdaptAddr
=
NULL
;
DWORD
dwRet
=
0
;
DWORD
dwSize
=
0x10000
;
DWORD
dwReturn
=
0
;
dwRet
=
GetAdaptersAddresses
(
AF_UNSPEC
,
GAA_FLAG_SKIP_UNICAST
\
|
GAA_FLAG_SKIP_ANYCAST
\
|
GAA_FLAG_SKIP_MULTICAST
\
|
GAA_FLAG_SKIP_DNS_SERVER
\
|
GAA_FLAG_SKIP_FRIENDLY_NAME
,
NULL
,
pAdaptAddr
,
&
dwSize
);
if
(
ERROR_BUFFER_OVERFLOW
==
dwRet
)
{
FREE
(
pAdaptAddr
);
if
(
NULL
==
(
pAdaptAddr
=
(
IP_ADAPTER_ADDRESSES
*
)
MALLOC
(
dwSize
)))
return
0
;
dwRet
=
GetAdaptersAddresses
(
AF_UNSPEC
,
GAA_FLAG_SKIP_UNICAST
\
|
GAA_FLAG_SKIP_ANYCAST
\
|
GAA_FLAG_SKIP_MULTICAST
\
|
GAA_FLAG_SKIP_DNS_SERVER
\
|
GAA_FLAG_SKIP_FRIENDLY_NAME
,
NULL
,
pAdaptAddr
,
&
dwSize
);
}
if
(
NO_ERROR
==
dwRet
)
{
pTmpAdaptAddr
=
pAdaptAddr
;
while
(
pTmpAdaptAddr
)
{
if
(
family
==
AF_INET
?
pTmpAdaptAddr
->
IfIndex
==
ifindex
:
pTmpAdaptAddr
->
Ipv6IfIndex
==
ifindex
)
{
dwReturn
=
(
pTmpAdaptAddr
->
IfType
==
IF_TYPE_SOFTWARE_LOOPBACK
)
?
1
:
(
family
==
AF_INET
)
?
pTmpAdaptAddr
->
Ipv6IfIndex
:
pTmpAdaptAddr
->
IfIndex
;
break
;
}
pTmpAdaptAddr
=
pTmpAdaptAddr
->
Next
;
}
FREE
(
pAdaptAddr
);
/* Loopback Interface */
if
(
ifindex
==
1
)
return
1
;
if
(
g_interface_map_table
==
NULL
)
if
(
!
libwinet_refresh_interface_map_table
())
return
-
1
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_interface_map_table
;
while
(
p
)
{
if
(
family
==
AF_INET
&&
ifindex
==
p
->
IfIndex
&&
p
->
Ipv6IfIndex
)
return
p
->
Ipv6IfIndex
;
else
if
(
family
==
AF_INET6
&&
ifindex
==
p
->
Ipv6IfIndex
&&
p
->
IfIndex
)
return
p
->
IfIndex
;
p
=
p
->
next
;
}
return
dwReturn
;
return
0
;
}
static
int
...
...
@@ -526,7 +522,7 @@ libwinet_dump_ipv6_route_table(struct cyginet_route *routes,
if
(
ignored
)
ignored
=
0
;
else
if
(
!
ignored
)
{
route
.
proto
=
MIB_IPPROTO_
OTHER
;
/* ?? */
route
.
proto
=
MIB_IPPROTO_
NETMGMT
;
/* ?? */
if
((
maxroutes
>
count
)
&&
(
proute
!=
NULL
))
{
memcpy
(
proute
,
&
route
,
sizeof
(
struct
cyginet_route
));
proute
++
;
...
...
@@ -816,8 +812,7 @@ cyginet_blackhole_index(struct in6_addr* addr6, char * addr)
dwRet
=
GetAdaptersAddresses
(
AF_UNSPEC
,
GAA_FLAG_SKIP_ANYCAST
\
|
GAA_FLAG_SKIP_MULTICAST
\
|
GAA_FLAG_SKIP_DNS_SERVER
\
|
GAA_FLAG_SKIP_FRIENDLY_NAME
,
|
GAA_FLAG_SKIP_DNS_SERVER
,
NULL
,
pAdaptAddr
,
&
dwSize
...
...
@@ -829,8 +824,7 @@ cyginet_blackhole_index(struct in6_addr* addr6, char * addr)
dwRet
=
GetAdaptersAddresses
(
AF_UNSPEC
,
GAA_FLAG_SKIP_ANYCAST
\
|
GAA_FLAG_SKIP_MULTICAST
\
|
GAA_FLAG_SKIP_DNS_SERVER
\
|
GAA_FLAG_SKIP_FRIENDLY_NAME
,
|
GAA_FLAG_SKIP_DNS_SERVER
,
NULL
,
pAdaptAddr
,
&
dwSize
...
...
@@ -843,16 +837,21 @@ cyginet_blackhole_index(struct in6_addr* addr6, char * addr)
if
(
pTmpAdaptAddr
->
IfIndex
&&
pTmpAdaptAddr
->
Ipv6IfIndex
&&
(
pTmpAdaptAddr
->
OperStatus
==
IfOperStatusUp
)
&&
(
pTmpAdaptAddr
->
IfType
!=
IF_TYPE_SOFTWARE_LOOPBACK
))
{
&&
(
pTmpAdaptAddr
->
IfType
!=
IF_TYPE_SOFTWARE_LOOPBACK
)
&&
!
wcscmp
(
pTmpAdaptAddr
->
FriendlyName
,
L"blackhole"
))
{
PIP_ADAPTER_UNICAST_ADDRESS
p
=
pTmpAdaptAddr
->
FirstUnicastAddress
;
while
(
p
)
{
SOCKADDR
*
s
;
s
=
(
p
->
Address
).
lpSockaddr
;
if
(
s
->
sa_family
==
AF_INET
)
memcpy
(
addr
,
&
(((
struct
sockaddr_in
*
)
s
)
->
sin_addr
),
4
);
else
if
(
s
->
sa_family
==
AF_INET6
)
memcpy
(
addr6
,
&
(((
struct
sockaddr_in6
*
)
s
)
->
sin6_addr
),
16
);
if
(
s
->
sa_family
==
AF_INET
)
{
if
(
addr
)
memcpy
(
addr
,
&
(((
struct
sockaddr_in
*
)
s
)
->
sin_addr
),
4
);
}
else
if
(
s
->
sa_family
==
AF_INET6
)
{
if
(
addr6
)
memcpy
(
addr6
,
&
(((
struct
sockaddr_in6
*
)
s
)
->
sin6_addr
),
16
);
}
p
=
p
->
Next
;
}
dwReturn
=
pTmpAdaptAddr
->
Ipv6IfIndex
;
...
...
@@ -876,15 +875,15 @@ cyginet_blackhole_index(struct in6_addr* addr6, char * addr)
* SetIpForwardEntry
*
* Or route command
*
*
* Or netsh routing add persistentroute
*
*
* Or netsh routing add rtmroute
*
* it need "Routing and Remote Access Service" running on the local
* machine. Use 'net start remoteaccess' on the local machine to
* start the service.
*
*
* 2. IPv6 route: command "netsh"
*
* C:/> netsh interface ipv6 add route
...
...
@@ -918,7 +917,7 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
const
int
MAX_BUFFER_SIZE
=
1024
;
const
char
*
cmdformat
=
"netsh interface ipv6 %s route "
"prefix=%s/%d interface=%d "
"
%s%s %s
%d"
;
"
nexthop=%s %cmetric=
%d"
;
char
cmdbuf
[
MAX_BUFFER_SIZE
];
char
sdest
[
INET6_ADDRSTRLEN
];
char
sgate
[
INET6_ADDRSTRLEN
];
...
...
@@ -935,7 +934,8 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
INET6_ADDRSTRLEN
))
return
-
1
;
/* metric clause results delete route command failed, so we add
'#' to commet this clause when delete route. */
if
(
snprintf
(
cmdbuf
,
MAX_BUFFER_SIZE
,
cmdformat
,
...
...
@@ -944,9 +944,8 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
sdest
,
plen
,
ifindex
,
strcmp
(
sgate
,
"::"
)
==
0
?
""
:
"nexthop="
,
strcmp
(
sgate
,
"::"
)
==
0
?
""
:
sgate
,
cmdflag
==
RTM_DELETE
?
"#"
:
"metric="
,
sgate
,
cmdflag
==
RTM_DELETE
?
'#'
:
' '
,
metric
)
>=
MAX_BUFFER_SIZE
)
return
-
1
;
...
...
@@ -956,23 +955,29 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
}
/* Add ipv4 route before Windows Vista */
else
if
(
0
)
{
/* Add ipv4 route before Windows Vista
, use IP Helper API
*/
else
{
MIB_IPFORWARDROW
Row
;
unsigned
long
Res
;
struct
in_addr
mask
;
plen2mask
(
plen
,
&
mask
);
memset
(
&
Row
,
0
,
sizeof
(
MIB_IPFORWARDROW
));
Row
.
dwForwardDest
=
(((
SOCKADDR_IN
*
)
dest
)
->
sin_addr
).
S_un
.
S_addr
;
Row
.
dwForwardPolicy
=
0
;
Row
.
dwForwardNextHop
=
(((
SOCKADDR_IN
*
)
gate
)
->
sin_addr
).
S_un
.
S_addr
;
Row
.
dwForwardIfIndex
=
libwinet_map_ifindex
(
AF_INET6
,
ifindex
);
Row
.
dwForwardMask
=
mask
.
S_un
.
S_addr
;
/*
* MIB_IPROUTE_TYPE_DIRECT <==> dwForwardNextHop == dwForwardDest
* MIB_IPROUTE_TYPE_LOCAL <==> dwForwardNextHop
== Ip of the interface
* MIB_IPROUTE_TYPE_LOCAL <==> dwForwardNextHop
in local interfaces
* MIB_IPROUTE_TYPE_INDIRECT all the others
*/
Row
.
dwForwardType
=
Row
.
dwForwardNextHop
==
Row
.
dwForwardDest
?
\
MIB_IPROUTE_TYPE_DIRECT
:
MIB_IPROUTE_TYPE_INDIRECT
;
Row
.
dwForwardType
=
MIB_IPROUTE_TYPE_INDIRECT
;
Row
.
dwForwardProto
=
MIB_IPPROTO_NETMGMT
;
Row
.
dwForwardAge
=
0
;
Row
.
dwForwardNextHopAS
=
0
;
...
...
@@ -999,7 +1004,7 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
return
-
1
;
}
/* 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 */
...
...
@@ -1036,7 +1041,7 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
MAX_BUFFER_SIZE,
"route %s %s MASK %s %s METRIC %d IF %d",
cmdflag == RTM_ADD ? "add" :
cmdflag
==
RTM_DELETE
?
"delete"
:
"change"
,
cmdflag == RTM_DELETE ? "delete" : "change",
sdest,
smask,
sgate,
...
...
@@ -1048,6 +1053,7 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
if (libwinet_run_command(cmdbuf) != 0)
return -1;
}
#endif /* if 0 */
#else
/* Add route entry after Windows Vista */
...
...
@@ -1098,75 +1104,118 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
return
1
;
}
static
int
libwinet_set_registry_key
(
char
*
key
,
char
*
name
,
int
value
,
int
def
value
)
int
cyginet_set_interface_forwards
(
const
char
*
ifname
,
int
value
)
{
HKEY
hKey
;
unsigned
long
type
;
unsigned
long
size
;
unsigned
long
old
;
if
(
RegOpenKeyEx
(
HKEY_LOCAL_MACHINE
,
key
,
0
,
KEY_READ
|
KEY_WRITE
,
&
hKey
)
!=
ERROR_SUCCESS
)
return
-
1
;
size
=
sizeof
(
old
);
/* For ipv4 */
/* netsh routing add interface ifname enabled/disabled */
char
cmdbuf
[
255
];
if
(
snprintf
(
cmdbuf
,
255
,
"netsh interface ipv6 set interface
\"
%s
\"
"
"forwarding=%s > /dev/null"
,
ifname
,
value
?
"enabled"
:
"disabled"
)
>
0
)
return
system
(
cmdbuf
);
return
-
1
;
}
if
(
RegQueryValueEx
(
hKey
,
name
,
NULL
,
&
type
,
(
unsigned
char
*
)
&
old
,
&
size
)
!=
ERROR_SUCCESS
||
type
!=
REG_DWORD
)
old
=
defvalue
;
int
cyginet_set_icmp6_redirect_accept
(
int
value
)
{
char
*
key
=
"SYSTEM
\\
CurrentControlSet
\\
Services
\\
Tcpip6
\\
Parameters"
;
char
*
name
=
"EnableICMPRedirect"
;
return
libwinet_set_registry_key
(
key
,
name
,
value
,
1
);
}
if
(
RegSetValueEx
(
hKey
,
name
,
0
,
REG_DWORD
,
(
unsigned
char
*
)
&
value
,
sizeof
(
value
)
))
{
RegCloseKey
(
hKey
);
return
-
1
;
static
void
libwinet_restore_ipv6_interface
()
{
char
cmdbuf
[
255
];
int
rc
=
0
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_interface_map_table
;
while
(
p
)
{
if
(
p
->
RouteFlags
!=
-
1
)
if
(
snprintf
(
cmdbuf
,
255
,
"netsh interface ipv6 set interface
\"
%s
\"
"
"forwarding=%s > /dev/null"
,
p
->
FriendlyName
,
p
->
RouteFlags
?
"enabled"
:
"disabled"
)
>
0
)
rc
=
system
(
cmdbuf
);
p
=
p
->
next
;
}
RegCloseKey
(
hKey
);
return
old
;
}
#if 0
int
cyginet_set_ipv6_forwards(int value)
{
char * key = "SYSTEM\\CurrentControlSet\\Services\\Tcpip6\\Parameters";
/*
int rc;
rc = libwinet_ipv6_interfaces_forwards(value);
if (rc == -1)
return -1;
if (value) {
if (ERROR_IO_PENDING != EnableRouter(NULL, NULL))
return -1;
}
else {
if (NO_ERROR != UnenableRouter(NULL, NULL))
return -1;
}
*/
char * name = "IPEnableRouter";
return libwinet_set_registry_key(key,
"IPEnableRouter"
,
name
,
value,
0
);
}
int
cyginet_set_icmp6_redirect_accept
(
int
value
)
static
int
libwinet_ipv6_interfaces_forwards(int forward
)
{
char
*
key
=
"SYSTEM
\\
CurrentControlSet
\\
Services
\\
Tcpip6
\\
Parameters"
;
const int MAX_BUFFER_SIZE = 255;
char cmdbuf[MAX_BUFFER_SIZE];
int result;
return
libwinet_set_registry_key
(
key
,
"EnableICMPRedirect"
,
value
,
1
);
struct if_nameindex * p;
struct if_nameindex * ptr;
if (NULL == (ptr = (struct if_nameindex *)if_nameindex()))
return -1;
p = ptr;
while (p -> if_index) {
if (snprintf(cmdbuf,
MAX_BUFFER_SIZE,
"netsh interface ipv6 set interface %d forwarding=%s",
p -> if_index,
forward ? "enabled" : "disabled"
) >= MAX_BUFFER_SIZE)
break;
if (libwinet_run_command(cmdbuf) != 0)
break;
p ++;
}
result = ! (p -> if_index);
if_freenameindex(ptr);
return result;
}
static void
libwinet_init_ipv6_interface()
{
char cmdbuf[255];
int rc=0;
PLIBWINET_INTERFACE_MAP_TABLE p = g_interface_map_table;
while (p) {
if (snprintf(cmdbuf,
255,
"netsh interface ipv6 set interface \"%s\" " \
"forwarding=enabled advertise=enabled > /dev/null",
p -> FriendlyName
) > 0) {
rc = system(cmdbuf);
}
p = p -> next;
}
}
#endif /* if 0 */
/*
* On Windows Vista and later, wireless network cards are reported as
...
...
@@ -1411,58 +1460,6 @@ cyginet_loopback_index(int family)
return
1
;
}
char
*
cyginet_ipv4_index2ifname
(
int
ifindex
)
{
IP_ADAPTER_ADDRESSES
*
pAdaptAddr
=
NULL
;
IP_ADAPTER_ADDRESSES
*
pTmpAdaptAddr
=
NULL
;
DWORD
dwRet
=
0
;
DWORD
dwSize
=
0x10000
;
DWORD
dwFamily
=
AF_INET
;
char
*
ifname
=
NULL
;
dwRet
=
GetAdaptersAddresses
(
dwFamily
,
GAA_FLAG_SKIP_UNICAST
\
|
GAA_FLAG_SKIP_ANYCAST
\
|
GAA_FLAG_SKIP_MULTICAST
\
|
GAA_FLAG_SKIP_DNS_SERVER
,
NULL
,
pAdaptAddr
,
&
dwSize
);
if
(
ERROR_BUFFER_OVERFLOW
==
dwRet
)
{
FREE
(
pAdaptAddr
);
if
(
NULL
==
(
pAdaptAddr
=
(
IP_ADAPTER_ADDRESSES
*
)
MALLOC
(
dwSize
)))
return
NULL
;
dwRet
=
GetAdaptersAddresses
(
dwFamily
,
GAA_FLAG_SKIP_UNICAST
\
|
GAA_FLAG_SKIP_ANYCAST
\
|
GAA_FLAG_SKIP_MULTICAST
\
|
GAA_FLAG_SKIP_DNS_SERVER
,
NULL
,
pAdaptAddr
,
&
dwSize
);
}
if
(
NO_ERROR
==
dwRet
)
{
pTmpAdaptAddr
=
pAdaptAddr
;
while
(
pTmpAdaptAddr
)
{
if
(
pTmpAdaptAddr
->
IfIndex
==
ifindex
)
{
ifname
=
cyginet_ifname
(
pTmpAdaptAddr
->
AdapterName
);
break
;
}
pTmpAdaptAddr
=
pTmpAdaptAddr
->
Next
;
}
FREE
(
pAdaptAddr
);
}
return
ifname
;
}
/*
* There are 3 ways to dump route table in the Windows:
*
...
...
@@ -1632,12 +1629,17 @@ cyginet_read_route_socket(void *buffer, size_t size)
return
0
;
}
int
cyginet_refresh_interface_table
()
{
return
libwinet_refresh_interface_map_table
();
}
int
cyginet_startup
()
{
WORD
wVersionRequested
;
WSADATA
wsaData
;
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested
=
MAKEWORD
(
2
,
2
);
return
WSAStartup
(
wVersionRequested
,
&
wsaData
);
...
...
@@ -1646,6 +1648,8 @@ cyginet_startup()
void
cyginet_cleanup
()
{
libwinet_restore_ipv6_interface
();
libwinet_free_interface_map_table
();
WSACleanup
();
}
...
...
@@ -1653,10 +1657,10 @@ char *
cyginet_guidname
(
const
char
*
ifname
)
{
PLIBWINET_INTERFACE_MAP_TABLE
p
;
if
(
!
interface_map_table
)
if
(
!
g_
interface_map_table
)
libwinet_refresh_interface_map_table
();
p
=
interface_map_table
;
p
=
g_
interface_map_table
;
while
(
p
)
{
if
(
strcmp
(
ifname
,
p
->
FriendlyName
)
==
0
)
return
p
->
AdapterName
;
...
...
@@ -1669,10 +1673,10 @@ char *
cyginet_ifname
(
const
char
*
guidname
)
{
PLIBWINET_INTERFACE_MAP_TABLE
p
;
if
(
!
interface_map_table
)
if
(
!
g_
interface_map_table
)
libwinet_refresh_interface_map_table
();
p
=
interface_map_table
;
p
=
g_
interface_map_table
;
while
(
p
)
{
if
(
strcmp
(
guidname
,
p
->
AdapterName
)
==
0
)
return
p
->
FriendlyName
;
...
...
@@ -1681,9 +1685,89 @@ cyginet_ifname(const char * guidname)
return
NULL
;
}
int
cyginet_add_ipentry
(
int
ifindex
,
struct
sockaddr
*
addr
)
{
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
)
return
-
1
;
memcpy
(
row
.
bPhysAddr
,
p
->
PhysicalAddress
,
row
.
dwPhysAddrLen
);
break
;
}
p
=
p
->
next
;
}
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
);
}
return
-
1
;
}
/* The following functions are reserved. */
#if 0
char *
cyginet_ipv4_index2ifname(int ifindex)
{
IP_ADAPTER_ADDRESSES *pAdaptAddr = NULL;
IP_ADAPTER_ADDRESSES *pTmpAdaptAddr = NULL;
DWORD dwRet = 0;
DWORD dwSize = 0x10000;
DWORD dwFamily = AF_INET;
char * ifname = NULL;
dwRet = GetAdaptersAddresses(dwFamily,
GAA_FLAG_SKIP_UNICAST \
| GAA_FLAG_SKIP_ANYCAST \
| GAA_FLAG_SKIP_MULTICAST \
| GAA_FLAG_SKIP_DNS_SERVER,
NULL,
pAdaptAddr,
&dwSize
);
if (ERROR_BUFFER_OVERFLOW == dwRet) {
FREE(pAdaptAddr);
if (NULL == (pAdaptAddr = (IP_ADAPTER_ADDRESSES*)MALLOC(dwSize)))
return NULL;
dwRet = GetAdaptersAddresses(dwFamily,
GAA_FLAG_SKIP_UNICAST \
| GAA_FLAG_SKIP_ANYCAST \
| GAA_FLAG_SKIP_MULTICAST \
| GAA_FLAG_SKIP_DNS_SERVER,
NULL,
pAdaptAddr,
&dwSize
);
}
if (NO_ERROR == dwRet) {
pTmpAdaptAddr = pAdaptAddr;
while (pTmpAdaptAddr) {
if (pTmpAdaptAddr -> IfIndex == ifindex) {
ifname = cyginet_ifname(pTmpAdaptAddr -> AdapterName);
break;
}
pTmpAdaptAddr = pTmpAdaptAddr->Next;
}
FREE(pAdaptAddr);
}
return ifname;
}
static int
libwinet_get_loopback_index(int family)
{
...
...
@@ -2282,7 +2366,7 @@ DWORD GetInterfaceIndexForAddress(SOCKADDR *pAddr)
FREE(pAdaptAddr);
}
return dwReturn;
}
...
...
@@ -2498,7 +2582,7 @@ runTestCases()
if_freenameindex
(
ptr
);
}
}
/*
printf("\n\nTest cyginet_ipv4_index2ifname:\n\n");
{
int ifindex = 1;
...
...
@@ -2507,10 +2591,10 @@ runTestCases()
cyginet_ipv4_index2ifname(ifindex)
);
}
*/
printf
(
"
\n\n
Test cyginet_guidname works in the Cygwin:
\n\n
"
);
{
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
while
(
p
)
{
printf
(
"%s:
\t\t
%s
\n
"
,
p
->
FriendlyName
,
...
...
@@ -2546,7 +2630,7 @@ runTestCases()
printf
(
"
\n\n
Test libwinet_is_wireless_interface:
\n\n
"
);
{
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
while
(
p
)
{
printf
(
"%s is wireless netcard: %d
\n
"
,
p
->
FriendlyName
,
...
...
@@ -2585,6 +2669,7 @@ runTestCases()
}
}
/*
printf("\n\nTest cyginet_set_ipv6_forwards:\n\n");
{
printf("cyginet_set_ipv6_forwards(1) return %d\n",
...
...
@@ -2604,11 +2689,12 @@ runTestCases()
cyginet_set_icmp6_redirect_accept(1)
);
}
*/
printf
(
"
\n\n
Test cyginet_interface_wireless:
\n\n
"
);
{
int
n
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
while
(
p
)
{
n
=
cyginet_interface_wireless
(
p
->
FriendlyName
,
1
);
printf
(
"%s is wireless netcard: %d
\n
"
,
p
->
FriendlyName
,
n
);
...
...
@@ -2619,7 +2705,7 @@ runTestCases()
printf
(
"
\n\n
Test cyginet_interface_mtu:
\n\n
"
);
{
int
n
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
while
(
p
)
{
n
=
cyginet_interface_mtu
(
p
->
FriendlyName
,
1
);
printf
(
"mtu of %s is : %d
\n
"
,
p
->
FriendlyName
,
n
);
...
...
@@ -2630,7 +2716,7 @@ runTestCases()
printf
(
"
\n\n
Test cyginet_interface_operational:
\n\n
"
);
{
int
n
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
while
(
p
)
{
n
=
cyginet_interface_operational
(
p
->
FriendlyName
,
1
);
printf
(
"%s is up: %d
\n
"
,
p
->
FriendlyName
,
n
);
...
...
@@ -2642,7 +2728,7 @@ runTestCases()
{
struct
sockaddr_in
sa
;
int
n
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
while
(
p
)
{
memset
(
&
sa
,
0
,
sizeof
(
sa
));
n
=
cyginet_interface_ipv4
(
p
->
FriendlyName
,
1
,
(
unsigned
char
*
)
&
sa
);
...
...
@@ -2655,7 +2741,7 @@ runTestCases()
{
int
n
;
struct
sockaddr_dl
sdl
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
while
(
p
)
{
memset
(
&
sdl
,
0
,
sizeof
(
struct
sockaddr_dl
));
n
=
cyginet_interface_sdl
(
&
sdl
,
p
->
FriendlyName
);
...
...
@@ -2767,9 +2853,9 @@ runTestCases()
if
(
inet_pton
(
AF_INET
,
"192.168.128.119"
,
&
dest4
.
sin_addr
)
!=
1
)
break
;
if
(
inet_pton
(
AF_INET
,
"192.168.12
8
.200"
,
&
gate4
.
sin_addr
)
!=
1
)
if
(
inet_pton
(
AF_INET
,
"192.168.12
1
.200"
,
&
gate4
.
sin_addr
)
!=
1
)
break
;
ifindex
=
2
;
ifindex
=
5
;
metric
=
3
;
prefix
=
32
;
...
...
@@ -2877,10 +2963,11 @@ int main(int argc, char* argv[])
printf
(
"
\n\n
Test libwinet_refresh_interface_map_table:
\n\n
"
);
{
if
(
libwinet_refresh_interface_map_table
())
{
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
while
(
p
)
{
printf
(
"Friendly Name:
\t
%s
\n
"
,
p
->
FriendlyName
);
printf
(
"Adapter Name:
\t
%s
\n
"
,
p
->
AdapterName
);
printf
(
"Forward flag:
\t
%d
\n
"
,
p
->
RouteFlags
);
printf
(
"IfType:
\t
%ld
\n
"
,
p
->
IfType
);
p
=
p
->
next
;
}
...
...
@@ -2891,8 +2978,15 @@ int main(int argc, char* argv[])
runTestCases
();
/* printf("\n\nTest libwinet_init_ipv6_interface:\n\n"); */
/* libwinet_init_ipv6_interface(); */
/* printf("\n\nTest libwinet_restore_ipv6_interface:\n\n"); */
/* libwinet_restore_ipv6_interface(); */
printf
(
"
\n\n
Test libwinet_free_interface_map_table:
\n\n
"
);
libwinet_free_interface_map_table
();
printf
(
"
\n\n
Test Finished.
\n\n
"
);
WSACleanup
();
return
0
;
...
...
component/babeld/cyginet.h
View file @
582eb114
...
...
@@ -46,15 +46,50 @@
IPv6 RFCs and Standards Working Groups
http://www.ipv6now.com.au/RFC.php
Routing Table Manager Version 2
Routing Table Manager Version 2
http://msdn.microsoft.com/en-us/library/windows/desktop/bb404201(v=vs.85).aspx
Using Routing Table Manager Version 2
Using Routing Table Manager Version 2, this section contains sample
code that can be used when developing clients such as routing
protocols.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa382335(v=vs.85).aspx
This section contains sample code that can be used when developing
clients such as routing protocols.
An introduction to the IPv6 protocol along with overviews on
deployment and IPv6 transitioning technologies is available on
Technet at Microsoft Internet Protocol Version 6 (IPv6).
http://go.microsoft.com/fwlink/p/?linkid=194338
http://technet.microsoft.com/en-us/network/bb530961.aspx
Internet Protocol Version 6 (IPv6)
http://msdn.microsoft.com/en-us//library/windows/desktop/ms738570(v=vs.85).aspx
IPv6 Link-local and Site-local Addresses
http://msdn.microsoft.com/zh-cn/library/windows/desktop/ms739166(v=vs.85).aspx
Recommended Configurations for IPv6
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740117(v=vs.85).aspx
IPv6 Support in Home Routers, It looks like a windows re6stnet.
http://msdn.microsoft.com/en-us/windows/hardware/gg463251.aspx
Neighbor Discovery in IPv6
http://tools.ietf.org/html/rfc4861
Default Address Selection for Internet Protocol version 6 (IPv6)
http://tools.ietf.org/html/rfc3484
Path MTU Discovery
http://tools.ietf.org/html/rfc1191
IPv6 Traffic Between Nodes on Different Subnets of an IPv4 Internetwork (6to4)
http://msdn.microsoft.com/zh-cn/library/windows/desktop/ms737598(v=vs.85).aspx
Multicast Listener Discovery (MLD)
http://msdn.microsoft.com/en-us/library/aa916334.aspx
IPv6 Addresses, it explains the relation between link-local address
and interface id
http://msdn.microsoft.com/en-us/library/aa921042.aspx
*/
#ifndef __CYGIFNET_H__
...
...
@@ -112,12 +147,15 @@ struct if_nameindex {
char
*
if_name
;
};
typedef
struct
_LIBWINET_INTERFACE_MAP_TABLE
{
PCHAR
FriendlyName
;
typedef
struct
_LIBWINET_INTERFACE_MAP_TABLE
{
PCHAR
FriendlyName
;
PCHAR
AdapterName
;
BYTE
PhysicalAddress
[
MAX_ADAPTER_ADDRESS_LENGTH
];
DWORD
PhysicalAddressLength
;
DWORD
IfType
;
int
RouteFlags
;
DWORD
IfIndex
;
DWORD
Ipv6IfIndex
;
VOID
*
next
;
}
LIBWINET_INTERFACE_MAP_TABLE
,
*
PLIBWINET_INTERFACE_MAP_TABLE
;
...
...
@@ -163,8 +201,8 @@ void cyginet_cleanup();
int
cyginet_start_monitor_route_changes
(
int
);
int
cyginet_stop_monitor_route_changes
();
int
cyginet_set_ipv6_forwards
(
int
);
int
cyginet_set_icmp6_redirect_accept
(
int
);
int
cyginet_set_interface_forwards
(
const
char
*
ifname
,
int
value
);
int
cyginet_interface_sdl
(
struct
sockaddr_dl
*
,
char
*
);
int
cyginet_interface_wireless
(
const
char
*
,
int
);
...
...
@@ -182,10 +220,9 @@ 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
*
);
char
*
cyginet_ipv4_index2ifname
(
int
);
int
cyginet_blackhole_index
(
struct
in6_addr
*
,
char
*
);
int
cyginet_refresh_interface_table
();
#endif
/* __CYGIFNET_H__ */
component/babeld/kernel_cygwin.c
View file @
582eb114
...
...
@@ -43,38 +43,15 @@ THE SOFTWARE.
#include "neighbour.h"
#include "kernel.h"
#include "util.h"
#include "interface.h"
#include "cyginet.h"
/*
* Some issues:
*
* 1. kernel_route
*
* RTM_BLACKHOLE, gateway will be set as loopback, is it right?
*
* 2. IN6_LINKLOCAL_IFINDEX && SET_IN6_LINKLOCAL_IFINDEX
*
* Do both of them work in the Windows?
*
* 3. kernel_interface_ipv4
*
* How to deal with many ipv4 address assigned in one interface,
* now only the first one returned.
*
*/
static
int
get_sdl
(
struct
sockaddr_dl
*
sdl
,
char
*
guidname
);
static
const
unsigned
char
v4prefix
[
16
]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0xFF
,
0xFF
,
0
,
0
,
0
,
0
};
static
int
ifindex_blackhole
=
-
1
;
static
struct
in6_addr
blackhole_addr6
=
{{
IN6ADDR_LOOPBACK_INIT
}};
static
char
blackhole_addr
[
1
][
1
][
16
]
=
{{{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x7f
,
0x00
,
0x00
,
0x01
}}};
int
export_table
=
-
1
,
import_table
=
-
1
;
int
...
...
@@ -110,113 +87,98 @@ get_sdl(struct sockaddr_dl *sdl, char *ifname)
return
cyginet_interface_sdl
(
sdl
,
ifname
);
}
/* KAME said : "Following two macros are highly depending on KAME Release" */
#define IN6_LINKLOCAL_IFINDEX(a) ((a).s6_addr[2] << 8 | (a).s6_addr[3])
#define SET_IN6_LINKLOCAL_IFINDEX(a, i) \
do { \
(a).s6_addr[2] = ((i) >> 8) & 0xff; \
(a).s6_addr[3] = (i) & 0xff; \
} while (0)
static
int
old_forwarding
=
-
1
;
static
int
old_accept_redirects
=
-
1
;
static
int
ifindex_lo
=
1
;
static
int
kernel_pipe_handles
[
2
];
/* It enables ip6.forwarding and disable ip6.redirect.
*
* Option 1:
*
* IPV6CTL_FORWARDING (ip6.forwarding) Boolean: enable/disable
* forward- ing of IPv6 packets. Also, identify if the node is
* acting as a router. Defaults to off.
*
* ==> In the Windows, MSDN says in the registry
*
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
*
* Value Name: IPEnableRouter
* Value type: REG_DWORD
* Value Data: 1
*
* A value of 1 enables TCP/IP forwarding for all network
* connections that are installed and used by this computer.
*
* Refer to: http://support.microsoft.com/kb/315236/en-us
*
* For ipv6, no global options to enable forwarding, but for each
* interface respectively.
*
* Option 2:
*
* ICMPV6CTL_REDIRACCEPT
*
* IPV6CTL_SENDREDIRECTS (ip6.redirect) Boolean: enable/disable
* sending of ICMPv6 redirects in response to unforwardable IPv6
* packets. This option is ignored unless the node is routing
* IPv6 packets, and should normally be enabled on all systems.
* Defaults to on.
*
* ==> MSDN says in the registry
*
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
*
* EnableICMPRedirect = 0
*
* Regarding ipv6, it's in the registry
*
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters
*
* 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".
*
*/
int
kernel_setup
(
int
setup
)
{
int
rc
=
0
;
int
forwarding
=
1
;
int
accept_redirects
=
0
;
int
reboot
=
0
;
/* It enables ip6.forwarding and disable ip6.redirect.
*
* Option 1:
*
* IPV6CTL_FORWARDING (ip6.forwarding) Boolean: enable/disable
* forward- ing of IPv6 packets. Also, identify if the node is
* acting as a router. Defaults to off.
*
* ==> command line:
*
* C:/> ipv6 ifc $If6Index forwards
*
* repeat this operation for all ipv6 interfaces
*
* List all ipv6 interface by the command:
*
* C:/> netsh interface ipv6 show interface
*
* ==> API: EnableRouter/DisableRouter (only for ipv4)
*
* ==> MSDN says in the registry
*
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
*
* Value Name: IPEnableRouter
* Value type: REG_DWORD
* Value Data: 1
*
* A value of 1 enables TCP/IP forwarding for all network
* connections that are installed and used by this computer.
*
* Refer to: http://support.microsoft.com/kb/315236/en-us
*
* Option 2:
*
* ICMPV6CTL_REDIRACCEPT
*
* IPV6CTL_SENDREDIRECTS (ip6.redirect) Boolean: enable/disable
* sending of ICMPv6 redirects in response to unforwardable IPv6
* packets. This option is ignored unless the node is routing
* IPv6 packets, and should normally be enabled on all systems.
* Defaults to on.
*
* ==> MSDN says in the registry
*
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
*
* EnableICMPRedirect = 0
*
* Refer to:
*
* http://technet.microsoft.com/en-us/library/cc766102(v=ws.10).aspx
*
* After change them, need to reboot machine.
*
* Notice:
*
* MSDN says nothing about ipv6, it should use the following key
*
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters
*
* Maybe later Window VISTA its corresponding APIs are
* WSAEnumProtocols, WSCUpdateProvider.
*
*/
int
flags
=
0
;
struct
interface
*
ifp
;
if
(
setup
)
{
int
flags
;
if
(
0
!=
cyginet_startup
())
return
-
1
;
if
((
rc
=
cyginet_set_ipv6_forwards
(
forwarding
))
==
-
1
)
{
fprintf
(
stderr
,
"Cannot enable IPv6 forwarding.
\n
"
);
/* 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;
}
old_forwarding
=
rc
;
reboot
=
(
rc
==
forwarding
)
?
reboot
:
1
;
if
((
rc
=
cyginet_set_icmp6_redirect_accept
(
accept_redirects
))
==
-
1
)
{
fprintf
(
stderr
,
"Cannot disable ICMPv6 redirect.
\n
"
);
if
(
reboot
)
cyginet_set_ipv6_forwards
(
old_forwarding
);
if (rc) {
fprintf(stderr,
"Disable ICMPv6 redirect successfully. Reboot computer "
"to take it effect now.\n\n"
);
return -1;
}
old_accept_redirects
=
rc
;
reboot
=
(
rc
==
accept_redirects
)
?
reboot
:
1
;
*/
FOR_ALL_INTERFACES
(
ifp
)
{
if
(
cyginet_set_interface_forwards
(
ifp
->
name
,
1
)
==
-
1
)
{
fprintf
(
stderr
,
"Cannot enable IPv6 forwarding.
\n
"
);
return
-
1
;
}
}
if
(
pipe
(
kernel_pipe_handles
)
==
-
1
)
return
-
1
;
if
((
flags
=
fcntl
(
kernel_pipe_handles
[
0
],
F_GETFL
,
0
))
<
0
)
...
...
@@ -225,34 +187,14 @@ kernel_setup(int setup)
goto
error
;
}
else
{
if
(
-
1
==
(
rc
=
cyginet_set_ipv6_forwards
(
old_forwarding
)))
return
-
1
;
reboot
=
(
rc
==
forwarding
)
?
reboot
:
1
;
if
(
-
1
==
(
rc
=
cyginet_set_icmp6_redirect_accept
(
old_accept_redirects
)))
return
-
1
;
reboot
=
(
rc
==
accept_redirects
)
?
reboot
:
1
;
close
(
kernel_pipe_handles
[
0
]);
close
(
kernel_pipe_handles
[
1
]);
cyginet_cleanup
();
}
if
(
reboot
)
fprintf
(
stderr
,
"%s IPv6 forwarding and %s ICMPv6 redirect successfully.
\n
"
"REBOOT NOW, so that these changes take effect.
\n\n
"
,
forwarding
?
"Enable"
:
"Disable"
,
accept_redirects
?
"enable"
:
"disable"
);
return
1
;
error:
{
if
(
reboot
)
{
cyginet_set_ipv6_forwards
(
old_forwarding
);
cyginet_set_icmp6_redirect_accept
(
old_accept_redirects
);
}
return
-
1
;
}
error:
return
-
1
;
}
int
...
...
@@ -363,12 +305,13 @@ 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
}}};
int
rc
,
ipv4
;
struct
sockaddr_in
ipv4_destnation
=
{
0
},
ipv4_gateway
=
{
0
};
struct
sockaddr_in6
ipv6_destnation
=
{
0
},
ipv6_gateway
=
{
0
};
struct
sockaddr
*
destination
,
*
gateway
;
int
route_ifindex
;
int
prefix_len
;
struct
sockaddr_storage
destination
=
{
0
};
struct
sockaddr_storage
gateway
=
{
0
};
/* Check that the protocol family is consistent. */
if
(
plen
>=
96
&&
v4mapped
(
dest
))
{
...
...
@@ -377,16 +320,12 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
return
-
1
;
}
ipv4
=
1
;
destination
=
(
struct
sockaddr
*
)
&
ipv4_destnation
;
gateway
=
(
struct
sockaddr
*
)
&
ipv4_gateway
;
}
else
{
if
(
v4mapped
(
gate
))
{
errno
=
EINVAL
;
return
-
1
;
}
ipv4
=
0
;
destination
=
(
struct
sockaddr
*
)
&
ipv6_destnation
;
gateway
=
(
struct
sockaddr
*
)
&
ipv6_gateway
;
}
if
(
operation
==
ROUTE_MODIFY
&&
newmetric
==
metric
&&
...
...
@@ -394,9 +333,8 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
return
0
;
if
(
operation
==
ROUTE_MODIFY
)
{
/* Do not use ROUTE_MODIFY when changing to a neighbour.
It is the only way to remove the "gateway" flag. */
if
(
ipv4
&&
plen
==
128
&&
memcmp
(
dest
,
newgate
,
16
)
==
0
)
{
if
((
metric
==
KERNEL_INFINITY
)
||
(
ipv4
&&
plen
==
128
&&
memcmp
(
dest
,
newgate
,
16
)
==
0
))
{
kernel_route
(
ROUTE_FLUSH
,
dest
,
plen
,
gate
,
ifindex
,
metric
,
NULL
,
0
,
0
);
...
...
@@ -409,6 +347,13 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
ifindex
=
newifindex
;
}
}
/* We don't add/delete a blackhole for default route */
else
if
(
newmetric
==
KERNEL_INFINITY
&&
IN6_IS_ADDR_UNSPECIFIED
(
dest
)
&&
IN6_IS_ADDR_UNSPECIFIED
(
newgate
))
return
0
;
kdebugf
(
"kernel_route: %s %s/%d metric %d dev %d nexthop %s
\n
"
,
operation
==
ROUTE_ADD
?
"add"
:
...
...
@@ -423,70 +368,70 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
if
(
metric
==
KERNEL_INFINITY
)
{
/* It means this route has property: RTF_BLACKHOLE */
if
(
ifindex_blackhole
<
0
)
{
/* ifindex_blackhole = cyginet_blackhole_index(&blackhole_addr6, */
/* blackhole_addr[0][0]+12 */
/* ); */
ifindex_blackhole
=
1
;
if
(
ifindex_blackhole
<=
0
)
if
(
ifindex_lo
<
0
)
{
ifindex_lo
=
cyginet_loopback_index
(
AF_UNSPEC
);
if
(
ifindex_lo
<=
0
)
return
-
1
;
}
route_ifindex
=
ifindex_
blackhole
;
route_ifindex
=
ifindex_
lo
;
}
#define PUSHADDR(dst, src) \
do { struct sockaddr_in *sin = (struct sockaddr_in*)(dst); \
do { struct sockaddr_in *sin = (struct sockaddr_in*)
&
(dst); \
sin->sin_family = AF_INET; \
memcpy(&sin->sin_addr, (src) + 12, 4); \
} while (0)
#define PUSHADDR6(dst, src) \
do { struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)(dst); \
do { struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)
&
(dst); \
sin6->sin6_family = AF_INET6; \
memcpy(&sin6->sin6_addr, (src), 16); \
if(IN6_IS_ADDR_LINKLOCAL (&sin6->sin6_addr)) \
SET_IN6_LINKLOCAL_IFINDEX (sin6->sin6_addr, ifindex); \
} while (0)
if
(
ipv4
)
{
PUSHADDR
(
destination
,
dest
);
if
(
metric
==
KERNEL_INFINITY
)
PUSHADDR
(
gateway
,
**
blackhole_addr
);
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
;
}
else
PUSHADDR
(
gateway
,
gate
);
}
else
{
PUSHADDR6
(
destination
,
dest
);
if
(
metric
==
KERNEL_INFINITY
)
PUSHADDR6
(
gateway
,
&
blackhole_addr6
);
else
PUSHADDR6
(
gateway
,
**
blackhole_addr6
);
else
PUSHADDR6
(
gateway
,
gate
);
}
#undef PUSHADDR
#undef PUSHADDR6
/*
W
hat if route_ifindex == 0 */
/*
w
hat if route_ifindex == 0 */
switch
(
operation
)
{
case
ROUTE_FLUSH
:
rc
=
cyginet_delete_route_entry
(
destination
,
rc
=
cyginet_delete_route_entry
(
(
struct
sockaddr
*
)
&
destination
,
prefix_len
,
gateway
,
(
struct
sockaddr
*
)
&
gateway
,
route_ifindex
,
metric
);
break
;
case
ROUTE_ADD
:
rc
=
cyginet_add_route_entry
(
destination
,
rc
=
cyginet_add_route_entry
(
(
struct
sockaddr
*
)
&
destination
,
prefix_len
,
gateway
,
(
struct
sockaddr
*
)
&
gateway
,
route_ifindex
,
metric
);
break
;
case
ROUTE_MODIFY
:
rc
=
cyginet_update_route_entry
(
destination
,
rc
=
cyginet_update_route_entry
(
(
struct
sockaddr
*
)
&
destination
,
prefix_len
,
gateway
,
(
struct
sockaddr
*
)
&
gateway
,
route_ifindex
,
metric
);
...
...
@@ -564,10 +509,6 @@ parse_kernel_route(struct cyginet_route *src, struct kernel_route *route)
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
);
}
}
else
if
(
sa
->
sa_family
==
AF_INET
)
{
struct
sockaddr_in
*
sin
=
(
struct
sockaddr_in
*
)
sa
;
v4tov6
(
route
->
gw
,
(
unsigned
char
*
)
&
sin
->
sin_addr
);
...
...
@@ -661,11 +602,6 @@ kernel_addresses(char *ifname, int ifindex, int ll,
if
(
!!
ll
!=
!!
IN6_IS_ADDR_LINKLOCAL
(
&
sin6
->
sin6_addr
))
goto
next
;
memcpy
(
routes
[
i
].
prefix
,
&
sin6
->
sin6_addr
,
16
);
if
(
ll
)
/* This a perfect example of counter-productive optimisation :
KAME encodes interface index onto bytes 2 and 3, so we have to
reset those bytes to 0 before passing them to babeld. */
memset
(
routes
[
i
].
prefix
+
2
,
0
,
2
);
routes
[
i
].
plen
=
128
;
routes
[
i
].
metric
=
0
;
routes
[
i
].
ifindex
=
ifindex
;
...
...
@@ -705,8 +641,9 @@ kernel_callback(int (*fn)(int, void*), void *closure)
/* In the Windows, we can't get the exact changed route, but the
route table is really changed. */
kdebugf
(
"Kernel table changed.
\n
"
);
cyginet_refresh_interface_table
();
clear_kernel_socket_event
();
return
fn
(
~
0
,
closure
);
}
...
...
component/babeld/net.c
View file @
582eb114
...
...
@@ -49,6 +49,11 @@ babel_socket(int port)
if
(
s
<
0
)
return
-
1
;
/* When this value is nonzero (the default on Windows), a socket
created for the AF_INET6 address family can be used to send and
receive IPv6 packets only. So it's not require to set in the
Windows XP. Actualy, this socket option is only supported on
Windows Vista or later. */
#if !defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x0600
rc
=
setsockopt
(
s
,
IPPROTO_IPV6
,
IPV6_V6ONLY
,
&
one
,
sizeof
(
one
));
if
(
rc
<
0
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment