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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Xiaohe Cao
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:
...
@@ -64,7 +64,7 @@ clean:
kernel.o
:
kernel_netlink.c kernel_socket.c kernel_cygwin.c
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
# 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)
$(CC)
$(CFLAGS)
$(LDFLAGS)
-DTEST_CYGINET
-o
$@
$<
$(LDLIBS)
component/babeld/README.cygwin
View file @
582eb114
...
@@ -46,7 +46,97 @@ Control Panel -> Network Connections.
...
@@ -46,7 +46,97 @@ Control Panel -> Network Connections.
You should see all the connections like "Local Area Connection
You should see all the connections like "Local Area Connection
3". Right click and rename this to something shorter and without
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
Notes
=====
=====
...
@@ -66,22 +156,31 @@ Notes
...
@@ -66,22 +156,31 @@ Notes
5. Ipv6 option "IPV6_V6ONLY" only works in the Windows Vista later.
5. Ipv6 option "IPV6_V6ONLY" only works in the Windows Vista later.
6. If one connection is assigned more than one ipv4 address, babeld
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
7. Regarding IPV6CTL_FORWARDING and IPV6CTL_SENDREDIRECTS, MSDN says
that you can set both of options for Ipv4 in the registry:
that you can set both of options in the registry:
"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters",
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
"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
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
the kernel_cygwin.c!kernel_route, we only use local address as
gateway in the BLACKHOLE route entry. Is it OK?
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
A: It's not OK actually
for ipv4. In the Windows, you can't use
gateway when add route entry. So the solution is find one
127.0.0.1 as gateway when add route entry. So the solution is
interface other than loopback interface, then use its
find one
interface other than loopback interface, then use its
uni-address as gateway, it will be a blackhole route entry. For
uni-address as gateway, it will be a blackhole route entry. For
example, if you have an interface which ip addr is
example, if you have an interface which ip addr is
192.168.128.100, and ifindex is 5, then
192.168.128.100, and ifindex is 5, then
...
@@ -92,3 +191,8 @@ Notes
...
@@ -92,3 +191,8 @@ Notes
9. IN6_LINKLOCAL_IFINDEX && SET_IN6_LINKLOCAL_IFINDEX, do both of them
9. IN6_LINKLOCAL_IFINDEX && SET_IN6_LINKLOCAL_IFINDEX, do both of them
work in the Windows?
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
/* The Win32 select only worked on socket handles. The Cygwin
* implementation allows select to function normally when given
* implementation allows select to function normally when given
* different types of file descriptors (sockets, pipes, handles,
* different types of file descriptors (sockets, pipes, handles,
...
@@ -58,7 +43,7 @@ void do_debugf(int level, const char *format, ...);
...
@@ -58,7 +43,7 @@ void do_debugf(int level, const char *format, ...);
static
HRESULT
(
WINAPI
*
ws_guidfromstring
)(
LPCTSTR
psz
,
LPGUID
pguid
)
=
NULL
;
static
HRESULT
(
WINAPI
*
ws_guidfromstring
)(
LPCTSTR
psz
,
LPGUID
pguid
)
=
NULL
;
static
HANDLE
event_notify_monitor_thread
=
WSA_INVALID_EVENT
;
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
int
libwinet_run_command
(
const
char
*
);
static
void
static
void
...
@@ -111,39 +96,64 @@ mask2len(const unsigned char *p, const int size)
...
@@ -111,39 +96,64 @@ mask2len(const unsigned char *p, const int size)
}
}
static
int
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
;
HKEY
hKey
;
char
cmdbuf
[
MAX_BUFFER_SIZE
];
unsigned
long
type
;
int
result
;
unsigned
long
size
;
unsigned
long
old
;
struct
if_nameindex
*
p
;
if
(
RegOpenKeyEx
(
HKEY_LOCAL_MACHINE
,
key
,
0
,
KEY_READ
|
KEY_WRITE
,
&
hKey
)
!=
struct
if_nameindex
*
ptr
;
ERROR_SUCCESS
)
if
(
NULL
==
(
ptr
=
(
struct
if_nameindex
*
)
if_nameindex
()))
return
-
1
;
return
-
1
;
p
=
ptr
;
size
=
sizeof
(
old
);
while
(
p
->
if_index
)
{
if
(
snprintf
(
cmdbuf
,
if
(
RegQueryValueEx
(
hKey
,
name
,
NULL
,
&
type
,
(
unsigned
char
*
)
&
old
,
&
size
)
!=
MAX_BUFFER_SIZE
,
ERROR_SUCCESS
||
type
!=
REG_DWORD
)
"netsh interface ipv6 set interface %d forwarding=%s"
,
old
=
defvalue
;
p
->
if_index
,
forward
?
"enabled"
:
"disabled"
if
(
RegSetValueEx
(
hKey
,
)
>=
MAX_BUFFER_SIZE
)
name
,
break
;
0
,
if
(
libwinet_run_command
(
cmdbuf
)
!=
0
)
REG_DWORD
,
break
;
(
unsigned
char
*
)
&
value
,
p
++
;
sizeof
(
value
)
))
{
RegCloseKey
(
hKey
);
return
-
1
;
}
}
result
=
!
(
p
->
if_index
);
if_freenameindex
(
ptr
);
RegCloseKey
(
hKey
);
return
result
;
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
static
void
libwinet_free_interface_map_table
()
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
;
PLIBWINET_INTERFACE_MAP_TABLE
s
;
while
(
p
)
{
while
(
p
)
{
if
(
p
->
AdapterName
)
if
(
p
->
AdapterName
)
...
@@ -154,7 +164,22 @@ libwinet_free_interface_map_table()
...
@@ -154,7 +164,22 @@ libwinet_free_interface_map_table()
p
=
p
->
next
;
p
=
p
->
next
;
FREE
(
s
);
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
static
int
...
@@ -191,13 +216,13 @@ libwinet_refresh_interface_map_table()
...
@@ -191,13 +216,13 @@ libwinet_refresh_interface_map_table()
if
(
NO_ERROR
==
dwRet
)
{
if
(
NO_ERROR
==
dwRet
)
{
if
(
interface_map_table
)
if
(
g_
interface_map_table
)
libwinet_free_interface_map_table
();
libwinet_free_interface_map_table
();
PLIBWINET_INTERFACE_MAP_TABLE
p
;
PLIBWINET_INTERFACE_MAP_TABLE
p
;
size_t
len
;
size_t
len
;
interface_map_table
=
NULL
;
g_
interface_map_table
=
NULL
;
pTmpAdaptAddr
=
pAdaptAddr
;
pTmpAdaptAddr
=
pAdaptAddr
;
while
(
pTmpAdaptAddr
)
{
while
(
pTmpAdaptAddr
)
{
...
@@ -206,8 +231,10 @@ libwinet_refresh_interface_map_table()
...
@@ -206,8 +231,10 @@ libwinet_refresh_interface_map_table()
dwRet
=
ERROR_BUFFER_OVERFLOW
;
dwRet
=
ERROR_BUFFER_OVERFLOW
;
break
;
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
,
len
=
WideCharToMultiByte
(
CP_ACP
,
0
,
0
,
pTmpAdaptAddr
->
FriendlyName
,
pTmpAdaptAddr
->
FriendlyName
,
...
@@ -250,9 +277,8 @@ libwinet_refresh_interface_map_table()
...
@@ -250,9 +277,8 @@ libwinet_refresh_interface_map_table()
pTmpAdaptAddr
->
PhysicalAddress
,
pTmpAdaptAddr
->
PhysicalAddress
,
p
->
PhysicalAddressLength
p
->
PhysicalAddressLength
);
);
pTmpAdaptAddr
=
pTmpAdaptAddr
->
Next
;
pTmpAdaptAddr
=
pTmpAdaptAddr
->
Next
;
interface_map_table
=
p
;
g_
interface_map_table
=
p
;
}
}
if
(
ERROR_BUFFER_OVERFLOW
==
dwRet
)
if
(
ERROR_BUFFER_OVERFLOW
==
dwRet
)
...
@@ -270,62 +296,32 @@ libwinet_refresh_interface_map_table()
...
@@ -270,62 +296,32 @@ libwinet_refresh_interface_map_table()
Return 0, if the interface only binds one ip version.
Return 0, if the interface only binds one ip version.
Special case:
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
static
int
libwinet_map_ifindex
(
int
family
,
int
ifindex
)
libwinet_map_ifindex
(
int
family
,
int
ifindex
)
{
{
IP_ADAPTER_ADDRESSES
*
pAdaptAddr
=
NULL
;
/* Loopback Interface */
IP_ADAPTER_ADDRESSES
*
pTmpAdaptAddr
=
NULL
;
if
(
ifindex
==
1
)
DWORD
dwRet
=
0
;
return
1
;
DWORD
dwSize
=
0x10000
;
if
(
g_interface_map_table
==
NULL
)
DWORD
dwReturn
=
0
;
if
(
!
libwinet_refresh_interface_map_table
())
return
-
1
;
dwRet
=
GetAdaptersAddresses
(
AF_UNSPEC
,
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_interface_map_table
;
GAA_FLAG_SKIP_UNICAST
\
while
(
p
)
{
|
GAA_FLAG_SKIP_ANYCAST
\
if
(
family
==
AF_INET
&&
ifindex
==
p
->
IfIndex
&&
p
->
Ipv6IfIndex
)
|
GAA_FLAG_SKIP_MULTICAST
\
return
p
->
Ipv6IfIndex
;
|
GAA_FLAG_SKIP_DNS_SERVER
\
else
if
(
family
==
AF_INET6
&&
ifindex
==
p
->
Ipv6IfIndex
&&
p
->
IfIndex
)
|
GAA_FLAG_SKIP_FRIENDLY_NAME
,
return
p
->
IfIndex
;
NULL
,
p
=
p
->
next
;
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
);
}
}
return
0
;
return
dwReturn
;
}
}
static
int
static
int
...
@@ -526,7 +522,7 @@ libwinet_dump_ipv6_route_table(struct cyginet_route *routes,
...
@@ -526,7 +522,7 @@ libwinet_dump_ipv6_route_table(struct cyginet_route *routes,
if
(
ignored
)
if
(
ignored
)
ignored
=
0
;
ignored
=
0
;
else
if
(
!
ignored
)
{
else
if
(
!
ignored
)
{
route
.
proto
=
MIB_IPPROTO_
OTHER
;
/* ?? */
route
.
proto
=
MIB_IPPROTO_
NETMGMT
;
/* ?? */
if
((
maxroutes
>
count
)
&&
(
proute
!=
NULL
))
{
if
((
maxroutes
>
count
)
&&
(
proute
!=
NULL
))
{
memcpy
(
proute
,
&
route
,
sizeof
(
struct
cyginet_route
));
memcpy
(
proute
,
&
route
,
sizeof
(
struct
cyginet_route
));
proute
++
;
proute
++
;
...
@@ -816,8 +812,7 @@ cyginet_blackhole_index(struct in6_addr* addr6, char * addr)
...
@@ -816,8 +812,7 @@ cyginet_blackhole_index(struct in6_addr* addr6, char * addr)
dwRet
=
GetAdaptersAddresses
(
AF_UNSPEC
,
dwRet
=
GetAdaptersAddresses
(
AF_UNSPEC
,
GAA_FLAG_SKIP_ANYCAST
\
GAA_FLAG_SKIP_ANYCAST
\
|
GAA_FLAG_SKIP_MULTICAST
\
|
GAA_FLAG_SKIP_MULTICAST
\
|
GAA_FLAG_SKIP_DNS_SERVER
\
|
GAA_FLAG_SKIP_DNS_SERVER
,
|
GAA_FLAG_SKIP_FRIENDLY_NAME
,
NULL
,
NULL
,
pAdaptAddr
,
pAdaptAddr
,
&
dwSize
&
dwSize
...
@@ -829,8 +824,7 @@ cyginet_blackhole_index(struct in6_addr* addr6, char * addr)
...
@@ -829,8 +824,7 @@ cyginet_blackhole_index(struct in6_addr* addr6, char * addr)
dwRet
=
GetAdaptersAddresses
(
AF_UNSPEC
,
dwRet
=
GetAdaptersAddresses
(
AF_UNSPEC
,
GAA_FLAG_SKIP_ANYCAST
\
GAA_FLAG_SKIP_ANYCAST
\
|
GAA_FLAG_SKIP_MULTICAST
\
|
GAA_FLAG_SKIP_MULTICAST
\
|
GAA_FLAG_SKIP_DNS_SERVER
\
|
GAA_FLAG_SKIP_DNS_SERVER
,
|
GAA_FLAG_SKIP_FRIENDLY_NAME
,
NULL
,
NULL
,
pAdaptAddr
,
pAdaptAddr
,
&
dwSize
&
dwSize
...
@@ -843,16 +837,21 @@ cyginet_blackhole_index(struct in6_addr* addr6, char * addr)
...
@@ -843,16 +837,21 @@ cyginet_blackhole_index(struct in6_addr* addr6, char * addr)
if
(
pTmpAdaptAddr
->
IfIndex
if
(
pTmpAdaptAddr
->
IfIndex
&&
pTmpAdaptAddr
->
Ipv6IfIndex
&&
pTmpAdaptAddr
->
Ipv6IfIndex
&&
(
pTmpAdaptAddr
->
OperStatus
==
IfOperStatusUp
)
&&
(
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
;
PIP_ADAPTER_UNICAST_ADDRESS
p
=
pTmpAdaptAddr
->
FirstUnicastAddress
;
while
(
p
)
{
while
(
p
)
{
SOCKADDR
*
s
;
SOCKADDR
*
s
;
s
=
(
p
->
Address
).
lpSockaddr
;
s
=
(
p
->
Address
).
lpSockaddr
;
if
(
s
->
sa_family
==
AF_INET
)
if
(
s
->
sa_family
==
AF_INET
)
{
memcpy
(
addr
,
&
(((
struct
sockaddr_in
*
)
s
)
->
sin_addr
),
4
);
if
(
addr
)
else
if
(
s
->
sa_family
==
AF_INET6
)
memcpy
(
addr
,
&
(((
struct
sockaddr_in
*
)
s
)
->
sin_addr
),
4
);
memcpy
(
addr6
,
&
(((
struct
sockaddr_in6
*
)
s
)
->
sin6_addr
),
16
);
}
else
if
(
s
->
sa_family
==
AF_INET6
)
{
if
(
addr6
)
memcpy
(
addr6
,
&
(((
struct
sockaddr_in6
*
)
s
)
->
sin6_addr
),
16
);
}
p
=
p
->
Next
;
p
=
p
->
Next
;
}
}
dwReturn
=
pTmpAdaptAddr
->
Ipv6IfIndex
;
dwReturn
=
pTmpAdaptAddr
->
Ipv6IfIndex
;
...
@@ -876,15 +875,15 @@ cyginet_blackhole_index(struct in6_addr* addr6, char * addr)
...
@@ -876,15 +875,15 @@ cyginet_blackhole_index(struct in6_addr* addr6, char * addr)
* SetIpForwardEntry
* SetIpForwardEntry
*
*
* Or route command
* Or route command
*
*
* Or netsh routing add persistentroute
* Or netsh routing add persistentroute
*
*
* Or netsh routing add rtmroute
* Or netsh routing add rtmroute
*
*
* it need "Routing and Remote Access Service" running on the local
* it need "Routing and Remote Access Service" running on the local
* machine. Use 'net start remoteaccess' on the local machine to
* machine. Use 'net start remoteaccess' on the local machine to
* start the service.
* start the service.
*
*
* 2. IPv6 route: command "netsh"
* 2. IPv6 route: command "netsh"
*
*
* C:/> netsh interface ipv6 add route
* C:/> netsh interface ipv6 add route
...
@@ -918,7 +917,7 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
...
@@ -918,7 +917,7 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
const
int
MAX_BUFFER_SIZE
=
1024
;
const
int
MAX_BUFFER_SIZE
=
1024
;
const
char
*
cmdformat
=
"netsh interface ipv6 %s route "
const
char
*
cmdformat
=
"netsh interface ipv6 %s route "
"prefix=%s/%d interface=%d "
"prefix=%s/%d interface=%d "
"
%s%s %s
%d"
;
"
nexthop=%s %cmetric=
%d"
;
char
cmdbuf
[
MAX_BUFFER_SIZE
];
char
cmdbuf
[
MAX_BUFFER_SIZE
];
char
sdest
[
INET6_ADDRSTRLEN
];
char
sdest
[
INET6_ADDRSTRLEN
];
char
sgate
[
INET6_ADDRSTRLEN
];
char
sgate
[
INET6_ADDRSTRLEN
];
...
@@ -935,7 +934,8 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
...
@@ -935,7 +934,8 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
INET6_ADDRSTRLEN
INET6_ADDRSTRLEN
))
))
return
-
1
;
return
-
1
;
/* metric clause results delete route command failed, so we add
'#' to commet this clause when delete route. */
if
(
snprintf
(
cmdbuf
,
if
(
snprintf
(
cmdbuf
,
MAX_BUFFER_SIZE
,
MAX_BUFFER_SIZE
,
cmdformat
,
cmdformat
,
...
@@ -944,9 +944,8 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
...
@@ -944,9 +944,8 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
sdest
,
sdest
,
plen
,
plen
,
ifindex
,
ifindex
,
strcmp
(
sgate
,
"::"
)
==
0
?
""
:
"nexthop="
,
sgate
,
strcmp
(
sgate
,
"::"
)
==
0
?
""
:
sgate
,
cmdflag
==
RTM_DELETE
?
'#'
:
' '
,
cmdflag
==
RTM_DELETE
?
"#"
:
"metric="
,
metric
metric
)
>=
MAX_BUFFER_SIZE
)
)
>=
MAX_BUFFER_SIZE
)
return
-
1
;
return
-
1
;
...
@@ -956,23 +955,29 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
...
@@ -956,23 +955,29 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
}
}
/* Add ipv4 route before Windows Vista */
/* Add ipv4 route before Windows Vista
, use IP Helper API
*/
else
if
(
0
)
{
else
{
MIB_IPFORWARDROW
Row
;
MIB_IPFORWARDROW
Row
;
unsigned
long
Res
;
unsigned
long
Res
;
struct
in_addr
mask
;
plen2mask
(
plen
,
&
mask
);
memset
(
&
Row
,
0
,
sizeof
(
MIB_IPFORWARDROW
));
memset
(
&
Row
,
0
,
sizeof
(
MIB_IPFORWARDROW
));
Row
.
dwForwardDest
=
(((
SOCKADDR_IN
*
)
dest
)
->
sin_addr
).
S_un
.
S_addr
;
Row
.
dwForwardDest
=
(((
SOCKADDR_IN
*
)
dest
)
->
sin_addr
).
S_un
.
S_addr
;
Row
.
dwForwardPolicy
=
0
;
Row
.
dwForwardPolicy
=
0
;
Row
.
dwForwardNextHop
=
(((
SOCKADDR_IN
*
)
gate
)
->
sin_addr
).
S_un
.
S_addr
;
Row
.
dwForwardNextHop
=
(((
SOCKADDR_IN
*
)
gate
)
->
sin_addr
).
S_un
.
S_addr
;
Row
.
dwForwardIfIndex
=
libwinet_map_ifindex
(
AF_INET6
,
ifindex
);
Row
.
dwForwardIfIndex
=
libwinet_map_ifindex
(
AF_INET6
,
ifindex
);
Row
.
dwForwardMask
=
mask
.
S_un
.
S_addr
;
/*
/*
* MIB_IPROUTE_TYPE_DIRECT <==> dwForwardNextHop == dwForwardDest
* 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
* MIB_IPROUTE_TYPE_INDIRECT all the others
*/
*/
Row
.
dwForwardType
=
Row
.
dwForwardNextHop
==
Row
.
dwForwardDest
?
\
Row
.
dwForwardType
=
Row
.
dwForwardNextHop
==
Row
.
dwForwardDest
?
\
MIB_IPROUTE_TYPE_DIRECT
:
MIB_IPROUTE_TYPE_INDIRECT
;
MIB_IPROUTE_TYPE_DIRECT
:
MIB_IPROUTE_TYPE_INDIRECT
;
Row
.
dwForwardType
=
MIB_IPROUTE_TYPE_INDIRECT
;
Row
.
dwForwardProto
=
MIB_IPPROTO_NETMGMT
;
Row
.
dwForwardProto
=
MIB_IPPROTO_NETMGMT
;
Row
.
dwForwardAge
=
0
;
Row
.
dwForwardAge
=
0
;
Row
.
dwForwardNextHopAS
=
0
;
Row
.
dwForwardNextHopAS
=
0
;
...
@@ -999,7 +1004,7 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
...
@@ -999,7 +1004,7 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
return
-
1
;
return
-
1
;
}
}
/* Use route command */
#if 0 /* Use route command */
else {
else {
/* route ADD dest MASK mask gate METRIC n IF index */
/* route ADD dest MASK mask gate METRIC n IF index */
/* route CHANGE 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,
...
@@ -1036,7 +1041,7 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
MAX_BUFFER_SIZE,
MAX_BUFFER_SIZE,
"route %s %s MASK %s %s METRIC %d IF %d",
"route %s %s MASK %s %s METRIC %d IF %d",
cmdflag == RTM_ADD ? "add" :
cmdflag == RTM_ADD ? "add" :
cmdflag
==
RTM_DELETE
?
"delete"
:
"change"
,
cmdflag == RTM_DELETE ? "delete" : "change",
sdest,
sdest,
smask,
smask,
sgate,
sgate,
...
@@ -1048,6 +1053,7 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
...
@@ -1048,6 +1053,7 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
if (libwinet_run_command(cmdbuf) != 0)
if (libwinet_run_command(cmdbuf) != 0)
return -1;
return -1;
}
}
#endif /* if 0 */
#else
#else
/* Add route entry after Windows Vista */
/* Add route entry after Windows Vista */
...
@@ -1098,75 +1104,118 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
...
@@ -1098,75 +1104,118 @@ libwinet_edit_route_entry(const struct sockaddr *dest,
return
1
;
return
1
;
}
}
static
int
int
libwinet_set_registry_key
(
char
*
key
,
char
*
name
,
int
value
,
int
def
value
)
cyginet_set_interface_forwards
(
const
char
*
ifname
,
int
value
)
{
{
HKEY
hKey
;
/* For ipv4 */
unsigned
long
type
;
/* netsh routing add interface ifname enabled/disabled */
unsigned
long
size
;
char
cmdbuf
[
255
];
unsigned
long
old
;
if
(
snprintf
(
cmdbuf
,
255
,
if
(
RegOpenKeyEx
(
HKEY_LOCAL_MACHINE
,
key
,
0
,
KEY_READ
|
KEY_WRITE
,
&
hKey
)
!=
"netsh interface ipv6 set interface
\"
%s
\"
"
ERROR_SUCCESS
)
"forwarding=%s > /dev/null"
,
return
-
1
;
ifname
,
value
?
"enabled"
:
"disabled"
size
=
sizeof
(
old
);
)
>
0
)
return
system
(
cmdbuf
);
return
-
1
;
}
if
(
RegQueryValueEx
(
hKey
,
name
,
NULL
,
&
type
,
(
unsigned
char
*
)
&
old
,
&
size
)
!=
int
ERROR_SUCCESS
||
type
!=
REG_DWORD
)
cyginet_set_icmp6_redirect_accept
(
int
value
)
old
=
defvalue
;
{
char
*
key
=
"SYSTEM
\\
CurrentControlSet
\\
Services
\\
Tcpip6
\\
Parameters"
;
char
*
name
=
"EnableICMPRedirect"
;
return
libwinet_set_registry_key
(
key
,
name
,
value
,
1
);
}
if
(
RegSetValueEx
(
hKey
,
static
void
name
,
libwinet_restore_ipv6_interface
()
0
,
{
REG_DWORD
,
char
cmdbuf
[
255
];
(
unsigned
char
*
)
&
value
,
int
rc
=
0
;
sizeof
(
value
)
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_interface_map_table
;
))
{
while
(
p
)
{
RegCloseKey
(
hKey
);
if
(
p
->
RouteFlags
!=
-
1
)
return
-
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
int
cyginet_set_ipv6_forwards(int value)
cyginet_set_ipv6_forwards(int value)
{
{
char * key = "SYSTEM\\CurrentControlSet\\Services\\Tcpip6\\Parameters";
char * key = "SYSTEM\\CurrentControlSet\\Services\\Tcpip6\\Parameters";
/*
char * name = "IPEnableRouter";
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;
}
*/
return libwinet_set_registry_key(key,
return libwinet_set_registry_key(key,
"IPEnableRouter"
,
name
,
value,
value,
0
0
);
);
}
}
int
static
int
cyginet_set_icmp6_redirect_accept
(
int
value
)
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
,
struct if_nameindex * p;
"EnableICMPRedirect"
,
struct if_nameindex * ptr;
value
,
if (NULL == (ptr = (struct if_nameindex *)if_nameindex()))
1
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
* On Windows Vista and later, wireless network cards are reported as
...
@@ -1411,58 +1460,6 @@ cyginet_loopback_index(int family)
...
@@ -1411,58 +1460,6 @@ cyginet_loopback_index(int family)
return
1
;
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:
* There are 3 ways to dump route table in the Windows:
*
*
...
@@ -1632,12 +1629,17 @@ cyginet_read_route_socket(void *buffer, size_t size)
...
@@ -1632,12 +1629,17 @@ cyginet_read_route_socket(void *buffer, size_t size)
return
0
;
return
0
;
}
}
int
cyginet_refresh_interface_table
()
{
return
libwinet_refresh_interface_map_table
();
}
int
int
cyginet_startup
()
cyginet_startup
()
{
{
WORD
wVersionRequested
;
WORD
wVersionRequested
;
WSADATA
wsaData
;
WSADATA
wsaData
;
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested
=
MAKEWORD
(
2
,
2
);
wVersionRequested
=
MAKEWORD
(
2
,
2
);
return
WSAStartup
(
wVersionRequested
,
&
wsaData
);
return
WSAStartup
(
wVersionRequested
,
&
wsaData
);
...
@@ -1646,6 +1648,8 @@ cyginet_startup()
...
@@ -1646,6 +1648,8 @@ cyginet_startup()
void
void
cyginet_cleanup
()
cyginet_cleanup
()
{
{
libwinet_restore_ipv6_interface
();
libwinet_free_interface_map_table
();
WSACleanup
();
WSACleanup
();
}
}
...
@@ -1653,10 +1657,10 @@ char *
...
@@ -1653,10 +1657,10 @@ char *
cyginet_guidname
(
const
char
*
ifname
)
cyginet_guidname
(
const
char
*
ifname
)
{
{
PLIBWINET_INTERFACE_MAP_TABLE
p
;
PLIBWINET_INTERFACE_MAP_TABLE
p
;
if
(
!
interface_map_table
)
if
(
!
g_
interface_map_table
)
libwinet_refresh_interface_map_table
();
libwinet_refresh_interface_map_table
();
p
=
interface_map_table
;
p
=
g_
interface_map_table
;
while
(
p
)
{
while
(
p
)
{
if
(
strcmp
(
ifname
,
p
->
FriendlyName
)
==
0
)
if
(
strcmp
(
ifname
,
p
->
FriendlyName
)
==
0
)
return
p
->
AdapterName
;
return
p
->
AdapterName
;
...
@@ -1669,10 +1673,10 @@ char *
...
@@ -1669,10 +1673,10 @@ char *
cyginet_ifname
(
const
char
*
guidname
)
cyginet_ifname
(
const
char
*
guidname
)
{
{
PLIBWINET_INTERFACE_MAP_TABLE
p
;
PLIBWINET_INTERFACE_MAP_TABLE
p
;
if
(
!
interface_map_table
)
if
(
!
g_
interface_map_table
)
libwinet_refresh_interface_map_table
();
libwinet_refresh_interface_map_table
();
p
=
interface_map_table
;
p
=
g_
interface_map_table
;
while
(
p
)
{
while
(
p
)
{
if
(
strcmp
(
guidname
,
p
->
AdapterName
)
==
0
)
if
(
strcmp
(
guidname
,
p
->
AdapterName
)
==
0
)
return
p
->
FriendlyName
;
return
p
->
FriendlyName
;
...
@@ -1681,9 +1685,89 @@ cyginet_ifname(const char * guidname)
...
@@ -1681,9 +1685,89 @@ cyginet_ifname(const char * guidname)
return
NULL
;
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. */
/* The following functions are reserved. */
#if 0
#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
static int
libwinet_get_loopback_index(int family)
libwinet_get_loopback_index(int family)
{
{
...
@@ -2282,7 +2366,7 @@ DWORD GetInterfaceIndexForAddress(SOCKADDR *pAddr)
...
@@ -2282,7 +2366,7 @@ DWORD GetInterfaceIndexForAddress(SOCKADDR *pAddr)
FREE(pAdaptAddr);
FREE(pAdaptAddr);
}
}
return dwReturn;
return dwReturn;
}
}
...
@@ -2498,7 +2582,7 @@ runTestCases()
...
@@ -2498,7 +2582,7 @@ runTestCases()
if_freenameindex
(
ptr
);
if_freenameindex
(
ptr
);
}
}
}
}
/*
printf("\n\nTest cyginet_ipv4_index2ifname:\n\n");
printf("\n\nTest cyginet_ipv4_index2ifname:\n\n");
{
{
int ifindex = 1;
int ifindex = 1;
...
@@ -2507,10 +2591,10 @@ runTestCases()
...
@@ -2507,10 +2591,10 @@ runTestCases()
cyginet_ipv4_index2ifname(ifindex)
cyginet_ipv4_index2ifname(ifindex)
);
);
}
}
*/
printf
(
"
\n\n
Test cyginet_guidname works in the Cygwin:
\n\n
"
);
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
)
{
while
(
p
)
{
printf
(
"%s:
\t\t
%s
\n
"
,
printf
(
"%s:
\t\t
%s
\n
"
,
p
->
FriendlyName
,
p
->
FriendlyName
,
...
@@ -2546,7 +2630,7 @@ runTestCases()
...
@@ -2546,7 +2630,7 @@ runTestCases()
printf
(
"
\n\n
Test libwinet_is_wireless_interface:
\n\n
"
);
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
)
{
while
(
p
)
{
printf
(
"%s is wireless netcard: %d
\n
"
,
printf
(
"%s is wireless netcard: %d
\n
"
,
p
->
FriendlyName
,
p
->
FriendlyName
,
...
@@ -2585,6 +2669,7 @@ runTestCases()
...
@@ -2585,6 +2669,7 @@ runTestCases()
}
}
}
}
/*
printf("\n\nTest cyginet_set_ipv6_forwards:\n\n");
printf("\n\nTest cyginet_set_ipv6_forwards:\n\n");
{
{
printf("cyginet_set_ipv6_forwards(1) return %d\n",
printf("cyginet_set_ipv6_forwards(1) return %d\n",
...
@@ -2604,11 +2689,12 @@ runTestCases()
...
@@ -2604,11 +2689,12 @@ runTestCases()
cyginet_set_icmp6_redirect_accept(1)
cyginet_set_icmp6_redirect_accept(1)
);
);
}
}
*/
printf
(
"
\n\n
Test cyginet_interface_wireless:
\n\n
"
);
printf
(
"
\n\n
Test cyginet_interface_wireless:
\n\n
"
);
{
{
int
n
;
int
n
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
while
(
p
)
{
while
(
p
)
{
n
=
cyginet_interface_wireless
(
p
->
FriendlyName
,
1
);
n
=
cyginet_interface_wireless
(
p
->
FriendlyName
,
1
);
printf
(
"%s is wireless netcard: %d
\n
"
,
p
->
FriendlyName
,
n
);
printf
(
"%s is wireless netcard: %d
\n
"
,
p
->
FriendlyName
,
n
);
...
@@ -2619,7 +2705,7 @@ runTestCases()
...
@@ -2619,7 +2705,7 @@ runTestCases()
printf
(
"
\n\n
Test cyginet_interface_mtu:
\n\n
"
);
printf
(
"
\n\n
Test cyginet_interface_mtu:
\n\n
"
);
{
{
int
n
;
int
n
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
while
(
p
)
{
while
(
p
)
{
n
=
cyginet_interface_mtu
(
p
->
FriendlyName
,
1
);
n
=
cyginet_interface_mtu
(
p
->
FriendlyName
,
1
);
printf
(
"mtu of %s is : %d
\n
"
,
p
->
FriendlyName
,
n
);
printf
(
"mtu of %s is : %d
\n
"
,
p
->
FriendlyName
,
n
);
...
@@ -2630,7 +2716,7 @@ runTestCases()
...
@@ -2630,7 +2716,7 @@ runTestCases()
printf
(
"
\n\n
Test cyginet_interface_operational:
\n\n
"
);
printf
(
"
\n\n
Test cyginet_interface_operational:
\n\n
"
);
{
{
int
n
;
int
n
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
while
(
p
)
{
while
(
p
)
{
n
=
cyginet_interface_operational
(
p
->
FriendlyName
,
1
);
n
=
cyginet_interface_operational
(
p
->
FriendlyName
,
1
);
printf
(
"%s is up: %d
\n
"
,
p
->
FriendlyName
,
n
);
printf
(
"%s is up: %d
\n
"
,
p
->
FriendlyName
,
n
);
...
@@ -2642,7 +2728,7 @@ runTestCases()
...
@@ -2642,7 +2728,7 @@ runTestCases()
{
{
struct
sockaddr_in
sa
;
struct
sockaddr_in
sa
;
int
n
;
int
n
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
while
(
p
)
{
while
(
p
)
{
memset
(
&
sa
,
0
,
sizeof
(
sa
));
memset
(
&
sa
,
0
,
sizeof
(
sa
));
n
=
cyginet_interface_ipv4
(
p
->
FriendlyName
,
1
,
(
unsigned
char
*
)
&
sa
);
n
=
cyginet_interface_ipv4
(
p
->
FriendlyName
,
1
,
(
unsigned
char
*
)
&
sa
);
...
@@ -2655,7 +2741,7 @@ runTestCases()
...
@@ -2655,7 +2741,7 @@ runTestCases()
{
{
int
n
;
int
n
;
struct
sockaddr_dl
sdl
;
struct
sockaddr_dl
sdl
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
interface_map_table
;
PLIBWINET_INTERFACE_MAP_TABLE
p
=
g_
interface_map_table
;
while
(
p
)
{
while
(
p
)
{
memset
(
&
sdl
,
0
,
sizeof
(
struct
sockaddr_dl
));
memset
(
&
sdl
,
0
,
sizeof
(
struct
sockaddr_dl
));
n
=
cyginet_interface_sdl
(
&
sdl
,
p
->
FriendlyName
);
n
=
cyginet_interface_sdl
(
&
sdl
,
p
->
FriendlyName
);
...
@@ -2767,9 +2853,9 @@ runTestCases()
...
@@ -2767,9 +2853,9 @@ runTestCases()
if
(
inet_pton
(
AF_INET
,
"192.168.128.119"
,
&
dest4
.
sin_addr
)
!=
1
)
if
(
inet_pton
(
AF_INET
,
"192.168.128.119"
,
&
dest4
.
sin_addr
)
!=
1
)
break
;
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
;
break
;
ifindex
=
2
;
ifindex
=
5
;
metric
=
3
;
metric
=
3
;
prefix
=
32
;
prefix
=
32
;
...
@@ -2877,10 +2963,11 @@ int main(int argc, char* argv[])
...
@@ -2877,10 +2963,11 @@ int main(int argc, char* argv[])
printf
(
"
\n\n
Test libwinet_refresh_interface_map_table:
\n\n
"
);
printf
(
"
\n\n
Test libwinet_refresh_interface_map_table:
\n\n
"
);
{
{
if
(
libwinet_refresh_interface_map_table
())
{
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
)
{
while
(
p
)
{
printf
(
"Friendly Name:
\t
%s
\n
"
,
p
->
FriendlyName
);
printf
(
"Friendly Name:
\t
%s
\n
"
,
p
->
FriendlyName
);
printf
(
"Adapter Name:
\t
%s
\n
"
,
p
->
AdapterName
);
printf
(
"Adapter Name:
\t
%s
\n
"
,
p
->
AdapterName
);
printf
(
"Forward flag:
\t
%d
\n
"
,
p
->
RouteFlags
);
printf
(
"IfType:
\t
%ld
\n
"
,
p
->
IfType
);
printf
(
"IfType:
\t
%ld
\n
"
,
p
->
IfType
);
p
=
p
->
next
;
p
=
p
->
next
;
}
}
...
@@ -2891,8 +2978,15 @@ int main(int argc, char* argv[])
...
@@ -2891,8 +2978,15 @@ int main(int argc, char* argv[])
runTestCases
();
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
"
);
printf
(
"
\n\n
Test libwinet_free_interface_map_table:
\n\n
"
);
libwinet_free_interface_map_table
();
libwinet_free_interface_map_table
();
printf
(
"
\n\n
Test Finished.
\n\n
"
);
WSACleanup
();
WSACleanup
();
return
0
;
return
0
;
...
...
component/babeld/cyginet.h
View file @
582eb114
...
@@ -46,15 +46,50 @@
...
@@ -46,15 +46,50 @@
IPv6 RFCs and Standards Working Groups
IPv6 RFCs and Standards Working Groups
http://www.ipv6now.com.au/RFC.php
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
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
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
An introduction to the IPv6 protocol along with overviews on
clients such as routing protocols.
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__
#ifndef __CYGIFNET_H__
...
@@ -112,12 +147,15 @@ struct if_nameindex {
...
@@ -112,12 +147,15 @@ struct if_nameindex {
char
*
if_name
;
char
*
if_name
;
};
};
typedef
struct
_LIBWINET_INTERFACE_MAP_TABLE
{
typedef
struct
_LIBWINET_INTERFACE_MAP_TABLE
{
PCHAR
FriendlyName
;
PCHAR
FriendlyName
;
PCHAR
AdapterName
;
PCHAR
AdapterName
;
BYTE
PhysicalAddress
[
MAX_ADAPTER_ADDRESS_LENGTH
];
BYTE
PhysicalAddress
[
MAX_ADAPTER_ADDRESS_LENGTH
];
DWORD
PhysicalAddressLength
;
DWORD
PhysicalAddressLength
;
DWORD
IfType
;
DWORD
IfType
;
int
RouteFlags
;
DWORD
IfIndex
;
DWORD
Ipv6IfIndex
;
VOID
*
next
;
VOID
*
next
;
}
LIBWINET_INTERFACE_MAP_TABLE
,
*
PLIBWINET_INTERFACE_MAP_TABLE
;
}
LIBWINET_INTERFACE_MAP_TABLE
,
*
PLIBWINET_INTERFACE_MAP_TABLE
;
...
@@ -163,8 +201,8 @@ void cyginet_cleanup();
...
@@ -163,8 +201,8 @@ void cyginet_cleanup();
int
cyginet_start_monitor_route_changes
(
int
);
int
cyginet_start_monitor_route_changes
(
int
);
int
cyginet_stop_monitor_route_changes
();
int
cyginet_stop_monitor_route_changes
();
int
cyginet_set_ipv6_forwards
(
int
);
int
cyginet_set_icmp6_redirect_accept
(
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_sdl
(
struct
sockaddr_dl
*
,
char
*
);
int
cyginet_interface_wireless
(
const
char
*
,
int
);
int
cyginet_interface_wireless
(
const
char
*
,
int
);
...
@@ -182,10 +220,9 @@ int cyginet_delete_route_entry(const struct sockaddr *, unsigned short,
...
@@ -182,10 +220,9 @@ int cyginet_delete_route_entry(const struct sockaddr *, unsigned short,
int
cyginet_update_route_entry
(
const
struct
sockaddr
*
,
unsigned
short
,
int
cyginet_update_route_entry
(
const
struct
sockaddr
*
,
unsigned
short
,
const
struct
sockaddr
*
,
int
,
unsigned
int
);
const
struct
sockaddr
*
,
int
,
unsigned
int
);
int
cyginet_add_ipentry
(
int
,
struct
sockaddr
*
);
char
*
cyginet_ifname
(
const
char
*
);
char
*
cyginet_ifname
(
const
char
*
);
char
*
cyginet_guidname
(
const
char
*
);
char
*
cyginet_guidname
(
const
char
*
);
char
*
cyginet_ipv4_index2ifname
(
int
);
int
cyginet_refresh_interface_table
();
int
cyginet_blackhole_index
(
struct
in6_addr
*
,
char
*
);
#endif
/* __CYGIFNET_H__ */
#endif
/* __CYGIFNET_H__ */
component/babeld/kernel_cygwin.c
View file @
582eb114
...
@@ -43,38 +43,15 @@ THE SOFTWARE.
...
@@ -43,38 +43,15 @@ THE SOFTWARE.
#include "neighbour.h"
#include "neighbour.h"
#include "kernel.h"
#include "kernel.h"
#include "util.h"
#include "util.h"
#include "interface.h"
#include "cyginet.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
int
get_sdl
(
struct
sockaddr_dl
*
sdl
,
char
*
guidname
);
static
const
unsigned
char
v4prefix
[
16
]
=
static
const
unsigned
char
v4prefix
[
16
]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0xFF
,
0xFF
,
0
,
0
,
0
,
0
};
{
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
export_table
=
-
1
,
import_table
=
-
1
;
int
int
...
@@ -110,113 +87,98 @@ get_sdl(struct sockaddr_dl *sdl, char *ifname)
...
@@ -110,113 +87,98 @@ get_sdl(struct sockaddr_dl *sdl, char *ifname)
return
cyginet_interface_sdl
(
sdl
,
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_forwarding
=
-
1
;
static
int
old_accept_redirects
=
-
1
;
static
int
old_accept_redirects
=
-
1
;
static
int
ifindex_lo
=
1
;
static
int
ifindex_lo
=
1
;
static
int
kernel_pipe_handles
[
2
];
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
int
kernel_setup
(
int
setup
)
kernel_setup
(
int
setup
)
{
{
int
rc
=
0
;
int
flags
=
0
;
int
forwarding
=
1
;
struct
interface
*
ifp
;
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.
*
*/
if
(
setup
)
{
if
(
setup
)
{
int
flags
;
if
(
0
!=
cyginet_startup
())
if
(
0
!=
cyginet_startup
())
return
-
1
;
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;
return -1;
}
}
old_forwarding
=
rc
;
reboot
=
(
rc
==
forwarding
)
?
reboot
:
1
;
if
((
rc
=
cyginet_set_icmp6_redirect_accept
(
accept_redirects
))
==
-
1
)
{
if (rc) {
fprintf
(
stderr
,
"Cannot disable ICMPv6 redirect.
\n
"
);
fprintf(stderr,
if
(
reboot
)
"Disable ICMPv6 redirect successfully. Reboot computer "
cyginet_set_ipv6_forwards
(
old_forwarding
);
"to take it effect now.\n\n"
);
return -1;
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
)
if
(
pipe
(
kernel_pipe_handles
)
==
-
1
)
return
-
1
;
return
-
1
;
if
((
flags
=
fcntl
(
kernel_pipe_handles
[
0
],
F_GETFL
,
0
))
<
0
)
if
((
flags
=
fcntl
(
kernel_pipe_handles
[
0
],
F_GETFL
,
0
))
<
0
)
...
@@ -225,34 +187,14 @@ kernel_setup(int setup)
...
@@ -225,34 +187,14 @@ kernel_setup(int setup)
goto
error
;
goto
error
;
}
}
else
{
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
[
0
]);
close
(
kernel_pipe_handles
[
1
]);
close
(
kernel_pipe_handles
[
1
]);
cyginet_cleanup
();
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
;
return
1
;
error:
{
error:
if
(
reboot
)
{
return
-
1
;
cyginet_set_ipv6_forwards
(
old_forwarding
);
cyginet_set_icmp6_redirect_accept
(
old_accept_redirects
);
}
return
-
1
;
}
}
}
int
int
...
@@ -363,12 +305,13 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
...
@@ -363,12 +305,13 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
const
unsigned
char
*
newgate
,
int
newifindex
,
const
unsigned
char
*
newgate
,
int
newifindex
,
unsigned
int
newmetric
)
unsigned
int
newmetric
)
{
{
char
blackhole_addr6
[
1
][
1
][
16
]
=
{{{
0
}}};
char
blackhole_addr
[
1
][
1
][
16
]
=
{{{
0
}}};
int
rc
,
ipv4
;
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
route_ifindex
;
int
prefix_len
;
int
prefix_len
;
struct
sockaddr_storage
destination
=
{
0
};
struct
sockaddr_storage
gateway
=
{
0
};
/* Check that the protocol family is consistent. */
/* Check that the protocol family is consistent. */
if
(
plen
>=
96
&&
v4mapped
(
dest
))
{
if
(
plen
>=
96
&&
v4mapped
(
dest
))
{
...
@@ -377,16 +320,12 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
...
@@ -377,16 +320,12 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
return
-
1
;
return
-
1
;
}
}
ipv4
=
1
;
ipv4
=
1
;
destination
=
(
struct
sockaddr
*
)
&
ipv4_destnation
;
gateway
=
(
struct
sockaddr
*
)
&
ipv4_gateway
;
}
else
{
}
else
{
if
(
v4mapped
(
gate
))
{
if
(
v4mapped
(
gate
))
{
errno
=
EINVAL
;
errno
=
EINVAL
;
return
-
1
;
return
-
1
;
}
}
ipv4
=
0
;
ipv4
=
0
;
destination
=
(
struct
sockaddr
*
)
&
ipv6_destnation
;
gateway
=
(
struct
sockaddr
*
)
&
ipv6_gateway
;
}
}
if
(
operation
==
ROUTE_MODIFY
&&
newmetric
==
metric
&&
if
(
operation
==
ROUTE_MODIFY
&&
newmetric
==
metric
&&
...
@@ -394,9 +333,8 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
...
@@ -394,9 +333,8 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
return
0
;
return
0
;
if
(
operation
==
ROUTE_MODIFY
)
{
if
(
operation
==
ROUTE_MODIFY
)
{
/* Do not use ROUTE_MODIFY when changing to a neighbour.
if
((
metric
==
KERNEL_INFINITY
)
||
It is the only way to remove the "gateway" flag. */
(
ipv4
&&
plen
==
128
&&
memcmp
(
dest
,
newgate
,
16
)
==
0
))
{
if
(
ipv4
&&
plen
==
128
&&
memcmp
(
dest
,
newgate
,
16
)
==
0
)
{
kernel_route
(
ROUTE_FLUSH
,
dest
,
plen
,
kernel_route
(
ROUTE_FLUSH
,
dest
,
plen
,
gate
,
ifindex
,
metric
,
gate
,
ifindex
,
metric
,
NULL
,
0
,
0
);
NULL
,
0
,
0
);
...
@@ -409,6 +347,13 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
...
@@ -409,6 +347,13 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
ifindex
=
newifindex
;
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
"
,
kdebugf
(
"kernel_route: %s %s/%d metric %d dev %d nexthop %s
\n
"
,
operation
==
ROUTE_ADD
?
"add"
:
operation
==
ROUTE_ADD
?
"add"
:
...
@@ -423,70 +368,70 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
...
@@ -423,70 +368,70 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
if
(
metric
==
KERNEL_INFINITY
)
{
if
(
metric
==
KERNEL_INFINITY
)
{
/* It means this route has property: RTF_BLACKHOLE */
/* It means this route has property: RTF_BLACKHOLE */
if
(
ifindex_blackhole
<
0
)
{
if
(
ifindex_lo
<
0
)
{
/* ifindex_blackhole = cyginet_blackhole_index(&blackhole_addr6, */
ifindex_lo
=
cyginet_loopback_index
(
AF_UNSPEC
);
/* blackhole_addr[0][0]+12 */
if
(
ifindex_lo
<=
0
)
/* ); */
ifindex_blackhole
=
1
;
if
(
ifindex_blackhole
<=
0
)
return
-
1
;
return
-
1
;
}
}
route_ifindex
=
ifindex_
blackhole
;
route_ifindex
=
ifindex_
lo
;
}
}
#define PUSHADDR(dst, src) \
#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; \
sin->sin_family = AF_INET; \
memcpy(&sin->sin_addr, (src) + 12, 4); \
memcpy(&sin->sin_addr, (src) + 12, 4); \
} while (0)
} while (0)
#define PUSHADDR6(dst, src) \
#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; \
sin6->sin6_family = AF_INET6; \
memcpy(&sin6->sin6_addr, (src), 16); \
memcpy(&sin6->sin6_addr, (src), 16); \
if(IN6_IS_ADDR_LINKLOCAL (&sin6->sin6_addr)) \
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
,
**
blackhole_addr
);
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
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
,
&
blackhole_addr6
);
PUSHADDR6
(
gateway
,
**
blackhole_addr6
);
else
else
PUSHADDR6
(
gateway
,
gate
);
PUSHADDR6
(
gateway
,
gate
);
}
}
#undef PUSHADDR
#undef PUSHADDR
#undef PUSHADDR6
#undef PUSHADDR6
/*
W
hat if route_ifindex == 0 */
/*
w
hat if route_ifindex == 0 */
switch
(
operation
)
{
switch
(
operation
)
{
case
ROUTE_FLUSH
:
case
ROUTE_FLUSH
:
rc
=
cyginet_delete_route_entry
(
destination
,
rc
=
cyginet_delete_route_entry
(
(
struct
sockaddr
*
)
&
destination
,
prefix_len
,
prefix_len
,
gateway
,
(
struct
sockaddr
*
)
&
gateway
,
route_ifindex
,
route_ifindex
,
metric
metric
);
);
break
;
break
;
case
ROUTE_ADD
:
case
ROUTE_ADD
:
rc
=
cyginet_add_route_entry
(
destination
,
rc
=
cyginet_add_route_entry
(
(
struct
sockaddr
*
)
&
destination
,
prefix_len
,
prefix_len
,
gateway
,
(
struct
sockaddr
*
)
&
gateway
,
route_ifindex
,
route_ifindex
,
metric
metric
);
);
break
;
break
;
case
ROUTE_MODIFY
:
case
ROUTE_MODIFY
:
rc
=
cyginet_update_route_entry
(
destination
,
rc
=
cyginet_update_route_entry
(
(
struct
sockaddr
*
)
&
destination
,
prefix_len
,
prefix_len
,
gateway
,
(
struct
sockaddr
*
)
&
gateway
,
route_ifindex
,
route_ifindex
,
metric
metric
);
);
...
@@ -564,10 +509,6 @@ parse_kernel_route(struct cyginet_route *src, struct kernel_route *route)
...
@@ -564,10 +509,6 @@ parse_kernel_route(struct cyginet_route *src, struct kernel_route *route)
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
);
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
)
{
}
else
if
(
sa
->
sa_family
==
AF_INET
)
{
struct
sockaddr_in
*
sin
=
(
struct
sockaddr_in
*
)
sa
;
struct
sockaddr_in
*
sin
=
(
struct
sockaddr_in
*
)
sa
;
v4tov6
(
route
->
gw
,
(
unsigned
char
*
)
&
sin
->
sin_addr
);
v4tov6
(
route
->
gw
,
(
unsigned
char
*
)
&
sin
->
sin_addr
);
...
@@ -661,11 +602,6 @@ kernel_addresses(char *ifname, int ifindex, int ll,
...
@@ -661,11 +602,6 @@ kernel_addresses(char *ifname, int ifindex, int ll,
if
(
!!
ll
!=
!!
IN6_IS_ADDR_LINKLOCAL
(
&
sin6
->
sin6_addr
))
if
(
!!
ll
!=
!!
IN6_IS_ADDR_LINKLOCAL
(
&
sin6
->
sin6_addr
))
goto
next
;
goto
next
;
memcpy
(
routes
[
i
].
prefix
,
&
sin6
->
sin6_addr
,
16
);
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
].
plen
=
128
;
routes
[
i
].
metric
=
0
;
routes
[
i
].
metric
=
0
;
routes
[
i
].
ifindex
=
ifindex
;
routes
[
i
].
ifindex
=
ifindex
;
...
@@ -705,8 +641,9 @@ kernel_callback(int (*fn)(int, void*), void *closure)
...
@@ -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
/* In the Windows, we can't get the exact changed route, but the
route table is really changed. */
route table is really changed. */
kdebugf
(
"Kernel table changed.
\n
"
);
kdebugf
(
"Kernel table changed.
\n
"
);
cyginet_refresh_interface_table
();
clear_kernel_socket_event
();
clear_kernel_socket_event
();
return
fn
(
~
0
,
closure
);
return
fn
(
~
0
,
closure
);
}
}
...
...
component/babeld/net.c
View file @
582eb114
...
@@ -49,6 +49,11 @@ babel_socket(int port)
...
@@ -49,6 +49,11 @@ babel_socket(int port)
if
(
s
<
0
)
if
(
s
<
0
)
return
-
1
;
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
#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
)
...
...
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