Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
f579b6a4
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
f579b6a4
编写于
8月 26, 2016
作者:
C
clanger
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8160174: java.net.NetworkInterface - fixes and improvements for network interface listing
Reviewed-by: chegar
上级
76d193f3
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
598 addition
and
562 deletion
+598
-562
src/solaris/native/java/net/NetworkInterface.c
src/solaris/native/java/net/NetworkInterface.c
+598
-562
未找到文件。
src/solaris/native/java/net/NetworkInterface.c
浏览文件 @
f579b6a4
...
...
@@ -25,9 +25,6 @@
#include <errno.h>
#include <strings.h>
#if defined(_ALLBSD_SOURCE) && defined(__OpenBSD__)
#include <sys/types.h>
#endif
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
...
...
@@ -46,7 +43,6 @@
#if defined(__linux__)
#include <sys/ioctl.h>
#include <bits/ioctls.h>
#include <sys/utsname.h>
#include <stdio.h>
#endif
...
...
@@ -76,9 +72,23 @@
#include "net_util.h"
#if defined(__linux__)
#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
#elif defined(__solaris__)
#ifndef SIOCGLIFHWADDR
#define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq)
#endif
#define DEV_PREFIX "/dev/"
#endif
#define CHECKED_MALLOC3(_pointer, _type, _size) \
do { \
_pointer = (_type)malloc(_size); \
if (_pointer == NULL) { \
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); \
return ifs;
/* return untouched list */
\
} \
} while(0)
typedef
struct
_netaddr
{
struct
sockaddr
*
addr
;
struct
sockaddr
*
brdcast
;
...
...
@@ -135,38 +145,31 @@ static int getFlags0(JNIEnv *env, jstring ifname);
static
netif
*
enumInterfaces
(
JNIEnv
*
env
);
static
netif
*
enumIPv4Interfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
);
#if
def AF_INET6
#if
defined(AF_INET6)
static
netif
*
enumIPv6Interfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
);
#endif
static
netif
*
addif
(
JNIEnv
*
env
,
int
sock
,
const
char
*
if_name
,
netif
*
ifs
,
struct
sockaddr
*
ifr_addrP
,
int
family
,
short
prefix
);
struct
sockaddr
*
ifr_addrP
,
struct
sockaddr
*
ifr_broadaddrP
,
int
family
,
short
prefix
);
static
void
freeif
(
netif
*
ifs
);
static
int
openSocket
(
JNIEnv
*
env
,
int
proto
);
static
int
openSocketWithFallback
(
JNIEnv
*
env
,
const
char
*
ifname
);
static
short
translateIPv4AddressToPrefix
(
struct
sockaddr_in
*
addr
);
static
short
translateIPv6AddressToPrefix
(
struct
sockaddr_in6
*
addr
);
static
struct
sockaddr
*
getBroadcast
(
JNIEnv
*
env
,
int
sock
,
const
char
*
name
,
struct
sockaddr
*
brdcast_store
);
static
short
getSubnet
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
);
static
int
getIndex
(
int
sock
,
const
char
*
ifname
);
static
int
getFlags
(
int
sock
,
const
char
*
ifname
,
int
*
flags
);
static
int
getMacAddress
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
,
static
int
getMacAddress
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
,
const
struct
in_addr
*
addr
,
unsigned
char
*
buf
);
static
int
getMTU
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
);
#if defined(__solaris__)
static
netif
*
enumIPvXInterfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
,
int
family
);
static
int
getMacFromDevice
(
JNIEnv
*
env
,
const
char
*
ifname
,
unsigned
char
*
retbuf
);
#ifndef SIOCGLIFHWADDR
#define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq)
#endif
#endif
/******************* Java entry points *****************************/
...
...
@@ -276,7 +279,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0
}
// if found create a NetworkInterface
if
(
curr
!=
NULL
)
{
;
if
(
curr
!=
NULL
)
{
obj
=
createNetworkInterface
(
env
,
curr
);
}
...
...
@@ -317,7 +320,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
}
// if found create a NetworkInterface
if
(
curr
!=
NULL
)
{
;
if
(
curr
!=
NULL
)
{
obj
=
createNetworkInterface
(
env
,
curr
);
}
...
...
@@ -335,7 +338,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
{
netif
*
ifs
,
*
curr
;
#if
def AF_INET6
#if
defined(AF_INET6)
int
family
=
(
getInetAddress_family
(
env
,
iaObj
)
==
IPv4
)
?
AF_INET
:
AF_INET6
;
#else
int
family
=
AF_INET
;
...
...
@@ -353,7 +356,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
while
(
curr
!=
NULL
)
{
netaddr
*
addrP
=
curr
->
addr
;
//
I
terate through each address on the interface
//
i
terate through each address on the interface
while
(
addrP
!=
NULL
)
{
if
(
family
==
addrP
->
family
)
{
...
...
@@ -368,7 +371,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
}
}
#if
def AF_INET6
#if
defined(AF_INET6)
if
(
family
==
AF_INET6
)
{
jbyte
*
bytes
=
(
jbyte
*
)
&
(
((
struct
sockaddr_in6
*
)
addrP
->
addr
)
->
sin6_addr
);
...
...
@@ -403,7 +406,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
}
// if found create a NetworkInterface
if
(
match
)
{
;
if
(
match
)
{
obj
=
createNetworkInterface
(
env
,
curr
);
}
...
...
@@ -651,7 +654,7 @@ static int getFlags0(JNIEnv *env, jstring name) {
* populates the InetAddress array based on the IP addresses for this
* interface.
*/
jobject
createNetworkInterface
(
JNIEnv
*
env
,
netif
*
ifs
)
{
static
jobject
createNetworkInterface
(
JNIEnv
*
env
,
netif
*
ifs
)
{
jobject
netifObj
;
jobject
name
;
jobjectArray
addrArr
;
...
...
@@ -729,7 +732,7 @@ jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
}
}
#if
def AF_INET6
#if
defined(AF_INET6)
if
(
addrP
->
family
==
AF_INET6
)
{
int
scope
=
0
;
iaObj
=
(
*
env
)
->
NewObject
(
env
,
ni_ia6cls
,
ni_ia6ctrID
);
...
...
@@ -820,7 +823,7 @@ static netif *enumInterfaces(JNIEnv *env) {
// return partial list if an exception occurs in the middle of process ???
// If IPv6 is available then enumerate IPv6 addresses.
#if
def AF_INET6
#if
defined(AF_INET6)
// User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
// so we have to call ipv6_available()
...
...
@@ -846,20 +849,10 @@ static netif *enumInterfaces(JNIEnv *env) {
return
ifs
;
}
#define CHECKED_MALLOC3(_pointer, _type, _size) \
do { \
_pointer = (_type)malloc(_size); \
if (_pointer == NULL) { \
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); \
return ifs;
/* return untouched list */
\
} \
} while(0)
/*
* Frees an interface list (including any attached addresses)
* Frees an interface list (including any attached addresses)
.
*/
void
freeif
(
netif
*
ifs
)
{
static
void
freeif
(
netif
*
ifs
)
{
netif
*
currif
=
ifs
;
netif
*
child
=
NULL
;
...
...
@@ -882,8 +875,10 @@ void freeif(netif *ifs) {
}
}
netif
*
addif
(
JNIEnv
*
env
,
int
sock
,
const
char
*
if_name
,
netif
*
ifs
,
struct
sockaddr
*
ifr_addrP
,
int
family
,
short
prefix
)
static
netif
*
addif
(
JNIEnv
*
env
,
int
sock
,
const
char
*
if_name
,
netif
*
ifs
,
struct
sockaddr
*
ifr_addrP
,
struct
sockaddr
*
ifr_broadaddrP
,
int
family
,
short
prefix
)
{
netif
*
currif
=
ifs
,
*
parent
;
netaddr
*
addrP
;
...
...
@@ -897,7 +892,6 @@ netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
#endif
char
*
name_colonP
;
int
mask
;
int
isVirtual
=
0
;
int
addr_size
;
int
flags
=
0
;
...
...
@@ -910,12 +904,12 @@ netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
name
[
ifnam_size
-
1
]
=
'\0'
;
*
vname
=
0
;
// Create and populate the netaddr node. If allocation fails
// return an un-updated list.
// Create and populate the netaddr node. If allocation fails
// return an un-updated list.
// Allocate for addr and brdcast at once
// Allocate for addr and brdcast at once
#if
def AF_INET6
#if
defined(AF_INET6)
addr_size
=
(
family
==
AF_INET
)
?
sizeof
(
struct
sockaddr_in
)
:
sizeof
(
struct
sockaddr_in6
);
#else
...
...
@@ -927,23 +921,16 @@ netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
memcpy
(
addrP
->
addr
,
ifr_addrP
,
addr_size
);
addrP
->
family
=
family
;
addrP
->
brdcast
=
NULL
;
addrP
->
mask
=
prefix
;
addrP
->
next
=
0
;
if
(
family
==
AF_INET
)
{
// Deal with broadcast addr & subnet mask
struct
sockaddr
*
brdcast_to
=
(
struct
sockaddr
*
)
((
char
*
)
addrP
+
sizeof
(
netaddr
)
+
addr_size
);
addrP
->
brdcast
=
getBroadcast
(
env
,
sock
,
name
,
brdcast_to
);
if
((
*
env
)
->
ExceptionCheck
(
env
)
==
JNI_TRUE
)
{
return
ifs
;
}
if
((
mask
=
getSubnet
(
env
,
sock
,
name
))
!=
-
1
)
{
addrP
->
mask
=
mask
;
}
else
if
((
*
env
)
->
ExceptionCheck
(
env
))
{
return
ifs
;
}
}
// for IPv4 add broadcast address
if
(
family
==
AF_INET
&&
ifr_broadaddrP
!=
NULL
)
{
addrP
->
brdcast
=
(
struct
sockaddr
*
)
((
char
*
)
addrP
+
sizeof
(
netaddr
)
+
addr_size
);
memcpy
(
addrP
->
brdcast
,
ifr_broadaddrP
,
addr_size
);
}
else
{
addrP
->
brdcast
=
NULL
;
}
// Deal with virtual interface with colon notation e.g. eth0:1
name_colonP
=
strchr
(
name
,
':'
);
...
...
@@ -1042,6 +1029,57 @@ netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
return
ifs
;
}
/*
* Determines the prefix value for an AF_INET subnet address.
*/
static
short
translateIPv4AddressToPrefix
(
struct
sockaddr_in
*
addr
)
{
short
prefix
=
0
;
unsigned
int
mask
=
ntohl
(
addr
->
sin_addr
.
s_addr
);
while
(
mask
)
{
mask
<<=
1
;
prefix
++
;
}
return
prefix
;
}
/*
* Determines the prefix value for an AF_INET6 subnet address.
*/
static
short
translateIPv6AddressToPrefix
(
struct
sockaddr_in6
*
addr
)
{
short
prefix
=
0
;
u_char
*
addrBytes
=
(
u_char
*
)
&
(
addr
->
sin6_addr
);
unsigned
int
byte
,
bit
;
for
(
byte
=
0
;
byte
<
sizeof
(
struct
in6_addr
);
byte
++
,
prefix
+=
8
)
{
if
(
addrBytes
[
byte
]
!=
0xff
)
{
break
;
}
}
if
(
byte
!=
sizeof
(
struct
in6_addr
))
{
for
(
bit
=
7
;
bit
!=
0
;
bit
--
,
prefix
++
)
{
if
(
!
(
addrBytes
[
byte
]
&
(
1
<<
bit
)))
{
break
;
}
}
for
(;
bit
!=
0
;
bit
--
)
{
if
(
addrBytes
[
byte
]
&
(
1
<<
bit
))
{
prefix
=
0
;
break
;
}
}
if
(
prefix
>
0
)
{
byte
++
;
for
(;
byte
<
sizeof
(
struct
in6_addr
);
byte
++
)
{
if
(
addrBytes
[
byte
])
{
prefix
=
0
;
}
}
}
}
return
prefix
;
}
/*
* Opens a socket for further ioct calls. proto is one of AF_INET or AF_INET6.
*/
...
...
@@ -1061,19 +1099,16 @@ static int openSocket(JNIEnv *env, int proto) {
return
sock
;
}
/** Linux **/
#if defined(__linux__)
/** Linux, AIX **/
#if defined(__linux__) || defined(_AIX)
#ifdef AF_INET6
#if defined(AF_INET6)
/*
* Opens a socket for further ioct calls. Tries AF_INET socket first and
* if it fa
l
ls return AF_INET6 socket.
* Opens a socket for further ioct
l
calls. Tries AF_INET socket first and
* if it fa
i
ls return AF_INET6 socket.
*/
// unused arg ifname and struct if2
static
int
openSocketWithFallback
(
JNIEnv
*
env
,
const
char
*
ifname
)
{
int
sock
;
struct
ifreq
if2
;
if
((
sock
=
JVM_Socket
(
AF_INET
,
SOCK_DGRAM
,
0
))
<
0
)
{
if
(
errno
==
EPROTONOSUPPORT
)
{
...
...
@@ -1093,63 +1128,82 @@ static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
// IPv6 socket regardless of type of address of an interface.
return
sock
;
}
#else
static
int
openSocketWithFallback
(
JNIEnv
*
env
,
const
char
*
ifname
)
{
return
openSocket
(
env
,
AF_INET
);
return
openSocket
(
env
,
AF_INET
);
}
#endif
/*
* Enumerates and returns all IPv4 interfaces on Linux.
*/
static
netif
*
enumIPv4Interfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
)
{
struct
ifconf
ifc
;
struct
ifreq
*
ifreqP
;
char
*
buf
=
NULL
;
int
numifs
;
unsigned
i
;
int
siocgifconfRequest
=
SIOCGIFCONF
;
#if defined(__linux__)
// need to do a dummy SIOCGIFCONF to determine the buffer size.
// do a dummy SIOCGIFCONF to determine the buffer size
// SIOCGIFCOUNT doesn't work
ifc
.
ifc_buf
=
NULL
;
if
(
ioctl
(
sock
,
SIOCGIFCONF
,
(
char
*
)
&
ifc
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGIFCONF failed"
);
return
ifs
;
}
#elif defined(_AIX)
ifc
.
ifc_buf
=
NULL
;
if
(
ioctl
(
sock
,
SIOCGSIZIFCONF
,
&
(
ifc
.
ifc_len
))
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGSIZIFCONF failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGIFCONF) failed"
);
return
ifs
;
}
#endif
/* __linux__ */
// call SIOCGIFCONF to enumerate the interfaces
CHECKED_MALLOC3
(
buf
,
char
*
,
ifc
.
ifc_len
);
ifc
.
ifc_buf
=
buf
;
#if defined(_AIX)
siocgifconfRequest
=
CSIOCGIFCONF
;
#endif
if
(
ioctl
(
sock
,
siocgifconfRequest
,
(
char
*
)
&
ifc
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGIFCONF failed"
);
if
(
ioctl
(
sock
,
SIOCGIFCONF
,
(
char
*
)
&
ifc
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGIFCONF) failed"
);
free
(
buf
);
return
ifs
;
}
//
I
terate through each interface
//
i
terate through each interface
ifreqP
=
ifc
.
ifc_req
;
for
(
i
=
0
;
i
<
ifc
.
ifc_len
/
sizeof
(
struct
ifreq
);
i
++
,
ifreqP
++
)
{
#if defined(_AIX)
if
(
ifreqP
->
ifr_addr
.
sa_family
!=
AF_INET
)
continue
;
#endif
// Add to the list
struct
sockaddr
addr
,
broadaddr
,
*
broadaddrP
=
NULL
;
short
prefix
=
0
;
// ignore non IPv4 interfaces
if
(
ifreqP
->
ifr_addr
.
sa_family
!=
AF_INET
)
{
continue
;
}
// save socket address
memcpy
(
&
addr
,
&
(
ifreqP
->
ifr_addr
),
sizeof
(
struct
sockaddr
));
// determine broadcast address, if applicable
if
((
ioctl
(
sock
,
SIOCGIFFLAGS
,
ifreqP
)
==
0
)
&&
ifreqP
->
ifr_flags
&
IFF_BROADCAST
)
{
// restore socket address to ifreqP
memcpy
(
&
(
ifreqP
->
ifr_addr
),
&
addr
,
sizeof
(
struct
sockaddr
));
if
(
ioctl
(
sock
,
SIOCGIFBRDADDR
,
ifreqP
)
==
0
)
{
memcpy
(
&
broadaddr
,
&
(
ifreqP
->
ifr_broadaddr
),
sizeof
(
struct
sockaddr
));
broadaddrP
=
&
broadaddr
;
}
}
// restore socket address to ifreqP
memcpy
(
&
(
ifreqP
->
ifr_addr
),
&
addr
,
sizeof
(
struct
sockaddr
));
// determine netmask
if
(
ioctl
(
sock
,
SIOCGIFNETMASK
,
ifreqP
)
==
0
)
{
prefix
=
translateIPv4AddressToPrefix
(
(
struct
sockaddr_in
*
)
&
(
ifreqP
->
ifr_netmask
));
}
// add interface to the list
ifs
=
addif
(
env
,
sock
,
ifreqP
->
ifr_name
,
ifs
,
(
struct
sockaddr
*
)
&
(
ifreqP
->
ifr_addr
),
AF_INET
,
0
);
&
addr
,
broadaddrP
,
AF_INET
,
prefix
);
//
If an exception occurred then free the list
//
in case of exception, free interface list and buffer and return NULL
if
((
*
env
)
->
ExceptionOccurred
(
env
))
{
free
(
buf
);
freeif
(
ifs
);
...
...
@@ -1157,23 +1211,20 @@ static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
}
}
//
Free socket and
buffer
//
free
buffer
free
(
buf
);
return
ifs
;
}
#if defined(AF_INET6) && defined(__linux__)
#if defined(AF_INET6)
/*
* Enumerates and returns all IPv6 interfaces on Linux.
*/
static
netif
*
enumIPv6Interfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
)
{
FILE
*
f
;
char
addr6
[
40
],
devname
[
21
];
char
addr6p
[
8
][
5
];
char
devname
[
21
],
addr6p
[
8
][
5
];
int
prefix
,
scope
,
dad_status
,
if_idx
;
uint8_t
ipv6addr
[
16
];
if
((
f
=
fopen
(
_PATH_PROCNET_IFINET6
,
"r"
))
!=
NULL
)
{
while
(
fscanf
(
f
,
"%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s
\n
"
,
...
...
@@ -1181,108 +1232,216 @@ static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
addr6p
[
4
],
addr6p
[
5
],
addr6p
[
6
],
addr6p
[
7
],
&
if_idx
,
&
prefix
,
&
scope
,
&
dad_status
,
devname
)
!=
EOF
)
{
struct
netif
*
ifs_ptr
=
NULL
;
struct
netif
*
last_ptr
=
NULL
;
char
addr6
[
40
];
struct
sockaddr_in6
addr
;
sprintf
(
addr6
,
"%s:%s:%s:%s:%s:%s:%s:%s"
,
addr6p
[
0
],
addr6p
[
1
],
addr6p
[
2
],
addr6p
[
3
],
addr6p
[
4
],
addr6p
[
5
],
addr6p
[
6
],
addr6p
[
7
]);
inet_pton
(
AF_INET6
,
addr6
,
ipv6addr
);
memset
(
&
addr
,
0
,
sizeof
(
struct
sockaddr_in6
));
memcpy
((
void
*
)
addr
.
sin6_addr
.
s6_addr
,
(
const
void
*
)
ipv6addr
,
16
);
inet_pton
(
AF_INET6
,
addr6
,
(
void
*
)
addr
.
sin6_addr
.
s6_addr
);
// set scope ID to interface index
addr
.
sin6_scope_id
=
if_idx
;
// add interface to the list
ifs
=
addif
(
env
,
sock
,
devname
,
ifs
,
(
struct
sockaddr
*
)
&
addr
,
AF_INET6
,
(
short
)
prefix
);
NULL
,
AF_INET6
,
(
short
)
prefix
);
//
If an exception occurred then return the list as is.
//
if an exception occurred then return the list as is
if
((
*
env
)
->
ExceptionOccurred
(
env
))
{
fclose
(
f
);
return
ifs
;
break
;
}
}
fclose
(
f
);
}
return
ifs
;
}
#endif
#endif
/* AF_INET6 */
#if defined(AF_INET6) && defined(_AIX)
/*
* Try to get the interface index.
*/
static
int
getIndex
(
int
sock
,
const
char
*
name
)
{
struct
ifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
ifr_name
,
name
,
sizeof
(
if2
.
ifr_name
)
-
1
);
if
(
ioctl
(
sock
,
SIOCGIFINDEX
,
(
char
*
)
&
if2
)
<
0
)
{
return
-
1
;
}
return
if2
.
ifr_ifindex
;
}
/*
* Enumerates and returns all IPv6 interfaces on AIX.
* Gets the Hardware address (usually MAC address) for the named interface.
* On return puts the data in buf, and returns the length, in byte, of the
* MAC address. Returns -1 if there is no hardware address on that interface.
*/
static
netif
*
enumIPv6Interfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
)
{
static
int
getMacAddress
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
,
const
struct
in_addr
*
addr
,
unsigned
char
*
buf
)
{
static
struct
ifreq
ifr
;
int
i
;
memset
((
char
*
)
&
ifr
,
0
,
sizeof
(
ifr
));
strncpy
(
ifr
.
ifr_name
,
ifname
,
sizeof
(
ifr
.
ifr_name
)
-
1
);
if
(
ioctl
(
sock
,
SIOCGIFHWADDR
,
&
ifr
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGIFHWADDR) failed"
);
return
-
1
;
}
memcpy
(
buf
,
&
ifr
.
ifr_hwaddr
.
sa_data
,
IFHWADDRLEN
);
// all bytes to 0 means no hardware address
for
(
i
=
0
;
i
<
IFHWADDRLEN
;
i
++
)
{
if
(
buf
[
i
]
!=
0
)
return
IFHWADDRLEN
;
}
return
-
1
;
}
static
int
getMTU
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
)
{
struct
ifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
ifr_name
,
ifname
,
sizeof
(
if2
.
ifr_name
)
-
1
);
if
(
ioctl
(
sock
,
SIOCGIFMTU
,
(
char
*
)
&
if2
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGIFMTU) failed"
);
return
-
1
;
}
return
if2
.
ifr_mtu
;
}
static
int
getFlags
(
int
sock
,
const
char
*
ifname
,
int
*
flags
)
{
struct
ifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
ifr_name
,
ifname
,
sizeof
(
if2
.
ifr_name
)
-
1
);
if
(
ioctl
(
sock
,
SIOCGIFFLAGS
,
(
char
*
)
&
if2
)
<
0
)
{
return
-
1
;
}
if
(
sizeof
(
if2
.
ifr_flags
)
==
sizeof
(
short
))
{
*
flags
=
(
if2
.
ifr_flags
&
0xffff
);
}
else
{
*
flags
=
if2
.
ifr_flags
;
}
return
0
;
}
#endif
/* __linux__ */
/** AIX **/
#if defined(_AIX)
#if defined(AF_INET6)
/*
* Opens a socket for further ioctl calls. Tries AF_INET socket first and
* if it fails return AF_INET6 socket.
*/
static
int
openSocketWithFallback
(
JNIEnv
*
env
,
const
char
*
ifname
)
{
int
sock
;
if
((
sock
=
socket
(
AF_INET
,
SOCK_DGRAM
,
0
))
<
0
)
{
if
(
errno
==
EPROTONOSUPPORT
)
{
if
((
sock
=
socket
(
AF_INET6
,
SOCK_DGRAM
,
0
))
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"IPV6 Socket creation failed"
);
return
-
1
;
}
}
else
{
// errno is not NOSUPPORT
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"IPV4 Socket creation failed"
);
return
-
1
;
}
}
return
sock
;
}
#else
static
int
openSocketWithFallback
(
JNIEnv
*
env
,
const
char
*
ifname
)
{
return
openSocket
(
env
,
AF_INET
);
}
#endif
/*
* Enumerates and returns all IPv4 interfaces on AIX.
*/
static
netif
*
enumIPv4Interfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
)
{
struct
ifconf
ifc
;
struct
ifreq
*
ifreqP
;
char
*
buf
;
int
numifs
;
char
*
buf
=
NULL
;
unsigned
i
;
unsigned
bufsize
;
char
*
cp
,
*
cplimit
;
// use SIOCGSIZIFCONF to get size for SIOCGIFCONF
ifc
.
ifc_buf
=
NULL
;
// call SIOCGSIZIFCONF to get the size of SIOCGIFCONF buffer
if
(
ioctl
(
sock
,
SIOCGSIZIFCONF
,
&
(
ifc
.
ifc_len
))
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGSIZIFCONF
failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGSIZIFCONF)
failed"
);
return
ifs
;
}
bufsize
=
ifc
.
ifc_len
;
buf
=
(
char
*
)
malloc
(
bufsize
);
if
(
!
buf
)
{
JNU_ThrowOutOfMemoryError
(
env
,
"Network interface native buffer allocation failed"
);
return
ifs
;
}
ifc
.
ifc_len
=
bufsize
;
// call CSIOCGIFCONF instead of SIOCGIFCONF where interface
// records will always have sizeof(struct ifreq) length.
// Be aware that only IPv4 data is complete this way.
CHECKED_MALLOC3
(
buf
,
char
*
,
ifc
.
ifc_len
);
ifc
.
ifc_buf
=
buf
;
if
(
ioctl
(
sock
,
SIOCGIFCONF
,
(
char
*
)
&
ifc
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl CSIOCGIFCONF
failed"
);
if
(
ioctl
(
sock
,
C
SIOCGIFCONF
,
(
char
*
)
&
ifc
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(CSIOCGIFCONF)
failed"
);
free
(
buf
);
return
ifs
;
}
//
I
terate through each interface
//
i
terate through each interface
ifreqP
=
ifc
.
ifc_req
;
cp
=
(
char
*
)
ifc
.
ifc_req
;
cplimit
=
cp
+
ifc
.
ifc_len
;
for
(
i
=
0
;
i
<
ifc
.
ifc_len
/
sizeof
(
struct
ifreq
);
i
++
,
ifreqP
++
)
{
struct
sockaddr
addr
,
broadaddr
,
*
broadaddrP
=
NULL
;
short
prefix
=
0
;
for
(;
cp
<
cplimit
;
cp
+=
(
sizeof
(
ifreqP
->
ifr_name
)
+
MAX
((
ifreqP
->
ifr_addr
).
sa_len
,
sizeof
(
ifreqP
->
ifr_addr
))))
{
ifreqP
=
(
struct
ifreq
*
)
cp
;
struct
ifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
ifr_name
,
ifreqP
->
ifr_name
,
sizeof
(
if2
.
ifr_name
)
-
1
);
// ignore non IPv4 interfaces
if
(
ifreqP
->
ifr_addr
.
sa_family
!=
AF_INET
)
{
continue
;
}
// save socket address
memcpy
(
&
addr
,
&
(
ifreqP
->
ifr_addr
),
sizeof
(
struct
sockaddr
));
// Skip interface that aren't UP
if
(
ioctl
(
sock
,
SIOCGIFFLAGS
,
(
char
*
)
&
if2
)
>=
0
)
{
if
(
!
(
if2
.
ifr_flags
&
IFF_UP
))
{
continue
;
// determine broadcast address, if applicable
if
((
ioctl
(
sock
,
SIOCGIFFLAGS
,
ifreqP
)
==
0
)
&&
ifreqP
->
ifr_flags
&
IFF_BROADCAST
)
{
// restore socket address to ifreqP
memcpy
(
&
(
ifreqP
->
ifr_addr
),
&
addr
,
sizeof
(
struct
sockaddr
));
if
(
ioctl
(
sock
,
SIOCGIFBRDADDR
,
ifreqP
)
==
0
)
{
memcpy
(
&
broadaddr
,
&
(
ifreqP
->
ifr_broadaddr
),
sizeof
(
struct
sockaddr
));
broadaddrP
=
&
broadaddr
;
}
}
if
(
ifreqP
->
ifr_addr
.
sa_family
!=
AF_INET6
)
continue
;
// restore socket address to ifreqP
memcpy
(
&
(
ifreqP
->
ifr_addr
),
&
addr
,
sizeof
(
struct
sockaddr
))
;
if
(
ioctl
(
sock
,
SIOCGIFSITE6
,
(
char
*
)
&
if2
)
>=
0
)
{
struct
sockaddr_in6
*
s6
=
(
struct
sockaddr_in6
*
)
&
(
ifreqP
->
ifr_addr
);
s6
->
sin6_scope_id
=
if2
.
ifr_site6
;
// determine netmask
if
(
ioctl
(
sock
,
SIOCGIFNETMASK
,
ifreqP
)
==
0
)
{
prefix
=
translateIPv4AddressToPrefix
(
(
struct
sockaddr_in
*
)
&
(
ifreqP
->
ifr_addr
));
}
//
Add
to the list
//
add interface
to the list
ifs
=
addif
(
env
,
sock
,
ifreqP
->
ifr_name
,
ifs
,
(
struct
sockaddr
*
)
&
(
ifreqP
->
ifr_addr
),
AF_INET6
,
0
);
&
addr
,
broadaddrP
,
AF_INET
,
prefix
);
//
If an exception occurred then free the list
//
in case of exception, free interface list and buffer and return NULL
if
((
*
env
)
->
ExceptionOccurred
(
env
))
{
free
(
buf
);
freeif
(
ifs
);
...
...
@@ -1290,89 +1449,94 @@ static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
}
}
//
Free socket and
buffer
//
free
buffer
free
(
buf
);
return
ifs
;
}
#endif
#if defined(AF_INET6)
static
int
getIndex
(
int
sock
,
const
char
*
name
)
{
// Try to get the interface index
#if defined(_AIX)
return
if_nametoindex
(
name
);
#else
struct
ifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
ifr_name
,
name
,
sizeof
(
if2
.
ifr_name
)
-
1
);
/*
* Enumerates and returns all IPv6 interfaces on AIX.
*/
static
netif
*
enumIPv6Interfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
)
{
struct
ifconf
ifc
;
struct
ifreq
*
ifreqP
;
char
*
buf
;
if
(
ioctl
(
sock
,
SIOCGIFINDEX
,
(
char
*
)
&
if2
)
<
0
)
{
return
-
1
;
// call SIOCGSIZIFCONF to get size for SIOCGIFCONF buffer
if
(
ioctl
(
sock
,
SIOCGSIZIFCONF
,
&
(
ifc
.
ifc_len
))
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGSIZIFCONF) failed"
);
return
ifs
;
}
return
if2
.
ifr_ifindex
;
#endif
}
// call SIOCGIFCONF to enumerate the interfaces
CHECKED_MALLOC3
(
buf
,
char
*
,
ifc
.
ifc_len
);
ifc
.
ifc_buf
=
buf
;
if
(
ioctl
(
sock
,
SIOCGIFCONF
,
(
char
*
)
&
ifc
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGIFCONF) failed"
);
free
(
buf
);
return
ifs
;
}
/*
* Returns the IPv4 broadcast address of a named interface, if it exists.
* Returns 0 if it doesn't have one.
*/
static
struct
sockaddr
*
getBroadcast
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
,
struct
sockaddr
*
brdcast_store
)
{
struct
sockaddr
*
ret
=
NULL
;
struct
ifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
ifr_name
,
ifname
,
sizeof
(
if2
.
ifr_name
)
-
1
);
// iterate through each interface
char
*
cp
=
(
char
*
)
ifc
.
ifc_req
;
char
*
cplimit
=
cp
+
ifc
.
ifc_len
;
// Let's make sure the interface does have a broadcast address.
if
(
ioctl
(
sock
,
SIOCGIFFLAGS
,
(
char
*
)
&
if2
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGIFFLAGS failed"
);
return
ret
;
}
for
(;
cp
<
cplimit
;
cp
+=
(
sizeof
(
ifreqP
->
ifr_name
)
+
MAX
((
ifreqP
->
ifr_addr
).
sa_len
,
sizeof
(
ifreqP
->
ifr_addr
))))
{
ifreqP
=
(
struct
ifreq
*
)
cp
;
short
prefix
=
0
;
if
(
if2
.
ifr_flags
&
IFF_BROADCAST
)
{
// It does, let's retrieve it
if
(
ioctl
(
sock
,
SIOCGIFBRDADDR
,
(
char
*
)
&
if2
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGIFBRDADDR failed"
);
return
ret
;
// ignore non IPv6 interfaces
if
(
ifreqP
->
ifr_addr
.
sa_family
!=
AF_INET6
)
{
continue
;
}
ret
=
brdcast_store
;
memcpy
(
ret
,
&
if2
.
ifr_broadaddr
,
sizeof
(
struct
sockaddr
));
}
// determine netmask
struct
in6_ifreq
if6
;
memset
((
char
*
)
&
if6
,
0
,
sizeof
(
if6
));
strncpy
(
if6
.
ifr_name
,
ifreqP
->
ifr_name
,
sizeof
(
if6
.
ifr_name
)
-
1
);
memcpy
(
&
(
if6
.
ifr_Addr
),
&
(
ifreqP
->
ifr_addr
),
sizeof
(
struct
sockaddr_in6
));
if
(
ioctl
(
sock
,
SIOCGIFNETMASK6
,
(
char
*
)
&
if6
)
>=
0
)
{
prefix
=
translateIPv6AddressToPrefix
(
&
(
if6
.
ifr_Addr
));
}
return
ret
;
}
// set scope ID to interface index
((
struct
sockaddr_in6
*
)
&
(
ifreqP
->
ifr_addr
))
->
sin6_scope_id
=
getIndex
(
sock
,
ifreqP
->
ifr_name
);
/*
* Returns the IPv4 subnet prefix length (aka subnet mask) for the named
* interface, if it has one, otherwise return -1.
*/
static
short
getSubnet
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
)
{
unsigned
int
mask
;
short
ret
;
struct
ifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
ifr_name
,
ifname
,
sizeof
(
if2
.
ifr_name
)
-
1
);
// add interface to the list
ifs
=
addif
(
env
,
sock
,
ifreqP
->
ifr_name
,
ifs
,
(
struct
sockaddr
*
)
&
(
ifreqP
->
ifr_addr
),
NULL
,
AF_INET6
,
prefix
);
if
(
ioctl
(
sock
,
SIOCGIFNETMASK
,
(
char
*
)
&
if2
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGIFNETMASK failed"
);
return
-
1
;
// if an exception occurred then free the list
if
((
*
env
)
->
ExceptionOccurred
(
env
))
{
free
(
buf
);
freeif
(
ifs
);
return
NULL
;
}
}
mask
=
ntohl
(((
struct
sockaddr_in
*
)
&
(
if2
.
ifr_addr
))
->
sin_addr
.
s_addr
);
ret
=
0
;
while
(
mask
)
{
mask
<<=
1
;
ret
++
;
}
// free buffer
free
(
buf
);
return
ifs
;
}
return
ret
;
#endif
/* AF_INET6 */
/*
* Try to get the interface index.
*/
static
int
getIndex
(
int
sock
,
const
char
*
name
)
{
int
index
=
if_nametoindex
(
name
);
return
(
index
==
0
)
?
-
1
:
index
;
}
/*
...
...
@@ -1381,10 +1545,9 @@ static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
* MAC address. Returns -1 if there is no hardware address on that interface.
*/
static
int
getMacAddress
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
,
const
struct
in_addr
*
addr
,
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
,
const
struct
in_addr
*
addr
,
unsigned
char
*
buf
)
{
#if defined (_AIX)
int
size
;
struct
kinfo_ndd
*
nddp
;
void
*
end
;
...
...
@@ -1424,48 +1587,20 @@ static int getMacAddress
}
return
-
1
;
#elif defined(__linux__)
static
struct
ifreq
ifr
;
int
i
;
memset
((
char
*
)
&
ifr
,
0
,
sizeof
(
ifr
));
strncpy
(
ifr
.
ifr_name
,
ifname
,
sizeof
(
ifr
.
ifr_name
)
-
1
);
if
(
ioctl
(
sock
,
SIOCGIFHWADDR
,
&
ifr
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGIFHWADDR failed"
);
return
-
1
;
}
memcpy
(
buf
,
&
ifr
.
ifr_hwaddr
.
sa_data
,
IFHWADDRLEN
);
// All bytes to 0 means no hardware address.
for
(
i
=
0
;
i
<
IFHWADDRLEN
;
i
++
)
{
if
(
buf
[
i
]
!=
0
)
return
IFHWADDRLEN
;
}
return
-
1
;
#endif
}
static
int
getMTU
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
)
{
static
int
getMTU
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
)
{
struct
ifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
if
(
ifname
!=
NULL
)
{
strncpy
(
if2
.
ifr_name
,
ifname
,
sizeof
(
if2
.
ifr_name
)
-
1
);
}
else
{
JNU_ThrowNullPointerException
(
env
,
"network interface name is NULL"
);
return
-
1
;
}
strncpy
(
if2
.
ifr_name
,
ifname
,
sizeof
(
if2
.
ifr_name
)
-
1
);
if
(
ioctl
(
sock
,
SIOCGIFMTU
,
(
char
*
)
&
if2
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"IOCTL SIOCGIFMTU
failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGIFMTU)
failed"
);
return
-
1
;
}
return
if2
.
ifr_mtu
;
return
if2
.
ifr_mtu
;
}
static
int
getFlags
(
int
sock
,
const
char
*
ifname
,
int
*
flags
)
{
...
...
@@ -1485,16 +1620,16 @@ static int getFlags(int sock, const char *ifname, int *flags) {
return
0
;
}
#endif
/* defined(__linux__) || defined(_AIX)
*/
#endif
/* _AIX
*/
/** Solaris **/
#if defined(__solaris__)
#if defined(AF_INET6)
/*
* Opens a socket for further ioct calls. Tries AF_INET socket first and
* if it fa
l
ls return AF_INET6 socket.
* Opens a socket for further ioct
l
calls. Tries AF_INET socket first and
* if it fa
i
ls return AF_INET6 socket.
*/
#ifdef AF_INET6
static
int
openSocketWithFallback
(
JNIEnv
*
env
,
const
char
*
ifname
)
{
int
sock
,
alreadyV6
=
0
;
struct
lifreq
if2
;
...
...
@@ -1502,35 +1637,32 @@ static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
if
((
sock
=
JVM_Socket
(
AF_INET
,
SOCK_DGRAM
,
0
))
<
0
)
{
if
(
errno
==
EPROTONOSUPPORT
)
{
if
((
sock
=
JVM_Socket
(
AF_INET6
,
SOCK_DGRAM
,
0
))
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"IPV6 Socket creation failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"IPV6 Socket creation failed"
);
return
-
1
;
}
alreadyV6
=
1
;
alreadyV6
=
1
;
}
else
{
// errno is not NOSUPPORT
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"IPV4 Socket creation failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"IPV4 Socket creation failed"
);
return
-
1
;
}
}
// Solaris requires that we have an IPv6 socket to query an interface
// without an IPv4 address - check it here. POSIX 1 require the kernel to
// return ENOTTY if the call is inappropriate for a device e.g. the NETMASK
// for a device having IPv6 only address but not all devices follow the
// standard so fall back on any error. It's not an ecologically friendly
// gesture but more reliable.
if
(
!
alreadyV6
)
{
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
lifr_name
,
ifname
,
sizeof
(
if2
.
lifr_name
)
-
1
);
if
(
ioctl
(
sock
,
SIOCGLIFNETMASK
,
(
char
*
)
&
if2
)
<
0
)
{
close
(
sock
);
if
((
sock
=
JVM_Socket
(
AF_INET6
,
SOCK_DGRAM
,
0
))
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"IPV6 Socket creation failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"IPV6 Socket creation failed"
);
return
-
1
;
}
}
...
...
@@ -1538,182 +1670,175 @@ static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
return
sock
;
}
#else
static
int
openSocketWithFallback
(
JNIEnv
*
env
,
const
char
*
ifname
)
{
return
openSocket
(
env
,
AF_INET
);
return
openSocket
(
env
,
AF_INET
);
}
#endif
/*
* Enumerates and returns all IPv4 interfaces.
* Enumerates and returns all IPv4 interfaces
on Solaris
.
*/
static
netif
*
enumIPv4Interfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
)
{
return
enumIPvXInterfaces
(
env
,
sock
,
ifs
,
AF_INET
);
}
#ifdef AF_INET6
static
netif
*
enumIPv6Interfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
)
{
return
enumIPvXInterfaces
(
env
,
sock
,
ifs
,
AF_INET6
);
}
#endif
/*
* Enumerates and returns all interfaces on Solaris.
* Uses the same code for IPv4 and IPv6.
*/
static
netif
*
enumIPvXInterfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
,
int
family
)
{
struct
lifconf
ifc
;
struct
lifreq
*
ifr
;
int
n
;
char
*
buf
;
struct
lifreq
*
ifreqP
;
struct
lifnum
numifs
;
unsigned
bufsize
;
char
*
buf
=
NULL
;
unsigned
i
;
//
Get the interface count
numifs
.
lifn_family
=
family
;
//
call SIOCGLIFNUM to get the size of SIOCGIFCONF buffer
numifs
.
lifn_family
=
AF_INET
;
numifs
.
lifn_flags
=
0
;
if
(
ioctl
(
sock
,
SIOCGLIFNUM
,
(
char
*
)
&
numifs
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGLIFNUM
failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGLIFNUM)
failed"
);
return
ifs
;
}
// Enumerate the interface configurations
bufsize
=
numifs
.
lifn_count
*
sizeof
(
struct
lifreq
);
CHECKED_MALLOC3
(
buf
,
char
*
,
bufsize
);
ifc
.
lifc_family
=
family
;
ifc
.
lifc_flags
=
0
;
ifc
.
lifc_len
=
bufsize
;
// call SIOCGLIFCONF to enumerate the interfaces
ifc
.
lifc_len
=
numifs
.
lifn_count
*
sizeof
(
struct
lifreq
);
CHECKED_MALLOC3
(
buf
,
char
*
,
ifc
.
lifc_len
);
ifc
.
lifc_buf
=
buf
;
ifc
.
lifc_family
=
AF_INET
;
ifc
.
lifc_flags
=
0
;
if
(
ioctl
(
sock
,
SIOCGLIFCONF
,
(
char
*
)
&
ifc
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGLIFCONF
failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGLIFCONF)
failed"
);
free
(
buf
);
return
ifs
;
}
// Iterate through each interface
ifr
=
ifc
.
lifc_req
;
for
(
n
=
0
;
n
<
numifs
.
lifn_count
;
n
++
,
ifr
++
)
{
int
index
=
-
1
;
struct
lifreq
if2
;
// iterate through each interface
ifreqP
=
ifc
.
lifc_req
;
for
(
i
=
0
;
i
<
numifs
.
lifn_count
;
i
++
,
ifreqP
++
)
{
struct
sockaddr
addr
,
*
broadaddrP
=
NULL
;
//
Ignore either IPv4 or IPv6 address
es
if
(
ifr
->
lifr_addr
.
ss_family
!=
family
)
{
//
ignore non IPv4 interfac
es
if
(
ifr
eqP
->
lifr_addr
.
ss_family
!=
AF_INET
)
{
continue
;
}
#ifdef AF_INET6
if
(
ifr
->
lifr_addr
.
ss_family
==
AF_INET6
)
{
struct
sockaddr_in6
*
s6
=
(
struct
sockaddr_in6
*
)
&
(
ifr
->
lifr_addr
);
s6
->
sin6_scope_id
=
getIndex
(
sock
,
ifr
->
lifr_name
);
// save socket address
memcpy
(
&
addr
,
&
(
ifreqP
->
lifr_addr
),
sizeof
(
struct
sockaddr
));
// determine broadcast address, if applicable
if
((
ioctl
(
sock
,
SIOCGLIFFLAGS
,
ifreqP
)
==
0
)
&&
ifreqP
->
lifr_flags
&
IFF_BROADCAST
)
{
// restore socket address to ifreqP
memcpy
(
&
(
ifreqP
->
lifr_addr
),
&
addr
,
sizeof
(
struct
sockaddr
));
// query broadcast address and set pointer to it
if
(
ioctl
(
sock
,
SIOCGLIFBRDADDR
,
ifreqP
)
==
0
)
{
broadaddrP
=
(
struct
sockaddr
*
)
&
(
ifreqP
->
lifr_broadaddr
);
}
}
#endif
// add to the list
ifs
=
addif
(
env
,
sock
,
ifr
->
lifr_name
,
ifs
,
(
struct
sockaddr
*
)
&
(
ifr
->
lifr_addr
),
family
,
(
short
)
ifr
->
lifr_addrlen
);
ifs
=
addif
(
env
,
sock
,
ifreqP
->
lifr_name
,
ifs
,
&
addr
,
broadaddrP
,
AF_INET
,
(
short
)
ifreqP
->
lifr_addrlen
);
//
I
f an exception occurred we return immediately
//
i
f an exception occurred we return immediately
if
((
*
env
)
->
ExceptionOccurred
(
env
))
{
free
(
buf
);
return
ifs
;
}
}
// free buffer
free
(
buf
);
return
ifs
;
}
static
int
getIndex
(
int
sock
,
const
char
*
name
)
{
// Try to get the interface index. (Not supported on Solaris 2.6 or 7)
struct
lifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
lifr_name
,
name
,
sizeof
(
if2
.
lifr_name
)
-
1
);
if
(
ioctl
(
sock
,
SIOCGLIFINDEX
,
(
char
*
)
&
if2
)
<
0
)
{
return
-
1
;
}
return
if2
.
lifr_index
;
}
#if defined(AF_INET6)
/*
* Returns the IPv4 broadcast address of a named interface, if it exists.
* Returns 0 if it doesn't have one.
* Enumerates and returns all IPv6 interfaces on Solaris.
*/
static
struct
sockaddr
*
getBroadcast
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
,
struct
sockaddr
*
brdcast_store
)
{
struct
sockaddr
*
ret
=
NULL
;
struct
lifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
lifr_name
,
ifname
,
sizeof
(
if2
.
lifr_name
)
-
1
);
static
netif
*
enumIPv6Interfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
)
{
struct
lifconf
ifc
;
struct
lifreq
*
ifreqP
;
struct
lifnum
numifs
;
char
*
buf
=
NULL
;
unsigned
i
;
// Let's make sure the interface does have a broadcast address
if
(
ioctl
(
sock
,
SIOCGLIFFLAGS
,
(
char
*
)
&
if2
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGLIFFLAGS failed"
);
return
ret
;
// call SIOCGLIFNUM to get the size of SIOCGLIFCONF buffer
numifs
.
lifn_family
=
AF_INET6
;
numifs
.
lifn_flags
=
0
;
if
(
ioctl
(
sock
,
SIOCGLIFNUM
,
(
char
*
)
&
numifs
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGLIFNUM) failed"
);
return
ifs
;
}
if
(
if2
.
lifr_flags
&
IFF_BROADCAST
)
{
// It does, let's retrieve it
if
(
ioctl
(
sock
,
SIOCGLIFBRDADDR
,
(
char
*
)
&
if2
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGLIFBRDADDR failed"
);
return
ret
;
// call SIOCGLIFCONF to enumerate the interfaces
ifc
.
lifc_len
=
numifs
.
lifn_count
*
sizeof
(
struct
lifreq
);
CHECKED_MALLOC3
(
buf
,
char
*
,
ifc
.
lifc_len
);
ifc
.
lifc_buf
=
buf
;
ifc
.
lifc_family
=
AF_INET6
;
ifc
.
lifc_flags
=
0
;
if
(
ioctl
(
sock
,
SIOCGLIFCONF
,
(
char
*
)
&
ifc
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGLIFCONF) failed"
);
free
(
buf
);
return
ifs
;
}
// iterate through each interface
ifreqP
=
ifc
.
lifc_req
;
for
(
i
=
0
;
i
<
numifs
.
lifn_count
;
i
++
,
ifreqP
++
)
{
// ignore non IPv6 interfaces
if
(
ifreqP
->
lifr_addr
.
ss_family
!=
AF_INET6
)
{
continue
;
}
ret
=
brdcast_store
;
memcpy
(
ret
,
&
if2
.
lifr_broadaddr
,
sizeof
(
struct
sockaddr
));
}
// set scope ID to interface index
((
struct
sockaddr_in6
*
)
&
(
ifreqP
->
lifr_addr
))
->
sin6_scope_id
=
getIndex
(
sock
,
ifreqP
->
lifr_name
);
return
ret
;
// add to the list
ifs
=
addif
(
env
,
sock
,
ifreqP
->
lifr_name
,
ifs
,
(
struct
sockaddr
*
)
&
(
ifreqP
->
lifr_addr
),
NULL
,
AF_INET6
,
(
short
)
ifreqP
->
lifr_addrlen
);
// if an exception occurred we return immediately
if
((
*
env
)
->
ExceptionOccurred
(
env
))
{
free
(
buf
);
return
ifs
;
}
}
// free buffer
free
(
buf
);
return
ifs
;
}
#endif
/* AF_INET6 */
/*
*
Returns the IPv4 subnet prefix length (aka subnet mask) for the named
*
interface, if it has one, otherwise return -1.
*
Try to get the interface index.
*
(Not supported on Solaris 2.6 or 7)
*/
static
short
getSubnet
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
)
{
unsigned
int
mask
;
short
ret
;
static
int
getIndex
(
int
sock
,
const
char
*
name
)
{
struct
lifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
lifr_name
,
if
name
,
sizeof
(
if2
.
lifr_name
)
-
1
);
strncpy
(
if2
.
lifr_name
,
name
,
sizeof
(
if2
.
lifr_name
)
-
1
);
if
(
ioctl
(
sock
,
SIOCGLIFNETMASK
,
(
char
*
)
&
if2
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGLIFNETMASK failed"
);
if
(
ioctl
(
sock
,
SIOCGLIFINDEX
,
(
char
*
)
&
if2
)
<
0
)
{
return
-
1
;
}
mask
=
ntohl
(((
struct
sockaddr_in
*
)
&
(
if2
.
lifr_addr
))
->
sin_addr
.
s_addr
);
ret
=
0
;
while
(
mask
)
{
mask
<<=
1
;
ret
++
;
}
return
ret
;
return
if2
.
lifr_index
;
}
#define DEV_PREFIX "/dev/"
/*
* Solaris specific DLPI code to get hardware address from a device.
* Unfortunately, at least up to Solaris X, you have to have special
* privileges (i.e. be root).
*/
static
int
getMacFromDevice
(
JNIEnv
*
env
,
const
char
*
ifname
,
unsigned
char
*
retbuf
)
(
JNIEnv
*
env
,
const
char
*
ifname
,
unsigned
char
*
retbuf
)
{
char
style1dev
[
MAXPATHLEN
];
int
fd
;
...
...
@@ -1739,8 +1864,8 @@ static int getMacFromDevice
msg
.
len
=
DL_PHYS_ADDR_REQ_SIZE
;
if
(
putmsg
(
fd
,
&
msg
,
NULL
,
0
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"putmsg
failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"putmsg()
failed"
);
return
-
1
;
}
...
...
@@ -1750,8 +1875,8 @@ static int getMacFromDevice
msg
.
len
=
0
;
msg
.
maxlen
=
sizeof
(
buf
);
if
(
getmsg
(
fd
,
&
msg
,
NULL
,
&
flags
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"getmsg
failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"getmsg()
failed"
);
return
-
1
;
}
...
...
@@ -1771,23 +1896,20 @@ static int getMacFromDevice
* MAC address. Returns -1 if there is no hardware address on that interface.
*/
static
int
getMacAddress
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
,
const
struct
in_addr
*
addr
,
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
,
const
struct
in_addr
*
addr
,
unsigned
char
*
buf
)
{
struct
arpreq
arpreq
;
struct
sockaddr_in
*
sin
;
struct
sockaddr_in
ipAddr
;
struct
lifreq
if2
;
int
len
,
i
;
struct
lifreq
lif
;
// First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
// try the old way.
memset
(
&
lif
,
0
,
sizeof
(
lif
));
str
lcpy
(
lif
.
lifr_name
,
ifname
,
sizeof
(
lif
.
lifr_name
)
);
memset
(
(
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
str
ncpy
(
if2
.
lifr_name
,
ifname
,
sizeof
(
if2
.
lifr_name
)
-
1
);
if
(
ioctl
(
sock
,
SIOCGLIFHWADDR
,
&
lif
)
!=
-
1
)
{
if
(
ioctl
(
sock
,
SIOCGLIFHWADDR
,
&
if2
)
!=
-
1
)
{
struct
sockaddr_dl
*
sp
;
sp
=
(
struct
sockaddr_dl
*
)
&
lif
.
lifr_addr
;
sp
=
(
struct
sockaddr_dl
*
)
&
if2
.
lifr_addr
;
memcpy
(
buf
,
&
sp
->
sdl_data
[
0
],
sp
->
sdl_alen
);
return
sp
->
sdl_alen
;
}
...
...
@@ -1798,6 +1920,10 @@ static int getMacAddress
if
((
len
=
getMacFromDevice
(
env
,
ifname
,
buf
))
==
0
)
{
// DLPI failed - trying to do arp lookup
struct
arpreq
arpreq
;
struct
sockaddr_in
*
sin
;
struct
sockaddr_in
ipAddr
;
if
(
addr
==
NULL
)
{
// No IPv4 address for that interface, so can't do an ARP lookup.
return
-
1
;
...
...
@@ -1805,8 +1931,8 @@ static int getMacAddress
len
=
6
;
//???
sin
=
(
struct
sockaddr_in
*
)
&
arpreq
.
arp_pa
;
memset
((
char
*
)
&
arpreq
,
0
,
sizeof
(
struct
arpreq
));
sin
=
(
struct
sockaddr_in
*
)
&
arpreq
.
arp_pa
;
memset
((
char
*
)
&
arpreq
,
0
,
sizeof
(
struct
arpreq
));
ipAddr
.
sin_port
=
0
;
ipAddr
.
sin_family
=
AF_INET
;
memcpy
(
&
ipAddr
.
sin_addr
,
addr
,
sizeof
(
struct
in_addr
));
...
...
@@ -1817,26 +1943,26 @@ static int getMacAddress
return
-
1
;
}
memcpy
(
buf
,
&
arpreq
.
arp_ha
.
sa_data
[
0
],
len
);
memcpy
(
buf
,
&
arpreq
.
arp_ha
.
sa_data
[
0
],
len
);
}
//
All bytes to 0 means no hardware address.
//
all bytes to 0 means no hardware address
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
buf
[
i
]
!=
0
)
return
len
;
if
(
buf
[
i
]
!=
0
)
return
len
;
}
return
-
1
;
}
static
int
getMTU
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
)
{
static
int
getMTU
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
)
{
struct
lifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
lifr_name
,
ifname
,
sizeof
(
if2
.
lifr_name
)
-
1
);
if
(
ioctl
(
sock
,
SIOCGLIFMTU
,
(
char
*
)
&
if2
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGLIFMTU
failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGLIFMTU)
failed"
);
return
-
1
;
}
...
...
@@ -1856,67 +1982,73 @@ static int getFlags(int sock, const char *ifname, int *flags) {
return
0
;
}
#endif
/* __solaris__ */
#endif
/* __solaris__ */
/** BSD **/
#if
def _ALLBSD_SOURCE
#if
defined(_ALLBSD_SOURCE)
#if defined(AF_INET6)
/*
* Opens a socket for further ioct calls. Tries AF_INET socket first and
* if it fa
l
ls return AF_INET6 socket.
* Opens a socket for further ioct
l
calls. Tries AF_INET socket first and
* if it fa
i
ls return AF_INET6 socket.
*/
#ifdef AF_INET6
static
int
openSocketWithFallback
(
JNIEnv
*
env
,
const
char
*
ifname
)
{
int
sock
;
struct
ifreq
if2
;
if
((
sock
=
JVM_Socket
(
AF_INET
,
SOCK_DGRAM
,
0
))
<
0
)
{
if
(
errno
==
EPROTONOSUPPORT
)
{
if
((
sock
=
JVM_Socket
(
AF_INET6
,
SOCK_DGRAM
,
0
))
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"IPV6 Socket creation failed"
);
return
-
1
;
}
}
else
{
// errno is not NOSUPPORT
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"IPV4 Socket creation failed"
);
return
-
1
;
}
}
if
((
sock
=
JVM_Socket
(
AF_INET
,
SOCK_DGRAM
,
0
))
<
0
)
{
if
(
errno
==
EPROTONOSUPPORT
)
{
if
((
sock
=
JVM_Socket
(
AF_INET6
,
SOCK_DGRAM
,
0
))
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"IPV6 Socket creation failed"
);
return
-
1
;
}
}
else
{
// errno is not NOSUPPORT
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"IPV4 Socket creation failed"
);
return
-
1
;
}
}
return
sock
;
return
sock
;
}
#else
static
int
openSocketWithFallback
(
JNIEnv
*
env
,
const
char
*
ifname
)
{
return
openSocket
(
env
,
AF_INET
);
return
openSocket
(
env
,
AF_INET
);
}
#endif
/*
* Enumerates and returns all IPv4 interfaces.
* Enumerates and returns all IPv4 interfaces
on BSD
.
*/
static
netif
*
enumIPv4Interfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
)
{
struct
ifaddrs
*
ifa
,
*
origifa
;
if
(
getifaddrs
(
&
origifa
)
!=
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"getifaddrs() function
failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"getifaddrs()
failed"
);
return
ifs
;
}
for
(
ifa
=
origifa
;
ifa
!=
NULL
;
ifa
=
ifa
->
ifa_next
)
{
struct
sockaddr
*
broadaddrP
=
NULL
;
//
Skip non-AF_INET entries.
//
ignore non IPv4 interfaces
if
(
ifa
->
ifa_addr
==
NULL
||
ifa
->
ifa_addr
->
sa_family
!=
AF_INET
)
continue
;
// Add to the list.
ifs
=
addif
(
env
,
sock
,
ifa
->
ifa_name
,
ifs
,
ifa
->
ifa_addr
,
AF_INET
,
0
);
// set ifa_broadaddr, if there is one
if
((
ifa
->
ifa_flags
&
IFF_POINTOPOINT
)
==
0
&&
ifa
->
ifa_flags
&
IFF_BROADCAST
)
{
broadaddrP
=
ifa
->
ifa_dstaddr
;
}
// add interface to the list
ifs
=
addif
(
env
,
sock
,
ifa
->
ifa_name
,
ifs
,
ifa
->
ifa_addr
,
broadaddrP
,
AF_INET
,
translateIPv4AddressToPrefix
((
struct
sockaddr_in
*
)
ifa
->
ifa_netmask
));
//
If an exception occurred then free the list.
//
if an exception occurred then free the list
if
((
*
env
)
->
ExceptionOccurred
(
env
))
{
freeifaddrs
(
origifa
);
freeif
(
ifs
);
...
...
@@ -1924,76 +2056,41 @@ static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
}
}
//
Free socket and
buffer
//
free ifaddrs
buffer
freeifaddrs
(
origifa
);
return
ifs
;
}
#ifdef AF_INET6
/*
* Determines the prefix on BSD for IPv6 interfaces.
*/
static
int
prefix
(
void
*
val
,
int
size
)
{
u_char
*
name
=
(
u_char
*
)
val
;
int
byte
,
bit
,
prefix
=
0
;
for
(
byte
=
0
;
byte
<
size
;
byte
++
,
prefix
+=
8
)
if
(
name
[
byte
]
!=
0xff
)
break
;
if
(
byte
==
size
)
return
prefix
;
for
(
bit
=
7
;
bit
!=
0
;
bit
--
,
prefix
++
)
if
(
!
(
name
[
byte
]
&
(
1
<<
bit
)))
break
;
for
(;
bit
!=
0
;
bit
--
)
if
(
name
[
byte
]
&
(
1
<<
bit
))
return
(
0
);
byte
++
;
for
(;
byte
<
size
;
byte
++
)
if
(
name
[
byte
])
return
(
0
);
return
prefix
;
}
#if defined(AF_INET6)
/*
* Enumerates and returns all IPv6 interfaces on BSD.
*/
static
netif
*
enumIPv6Interfaces
(
JNIEnv
*
env
,
int
sock
,
netif
*
ifs
)
{
struct
ifaddrs
*
ifa
,
*
origifa
;
struct
sockaddr_in6
*
sin6
;
struct
in6_ifreq
ifr6
;
if
(
getifaddrs
(
&
origifa
)
!=
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"getifaddrs() function
failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"getifaddrs()
failed"
);
return
ifs
;
}
for
(
ifa
=
origifa
;
ifa
!=
NULL
;
ifa
=
ifa
->
ifa_next
)
{
// Skip non-AF_INET6 entries.
// ignore non IPv6 interfaces
if
(
ifa
->
ifa_addr
==
NULL
||
ifa
->
ifa_addr
->
sa_family
!=
AF_INET6
)
continue
;
memset
(
&
ifr6
,
0
,
sizeof
(
ifr6
));
strlcpy
(
ifr6
.
ifr_name
,
ifa
->
ifa_name
,
sizeof
(
ifr6
.
ifr_name
));
memcpy
(
&
ifr6
.
ifr_addr
,
ifa
->
ifa_addr
,
MIN
(
sizeof
(
ifr6
.
ifr_addr
),
ifa
->
ifa_addr
->
sa_len
));
if
(
ioctl
(
sock
,
SIOCGIFNETMASK_IN6
,
(
caddr_t
)
&
ifr6
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGIFNETMASK_IN6 failed"
);
freeifaddrs
(
origifa
);
freeif
(
ifs
);
return
NULL
;
}
// set scope ID to interface index
((
struct
sockaddr_in6
*
)
ifa
->
ifa_addr
)
->
sin6_scope_id
=
getIndex
(
sock
,
ifa
->
ifa_name
);
// Add to the list.
sin6
=
(
struct
sockaddr_in6
*
)
&
ifr6
.
ifr_addr
;
ifs
=
addif
(
env
,
sock
,
ifa
->
ifa_name
,
ifs
,
ifa
->
ifa_addr
,
AF_INET6
,
(
short
)
prefix
(
&
sin6
->
sin6_addr
,
sizeof
(
struct
in6_addr
)));
// add interface to the list
ifs
=
addif
(
env
,
sock
,
ifa
->
ifa_name
,
ifs
,
ifa
->
ifa_addr
,
NULL
,
AF_INET6
,
translateIPv6AddressToPrefix
((
struct
sockaddr_in6
*
)
ifa
->
ifa_netmask
));
//
If an exception occurred then free the list.
//
if an exception occurred then free the list
if
((
*
env
)
->
ExceptionOccurred
(
env
))
{
freeifaddrs
(
origifa
);
freeif
(
ifs
);
...
...
@@ -2001,16 +2098,21 @@ static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
}
}
//
Free socket and
ifaddrs buffer
//
free
ifaddrs buffer
freeifaddrs
(
origifa
);
return
ifs
;
}
#endif
#endif
/* AF_INET6 */
/*
* Try to get the interface index.
*/
static
int
getIndex
(
int
sock
,
const
char
*
name
)
{
#ifdef __FreeBSD__
// Try to get the interface index
// (Not supported on Solaris 2.6 or 7)
#if !defined(__FreeBSD__)
int
index
=
if_nametoindex
(
name
);
return
(
index
==
0
)
?
-
1
:
index
;
#else
struct
ifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
ifr_name
,
name
,
sizeof
(
if2
.
ifr_name
)
-
1
);
...
...
@@ -2020,81 +2122,16 @@ static int getIndex(int sock, const char *name) {
}
return
if2
.
ifr_index
;
#else
// Try to get the interface index using BSD specific if_nametoindex
int
index
=
if_nametoindex
(
name
);
return
(
index
==
0
)
?
-
1
:
index
;
#endif
}
/*
* Returns the IPv4 broadcast address of a named interface, if it exists.
* Returns 0 if it doesn't have one.
*/
static
struct
sockaddr
*
getBroadcast
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
,
struct
sockaddr
*
brdcast_store
)
{
struct
sockaddr
*
ret
=
NULL
;
struct
ifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
ifr_name
,
ifname
,
sizeof
(
if2
.
ifr_name
)
-
1
);
// Make sure the interface does have a broadcast address
if
(
ioctl
(
sock
,
SIOCGIFFLAGS
,
(
char
*
)
&
if2
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGIFFLAGS failed"
);
return
ret
;
}
if
(
if2
.
ifr_flags
&
IFF_BROADCAST
)
{
// It does, let's retrieve it
if
(
ioctl
(
sock
,
SIOCGIFBRDADDR
,
(
char
*
)
&
if2
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGIFBRDADDR failed"
);
return
ret
;
}
ret
=
brdcast_store
;
memcpy
(
ret
,
&
if2
.
ifr_broadaddr
,
sizeof
(
struct
sockaddr
));
}
return
ret
;
}
/*
* Returns the IPv4 subnet prefix length (aka subnet mask) for the named
* interface, if it has one, otherwise return -1.
*/
static
short
getSubnet
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
)
{
unsigned
int
mask
;
short
ret
;
struct
ifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
ifr_name
,
ifname
,
sizeof
(
if2
.
ifr_name
)
-
1
);
if
(
ioctl
(
sock
,
SIOCGIFNETMASK
,
(
char
*
)
&
if2
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGIFNETMASK failed"
);
return
-
1
;
}
mask
=
ntohl
(((
struct
sockaddr_in
*
)
&
(
if2
.
ifr_addr
))
->
sin_addr
.
s_addr
);
ret
=
0
;
while
(
mask
)
{
mask
<<=
1
;
ret
++
;
}
return
ret
;
}
/*
* Gets the Hardware address (usually MAC address) for the named interface.
* return puts the data in buf, and returns the length, in byte, of the
*
On
return puts the data in buf, and returns the length, in byte, of the
* MAC address. Returns -1 if there is no hardware address on that interface.
*/
static
int
getMacAddress
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
,
const
struct
in_addr
*
addr
,
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
,
const
struct
in_addr
*
addr
,
unsigned
char
*
buf
)
{
struct
ifaddrs
*
ifa0
,
*
ifa
;
...
...
@@ -2123,23 +2160,22 @@ static int getMacAddress
return
-
1
;
}
static
int
getMTU
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
)
{
static
int
getMTU
(
JNIEnv
*
env
,
int
sock
,
const
char
*
ifname
)
{
struct
ifreq
if2
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
ifr_name
,
ifname
,
sizeof
(
if2
.
ifr_name
)
-
1
);
if
(
ioctl
(
sock
,
SIOCGIFMTU
,
(
char
*
)
&
if2
)
<
0
)
{
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl SIOCGIFMTU
failed"
);
NET_ThrowByNameWithLastError
(
env
,
JNU_JAVANETPKG
"SocketException"
,
"ioctl(SIOCGIFMTU)
failed"
);
return
-
1
;
}
return
if2
.
ifr_mtu
;
return
if2
.
ifr_mtu
;
}
static
int
getFlags
(
int
sock
,
const
char
*
ifname
,
int
*
flags
)
{
struct
ifreq
if2
;
int
ret
=
-
1
;
memset
((
char
*
)
&
if2
,
0
,
sizeof
(
if2
));
strncpy
(
if2
.
ifr_name
,
ifname
,
sizeof
(
if2
.
ifr_name
)
-
1
);
...
...
@@ -2154,4 +2190,4 @@ static int getFlags(int sock, const char *ifname, int *flags) {
}
return
0
;
}
#endif
/* _
_ALLBSD_SOURCE__
*/
#endif
/* _
ALLBSD_SOURCE
*/
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录