annotate src/solaris/native/java/net/NetworkInterface.c @ 4501:07abe3cc996f

7079012: test/java/net/NetworkInterface/NetParamsTest.java fails with SocketException getting mac address Reviewed-by: michaelm
author chegar
date Thu, 27 Oct 2011 15:44:32 +0100
parents 272483f6650b
children 5cca2f1a37da
rev   line source
duke@0 1 /*
ohair@3909 2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
duke@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0 4 *
duke@0 5 * This code is free software; you can redistribute it and/or modify it
duke@0 6 * under the terms of the GNU General Public License version 2 only, as
ohair@2362 7 * published by the Free Software Foundation. Oracle designates this
duke@0 8 * particular file as subject to the "Classpath" exception as provided
ohair@2362 9 * by Oracle in the LICENSE file that accompanied this code.
duke@0 10 *
duke@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@0 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@0 15 * accompanied this code).
duke@0 16 *
duke@0 17 * You should have received a copy of the GNU General Public License version
duke@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0 20 *
ohair@2362 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@2362 22 * or visit www.oracle.com if you need additional information or have any
ohair@2362 23 * questions.
duke@0 24 */
duke@0 25
dsamersoff@2545 26
duke@0 27 #include <errno.h>
duke@0 28 #include <strings.h>
duke@0 29 #include <netinet/in.h>
duke@0 30 #include <stdlib.h>
duke@0 31 #include <string.h>
duke@0 32 #include <sys/types.h>
duke@0 33 #include <sys/socket.h>
duke@0 34 #include <arpa/inet.h>
duke@0 35 #include <net/if.h>
duke@0 36 #include <net/if_arp.h>
dsamersoff@2545 37
duke@0 38 #ifdef __solaris__
duke@0 39 #include <sys/dlpi.h>
duke@0 40 #include <fcntl.h>
duke@0 41 #include <stropts.h>
dsamersoff@2545 42 #include <sys/sockio.h>
duke@0 43 #endif
dsamersoff@2545 44
duke@0 45 #ifdef __linux__
duke@0 46 #include <sys/ioctl.h>
duke@0 47 #include <bits/ioctls.h>
duke@0 48 #include <sys/utsname.h>
duke@0 49 #include <stdio.h>
duke@0 50 #endif
duke@0 51
duke@0 52 #ifdef __linux__
duke@0 53 #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
duke@0 54 #endif
duke@0 55
duke@0 56 #include "jvm.h"
duke@0 57 #include "jni_util.h"
duke@0 58 #include "net_util.h"
duke@0 59
duke@0 60 typedef struct _netaddr {
duke@0 61 struct sockaddr *addr;
duke@0 62 struct sockaddr *brdcast;
duke@0 63 short mask;
duke@0 64 int family; /* to make searches simple */
duke@0 65 struct _netaddr *next;
duke@0 66 } netaddr;
duke@0 67
duke@0 68 typedef struct _netif {
duke@0 69 char *name;
duke@0 70 int index;
duke@0 71 char virtual;
duke@0 72 netaddr *addr;
duke@0 73 struct _netif *childs;
duke@0 74 struct _netif *next;
duke@0 75 } netif;
duke@0 76
duke@0 77 /************************************************************************
duke@0 78 * NetworkInterface
duke@0 79 */
duke@0 80
duke@0 81 #include "java_net_NetworkInterface.h"
duke@0 82
duke@0 83 /************************************************************************
duke@0 84 * NetworkInterface
duke@0 85 */
duke@0 86 jclass ni_class;
duke@0 87 jfieldID ni_nameID;
duke@0 88 jfieldID ni_indexID;
duke@0 89 jfieldID ni_descID;
duke@0 90 jfieldID ni_addrsID;
duke@0 91 jfieldID ni_bindsID;
duke@0 92 jfieldID ni_virutalID;
duke@0 93 jfieldID ni_childsID;
duke@0 94 jfieldID ni_parentID;
duke@0 95 jmethodID ni_ctrID;
duke@0 96
duke@0 97 static jclass ni_iacls;
duke@0 98 static jclass ni_ia4cls;
duke@0 99 static jclass ni_ia6cls;
duke@0 100 static jclass ni_ibcls;
duke@0 101 static jmethodID ni_ia4ctrID;
duke@0 102 static jmethodID ni_ia6ctrID;
duke@0 103 static jmethodID ni_ibctrID;
duke@0 104 static jfieldID ni_iaaddressID;
duke@0 105 static jfieldID ni_iafamilyID;
duke@0 106 static jfieldID ni_ia6ipaddressID;
duke@0 107 static jfieldID ni_ibaddressID;
duke@0 108 static jfieldID ni_ib4broadcastID;
duke@0 109 static jfieldID ni_ib4maskID;
duke@0 110
dsamersoff@2545 111 /** Private methods declarations **/
duke@0 112 static jobject createNetworkInterface(JNIEnv *env, netif *ifs);
dsamersoff@2545 113 static int getFlags0(JNIEnv *env, jstring ifname);
duke@0 114
dsamersoff@2545 115 static netif *enumInterfaces(JNIEnv *env);
dsamersoff@2545 116 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs);
dsamersoff@2545 117
duke@0 118 #ifdef AF_INET6
dsamersoff@2545 119 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
duke@0 120 #endif
duke@0 121
dsamersoff@2545 122 static netif *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix);
dsamersoff@2545 123 static void freeif(netif *ifs);
dsamersoff@2545 124
dsamersoff@2545 125 static int openSocket(JNIEnv *env, int proto);
dsamersoff@2545 126 static int openSocketWithFallback(JNIEnv *env, const char *ifname);
dsamersoff@2545 127
dsamersoff@2545 128
dsamersoff@2545 129 static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name, struct sockaddr *brdcast_store);
dsamersoff@2545 130 static short getSubnet(JNIEnv *env, int sock, const char *ifname);
chegar@2578 131 static int getIndex(int sock, const char *ifname);
dsamersoff@2545 132
chegar@2626 133 static int getFlags(int sock, const char *ifname);
dsamersoff@2545 134 static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf);
dsamersoff@2545 135 static int getMTU(JNIEnv *env, int sock, const char *ifname);
dsamersoff@2545 136
dsamersoff@2545 137
dsamersoff@2545 138
dsamersoff@2545 139 #ifdef __solaris__
dsamersoff@2545 140 static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family);
dsamersoff@2545 141 static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf);
chegar@4501 142
chegar@4501 143 #ifndef SIOCGLIFHWADDR
chegar@4501 144 #define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq)
dsamersoff@2545 145 #endif
dsamersoff@2545 146
chegar@4501 147 #endif
dsamersoff@2545 148
dsamersoff@2545 149 /******************* Java entry points *****************************/
duke@0 150
duke@0 151 /*
duke@0 152 * Class: java_net_NetworkInterface
duke@0 153 * Method: init
duke@0 154 * Signature: ()V
duke@0 155 */
duke@0 156 JNIEXPORT void JNICALL
duke@0 157 Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls) {
duke@0 158 ni_class = (*env)->FindClass(env,"java/net/NetworkInterface");
duke@0 159 ni_class = (*env)->NewGlobalRef(env, ni_class);
duke@0 160 ni_nameID = (*env)->GetFieldID(env, ni_class,"name", "Ljava/lang/String;");
duke@0 161 ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I");
duke@0 162 ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;");
duke@0 163 ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;");
duke@0 164 ni_descID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;");
duke@0 165 ni_virutalID = (*env)->GetFieldID(env, ni_class, "virtual", "Z");
duke@0 166 ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;");
duke@0 167 ni_parentID = (*env)->GetFieldID(env, ni_class, "parent", "Ljava/net/NetworkInterface;");
duke@0 168 ni_ctrID = (*env)->GetMethodID(env, ni_class, "<init>", "()V");
duke@0 169
duke@0 170 ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
duke@0 171 ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
duke@0 172 ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
duke@0 173 ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
duke@0 174 ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address");
duke@0 175 ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
duke@0 176 ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress");
duke@0 177 ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls);
duke@0 178 ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
duke@0 179 ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
duke@0 180 ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");
duke@0 181 ni_iaaddressID = (*env)->GetFieldID(env, ni_iacls, "address", "I");
duke@0 182 ni_iafamilyID = (*env)->GetFieldID(env, ni_iacls, "family", "I");
duke@0 183 ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
duke@0 184 ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");
duke@0 185 ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");
duke@0 186 ni_ib4maskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");
duke@0 187 }
duke@0 188
duke@0 189
duke@0 190 /*
duke@0 191 * Class: java_net_NetworkInterface
duke@0 192 * Method: getByName0
duke@0 193 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
duke@0 194 */
duke@0 195 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0
duke@0 196 (JNIEnv *env, jclass cls, jstring name) {
duke@0 197
duke@0 198 netif *ifs, *curr;
duke@0 199 jboolean isCopy;
dsamersoff@2545 200 const char* name_utf;
duke@0 201 jobject obj = NULL;
duke@0 202
duke@0 203 ifs = enumInterfaces(env);
duke@0 204 if (ifs == NULL) {
duke@0 205 return NULL;
duke@0 206 }
duke@0 207
dsamersoff@2545 208 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
dsamersoff@2545 209
duke@0 210 /*
duke@0 211 * Search the list of interface based on name
duke@0 212 */
duke@0 213 curr = ifs;
duke@0 214 while (curr != NULL) {
duke@0 215 if (strcmp(name_utf, curr->name) == 0) {
duke@0 216 break;
duke@0 217 }
duke@0 218 curr = curr->next;
duke@0 219 }
duke@0 220
duke@0 221 /* if found create a NetworkInterface */
duke@0 222 if (curr != NULL) {;
duke@0 223 obj = createNetworkInterface(env, curr);
duke@0 224 }
duke@0 225
duke@0 226 /* release the UTF string and interface list */
duke@0 227 (*env)->ReleaseStringUTFChars(env, name, name_utf);
duke@0 228 freeif(ifs);
duke@0 229
duke@0 230 return obj;
duke@0 231 }
duke@0 232
duke@0 233
duke@0 234 /*
duke@0 235 * Class: java_net_NetworkInterface
jccollet@509 236 * Method: getByIndex0
duke@0 237 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
duke@0 238 */
jccollet@509 239 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
duke@0 240 (JNIEnv *env, jclass cls, jint index) {
duke@0 241
duke@0 242 netif *ifs, *curr;
duke@0 243 jobject obj = NULL;
duke@0 244
duke@0 245 if (index <= 0) {
duke@0 246 return NULL;
duke@0 247 }
duke@0 248
duke@0 249 ifs = enumInterfaces(env);
duke@0 250 if (ifs == NULL) {
duke@0 251 return NULL;
duke@0 252 }
duke@0 253
duke@0 254 /*
duke@0 255 * Search the list of interface based on index
duke@0 256 */
duke@0 257 curr = ifs;
duke@0 258 while (curr != NULL) {
duke@0 259 if (index == curr->index) {
duke@0 260 break;
duke@0 261 }
duke@0 262 curr = curr->next;
duke@0 263 }
duke@0 264
duke@0 265 /* if found create a NetworkInterface */
duke@0 266 if (curr != NULL) {;
duke@0 267 obj = createNetworkInterface(env, curr);
duke@0 268 }
duke@0 269
duke@0 270 freeif(ifs);
duke@0 271 return obj;
duke@0 272 }
duke@0 273
duke@0 274 /*
duke@0 275 * Class: java_net_NetworkInterface
duke@0 276 * Method: getByInetAddress0
duke@0 277 * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
duke@0 278 */
duke@0 279 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
duke@0 280 (JNIEnv *env, jclass cls, jobject iaObj) {
duke@0 281
duke@0 282 netif *ifs, *curr;
dsamersoff@2545 283
chegar@2112 284 #ifdef AF_INET6
dsamersoff@2545 285 int family = ( (*env)->GetIntField(env, iaObj, ni_iafamilyID) == IPv4 ) ? AF_INET : AF_INET6;
chegar@2112 286 #else
dsamersoff@2545 287 int family = AF_INET;
chegar@2112 288 #endif
dsamersoff@2545 289
duke@0 290 jobject obj = NULL;
duke@0 291 jboolean match = JNI_FALSE;
duke@0 292
duke@0 293 ifs = enumInterfaces(env);
duke@0 294 if (ifs == NULL) {
duke@0 295 return NULL;
duke@0 296 }
duke@0 297
duke@0 298 curr = ifs;
duke@0 299 while (curr != NULL) {
duke@0 300 netaddr *addrP = curr->addr;
duke@0 301
duke@0 302 /*
duke@0 303 * Iterate through each address on the interface
duke@0 304 */
duke@0 305 while (addrP != NULL) {
duke@0 306
duke@0 307 if (family == addrP->family) {
duke@0 308 if (family == AF_INET) {
duke@0 309 int address1 = htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr);
duke@0 310 int address2 = (*env)->GetIntField(env, iaObj, ni_iaaddressID);
duke@0 311
duke@0 312 if (address1 == address2) {
duke@0 313 match = JNI_TRUE;
duke@0 314 break;
duke@0 315 }
duke@0 316 }
duke@0 317
duke@0 318 #ifdef AF_INET6
duke@0 319 if (family == AF_INET6) {
duke@0 320 jbyte *bytes = (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr);
duke@0 321 jbyteArray ipaddress = (*env)->GetObjectField(env, iaObj, ni_ia6ipaddressID);
duke@0 322 jbyte caddr[16];
duke@0 323 int i;
duke@0 324
duke@0 325 (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr);
duke@0 326 i = 0;
duke@0 327 while (i < 16) {
duke@0 328 if (caddr[i] != bytes[i]) {
duke@0 329 break;
duke@0 330 }
duke@0 331 i++;
duke@0 332 }
duke@0 333 if (i >= 16) {
duke@0 334 match = JNI_TRUE;
duke@0 335 break;
duke@0 336 }
duke@0 337 }
duke@0 338 #endif
duke@0 339
duke@0 340 }
duke@0 341
duke@0 342 if (match) {
duke@0 343 break;
duke@0 344 }
duke@0 345 addrP = addrP->next;
duke@0 346 }
duke@0 347
duke@0 348 if (match) {
duke@0 349 break;
duke@0 350 }
duke@0 351 curr = curr->next;
duke@0 352 }
duke@0 353
duke@0 354 /* if found create a NetworkInterface */
duke@0 355 if (match) {;
duke@0 356 obj = createNetworkInterface(env, curr);
duke@0 357 }
duke@0 358
duke@0 359 freeif(ifs);
duke@0 360 return obj;
duke@0 361 }
duke@0 362
duke@0 363
duke@0 364 /*
duke@0 365 * Class: java_net_NetworkInterface
duke@0 366 * Method: getAll
duke@0 367 * Signature: ()[Ljava/net/NetworkInterface;
duke@0 368 */
duke@0 369 JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll
duke@0 370 (JNIEnv *env, jclass cls) {
duke@0 371
duke@0 372 netif *ifs, *curr;
duke@0 373 jobjectArray netIFArr;
duke@0 374 jint arr_index, ifCount;
duke@0 375
duke@0 376 ifs = enumInterfaces(env);
duke@0 377 if (ifs == NULL) {
duke@0 378 return NULL;
duke@0 379 }
duke@0 380
duke@0 381 /* count the interface */
duke@0 382 ifCount = 0;
duke@0 383 curr = ifs;
duke@0 384 while (curr != NULL) {
duke@0 385 ifCount++;
duke@0 386 curr = curr->next;
duke@0 387 }
duke@0 388
duke@0 389 /* allocate a NetworkInterface array */
duke@0 390 netIFArr = (*env)->NewObjectArray(env, ifCount, cls, NULL);
duke@0 391 if (netIFArr == NULL) {
duke@0 392 freeif(ifs);
duke@0 393 return NULL;
duke@0 394 }
duke@0 395
duke@0 396 /*
duke@0 397 * Iterate through the interfaces, create a NetworkInterface instance
duke@0 398 * for each array element and populate the object.
duke@0 399 */
duke@0 400 curr = ifs;
duke@0 401 arr_index = 0;
duke@0 402 while (curr != NULL) {
duke@0 403 jobject netifObj;
duke@0 404
duke@0 405 netifObj = createNetworkInterface(env, curr);
duke@0 406 if (netifObj == NULL) {
duke@0 407 freeif(ifs);
duke@0 408 return NULL;
duke@0 409 }
duke@0 410
duke@0 411 /* put the NetworkInterface into the array */
duke@0 412 (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);
duke@0 413
duke@0 414 curr = curr->next;
duke@0 415 }
duke@0 416
duke@0 417 freeif(ifs);
duke@0 418 return netIFArr;
duke@0 419 }
duke@0 420
dsamersoff@2545 421
dsamersoff@2545 422 /*
dsamersoff@2545 423 * Class: java_net_NetworkInterface
dsamersoff@2545 424 * Method: isUp0
dsamersoff@2545 425 * Signature: (Ljava/lang/String;I)Z
dsamersoff@2545 426 */
dsamersoff@2545 427 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0(JNIEnv *env, jclass cls, jstring name, jint index) {
dsamersoff@2545 428 int ret = getFlags0(env, name);
dsamersoff@2545 429 return ((ret & IFF_UP) && (ret & IFF_RUNNING)) ? JNI_TRUE : JNI_FALSE;
dsamersoff@2545 430 }
dsamersoff@2545 431
dsamersoff@2545 432 /*
dsamersoff@2545 433 * Class: java_net_NetworkInterface
dsamersoff@2545 434 * Method: isP2P0
dsamersoff@2545 435 * Signature: (Ljava/lang/String;I)Z
dsamersoff@2545 436 */
dsamersoff@2545 437 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0(JNIEnv *env, jclass cls, jstring name, jint index) {
dsamersoff@2545 438 int ret = getFlags0(env, name);
dsamersoff@2545 439 return (ret & IFF_POINTOPOINT) ? JNI_TRUE : JNI_FALSE;
dsamersoff@2545 440 }
dsamersoff@2545 441
dsamersoff@2545 442 /*
dsamersoff@2545 443 * Class: java_net_NetworkInterface
dsamersoff@2545 444 * Method: isLoopback0
dsamersoff@2545 445 * Signature: (Ljava/lang/String;I)Z
dsamersoff@2545 446 */
dsamersoff@2545 447 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0(JNIEnv *env, jclass cls, jstring name, jint index) {
dsamersoff@2545 448 int ret = getFlags0(env, name);
dsamersoff@2545 449 return (ret & IFF_LOOPBACK) ? JNI_TRUE : JNI_FALSE;
dsamersoff@2545 450 }
dsamersoff@2545 451
dsamersoff@2545 452 /*
dsamersoff@2545 453 * Class: java_net_NetworkInterface
dsamersoff@2545 454 * Method: supportsMulticast0
dsamersoff@2545 455 * Signature: (Ljava/lang/String;I)Z
dsamersoff@2545 456 */
dsamersoff@2545 457 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0(JNIEnv *env, jclass cls, jstring name, jint index) {
dsamersoff@2545 458 int ret = getFlags0(env, name);
dsamersoff@2545 459 return (ret & IFF_MULTICAST) ? JNI_TRUE : JNI_FALSE;
dsamersoff@2545 460 }
dsamersoff@2545 461
dsamersoff@2545 462 /*
dsamersoff@2545 463 * Class: java_net_NetworkInterface
dsamersoff@2545 464 * Method: getMacAddr0
dsamersoff@2545 465 * Signature: ([bLjava/lang/String;I)[b
dsamersoff@2545 466 */
dsamersoff@2545 467 JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
dsamersoff@2545 468 jint addr;
dsamersoff@2545 469 jbyte caddr[4];
dsamersoff@2545 470 struct in_addr iaddr;
dsamersoff@2545 471 jbyteArray ret = NULL;
dsamersoff@2545 472 unsigned char mac[16];
dsamersoff@2545 473 int len;
dsamersoff@2545 474 int sock;
dsamersoff@2545 475 jboolean isCopy;
dsamersoff@2545 476 const char* name_utf;
dsamersoff@2545 477
dsamersoff@2545 478 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
dsamersoff@2545 479
dsamersoff@2545 480 if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
dsamersoff@2545 481 (*env)->ReleaseStringUTFChars(env, name, name_utf);
dsamersoff@2545 482 return JNI_FALSE;
dsamersoff@2545 483 }
dsamersoff@2545 484
dsamersoff@2545 485
dsamersoff@2545 486 if (!IS_NULL(addrArray)) {
dsamersoff@2545 487 (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
dsamersoff@2545 488 addr = ((caddr[0]<<24) & 0xff000000);
dsamersoff@2545 489 addr |= ((caddr[1] <<16) & 0xff0000);
dsamersoff@2545 490 addr |= ((caddr[2] <<8) & 0xff00);
dsamersoff@2545 491 addr |= (caddr[3] & 0xff);
dsamersoff@2545 492 iaddr.s_addr = htonl(addr);
dsamersoff@2545 493 len = getMacAddress(env, sock, name_utf, &iaddr, mac);
dsamersoff@2545 494 } else {
dsamersoff@2545 495 len = getMacAddress(env, sock, name_utf,NULL, mac);
dsamersoff@2545 496 }
dsamersoff@2545 497 if (len > 0) {
dsamersoff@2545 498 ret = (*env)->NewByteArray(env, len);
dsamersoff@2545 499 if (IS_NULL(ret)) {
dsamersoff@2545 500 /* we may have memory to free at the end of this */
dsamersoff@2545 501 goto fexit;
dsamersoff@2545 502 }
dsamersoff@2545 503 (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac));
dsamersoff@2545 504 }
dsamersoff@2545 505 fexit:
dsamersoff@2545 506 /* release the UTF string and interface list */
dsamersoff@2545 507 (*env)->ReleaseStringUTFChars(env, name, name_utf);
dsamersoff@2545 508
dsamersoff@2545 509 close(sock);
dsamersoff@2545 510 return ret;
dsamersoff@2545 511 }
dsamersoff@2545 512
dsamersoff@2545 513 /*
dsamersoff@2545 514 * Class: java_net_NetworkInterface
dsamersoff@2545 515 * Method: getMTU0
dsamersoff@2545 516 * Signature: ([bLjava/lang/String;I)I
dsamersoff@2545 517 */
dsamersoff@2545 518
dsamersoff@2545 519 JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) {
dsamersoff@2545 520 jboolean isCopy;
dsamersoff@2545 521 int ret = -1;
dsamersoff@2545 522 int sock;
dsamersoff@2545 523 const char* name_utf;
dsamersoff@2545 524
dsamersoff@2545 525 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
dsamersoff@2545 526
dsamersoff@2545 527 if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
dsamersoff@2545 528 (*env)->ReleaseStringUTFChars(env, name, name_utf);
dsamersoff@2545 529 return JNI_FALSE;
dsamersoff@2545 530 }
dsamersoff@2545 531
dsamersoff@2545 532 ret = getMTU(env, sock, name_utf);
dsamersoff@2545 533
dsamersoff@2545 534 (*env)->ReleaseStringUTFChars(env, name, name_utf);
dsamersoff@2545 535
dsamersoff@2545 536 close(sock);
dsamersoff@2545 537 return ret;
dsamersoff@2545 538 }
dsamersoff@2545 539
dsamersoff@2545 540 /*** Private methods definitions ****/
dsamersoff@2545 541
dsamersoff@2545 542 static int getFlags0(JNIEnv *env, jstring name) {
dsamersoff@2545 543 jboolean isCopy;
dsamersoff@2545 544 int ret, sock;
dsamersoff@2545 545 const char* name_utf;
dsamersoff@2545 546
dsamersoff@2545 547 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
dsamersoff@2545 548
dsamersoff@2545 549 if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
dsamersoff@2545 550 (*env)->ReleaseStringUTFChars(env, name, name_utf);
dsamersoff@2545 551 return -1;
dsamersoff@2545 552 }
dsamersoff@2545 553
dsamersoff@2545 554 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
dsamersoff@2545 555
chegar@2626 556 ret = getFlags(sock, name_utf);
dsamersoff@2545 557
dsamersoff@2545 558 close(sock);
dsamersoff@2545 559 (*env)->ReleaseStringUTFChars(env, name, name_utf);
dsamersoff@2545 560
dsamersoff@2545 561 if (ret < 0) {
dsamersoff@2545 562 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed");
dsamersoff@2545 563 return -1;
dsamersoff@2545 564 }
dsamersoff@2545 565
dsamersoff@2545 566 return ret;
dsamersoff@2545 567 }
dsamersoff@2545 568
dsamersoff@2545 569
dsamersoff@2545 570
dsamersoff@2545 571
duke@0 572 /*
duke@0 573 * Create a NetworkInterface object, populate the name and index, and
duke@0 574 * populate the InetAddress array based on the IP addresses for this
duke@0 575 * interface.
duke@0 576 */
dsamersoff@2545 577 jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
duke@0 578 jobject netifObj;
duke@0 579 jobject name;
duke@0 580 jobjectArray addrArr;
duke@0 581 jobjectArray bindArr;
duke@0 582 jobjectArray childArr;
dsamersoff@2545 583 netaddr *addrs;
duke@0 584 jint addr_index, addr_count, bind_index;
duke@0 585 jint child_count, child_index;
duke@0 586 netaddr *addrP;
duke@0 587 netif *childP;
duke@0 588 jobject tmp;
duke@0 589
duke@0 590 /*
duke@0 591 * Create a NetworkInterface object and populate it
duke@0 592 */
duke@0 593 netifObj = (*env)->NewObject(env, ni_class, ni_ctrID);
duke@0 594 name = (*env)->NewStringUTF(env, ifs->name);
duke@0 595 if (netifObj == NULL || name == NULL) {
duke@0 596 return NULL;
duke@0 597 }
duke@0 598 (*env)->SetObjectField(env, netifObj, ni_nameID, name);
duke@0 599 (*env)->SetObjectField(env, netifObj, ni_descID, name);
duke@0 600 (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);
duke@0 601 (*env)->SetBooleanField(env, netifObj, ni_virutalID, ifs->virtual ? JNI_TRUE : JNI_FALSE);
duke@0 602
duke@0 603 /*
duke@0 604 * Count the number of address on this interface
duke@0 605 */
duke@0 606 addr_count = 0;
duke@0 607 addrP = ifs->addr;
duke@0 608 while (addrP != NULL) {
duke@0 609 addr_count++;
duke@0 610 addrP = addrP->next;
duke@0 611 }
duke@0 612
duke@0 613 /*
duke@0 614 * Create the array of InetAddresses
duke@0 615 */
duke@0 616 addrArr = (*env)->NewObjectArray(env, addr_count, ni_iacls, NULL);
duke@0 617 if (addrArr == NULL) {
duke@0 618 return NULL;
duke@0 619 }
duke@0 620
duke@0 621 bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL);
duke@0 622 if (bindArr == NULL) {
dsamersoff@2545 623 return NULL;
duke@0 624 }
duke@0 625 addrP = ifs->addr;
duke@0 626 addr_index = 0;
duke@0 627 bind_index = 0;
duke@0 628 while (addrP != NULL) {
duke@0 629 jobject iaObj = NULL;
duke@0 630 jobject ibObj = NULL;
duke@0 631
duke@0 632 if (addrP->family == AF_INET) {
duke@0 633 iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
duke@0 634 if (iaObj) {
dsamersoff@2545 635 (*env)->SetIntField(env, iaObj, ni_iaaddressID, htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
duke@0 636 }
duke@0 637 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
duke@0 638 if (ibObj) {
dsamersoff@2545 639 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
dsamersoff@2545 640 if (addrP->brdcast) {
dsamersoff@2545 641 jobject ia2Obj = NULL;
dsamersoff@2545 642 ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
dsamersoff@2545 643 if (ia2Obj) {
dsamersoff@2545 644 (*env)->SetIntField(env, ia2Obj, ni_iaaddressID,
dsamersoff@2545 645 htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
dsamersoff@2545 646 (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
dsamersoff@2545 647 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
dsamersoff@2545 648 }
dsamersoff@2545 649 }
dsamersoff@2545 650 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
duke@0 651 }
duke@0 652 }
duke@0 653
duke@0 654 #ifdef AF_INET6
duke@0 655 if (addrP->family == AF_INET6) {
duke@0 656 int scope=0;
duke@0 657 iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
duke@0 658 if (iaObj) {
duke@0 659 jbyteArray ipaddress = (*env)->NewByteArray(env, 16);
duke@0 660 if (ipaddress == NULL) {
duke@0 661 return NULL;
duke@0 662 }
duke@0 663 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
dsamersoff@2545 664 (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
dsamersoff@2545 665
duke@0 666 scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
dsamersoff@2545 667
duke@0 668 if (scope != 0) { /* zero is default value, no need to set */
duke@0 669 (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
duke@0 670 (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
duke@0 671 (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj);
duke@0 672 }
duke@0 673 (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
duke@0 674 }
duke@0 675 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
duke@0 676 if (ibObj) {
dsamersoff@2545 677 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
dsamersoff@2545 678 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
dsamersoff@2545 679 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
duke@0 680 }
duke@0 681 }
duke@0 682 #endif
duke@0 683
duke@0 684 if (iaObj == NULL) {
duke@0 685 return NULL;
duke@0 686 }
duke@0 687
duke@0 688 (*env)->SetObjectArrayElement(env, addrArr, addr_index++, iaObj);
duke@0 689 addrP = addrP->next;
duke@0 690 }
duke@0 691
duke@0 692 /*
duke@0 693 * See if there is any virtual interface attached to this one.
duke@0 694 */
duke@0 695 child_count = 0;
duke@0 696 childP = ifs->childs;
duke@0 697 while (childP) {
dsamersoff@2545 698 child_count++;
dsamersoff@2545 699 childP = childP->next;
duke@0 700 }
duke@0 701
duke@0 702 childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL);
duke@0 703 if (childArr == NULL) {
dsamersoff@2545 704 return NULL;
duke@0 705 }
duke@0 706
duke@0 707 /*
duke@0 708 * Create the NetworkInterface instances for the sub-interfaces as
duke@0 709 * well.
duke@0 710 */
duke@0 711 child_index = 0;
duke@0 712 childP = ifs->childs;
duke@0 713 while(childP) {
duke@0 714 tmp = createNetworkInterface(env, childP);
duke@0 715 if (tmp == NULL) {
dsamersoff@2545 716 return NULL;
duke@0 717 }
duke@0 718 (*env)->SetObjectField(env, tmp, ni_parentID, netifObj);
duke@0 719 (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp);
duke@0 720 childP = childP->next;
duke@0 721 }
duke@0 722 (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
duke@0 723 (*env)->SetObjectField(env, netifObj, ni_bindsID, bindArr);
duke@0 724 (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
duke@0 725
duke@0 726 /* return the NetworkInterface */
duke@0 727 return netifObj;
duke@0 728 }
duke@0 729
duke@0 730 /*
duke@0 731 * Enumerates all interfaces
duke@0 732 */
duke@0 733 static netif *enumInterfaces(JNIEnv *env) {
duke@0 734 netif *ifs;
dsamersoff@2545 735 int sock;
duke@0 736
duke@0 737 /*
duke@0 738 * Enumerate IPv4 addresses
duke@0 739 */
dsamersoff@2545 740
dsamersoff@2545 741 sock = openSocket(env, AF_INET);
dsamersoff@2545 742 if (sock < 0 && (*env)->ExceptionOccurred(env)) {
dsamersoff@2545 743 return NULL;
duke@0 744 }
duke@0 745
dsamersoff@2545 746 ifs = enumIPv4Interfaces(env, sock, NULL);
dsamersoff@2545 747 close(sock);
dsamersoff@2545 748
dsamersoff@2545 749 if (ifs == NULL && (*env)->ExceptionOccurred(env)) {
dsamersoff@2545 750 return NULL;
dsamersoff@2545 751 }
dsamersoff@2545 752
dsamersoff@2545 753 /* return partial list if exception occure in the middle of process ???*/
dsamersoff@2545 754
duke@0 755 /*
duke@0 756 * If IPv6 is available then enumerate IPv6 addresses.
duke@0 757 */
duke@0 758 #ifdef AF_INET6
dsamersoff@2545 759
dsamersoff@2605 760 /* User can disable ipv6 expicitly by -Djava.net.preferIPv4Stack=true,
dsamersoff@2605 761 * so we have to call ipv6_available()
dsamersoff@2605 762 */
dsamersoff@2605 763 if (ipv6_available()) {
duke@0 764
dsamersoff@2605 765 sock = openSocket(env, AF_INET6);
dsamersoff@2605 766 if (sock < 0 && (*env)->ExceptionOccurred(env)) {
dsamersoff@2605 767 freeif(ifs);
dsamersoff@2605 768 return NULL;
dsamersoff@2605 769 }
dsamersoff@2605 770
dsamersoff@2605 771 ifs = enumIPv6Interfaces(env, sock, ifs);
dsamersoff@2605 772 close(sock);
dsamersoff@2605 773
dsamersoff@2605 774 if ((*env)->ExceptionOccurred(env)) {
dsamersoff@2605 775 freeif(ifs);
dsamersoff@2605 776 return NULL;
dsamersoff@2605 777 }
dsamersoff@2605 778
dsamersoff@2605 779 }
duke@0 780 #endif
duke@0 781
duke@0 782 return ifs;
duke@0 783 }
duke@0 784
dsamersoff@2545 785 #define CHECKED_MALLOC3(_pointer,_type,_size) \
dsamersoff@2545 786 do{ \
dsamersoff@2545 787 _pointer = (_type)malloc( _size ); \
dsamersoff@2545 788 if (_pointer == NULL) { \
dsamersoff@2545 789 JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); \
dsamersoff@2545 790 return ifs; /* return untouched list */ \
dsamersoff@2545 791 } \
dsamersoff@2545 792 } while(0)
duke@0 793
duke@0 794
duke@0 795 /*
duke@0 796 * Free an interface list (including any attached addresses)
duke@0 797 */
duke@0 798 void freeif(netif *ifs) {
duke@0 799 netif *currif = ifs;
dsamersoff@2545 800 netif *child = NULL;
duke@0 801
duke@0 802 while (currif != NULL) {
duke@0 803 netaddr *addrP = currif->addr;
duke@0 804 while (addrP != NULL) {
duke@0 805 netaddr *next = addrP->next;
duke@0 806 free(addrP);
duke@0 807 addrP = next;
dsamersoff@2545 808 }
duke@0 809
dsamersoff@2545 810 /*
dsamersoff@2545 811 * Don't forget to free the sub-interfaces.
dsamersoff@2545 812 */
dsamersoff@2545 813 if (currif->childs != NULL) {
dsamersoff@2545 814 freeif(currif->childs);
dsamersoff@2545 815 }
duke@0 816
dsamersoff@2545 817 ifs = currif->next;
dsamersoff@2545 818 free(currif);
dsamersoff@2545 819 currif = ifs;
duke@0 820 }
duke@0 821 }
duke@0 822
dsamersoff@2545 823 netif *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix) {
dsamersoff@2545 824 netif *currif = ifs, *parent;
duke@0 825 netaddr *addrP;
dsamersoff@2545 826
dsamersoff@2545 827 #ifdef __solaris__
dsamersoff@2545 828 char name[LIFNAMSIZ], vname[LIFNAMSIZ];
dsamersoff@2545 829 #else
dsamersoff@2545 830 char name[IFNAMSIZ], vname[IFNAMSIZ];
dsamersoff@2545 831 #endif
dsamersoff@2545 832
dsamersoff@2545 833 char *name_colonP;
dsamersoff@2545 834 int mask;
duke@0 835 int isVirtual = 0;
dsamersoff@2545 836 int addr_size;
duke@0 837
duke@0 838 /*
duke@0 839 * If the interface name is a logical interface then we
duke@0 840 * remove the unit number so that we have the physical
duke@0 841 * interface (eg: hme0:1 -> hme0). NetworkInterface
duke@0 842 * currently doesn't have any concept of physical vs.
duke@0 843 * logical interfaces.
duke@0 844 */
duke@0 845 strcpy(name, if_name);
dsamersoff@2545 846 *vname = 0;
duke@0 847
duke@0 848 /*
duke@0 849 * Create and populate the netaddr node. If allocation fails
duke@0 850 * return an un-updated list.
duke@0 851 */
dsamersoff@2545 852 /*Allocate for addr and brdcast at once*/
dsamersoff@2545 853
dsamersoff@2545 854 #ifdef AF_INET6
dsamersoff@2545 855 addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
dsamersoff@2545 856 #else
dsamersoff@2545 857 addr_size = sizeof(struct sockaddr_in);
dsamersoff@2545 858 #endif
dsamersoff@2545 859
dsamersoff@2545 860 CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr)+2*addr_size);
dsamersoff@2545 861 addrP->addr = (struct sockaddr *)( (char *) addrP+sizeof(netaddr) );
dsamersoff@2545 862 memcpy(addrP->addr, ifr_addrP, addr_size);
dsamersoff@2545 863
duke@0 864 addrP->family = family;
duke@0 865 addrP->brdcast = NULL;
duke@0 866 addrP->mask = prefix;
dsamersoff@2545 867 addrP->next = 0;
duke@0 868 if (family == AF_INET) {
duke@0 869 /*
duke@0 870 * Deal with brodcast addr & subnet mask
duke@0 871 */
dsamersoff@2545 872 struct sockaddr * brdcast_to = (struct sockaddr *) ((char *) addrP + sizeof(netaddr) + addr_size);
dsamersoff@2545 873 addrP->brdcast = getBroadcast(env, sock, name, brdcast_to );
duke@0 874
dsamersoff@2545 875 if (addrP->brdcast && (mask = getSubnet(env, sock, name)) != -1) {
dsamersoff@2545 876 addrP->mask = mask;
dsamersoff@2545 877 }
dsamersoff@2545 878 }
dsamersoff@2545 879
dsamersoff@2545 880 /**
dsamersoff@2545 881 * Deal with virtual interface with colon notaion e.g. eth0:1
dsamersoff@2545 882 */
dsamersoff@2545 883 name_colonP = strchr(name, ':');
dsamersoff@2545 884 if (name_colonP != NULL) {
duke@0 885 /**
duke@0 886 * This is a virtual interface. If we are able to access the parent
duke@0 887 * we need to create a new entry if it doesn't exist yet *and* update
duke@0 888 * the 'parent' interface with the new records.
duke@0 889 */
dsamersoff@2545 890 *name_colonP = 0;
chegar@2626 891 if (getFlags(sock, name) < 0) {
chegar@894 892 // failed to access parent interface do not create parent.
chegar@894 893 // We are a virtual interface with no parent.
chegar@894 894 isVirtual = 1;
dsamersoff@2545 895 *name_colonP = ':';
duke@0 896 }
dsamersoff@2545 897 else{
dsamersoff@2545 898 // Got access to parent, so create it if necessary.
dsamersoff@2545 899 // Save original name to vname and truncate name by ':'
dsamersoff@2545 900 memcpy(vname, name, sizeof(vname) );
dsamersoff@2545 901 vname[name_colonP - name] = ':';
dsamersoff@2545 902 }
duke@0 903 }
duke@0 904
duke@0 905 /*
duke@0 906 * Check if this is a "new" interface. Use the interface
duke@0 907 * name for matching because index isn't supported on
duke@0 908 * Solaris 2.6 & 7.
duke@0 909 */
duke@0 910 while (currif != NULL) {
duke@0 911 if (strcmp(name, currif->name) == 0) {
duke@0 912 break;
duke@0 913 }
duke@0 914 currif = currif->next;
duke@0 915 }
duke@0 916
duke@0 917 /*
duke@0 918 * If "new" then create an netif structure and
duke@0 919 * insert it onto the list.
duke@0 920 */
duke@0 921 if (currif == NULL) {
dsamersoff@2545 922 CHECKED_MALLOC3(currif, netif *, sizeof(netif)+IFNAMSIZ );
dsamersoff@2545 923 currif->name = (char *) currif+sizeof(netif);
dsamersoff@2545 924 strcpy(currif->name, name);
chegar@2578 925 currif->index = getIndex(sock, name);
dsamersoff@2545 926 currif->addr = NULL;
dsamersoff@2545 927 currif->childs = NULL;
dsamersoff@2545 928 currif->virtual = isVirtual;
dsamersoff@2545 929 currif->next = ifs;
dsamersoff@2545 930 ifs = currif;
duke@0 931 }
duke@0 932
duke@0 933 /*
duke@0 934 * Finally insert the address on the interface
duke@0 935 */
duke@0 936 addrP->next = currif->addr;
duke@0 937 currif->addr = addrP;
duke@0 938
duke@0 939 parent = currif;
duke@0 940
duke@0 941 /**
duke@0 942 * Let's deal with the virtual interface now.
duke@0 943 */
duke@0 944 if (vname[0]) {
dsamersoff@2545 945 netaddr *tmpaddr;
duke@0 946
dsamersoff@2545 947 currif = parent->childs;
duke@0 948
dsamersoff@2545 949 while (currif != NULL) {
dsamersoff@2545 950 if (strcmp(vname, currif->name) == 0) {
dsamersoff@2545 951 break;
dsamersoff@2545 952 }
dsamersoff@2545 953 currif = currif->next;
duke@0 954 }
dsamersoff@2545 955
dsamersoff@2545 956 if (currif == NULL) {
dsamersoff@2545 957 CHECKED_MALLOC3(currif, netif *, sizeof(netif)+ IFNAMSIZ );
dsamersoff@2545 958 currif->name = (char *) currif + sizeof(netif);
dsamersoff@2545 959 strcpy(currif->name, vname);
chegar@2578 960 currif->index = getIndex(sock, vname);
dsamersoff@2545 961 currif->addr = NULL;
dsamersoff@2545 962 /* Need to duplicate the addr entry? */
dsamersoff@2545 963 currif->virtual = 1;
dsamersoff@2545 964 currif->childs = NULL;
dsamersoff@2545 965 currif->next = parent->childs;
dsamersoff@2545 966 parent->childs = currif;
duke@0 967 }
dsamersoff@2545 968
dsamersoff@2545 969 CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr)+2*addr_size);
dsamersoff@2545 970 memcpy(tmpaddr, addrP, sizeof(netaddr));
dsamersoff@2545 971 if (addrP->addr != NULL) {
dsamersoff@2545 972 tmpaddr->addr = (struct sockaddr *) ( (char*)tmpaddr + sizeof(netaddr) ) ;
dsamersoff@2545 973 memcpy(tmpaddr->addr, addrP->addr, addr_size);
duke@0 974 }
duke@0 975
dsamersoff@2545 976 if (addrP->brdcast != NULL) {
dsamersoff@2545 977 tmpaddr->brdcast = (struct sockaddr *) ((char *) tmpaddr + sizeof(netaddr)+addr_size);
dsamersoff@2545 978 memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
dsamersoff@2545 979 }
dsamersoff@2545 980
dsamersoff@2545 981 tmpaddr->next = currif->addr;
dsamersoff@2545 982 currif->addr = tmpaddr;
duke@0 983 }
duke@0 984
duke@0 985 return ifs;
duke@0 986 }
duke@0 987
dsamersoff@2545 988 /* Open socket for further ioct calls
dsamersoff@2545 989 * proto is AF_INET/AF_INET6
duke@0 990 */
dsamersoff@2545 991 static int openSocket(JNIEnv *env, int proto){
dsamersoff@2545 992 int sock;
duke@0 993
dsamersoff@2545 994 if ((sock = JVM_Socket(proto, SOCK_DGRAM, 0)) < 0) {
dsamersoff@2545 995 /*
dsamersoff@2545 996 * If EPROTONOSUPPORT is returned it means we don't have
dsamersoff@2545 997 * support for this proto so don't throw an exception.
dsamersoff@2545 998 */
dsamersoff@2545 999 if (errno != EPROTONOSUPPORT) {
dsamersoff@2545 1000 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Socket creation failed");
dsamersoff@2545 1001 }
dsamersoff@2545 1002 return -1;
chegar@375 1003 }
chegar@375 1004
dsamersoff@2545 1005 return sock;
dsamersoff@2545 1006 }
chegar@375 1007
dsamersoff@2545 1008
dsamersoff@2545 1009 /** Linux **/
dsamersoff@2545 1010 #ifdef __linux__
dsamersoff@2545 1011 /* Open socket for further ioct calls, try v4 socket first and
dsamersoff@2545 1012 * if it falls return v6 socket
dsamersoff@2545 1013 */
dsamersoff@2545 1014
dsamersoff@2545 1015 #ifdef AF_INET6
dsamersoff@2545 1016 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
dsamersoff@2545 1017 int sock;
dsamersoff@2545 1018 struct ifreq if2;
dsamersoff@2545 1019
dsamersoff@2545 1020 if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
dsamersoff@2545 1021 if (errno == EPROTONOSUPPORT){
dsamersoff@2545 1022 if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
dsamersoff@2545 1023 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
dsamersoff@2545 1024 return -1;
dsamersoff@2545 1025 }
dsamersoff@2545 1026 }
dsamersoff@2545 1027 else{ // errno is not NOSUPPORT
dsamersoff@2545 1028 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
dsamersoff@2545 1029 return -1;
dsamersoff@2545 1030 }
dsamersoff@2545 1031 }
dsamersoff@2545 1032
dsamersoff@2545 1033 /* Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or IPv6 socket regardless of type
dsamersoff@2545 1034 of address of an interface */
dsamersoff@2545 1035
dsamersoff@2545 1036 return sock;
dsamersoff@2545 1037 }
dsamersoff@2545 1038
dsamersoff@2545 1039 #else
dsamersoff@2545 1040 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
dsamersoff@2545 1041 return openSocket(env,AF_INET);
dsamersoff@2545 1042 }
dsamersoff@2545 1043 #endif
dsamersoff@2545 1044
dsamersoff@2545 1045 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
dsamersoff@2545 1046 struct ifconf ifc;
dsamersoff@2545 1047 struct ifreq *ifreqP;
dsamersoff@2545 1048 char *buf;
dsamersoff@2545 1049 int numifs;
dsamersoff@2545 1050 unsigned i;
dsamersoff@2545 1051
dsamersoff@2545 1052
dsamersoff@2545 1053 /* need to do a dummy SIOCGIFCONF to determine the buffer size.
dsamersoff@2545 1054 * SIOCGIFCOUNT doesn't work
dsamersoff@2545 1055 */
dsamersoff@2545 1056 ifc.ifc_buf = NULL;
dsamersoff@2545 1057 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
dsamersoff@2545 1058 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
dsamersoff@2545 1059 return ifs;
chegar@375 1060 }
dsamersoff@2545 1061
dsamersoff@2545 1062 CHECKED_MALLOC3(buf,char *, ifc.ifc_len);
dsamersoff@2545 1063
dsamersoff@2545 1064 ifc.ifc_buf = buf;
dsamersoff@2545 1065 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
dsamersoff@2545 1066 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
dsamersoff@2545 1067 (void) free(buf);
dsamersoff@2545 1068 return ifs;
dsamersoff@2545 1069 }
dsamersoff@2545 1070
dsamersoff@2545 1071 /*
dsamersoff@2545 1072 * Iterate through each interface
dsamersoff@2545 1073 */
dsamersoff@2545 1074 ifreqP = ifc.ifc_req;
dsamersoff@2545 1075 for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
dsamersoff@2545 1076 /*
dsamersoff@2545 1077 * Add to the list
dsamersoff@2545 1078 */
dsamersoff@2545 1079 ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0);
dsamersoff@2545 1080
dsamersoff@2545 1081 /*
dsamersoff@2545 1082 * If an exception occurred then free the list
dsamersoff@2545 1083 */
dsamersoff@2545 1084 if ((*env)->ExceptionOccurred(env)) {
dsamersoff@2545 1085 free(buf);
dsamersoff@2545 1086 freeif(ifs);
dsamersoff@2545 1087 return NULL;
dsamersoff@2545 1088 }
dsamersoff@2545 1089 }
dsamersoff@2545 1090
dsamersoff@2545 1091 /*
dsamersoff@2545 1092 * Free socket and buffer
dsamersoff@2545 1093 */
dsamersoff@2545 1094 free(buf);
dsamersoff@2545 1095 return ifs;
dsamersoff@2545 1096 }
dsamersoff@2545 1097
dsamersoff@2545 1098
dsamersoff@2545 1099 /*
dsamersoff@2545 1100 * Enumerates and returns all IPv6 interfaces on Linux
dsamersoff@2545 1101 */
dsamersoff@2545 1102
dsamersoff@2545 1103 #ifdef AF_INET6
dsamersoff@2545 1104 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
dsamersoff@2545 1105 FILE *f;
chegar@3657 1106 char addr6[40], devname[21];
dsamersoff@2545 1107 char addr6p[8][5];
dsamersoff@2545 1108 int plen, scope, dad_status, if_idx;
dsamersoff@2545 1109 uint8_t ipv6addr[16];
dsamersoff@2545 1110
dsamersoff@2545 1111 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
dsamersoff@2545 1112 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
dsamersoff@2545 1113 addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7],
dsamersoff@2545 1114 &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
dsamersoff@2545 1115
dsamersoff@2545 1116 struct netif *ifs_ptr = NULL;
dsamersoff@2545 1117 struct netif *last_ptr = NULL;
dsamersoff@2545 1118 struct sockaddr_in6 addr;
dsamersoff@2545 1119
dsamersoff@2545 1120 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
dsamersoff@2545 1121 addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
dsamersoff@2545 1122 inet_pton(AF_INET6, addr6, ipv6addr);
dsamersoff@2545 1123
dsamersoff@2545 1124 memset(&addr, 0, sizeof(struct sockaddr_in6));
dsamersoff@2545 1125 memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16);
dsamersoff@2545 1126
dsamersoff@2545 1127 addr.sin6_scope_id = if_idx;
dsamersoff@2545 1128
dsamersoff@2545 1129 ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, AF_INET6, plen);
dsamersoff@2545 1130
dsamersoff@2545 1131
dsamersoff@2545 1132 /*
dsamersoff@2545 1133 * If an exception occurred then return the list as is.
dsamersoff@2545 1134 */
dsamersoff@2545 1135 if ((*env)->ExceptionOccurred(env)) {
dsamersoff@2545 1136 fclose(f);
dsamersoff@2545 1137 return ifs;
dsamersoff@2545 1138 }
dsamersoff@2545 1139 }
dsamersoff@2545 1140 fclose(f);
dsamersoff@2545 1141 }
dsamersoff@2545 1142 return ifs;
dsamersoff@2545 1143 }
chegar@375 1144 #endif
duke@0 1145
dsamersoff@2545 1146
chegar@2578 1147 static int getIndex(int sock, const char *name){
dsamersoff@2545 1148 /*
dsamersoff@2545 1149 * Try to get the interface index
dsamersoff@2545 1150 * (Not supported on Solaris 2.6 or 7)
dsamersoff@2545 1151 */
dsamersoff@2545 1152 struct ifreq if2;
dsamersoff@2545 1153 strcpy(if2.ifr_name, name);
dsamersoff@2545 1154
dsamersoff@2545 1155 if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
dsamersoff@2545 1156 return -1;
dsamersoff@2545 1157 }
dsamersoff@2545 1158
dsamersoff@2545 1159 return if2.ifr_ifindex;
duke@0 1160 }
duke@0 1161
duke@0 1162 /**
duke@0 1163 * Returns the IPv4 broadcast address of a named interface, if it exists.
duke@0 1164 * Returns 0 if it doesn't have one.
duke@0 1165 */
dsamersoff@2545 1166 static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
duke@0 1167 struct sockaddr *ret = NULL;
duke@0 1168 struct ifreq if2;
duke@0 1169
duke@0 1170 memset((char *) &if2, 0, sizeof(if2));
duke@0 1171 strcpy(if2.ifr_name, ifname);
dsamersoff@2545 1172
duke@0 1173 /* Let's make sure the interface does have a broadcast address */
dsamersoff@2545 1174 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
dsamersoff@2545 1175 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFFLAGS failed");
dsamersoff@2545 1176 return ret;
duke@0 1177 }
dsamersoff@2545 1178
dsamersoff@2545 1179 if (if2.ifr_flags & IFF_BROADCAST) {
dsamersoff@2545 1180 /* It does, let's retrieve it*/
dsamersoff@2545 1181 if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
dsamersoff@2545 1182 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
dsamersoff@2545 1183 return ret;
dsamersoff@2545 1184 }
dsamersoff@2545 1185
dsamersoff@2545 1186 ret = brdcast_store;
duke@0 1187 memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
duke@0 1188 }
dsamersoff@2545 1189
duke@0 1190 return ret;
duke@0 1191 }
duke@0 1192
duke@0 1193 /**
duke@0 1194 * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
duke@0 1195 * interface, if it has one, otherwise return -1.
duke@0 1196 */
dsamersoff@2545 1197 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
dsamersoff@2545 1198 unsigned int mask;
dsamersoff@2545 1199 short ret;
dsamersoff@2545 1200 struct ifreq if2;
dsamersoff@2545 1201
dsamersoff@2545 1202 memset((char *) &if2, 0, sizeof(if2));
dsamersoff@2545 1203 strcpy(if2.ifr_name, ifname);
dsamersoff@2545 1204
dsamersoff@2545 1205 if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
dsamersoff@2545 1206 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
dsamersoff@2545 1207 return -1;
dsamersoff@2545 1208 }
dsamersoff@2545 1209
dsamersoff@2545 1210 mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
dsamersoff@2545 1211 ret = 0;
dsamersoff@2545 1212 while (mask) {
dsamersoff@2545 1213 mask <<= 1;
dsamersoff@2545 1214 ret++;
dsamersoff@2545 1215 }
dsamersoff@2545 1216
dsamersoff@2545 1217 return ret;
dsamersoff@2545 1218 }
dsamersoff@2545 1219
dsamersoff@2545 1220 /**
dsamersoff@2545 1221 * Get the Hardware address (usually MAC address) for the named interface.
dsamersoff@2545 1222 * return puts the data in buf, and returns the length, in byte, of the
dsamersoff@2545 1223 * MAC address. Returns -1 if there is no hardware address on that interface.
dsamersoff@2545 1224 */
dsamersoff@2545 1225 static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
dsamersoff@2545 1226 static struct ifreq ifr;
dsamersoff@2545 1227 int i;
dsamersoff@2545 1228
dsamersoff@2545 1229 strcpy(ifr.ifr_name, ifname);
dsamersoff@2545 1230 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
dsamersoff@2545 1231 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFHWADDR failed");
dsamersoff@2545 1232 return -1;
dsamersoff@2545 1233 }
dsamersoff@2545 1234
dsamersoff@2545 1235 memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
dsamersoff@2545 1236
dsamersoff@2545 1237 /*
dsamersoff@2545 1238 * All bytes to 0 means no hardware address.
dsamersoff@2545 1239 */
dsamersoff@2545 1240
dsamersoff@2545 1241 for (i = 0; i < IFHWADDRLEN; i++) {
dsamersoff@2545 1242 if (buf[i] != 0)
dsamersoff@2545 1243 return IFHWADDRLEN;
dsamersoff@2545 1244 }
dsamersoff@2545 1245
dsamersoff@2545 1246 return -1;
dsamersoff@2545 1247 }
dsamersoff@2545 1248
dsamersoff@2545 1249 static int getMTU(JNIEnv *env, int sock, const char *ifname) {
dsamersoff@2545 1250 struct ifreq if2;
dsamersoff@2545 1251
dsamersoff@2545 1252 memset((char *) &if2, 0, sizeof(if2));
dsamersoff@2545 1253 strcpy(if2.ifr_name, ifname);
dsamersoff@2545 1254
dsamersoff@2545 1255 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
dsamersoff@2545 1256 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
dsamersoff@2545 1257 return -1;
dsamersoff@2545 1258 }
dsamersoff@2545 1259
dsamersoff@2545 1260 return if2.ifr_mtu;
dsamersoff@2545 1261 }
dsamersoff@2545 1262
chegar@2626 1263 static int getFlags(int sock, const char *ifname) {
duke@0 1264 struct ifreq if2;
dsamersoff@2545 1265 int ret = -1;
duke@0 1266
duke@0 1267 memset((char *) &if2, 0, sizeof(if2));
duke@0 1268 strcpy(if2.ifr_name, ifname);
dsamersoff@2545 1269
dsamersoff@2545 1270 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){
dsamersoff@2545 1271 return -1;
duke@0 1272 }
dsamersoff@2545 1273
dsamersoff@2545 1274 return if2.ifr_flags;
duke@0 1275 }
duke@0 1276
dsamersoff@2545 1277 #endif
dsamersoff@2545 1278
dsamersoff@2545 1279 /** Solaris **/
duke@0 1280 #ifdef __solaris__
dsamersoff@2545 1281 /* Open socket for further ioct calls, try v4 socket first and
dsamersoff@2545 1282 * if it falls return v6 socket
dsamersoff@2545 1283 */
dsamersoff@2545 1284
dsamersoff@2545 1285 #ifdef AF_INET6
dsamersoff@2545 1286 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
dsamersoff@2545 1287 int sock, alreadyV6 = 0;
dsamersoff@2545 1288 struct lifreq if2;
dsamersoff@2545 1289
dsamersoff@2545 1290 if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
dsamersoff@2545 1291 if (errno == EPROTONOSUPPORT){
dsamersoff@2545 1292 if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
dsamersoff@2545 1293 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
dsamersoff@2545 1294 return -1;
dsamersoff@2545 1295 }
dsamersoff@2545 1296
dsamersoff@2545 1297 alreadyV6=1;
dsamersoff@2545 1298 }
dsamersoff@2545 1299 else{ // errno is not NOSUPPORT
dsamersoff@2545 1300 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
dsamersoff@2545 1301 return -1;
dsamersoff@2545 1302 }
dsamersoff@2545 1303 }
dsamersoff@2545 1304
dsamersoff@2545 1305 /**
dsamersoff@2545 1306 * Solaris requires that we have IPv6 socket to query an
dsamersoff@2545 1307 * interface without IPv4 address - check it here
dsamersoff@2545 1308 * POSIX 1 require the kernell to return ENOTTY if the call is
dsamersoff@2545 1309 * unappropriate for device e.g. NETMASK for device having IPv6
dsamersoff@2545 1310 * only address but not all devices follows the standart so
dsamersoff@2545 1311 * fallback on any error. It's not an ecology friendly but more
dsamersoff@2545 1312 * reliable.
dsamersoff@2545 1313 */
dsamersoff@2545 1314
dsamersoff@2545 1315 if (! alreadyV6 ){
dsamersoff@2545 1316 memset((char *) &if2, 0, sizeof(if2));
dsamersoff@2545 1317 strcpy(if2.lifr_name, ifname);
dsamersoff@2545 1318 if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
dsamersoff@2545 1319 close(sock);
dsamersoff@2545 1320 if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
dsamersoff@2545 1321 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
dsamersoff@2545 1322 return -1;
dsamersoff@2545 1323 }
dsamersoff@2545 1324 }
dsamersoff@2545 1325 }
dsamersoff@2545 1326
dsamersoff@2545 1327 return sock;
dsamersoff@2545 1328 }
dsamersoff@2545 1329
dsamersoff@2545 1330 #else
dsamersoff@2545 1331 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
dsamersoff@2545 1332 return openSocket(env,AF_INET);
dsamersoff@2545 1333 }
dsamersoff@2545 1334 #endif
dsamersoff@2545 1335
dsamersoff@2545 1336 /*
dsamersoff@2545 1337 * Enumerates and returns all IPv4 interfaces
dsamersoff@2545 1338 * (linux verison)
dsamersoff@2545 1339 */
dsamersoff@2545 1340
dsamersoff@2545 1341 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
dsamersoff@2545 1342 return enumIPvXInterfaces(env,sock, ifs, AF_INET);
dsamersoff@2545 1343 }
dsamersoff@2545 1344
dsamersoff@2545 1345 #ifdef AF_INET6
dsamersoff@2545 1346 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
dsamersoff@2545 1347 return enumIPvXInterfaces(env,sock, ifs, AF_INET6);
dsamersoff@2545 1348 }
dsamersoff@2545 1349 #endif
dsamersoff@2545 1350
dsamersoff@2545 1351 /*
dsamersoff@2545 1352 Enumerates and returns all interfaces on Solaris
dsamersoff@2545 1353 use the same code for IPv4 and IPv6
dsamersoff@2545 1354 */
dsamersoff@2545 1355 static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family) {
dsamersoff@2545 1356 struct lifconf ifc;
dsamersoff@2545 1357 struct lifreq *ifr;
dsamersoff@2545 1358 int n;
dsamersoff@2545 1359 char *buf;
dsamersoff@2545 1360 struct lifnum numifs;
dsamersoff@2545 1361 unsigned bufsize;
dsamersoff@2545 1362
dsamersoff@2545 1363 /*
dsamersoff@2545 1364 * Get the interface count
dsamersoff@2545 1365 */
dsamersoff@2545 1366 numifs.lifn_family = family;
dsamersoff@2545 1367 numifs.lifn_flags = 0;
dsamersoff@2545 1368 if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
dsamersoff@2545 1369 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFNUM failed");
dsamersoff@2545 1370 return ifs;
dsamersoff@2545 1371 }
dsamersoff@2545 1372
dsamersoff@2545 1373 /*
dsamersoff@2545 1374 * Enumerate the interface configurations
dsamersoff@2545 1375 */
dsamersoff@2545 1376 bufsize = numifs.lifn_count * sizeof (struct lifreq);
dsamersoff@2545 1377 CHECKED_MALLOC3(buf, char *, bufsize);
dsamersoff@2545 1378
dsamersoff@2545 1379 ifc.lifc_family = family;
dsamersoff@2545 1380 ifc.lifc_flags = 0;
dsamersoff@2545 1381 ifc.lifc_len = bufsize;
dsamersoff@2545 1382 ifc.lifc_buf = buf;
dsamersoff@2545 1383 if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
dsamersoff@2545 1384 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFCONF failed");
dsamersoff@2545 1385 free(buf);
dsamersoff@2545 1386 return ifs;
dsamersoff@2545 1387 }
dsamersoff@2545 1388
dsamersoff@2545 1389 /*
dsamersoff@2545 1390 * Iterate through each interface
dsamersoff@2545 1391 */
dsamersoff@2545 1392 ifr = ifc.lifc_req;
dsamersoff@2545 1393 for (n=0; n<numifs.lifn_count; n++, ifr++) {
dsamersoff@2545 1394 int index = -1;
dsamersoff@2545 1395 struct lifreq if2;
dsamersoff@2545 1396
dsamersoff@2545 1397 /*
dsamersoff@2545 1398 * Ignore either IPv4 or IPv6 addresses
dsamersoff@2545 1399 */
dsamersoff@2545 1400 if (ifr->lifr_addr.ss_family != family) {
dsamersoff@2545 1401 continue;
dsamersoff@2545 1402 }
dsamersoff@2545 1403
chegar@2578 1404 #ifdef AF_INET6
chegar@2578 1405 if (ifr->lifr_addr.ss_family == AF_INET6) {
chegar@2578 1406 struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr);
chegar@2578 1407 s6->sin6_scope_id = getIndex(sock, ifr->lifr_name);
chegar@2578 1408 }
chegar@2578 1409 #endif
chegar@2578 1410
dsamersoff@2545 1411 /* add to the list */
dsamersoff@2545 1412 ifs = addif(env, sock,ifr->lifr_name, ifs, (struct sockaddr *)&(ifr->lifr_addr),family, (short) ifr->lifr_addrlen);
dsamersoff@2545 1413
dsamersoff@2545 1414 /*
dsamersoff@2545 1415 * If an exception occurred we return immediately
dsamersoff@2545 1416 */
dsamersoff@2545 1417 if ((*env)->ExceptionOccurred(env)) {
dsamersoff@2545 1418 free(buf);
dsamersoff@2545 1419 return ifs;
dsamersoff@2545 1420 }
dsamersoff@2545 1421
dsamersoff@2545 1422 }
dsamersoff@2545 1423
dsamersoff@2545 1424 free(buf);
dsamersoff@2545 1425 return ifs;
dsamersoff@2545 1426 }
dsamersoff@2545 1427
chegar@2578 1428 static int getIndex(int sock, const char *name){
dsamersoff@2545 1429 /*
dsamersoff@2545 1430 * Try to get the interface index
dsamersoff@2545 1431 * (Not supported on Solaris 2.6 or 7)
dsamersoff@2545 1432 */
dsamersoff@2545 1433 struct lifreq if2;
dsamersoff@2545 1434 strcpy(if2.lifr_name, name);
dsamersoff@2545 1435
dsamersoff@2545 1436 if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) {
dsamersoff@2545 1437 return -1;
dsamersoff@2545 1438 }
dsamersoff@2545 1439
dsamersoff@2545 1440 return if2.lifr_index;
dsamersoff@2545 1441 }
dsamersoff@2545 1442
dsamersoff@2545 1443 /**
dsamersoff@2545 1444 * Returns the IPv4 broadcast address of a named interface, if it exists.
dsamersoff@2545 1445 * Returns 0 if it doesn't have one.
dsamersoff@2545 1446 */
dsamersoff@2545 1447 static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
dsamersoff@2545 1448 struct sockaddr *ret = NULL;
dsamersoff@2545 1449 struct lifreq if2;
dsamersoff@2545 1450
dsamersoff@2545 1451 memset((char *) &if2, 0, sizeof(if2));
dsamersoff@2545 1452 strcpy(if2.lifr_name, ifname);
dsamersoff@2545 1453
dsamersoff@2545 1454 /* Let's make sure the interface does have a broadcast address */
dsamersoff@2545 1455 if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) {
dsamersoff@2545 1456 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed");
dsamersoff@2545 1457 return ret;
dsamersoff@2545 1458 }
dsamersoff@2545 1459
dsamersoff@2545 1460 if (if2.lifr_flags & IFF_BROADCAST) {
dsamersoff@2545 1461 /* It does, let's retrieve it*/
dsamersoff@2545 1462 if (ioctl(sock, SIOCGLIFBRDADDR, (char *)&if2) < 0) {
dsamersoff@2545 1463 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFBRDADDR failed");
dsamersoff@2545 1464 return ret;
dsamersoff@2545 1465 }
dsamersoff@2545 1466
dsamersoff@2545 1467 ret = brdcast_store;
dsamersoff@2545 1468 memcpy(ret, &if2.lifr_broadaddr, sizeof(struct sockaddr));
dsamersoff@2545 1469 }
dsamersoff@2545 1470
dsamersoff@2545 1471 return ret;
dsamersoff@2545 1472 }
dsamersoff@2545 1473
dsamersoff@2545 1474 /**
dsamersoff@2545 1475 * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
dsamersoff@2545 1476 * interface, if it has one, otherwise return -1.
dsamersoff@2545 1477 */
dsamersoff@2545 1478 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
dsamersoff@2545 1479 unsigned int mask;
dsamersoff@2545 1480 short ret;
dsamersoff@2545 1481 struct lifreq if2;
dsamersoff@2545 1482
dsamersoff@2545 1483 memset((char *) &if2, 0, sizeof(if2));
dsamersoff@2545 1484 strcpy(if2.lifr_name, ifname);
dsamersoff@2545 1485
dsamersoff@2545 1486 if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
dsamersoff@2545 1487 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFNETMASK failed");
dsamersoff@2545 1488 return -1;
dsamersoff@2545 1489 }
dsamersoff@2545 1490
dsamersoff@2545 1491 mask = ntohl(((struct sockaddr_in*)&(if2.lifr_addr))->sin_addr.s_addr);
dsamersoff@2545 1492 ret = 0;
dsamersoff@2545 1493
dsamersoff@2545 1494 while (mask) {
dsamersoff@2545 1495 mask <<= 1;
dsamersoff@2545 1496 ret++;
dsamersoff@2545 1497 }
dsamersoff@2545 1498
dsamersoff@2545 1499 return ret;
dsamersoff@2545 1500 }
dsamersoff@2545 1501
dsamersoff@2545 1502
dsamersoff@2545 1503
dsamersoff@2545 1504 #define DEV_PREFIX "/dev/"
duke@0 1505
duke@0 1506 /**
duke@0 1507 * Solaris specific DLPI code to get hardware address from a device.
duke@0 1508 * Unfortunately, at least up to Solaris X, you have to have special
duke@0 1509 * privileges (i.e. be root).
duke@0 1510 */
duke@0 1511 static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf) {
dsamersoff@2545 1512 char style1dev[MAXPATHLEN];
dsamersoff@2545 1513 int fd;
dsamersoff@2545 1514 dl_phys_addr_req_t dlpareq;
dsamersoff@2545 1515 dl_phys_addr_ack_t *dlpaack;
dsamersoff@2545 1516 struct strbuf msg;
dsamersoff@2545 1517 char buf[128];
dsamersoff@2545 1518 int flags = 0;
duke@0 1519
dsamersoff@2545 1520 /**
dsamersoff@2545 1521 * Device is in /dev
dsamersoff@2545 1522 * e.g.: /dev/bge0
dsamersoff@2545 1523 */
dsamersoff@2545 1524 strcpy(style1dev, DEV_PREFIX);
dsamersoff@2545 1525 strcat(style1dev, ifname);
dsamersoff@2545 1526 if ((fd = open(style1dev, O_RDWR)) < 0) {
dsamersoff@2545 1527 /*
dsamersoff@2545 1528 * Can't open it. We probably are missing the privilege.
dsamersoff@2545 1529 * We'll have to try something else
dsamersoff@2545 1530 */
dsamersoff@2545 1531 return 0;
dsamersoff@2545 1532 }
duke@0 1533
dsamersoff@2545 1534 dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
dsamersoff@2545 1535 dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
dsamersoff@2545 1536
dsamersoff@2545 1537 msg.buf = (char *)&dlpareq;
dsamersoff@2545 1538 msg.len = DL_PHYS_ADDR_REQ_SIZE;
dsamersoff@2545 1539
dsamersoff@2545 1540 if (putmsg(fd, &msg, NULL, 0) < 0) {
dsamersoff@2545 1541 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "putmsg failed");
dsamersoff@2545 1542 return -1;
dsamersoff@2545 1543 }
dsamersoff@2545 1544
dsamersoff@2545 1545 dlpaack = (dl_phys_addr_ack_t *)buf;
dsamersoff@2545 1546
dsamersoff@2545 1547 msg.buf = (char *)buf;
dsamersoff@2545 1548 msg.len = 0;
dsamersoff@2545 1549 msg.maxlen = sizeof (buf);
dsamersoff@2545 1550 if (getmsg(fd, &msg, NULL, &flags) < 0) {
dsamersoff@2545 1551 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "getmsg failed");
dsamersoff@2545 1552 return -1;
dsamersoff@2545 1553 }
dsamersoff@2545 1554
dsamersoff@2545 1555 if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
dsamersoff@2545 1556 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Couldn't obtain phys addr\n");
dsamersoff@2545 1557 return -1;
dsamersoff@2545 1558 }
dsamersoff@2545 1559
dsamersoff@2545 1560 memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
dsamersoff@2545 1561 return dlpaack->dl_addr_length;
duke@0 1562 }
duke@0 1563
duke@0 1564 /**
duke@0 1565 * Get the Hardware address (usually MAC address) for the named interface.
duke@0 1566 * return puts the data in buf, and returns the length, in byte, of the
duke@0 1567 * MAC address. Returns -1 if there is no hardware address on that interface.
duke@0 1568 */
dsamersoff@2545 1569 static int getMacAddress(JNIEnv *env, int sock, const char *ifname, const struct in_addr* addr, unsigned char *buf) {
dsamersoff@2545 1570 struct arpreq arpreq;
dsamersoff@2545 1571 struct sockaddr_in* sin;
dsamersoff@2545 1572 struct sockaddr_in ipAddr;
dsamersoff@2545 1573 int len, i;
chegar@4501 1574 struct lifreq lif;
chegar@4501 1575
chegar@4501 1576 /* First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
chegar@4501 1577 * try the old way.
chegar@4501 1578 */
chegar@4501 1579 memset(&lif, 0, sizeof(lif));
chegar@4501 1580 strlcpy(lif.lifr_name, ifname, sizeof(lif.lifr_name));
chegar@4501 1581
chegar@4501 1582 if (ioctl(sock, SIOCGLIFHWADDR, &lif) != -1) {
chegar@4501 1583 struct sockaddr_dl *sp;
chegar@4501 1584 sp = (struct sockaddr_dl *)&lif.lifr_addr;
chegar@4501 1585 memcpy(buf, &sp->sdl_data[0], sp->sdl_alen);
chegar@4501 1586 return sp->sdl_alen;
chegar@4501 1587 }
duke@0 1588
dsamersoff@2545 1589 /**
dsamersoff@2545 1590 * On Solaris we have to use DLPI, but it will only work if we have
dsamersoff@2545 1591 * privileged access (i.e. root). If that fails, we try a lookup
dsamersoff@2545 1592 * in the ARP table, which requires an IPv4 address.
dsamersoff@2545 1593 */
dsamersoff@2545 1594 if ((len = getMacFromDevice(env, ifname, buf)) == 0) {
dsamersoff@2545 1595 /*DLPI failed - trying to do arp lookup*/
duke@0 1596
chegar@4501 1597 if (addr == NULL) {
chegar@4501 1598 /**
chegar@4501 1599 * No IPv4 address for that interface, so can't do an ARP lookup.
chegar@4501 1600 */
chegar@4501 1601 return -1;
chegar@4501 1602 }
dsamersoff@2545 1603
chegar@4501 1604 len = 6; //???
dsamersoff@2545 1605
chegar@4501 1606 sin = (struct sockaddr_in *) &arpreq.arp_pa;
chegar@4501 1607 memset((char *) &arpreq, 0, sizeof(struct arpreq));
chegar@4501 1608 ipAddr.sin_port = 0;
chegar@4501 1609 ipAddr.sin_family = AF_INET;
chegar@4501 1610 memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
chegar@4501 1611 memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
chegar@4501 1612 arpreq.arp_flags= ATF_PUBL;
dsamersoff@2545 1613
chegar@4501 1614 if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
chegar@4501 1615 return -1;
chegar@4501 1616 }
dsamersoff@2545 1617
chegar@4501 1618 memcpy(buf, &arpreq.arp_ha.sa_data[0], len );
chegar@4501 1619 }
duke@0 1620
dsamersoff@2545 1621 /*
dsamersoff@2545 1622 * All bytes to 0 means no hardware address.
dsamersoff@2545 1623 */
duke@0 1624
dsamersoff@2545 1625 for (i = 0; i < len; i++) {
dsamersoff@2545 1626 if (buf[i] != 0)
dsamersoff@2545 1627 return len;
dsamersoff@2545 1628 }
dsamersoff@2545 1629
duke@0 1630 return -1;
duke@0 1631 }
duke@0 1632
dsamersoff@2545 1633 static int getMTU(JNIEnv *env, int sock, const char *ifname) {
dsamersoff@2545 1634 struct lifreq if2;
duke@0 1635
dsamersoff@2545 1636 memset((char *) &if2, 0, sizeof(if2));
dsamersoff@2545 1637 strcpy(if2.lifr_name, ifname);
dsamersoff@2545 1638
dsamersoff@2545 1639 if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
dsamersoff@2545 1640 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFMTU failed");
dsamersoff@2545 1641 return -1;
dsamersoff@2545 1642 }
dsamersoff@2545 1643
dsamersoff@2545 1644 return if2.lifr_mtu;
duke@0 1645 }
duke@0 1646
dsamersoff@2545 1647
chegar@2626 1648 static int getFlags(int sock, const char *ifname) {
dsamersoff@2545 1649 struct lifreq lifr;
dsamersoff@2545 1650 memset((caddr_t)&lifr, 0, sizeof(lifr));
dsamersoff@2545 1651 strcpy((caddr_t)&(lifr.lifr_name), ifname);
dsamersoff@2545 1652
dsamersoff@2545 1653 if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
dsamersoff@2545 1654 return -1;
dsamersoff@2545 1655 }
dsamersoff@2545 1656
dsamersoff@2545 1657 return lifr.lifr_flags;
duke@0 1658 }
duke@0 1659
duke@0 1660
dsamersoff@2545 1661 #endif
duke@0 1662
duke@0 1663