1 /* |
1 /* |
2 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. |
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. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
48 #ifdef __linux__ |
48 #ifdef __linux__ |
49 #include <sys/ioctl.h> |
49 #include <sys/ioctl.h> |
50 #include <bits/ioctls.h> |
50 #include <bits/ioctls.h> |
51 #include <sys/utsname.h> |
51 #include <sys/utsname.h> |
52 #include <stdio.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> |
53 #endif |
60 #endif |
54 |
61 |
55 #ifdef __linux__ |
62 #ifdef __linux__ |
56 #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6" |
63 #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6" |
57 #endif |
64 #endif |
1078 #endif |
1085 #endif |
1079 |
1086 |
1080 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) { |
1087 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) { |
1081 struct ifconf ifc; |
1088 struct ifconf ifc; |
1082 struct ifreq *ifreqP; |
1089 struct ifreq *ifreqP; |
1083 char *buf; |
1090 char *buf = NULL; |
1084 int numifs; |
1091 int numifs; |
1085 unsigned i; |
1092 unsigned i; |
1086 |
1093 int siocgifconfRequest = SIOCGIFCONF; |
1087 |
1094 |
|
1095 |
|
1096 #if defined(__linux__) |
1088 /* need to do a dummy SIOCGIFCONF to determine the buffer size. |
1097 /* need to do a dummy SIOCGIFCONF to determine the buffer size. |
1089 * SIOCGIFCOUNT doesn't work |
1098 * SIOCGIFCOUNT doesn't work |
1090 */ |
1099 */ |
1091 ifc.ifc_buf = NULL; |
1100 ifc.ifc_buf = NULL; |
1092 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { |
1101 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { |
1093 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed"); |
1102 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed"); |
1094 return ifs; |
1103 return ifs; |
1095 } |
1104 } |
|
1105 #elif defined(_AIX) |
|
1106 ifc.ifc_buf = NULL; |
|
1107 if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) { |
|
1108 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGSIZIFCONF failed"); |
|
1109 return ifs; |
|
1110 } |
|
1111 #endif /* __linux__ */ |
1096 |
1112 |
1097 CHECKED_MALLOC3(buf,char *, ifc.ifc_len); |
1113 CHECKED_MALLOC3(buf,char *, ifc.ifc_len); |
1098 |
1114 |
1099 ifc.ifc_buf = buf; |
1115 ifc.ifc_buf = buf; |
1100 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { |
1116 #if defined(_AIX) |
|
1117 siocgifconfRequest = CSIOCGIFCONF; |
|
1118 #endif |
|
1119 if (ioctl(sock, siocgifconfRequest, (char *)&ifc) < 0) { |
1101 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed"); |
1120 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed"); |
1102 (void) free(buf); |
1121 (void) free(buf); |
1103 return ifs; |
1122 return ifs; |
1104 } |
1123 } |
1105 |
1124 |
1106 /* |
1125 /* |
1107 * Iterate through each interface |
1126 * Iterate through each interface |
1108 */ |
1127 */ |
1109 ifreqP = ifc.ifc_req; |
1128 ifreqP = ifc.ifc_req; |
1110 for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) { |
1129 for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) { |
|
1130 #if defined(_AIX) |
|
1131 if (ifreqP->ifr_addr.sa_family != AF_INET) continue; |
|
1132 #endif |
1111 /* |
1133 /* |
1112 * Add to the list |
1134 * Add to the list |
1113 */ |
1135 */ |
1114 ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0); |
1136 ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0); |
1115 |
1137 |
1133 |
1155 |
1134 /* |
1156 /* |
1135 * Enumerates and returns all IPv6 interfaces on Linux |
1157 * Enumerates and returns all IPv6 interfaces on Linux |
1136 */ |
1158 */ |
1137 |
1159 |
1138 #ifdef AF_INET6 |
1160 #if defined(AF_INET6) && defined(__linux__) |
1139 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) { |
1161 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) { |
1140 FILE *f; |
1162 FILE *f; |
1141 char addr6[40], devname[21]; |
1163 char addr6[40], devname[21]; |
1142 char addr6p[8][5]; |
1164 char addr6p[8][5]; |
1143 int plen, scope, dad_status, if_idx; |
1165 int plen, scope, dad_status, if_idx; |
1177 return ifs; |
1199 return ifs; |
1178 } |
1200 } |
1179 #endif |
1201 #endif |
1180 |
1202 |
1181 |
1203 |
|
1204 /* |
|
1205 * Enumerates and returns all IPv6 interfaces on AIX |
|
1206 */ |
|
1207 |
|
1208 #if defined(AF_INET6) && defined(_AIX) |
|
1209 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) { |
|
1210 struct ifconf ifc; |
|
1211 struct ifreq *ifreqP; |
|
1212 char *buf; |
|
1213 int numifs; |
|
1214 unsigned i; |
|
1215 unsigned bufsize; |
|
1216 char *cp, *cplimit; |
|
1217 |
|
1218 /* use SIOCGSIZIFCONF to get size for SIOCGIFCONF */ |
|
1219 |
|
1220 ifc.ifc_buf = NULL; |
|
1221 if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) { |
|
1222 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", |
|
1223 "ioctl SIOCGSIZIFCONF failed"); |
|
1224 return ifs; |
|
1225 } |
|
1226 bufsize = ifc.ifc_len; |
|
1227 |
|
1228 buf = (char *)malloc(bufsize); |
|
1229 if (!buf) { |
|
1230 JNU_ThrowOutOfMemoryError(env, "Network interface native buffer allocation failed"); |
|
1231 return ifs; |
|
1232 } |
|
1233 ifc.ifc_len = bufsize; |
|
1234 ifc.ifc_buf = buf; |
|
1235 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { |
|
1236 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", |
|
1237 "ioctl CSIOCGIFCONF failed"); |
|
1238 free(buf); |
|
1239 return ifs; |
|
1240 } |
|
1241 |
|
1242 /* |
|
1243 * Iterate through each interface |
|
1244 */ |
|
1245 ifreqP = ifc.ifc_req; |
|
1246 cp = (char *)ifc.ifc_req; |
|
1247 cplimit = cp + ifc.ifc_len; |
|
1248 |
|
1249 for ( ; cp < cplimit; cp += (sizeof(ifreqP->ifr_name) + MAX((ifreqP->ifr_addr).sa_len, sizeof(ifreqP->ifr_addr)))) { |
|
1250 ifreqP = (struct ifreq *)cp; |
|
1251 struct ifreq if2; |
|
1252 |
|
1253 memset((char *)&if2, 0, sizeof(if2)); |
|
1254 strcpy(if2.ifr_name, ifreqP->ifr_name); |
|
1255 |
|
1256 /* |
|
1257 * Skip interface that aren't UP |
|
1258 */ |
|
1259 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) { |
|
1260 if (!(if2.ifr_flags & IFF_UP)) { |
|
1261 continue; |
|
1262 } |
|
1263 } |
|
1264 |
|
1265 if (ifreqP->ifr_addr.sa_family != AF_INET6) |
|
1266 continue; |
|
1267 |
|
1268 /* |
|
1269 * Add to the list |
|
1270 */ |
|
1271 ifs = addif(env, sock, ifreqP->ifr_name, ifs, |
|
1272 (struct sockaddr *)&(ifreqP->ifr_addr), |
|
1273 AF_INET6, 0); |
|
1274 |
|
1275 /* |
|
1276 * If an exception occurred then free the list |
|
1277 */ |
|
1278 if ((*env)->ExceptionOccurred(env)) { |
|
1279 free(buf); |
|
1280 freeif(ifs); |
|
1281 return NULL; |
|
1282 } |
|
1283 } |
|
1284 |
|
1285 /* |
|
1286 * Free socket and buffer |
|
1287 */ |
|
1288 free(buf); |
|
1289 return ifs; |
|
1290 } |
|
1291 #endif |
|
1292 |
|
1293 |
1182 static int getIndex(int sock, const char *name){ |
1294 static int getIndex(int sock, const char *name){ |
1183 /* |
1295 /* |
1184 * Try to get the interface index |
1296 * Try to get the interface index |
1185 * (Not supported on Solaris 2.6 or 7) |
|
1186 */ |
1297 */ |
|
1298 #if defined(_AIX) |
|
1299 return if_nametoindex(name); |
|
1300 #else |
1187 struct ifreq if2; |
1301 struct ifreq if2; |
1188 strcpy(if2.ifr_name, name); |
1302 strcpy(if2.ifr_name, name); |
1189 |
1303 |
1190 if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) { |
1304 if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) { |
1191 return -1; |
1305 return -1; |
1192 } |
1306 } |
1193 |
1307 |
1194 return if2.ifr_ifindex; |
1308 return if2.ifr_ifindex; |
|
1309 #endif |
1195 } |
1310 } |
1196 |
1311 |
1197 /** |
1312 /** |
1198 * Returns the IPv4 broadcast address of a named interface, if it exists. |
1313 * Returns the IPv4 broadcast address of a named interface, if it exists. |
1199 * Returns 0 if it doesn't have one. |
1314 * Returns 0 if it doesn't have one. |
1256 * Get the Hardware address (usually MAC address) for the named interface. |
1371 * Get the Hardware address (usually MAC address) for the named interface. |
1257 * return puts the data in buf, and returns the length, in byte, of the |
1372 * return puts the data in buf, and returns the length, in byte, of the |
1258 * MAC address. Returns -1 if there is no hardware address on that interface. |
1373 * MAC address. Returns -1 if there is no hardware address on that interface. |
1259 */ |
1374 */ |
1260 static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) { |
1375 static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) { |
|
1376 #if defined (_AIX) |
|
1377 int size; |
|
1378 struct kinfo_ndd *nddp; |
|
1379 void *end; |
|
1380 |
|
1381 size = getkerninfo(KINFO_NDD, 0, 0, 0); |
|
1382 if (size == 0) { |
|
1383 return -1; |
|
1384 } |
|
1385 |
|
1386 if (size < 0) { |
|
1387 perror("getkerninfo 1"); |
|
1388 return -1; |
|
1389 } |
|
1390 |
|
1391 nddp = (struct kinfo_ndd *)malloc(size); |
|
1392 |
|
1393 if (!nddp) { |
|
1394 return -1; |
|
1395 } |
|
1396 |
|
1397 if (getkerninfo(KINFO_NDD, nddp, &size, 0) < 0) { |
|
1398 perror("getkerninfo 2"); |
|
1399 return -1; |
|
1400 } |
|
1401 |
|
1402 end = (void *)nddp + size; |
|
1403 while ((void *)nddp < end) { |
|
1404 if (!strcmp(nddp->ndd_alias, ifname) || |
|
1405 !strcmp(nddp->ndd_name, ifname)) { |
|
1406 bcopy(nddp->ndd_addr, buf, 6); |
|
1407 return 6; |
|
1408 } else { |
|
1409 nddp++; |
|
1410 } |
|
1411 } |
|
1412 |
|
1413 return -1; |
|
1414 |
|
1415 #elif defined(__linux__) |
1261 static struct ifreq ifr; |
1416 static struct ifreq ifr; |
1262 int i; |
1417 int i; |
1263 |
1418 |
1264 strcpy(ifr.ifr_name, ifname); |
1419 strcpy(ifr.ifr_name, ifname); |
1265 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) { |
1420 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) { |