annotate src/solaris/native/java/net/NetworkInterface.c @ 4632:5cca2f1a37da

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