1 /*
2 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <arpa/inet.h>
38 #include <net/if.h>
39 #include <net/if_arp.h>
40
41 #ifdef __solaris__
42 #include <sys/dlpi.h>
43 #include <fcntl.h>
44 #include <stropts.h>
45 #include <sys/sockio.h>
46 #endif
47
48 #ifdef __linux__
49 #include <sys/ioctl.h>
50 #include <bits/ioctls.h>
51 #include <sys/utsname.h>
52 #include <stdio.h>
53 #endif
54
55 #ifdef __linux__
56 #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
57 #endif
58
59 #if defined(_ALLBSD_SOURCE)
60 #include <sys/param.h>
61 #include <sys/ioctl.h>
62 #include <sys/sockio.h>
63 #if defined(__APPLE__)
64 #include <net/ethernet.h>
65 #include <net/if_var.h>
66 #include <net/if_dl.h>
67 #include <netinet/in_var.h>
68 #include <ifaddrs.h>
69 #endif
70 #endif
71
72 #include "jvm.h"
73 #include "jni_util.h"
74 #include "net_util.h"
1007 * proto is AF_INET/AF_INET6
1008 */
1009 static int openSocket(JNIEnv *env, int proto){
1010 int sock;
1011
1012 if ((sock = JVM_Socket(proto, SOCK_DGRAM, 0)) < 0) {
1013 /*
1014 * If EPROTONOSUPPORT is returned it means we don't have
1015 * support for this proto so don't throw an exception.
1016 */
1017 if (errno != EPROTONOSUPPORT) {
1018 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Socket creation failed");
1019 }
1020 return -1;
1021 }
1022
1023 return sock;
1024 }
1025
1026
1027 /** Linux **/
1028 #ifdef __linux__
1029 /* Open socket for further ioct calls, try v4 socket first and
1030 * if it falls return v6 socket
1031 */
1032
1033 #ifdef AF_INET6
1034 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1035 int sock;
1036 struct ifreq if2;
1037
1038 if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1039 if (errno == EPROTONOSUPPORT){
1040 if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
1041 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1042 return -1;
1043 }
1044 }
1045 else{ // errno is not NOSUPPORT
1046 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
1047 return -1;
1048 }
1049 }
1050
1051 /* Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or IPv6 socket regardless of type
1052 of address of an interface */
1053
1054 return sock;
1055 }
1056
1057 #else
1058 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1059 return openSocket(env,AF_INET);
1060 }
1061 #endif
1062
1063 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1064 struct ifconf ifc;
1065 struct ifreq *ifreqP;
1066 char *buf;
1067 int numifs;
1068 unsigned i;
1069
1070
1071 /* need to do a dummy SIOCGIFCONF to determine the buffer size.
1072 * SIOCGIFCOUNT doesn't work
1073 */
1074 ifc.ifc_buf = NULL;
1075 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1076 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
1077 return ifs;
1078 }
1079
1080 CHECKED_MALLOC3(buf,char *, ifc.ifc_len);
1081
1082 ifc.ifc_buf = buf;
1083 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1084 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
1085 (void) free(buf);
1086 return ifs;
1087 }
1088
1089 /*
1090 * Iterate through each interface
1091 */
1092 ifreqP = ifc.ifc_req;
1093 for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
1094 /*
1095 * Add to the list
1096 */
1097 ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0);
1098
1099 /*
1100 * If an exception occurred then free the list
1101 */
1102 if ((*env)->ExceptionOccurred(env)) {
1103 free(buf);
1104 freeif(ifs);
1105 return NULL;
1106 }
1107 }
1108
1109 /*
1110 * Free socket and buffer
1111 */
1112 free(buf);
1113 return ifs;
1114 }
1115
1116
1117 /*
1118 * Enumerates and returns all IPv6 interfaces on Linux
1119 */
1120
1121 #ifdef AF_INET6
1122 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1123 FILE *f;
1124 char addr6[40], devname[21];
1125 char addr6p[8][5];
1126 int plen, scope, dad_status, if_idx;
1127 uint8_t ipv6addr[16];
1128
1129 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
1130 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
1131 addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7],
1132 &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
1133
1134 struct netif *ifs_ptr = NULL;
1135 struct netif *last_ptr = NULL;
1136 struct sockaddr_in6 addr;
1137
1138 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
1139 addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
1140 inet_pton(AF_INET6, addr6, ipv6addr);
1141
1145 addr.sin6_scope_id = if_idx;
1146
1147 ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, AF_INET6, plen);
1148
1149
1150 /*
1151 * If an exception occurred then return the list as is.
1152 */
1153 if ((*env)->ExceptionOccurred(env)) {
1154 fclose(f);
1155 return ifs;
1156 }
1157 }
1158 fclose(f);
1159 }
1160 return ifs;
1161 }
1162 #endif
1163
1164
1165 static int getIndex(int sock, const char *name){
1166 /*
1167 * Try to get the interface index
1168 * (Not supported on Solaris 2.6 or 7)
1169 */
1170 struct ifreq if2;
1171 strcpy(if2.ifr_name, name);
1172
1173 if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
1174 return -1;
1175 }
1176
1177 return if2.ifr_ifindex;
1178 }
1179
1180 /**
1181 * Returns the IPv4 broadcast address of a named interface, if it exists.
1182 * Returns 0 if it doesn't have one.
1183 */
1184 static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
1185 struct sockaddr *ret = NULL;
1186 struct ifreq if2;
1187
1188 memset((char *) &if2, 0, sizeof(if2));
1189 strcpy(if2.ifr_name, ifname);
1190
1191 /* Let's make sure the interface does have a broadcast address */
1192 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
1193 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFFLAGS failed");
1194 return ret;
1195 }
1196
1197 if (if2.ifr_flags & IFF_BROADCAST) {
1224 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
1225 return -1;
1226 }
1227
1228 mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
1229 ret = 0;
1230 while (mask) {
1231 mask <<= 1;
1232 ret++;
1233 }
1234
1235 return ret;
1236 }
1237
1238 /**
1239 * Get the Hardware address (usually MAC address) for the named interface.
1240 * return puts the data in buf, and returns the length, in byte, of the
1241 * MAC address. Returns -1 if there is no hardware address on that interface.
1242 */
1243 static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
1244 static struct ifreq ifr;
1245 int i;
1246
1247 strcpy(ifr.ifr_name, ifname);
1248 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
1249 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFHWADDR failed");
1250 return -1;
1251 }
1252
1253 memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1254
1255 /*
1256 * All bytes to 0 means no hardware address.
1257 */
1258
1259 for (i = 0; i < IFHWADDRLEN; i++) {
1260 if (buf[i] != 0)
1261 return IFHWADDRLEN;
1262 }
1263
1264 return -1;
1265 }
1266
1267 static int getMTU(JNIEnv *env, int sock, const char *ifname) {
1268 struct ifreq if2;
1269
1270 memset((char *) &if2, 0, sizeof(if2));
1271 strcpy(if2.ifr_name, ifname);
1272
1273 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1274 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
1275 return -1;
1276 }
1277
1278 return if2.ifr_mtu;
1279 }
1280
1281 static int getFlags(int sock, const char *ifname, int *flags) {
1282 struct ifreq if2;
1283
1284 memset((char *) &if2, 0, sizeof(if2));
|
1 /*
2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <arpa/inet.h>
38 #include <net/if.h>
39 #include <net/if_arp.h>
40
41 #ifdef __solaris__
42 #include <sys/dlpi.h>
43 #include <fcntl.h>
44 #include <stropts.h>
45 #include <sys/sockio.h>
46 #endif
47
48 #ifdef __linux__
49 #include <sys/ioctl.h>
50 #include <bits/ioctls.h>
51 #include <sys/utsname.h>
52 #include <stdio.h>
53 #endif
54
55 #if defined(AIX)
56 #include <sys/ioctl.h>
57 #include <netinet/in6_var.h>
58 #include <sys/ndd_var.h>
59 #include <sys/kinfo.h>
60 #endif
61
62 #ifdef __linux__
63 #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
64 #endif
65
66 #if defined(_ALLBSD_SOURCE)
67 #include <sys/param.h>
68 #include <sys/ioctl.h>
69 #include <sys/sockio.h>
70 #if defined(__APPLE__)
71 #include <net/ethernet.h>
72 #include <net/if_var.h>
73 #include <net/if_dl.h>
74 #include <netinet/in_var.h>
75 #include <ifaddrs.h>
76 #endif
77 #endif
78
79 #include "jvm.h"
80 #include "jni_util.h"
81 #include "net_util.h"
1014 * proto is AF_INET/AF_INET6
1015 */
1016 static int openSocket(JNIEnv *env, int proto){
1017 int sock;
1018
1019 if ((sock = JVM_Socket(proto, SOCK_DGRAM, 0)) < 0) {
1020 /*
1021 * If EPROTONOSUPPORT is returned it means we don't have
1022 * support for this proto so don't throw an exception.
1023 */
1024 if (errno != EPROTONOSUPPORT) {
1025 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Socket creation failed");
1026 }
1027 return -1;
1028 }
1029
1030 return sock;
1031 }
1032
1033
1034 /** Linux, AIX **/
1035 #if defined(__linux__) || defined(AIX)
1036 /* Open socket for further ioct calls, try v4 socket first and
1037 * if it falls return v6 socket
1038 */
1039
1040 #ifdef AF_INET6
1041 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1042 int sock;
1043 struct ifreq if2;
1044
1045 if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1046 if (errno == EPROTONOSUPPORT){
1047 if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
1048 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1049 return -1;
1050 }
1051 }
1052 else{ // errno is not NOSUPPORT
1053 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
1054 return -1;
1055 }
1056 }
1057
1058 /* Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or IPv6 socket regardless of type
1059 of address of an interface */
1060
1061 return sock;
1062 }
1063
1064 #else
1065 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1066 return openSocket(env,AF_INET);
1067 }
1068 #endif
1069
1070 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1071 struct ifconf ifc;
1072 struct ifreq *ifreqP;
1073 char *buf = NULL;
1074 int numifs;
1075 unsigned i;
1076
1077
1078 #if defined(__linux__)
1079 /* need to do a dummy SIOCGIFCONF to determine the buffer size.
1080 * SIOCGIFCOUNT doesn't work
1081 */
1082 ifc.ifc_buf = NULL;
1083 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1084 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
1085 return ifs;
1086 }
1087 #elif defined(AIX)
1088 ifc.ifc_buf = NULL;
1089 if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
1090 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGSIZIFCONF failed");
1091 return ifs;
1092 }
1093 #endif /* __linux__ */
1094
1095 CHECKED_MALLOC3(buf,char *, ifc.ifc_len);
1096
1097 ifc.ifc_buf = buf;
1098 int request = SIOCGIFCONF;
1099 #if defined(AIX)
1100 request = CSIOCGIFCONF;
1101 #endif
1102 if (ioctl(sock, request, (char *)&ifc) < 0) {
1103 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
1104 (void) free(buf);
1105 return ifs;
1106 }
1107
1108 /*
1109 * Iterate through each interface
1110 */
1111 ifreqP = ifc.ifc_req;
1112 for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
1113 #if defined(AIX)
1114 if (ifreqP->ifr_addr.sa_family != AF_INET) continue;
1115 #endif
1116 /*
1117 * Add to the list
1118 */
1119 ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0);
1120
1121 /*
1122 * If an exception occurred then free the list
1123 */
1124 if ((*env)->ExceptionOccurred(env)) {
1125 free(buf);
1126 freeif(ifs);
1127 return NULL;
1128 }
1129 }
1130
1131 /*
1132 * Free socket and buffer
1133 */
1134 free(buf);
1135 return ifs;
1136 }
1137
1138
1139 /*
1140 * Enumerates and returns all IPv6 interfaces on Linux
1141 */
1142
1143 #if defined(AF_INET6) && defined(__linux__)
1144 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1145 FILE *f;
1146 char addr6[40], devname[21];
1147 char addr6p[8][5];
1148 int plen, scope, dad_status, if_idx;
1149 uint8_t ipv6addr[16];
1150
1151 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
1152 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
1153 addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7],
1154 &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
1155
1156 struct netif *ifs_ptr = NULL;
1157 struct netif *last_ptr = NULL;
1158 struct sockaddr_in6 addr;
1159
1160 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
1161 addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
1162 inet_pton(AF_INET6, addr6, ipv6addr);
1163
1167 addr.sin6_scope_id = if_idx;
1168
1169 ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, AF_INET6, plen);
1170
1171
1172 /*
1173 * If an exception occurred then return the list as is.
1174 */
1175 if ((*env)->ExceptionOccurred(env)) {
1176 fclose(f);
1177 return ifs;
1178 }
1179 }
1180 fclose(f);
1181 }
1182 return ifs;
1183 }
1184 #endif
1185
1186
1187 /*
1188 * Enumerates and returns all IPv6 interfaces on AIX
1189 */
1190
1191 #if defined(AF_INET6) && defined(AIX)
1192 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1193 struct ifconf ifc;
1194 struct ifreq *ifreqP;
1195 char *buf;
1196 int numifs;
1197 unsigned i;
1198 unsigned bufsize;
1199 char *cp, *cplimit;
1200
1201 /* use SIOCGSIZIFCONF to get size for SIOCGIFCONF */
1202
1203 ifc.ifc_buf = NULL;
1204 if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
1205 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
1206 "ioctl SIOCGSIZIFCONF failed");
1207 return ifs;
1208 }
1209 bufsize = ifc.ifc_len;
1210
1211 buf = (char *)malloc(bufsize);
1212 if (!buf) {
1213 JNU_ThrowOutOfMemoryError(env, "Network interface native buffer allocation failed");
1214 return ifs;
1215 }
1216 ifc.ifc_len = bufsize;
1217 ifc.ifc_buf = buf;
1218 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1219 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
1220 "ioctl CSIOCGIFCONF failed");
1221 free(buf);
1222 return ifs;
1223 }
1224
1225 /*
1226 * Iterate through each interface
1227 */
1228 ifreqP = ifc.ifc_req;
1229 cp = (char *)ifc.ifc_req;
1230 cplimit = cp + ifc.ifc_len;
1231
1232 for ( ; cp < cplimit; cp += (sizeof(ifreqP->ifr_name) + MAX((ifreqP->ifr_addr).sa_len, sizeof(ifreqP->ifr_addr)))) {
1233 ifreqP = (struct ifreq *)cp;
1234 struct ifreq if2;
1235
1236 memset((char *)&if2, 0, sizeof(if2));
1237 strcpy(if2.ifr_name, ifreqP->ifr_name);
1238
1239 /*
1240 * Skip interface that aren't UP
1241 */
1242 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
1243 if (!(if2.ifr_flags & IFF_UP)) {
1244 continue;
1245 }
1246 }
1247
1248 if (ifreqP->ifr_addr.sa_family != AF_INET6)
1249 continue;
1250
1251 /*
1252 * Add to the list
1253 */
1254 ifs = addif(env, sock, ifreqP->ifr_name, ifs,
1255 (struct sockaddr *)&(ifreqP->ifr_addr),
1256 AF_INET6, 0);
1257
1258 /*
1259 * If an exception occurred then free the list
1260 */
1261 if ((*env)->ExceptionOccurred(env)) {
1262 free(buf);
1263 freeif(ifs);
1264 return NULL;
1265 }
1266 }
1267
1268 /*
1269 * Free socket and buffer
1270 */
1271 free(buf);
1272 return ifs;
1273 }
1274 #endif
1275
1276
1277 static int getIndex(int sock, const char *name){
1278 /*
1279 * Try to get the interface index
1280 */
1281 #if defined(AIX)
1282 return if_nametoindex(name);
1283 #else
1284 struct ifreq if2;
1285 strcpy(if2.ifr_name, name);
1286
1287 if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
1288 return -1;
1289 }
1290
1291 return if2.ifr_ifindex;
1292 #endif
1293 }
1294
1295 /**
1296 * Returns the IPv4 broadcast address of a named interface, if it exists.
1297 * Returns 0 if it doesn't have one.
1298 */
1299 static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
1300 struct sockaddr *ret = NULL;
1301 struct ifreq if2;
1302
1303 memset((char *) &if2, 0, sizeof(if2));
1304 strcpy(if2.ifr_name, ifname);
1305
1306 /* Let's make sure the interface does have a broadcast address */
1307 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
1308 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFFLAGS failed");
1309 return ret;
1310 }
1311
1312 if (if2.ifr_flags & IFF_BROADCAST) {
1339 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
1340 return -1;
1341 }
1342
1343 mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
1344 ret = 0;
1345 while (mask) {
1346 mask <<= 1;
1347 ret++;
1348 }
1349
1350 return ret;
1351 }
1352
1353 /**
1354 * Get the Hardware address (usually MAC address) for the named interface.
1355 * return puts the data in buf, and returns the length, in byte, of the
1356 * MAC address. Returns -1 if there is no hardware address on that interface.
1357 */
1358 static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
1359 #if defined (AIX)
1360 int size;
1361 struct kinfo_ndd *nddp;
1362 void *end;
1363
1364 size = getkerninfo(KINFO_NDD, 0, 0, 0);
1365 if (size == 0) {
1366 return -1;
1367 }
1368
1369 if (size < 0) {
1370 perror("getkerninfo 1");
1371 return -1;
1372 }
1373
1374 nddp = (struct kinfo_ndd *)malloc(size);
1375
1376 if (!nddp) {
1377 return -1;
1378 }
1379
1380 if (getkerninfo(KINFO_NDD, nddp, &size, 0) < 0) {
1381 exit(1);
1382 }
1383
1384 end = (void *)nddp + size;
1385 while ((void *)nddp < end) {
1386 if (!strcmp(nddp->ndd_alias, ifname) ||
1387 !strcmp(nddp->ndd_name, ifname)) {
1388 bcopy(nddp->ndd_addr, buf, 6);
1389 return 6;
1390 } else {
1391 nddp++;
1392 }
1393 }
1394
1395 return -1;
1396
1397 #elif defined(__linux__)
1398 static struct ifreq ifr;
1399 int i;
1400
1401 strcpy(ifr.ifr_name, ifname);
1402 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
1403 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFHWADDR failed");
1404 return -1;
1405 }
1406
1407 memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1408
1409 /*
1410 * All bytes to 0 means no hardware address.
1411 */
1412
1413 for (i = 0; i < IFHWADDRLEN; i++) {
1414 if (buf[i] != 0)
1415 return IFHWADDRLEN;
1416 }
1417
1418 return -1;
1419 #endif
1420 }
1421
1422 static int getMTU(JNIEnv *env, int sock, const char *ifname) {
1423 struct ifreq if2;
1424
1425 memset((char *) &if2, 0, sizeof(if2));
1426 strcpy(if2.ifr_name, ifname);
1427
1428 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1429 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
1430 return -1;
1431 }
1432
1433 return if2.ifr_mtu;
1434 }
1435
1436 static int getFlags(int sock, const char *ifname, int *flags) {
1437 struct ifreq if2;
1438
1439 memset((char *) &if2, 0, sizeof(if2));
|