annotate src/solaris/native/java/net/NetworkInterface.c @ 0:37a05a11f281

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