63 #include <net/if_var.h>
64 #include <net/if_dl.h>
65 #include <netinet/in_var.h>
66 #include <ifaddrs.h>
67 #endif
68 #endif
69
70 #include "jvm.h"
71 #include "jni_util.h"
72 #include "net_util.h"
73
74 #if defined(__linux__)
75 #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
76 #elif defined(__solaris__)
77 #ifndef SIOCGLIFHWADDR
78 #define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq)
79 #endif
80 #define DEV_PREFIX "/dev/"
81 #endif
82
83 #define CHECKED_MALLOC3(_pointer, _type, _size) \
84 do { \
85 _pointer = (_type)malloc(_size); \
86 if (_pointer == NULL) { \
87 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); \
88 return ifs; /* return untouched list */ \
89 } \
90 } while(0)
91
92 typedef struct _netaddr {
93 struct sockaddr *addr;
94 struct sockaddr *brdcast;
95 short mask;
96 int family; /* to make searches simple */
97 struct _netaddr *next;
98 } netaddr;
99
100 typedef struct _netif {
101 char *name;
102 int index;
141 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs);
142
143 #if defined(AF_INET6)
144 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
145 #endif
146
147 static netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
148 struct sockaddr *ifr_addrP,
149 struct sockaddr *ifr_broadaddrP,
150 int family, short prefix);
151 static void freeif(netif *ifs);
152
153 static int openSocket(JNIEnv *env, int proto);
154 static int openSocketWithFallback(JNIEnv *env, const char *ifname);
155
156 static short translateIPv4AddressToPrefix(struct sockaddr_in *addr);
157 static short translateIPv6AddressToPrefix(struct sockaddr_in6 *addr);
158
159 static int getIndex(int sock, const char *ifname);
160 static int getFlags(int sock, const char *ifname, int *flags);
161 static int getMacAddress(JNIEnv *env, int sock, const char *ifname,
162 const struct in_addr *addr, unsigned char *buf);
163 static int getMTU(JNIEnv *env, int sock, const char *ifname);
164
165 #if defined(__solaris__)
166 static int getMacFromDevice(JNIEnv *env, const char *ifname,
167 unsigned char *retbuf);
168 #endif
169
170 /******************* Java entry points *****************************/
171
172 /*
173 * Class: java_net_NetworkInterface
174 * Method: init
175 * Signature: ()V
176 */
177 JNIEXPORT void JNICALL Java_java_net_NetworkInterface_init
178 (JNIEnv *env, jclass cls)
179 {
180 ni_class = (*env)->FindClass(env, "java/net/NetworkInterface");
181 CHECK_NULL(ni_class);
220 CHECK_NULL(ni_ib4maskID);
221 ni_defaultIndexID = (*env)->GetStaticFieldID(env, ni_class, "defaultIndex",
222 "I");
223 CHECK_NULL(ni_defaultIndexID);
224 initInetAddressIDs(env);
225 }
226
227 /*
228 * Class: java_net_NetworkInterface
229 * Method: getByName0
230 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
231 */
232 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0
233 (JNIEnv *env, jclass cls, jstring name)
234 {
235 netif *ifs, *curr;
236 jboolean isCopy;
237 const char* name_utf;
238 jobject obj = NULL;
239
240 ifs = enumInterfaces(env);
241 if (ifs == NULL) {
242 return NULL;
243 }
244
245 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
246 if (name_utf == NULL) {
247 if (!(*env)->ExceptionCheck(env))
248 JNU_ThrowOutOfMemoryError(env, NULL);
249 freeif(ifs);
250 return NULL;
251 }
252
253 // Search the list of interface based on name
254 curr = ifs;
255 while (curr != NULL) {
256 if (strcmp(name_utf, curr->name) == 0) {
257 break;
258 }
259 curr = curr->next;
260 }
261
262 // if found create a NetworkInterface
263 if (curr != NULL) {
264 obj = createNetworkInterface(env, curr);
265 }
266
267 // release the UTF string and interface list
268 (*env)->ReleaseStringUTFChars(env, name, name_utf);
269 freeif(ifs);
270
271 return obj;
272 }
273
274 /*
275 * Class: java_net_NetworkInterface
276 * Method: getByIndex0
277 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
278 */
279 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
280 (JNIEnv *env, jclass cls, jint index)
281 {
282 netif *ifs, *curr;
283 jobject obj = NULL;
284
285 if (index <= 0) {
286 return NULL;
287 }
288 ifs = enumInterfaces(env);
289 if (ifs == NULL) {
290 return NULL;
291 }
292
293 // Search the list of interface based on index
294 curr = ifs;
295 while (curr != NULL) {
296 if (index == curr->index) {
297 break;
298 }
299 curr = curr->next;
300 }
301
302 // if found create a NetworkInterface
303 if (curr != NULL) {
304 obj = createNetworkInterface(env, curr);
305 }
306
307 freeif(ifs);
308 return obj;
309 }
310
311 /*
312 * Class: java_net_NetworkInterface
313 * Method: getByInetAddress0
314 * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
315 */
316 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
317 (JNIEnv *env, jclass cls, jobject iaObj)
318 {
319 netif *ifs, *curr;
320
321 #if defined(AF_INET6)
322 int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6;
323 #else
324 int family = AF_INET;
325 #endif
326
327 jobject obj = NULL;
328 jboolean match = JNI_FALSE;
329
330 ifs = enumInterfaces(env);
331 if (ifs == NULL) {
332 return NULL;
333 }
334
335 curr = ifs;
336 while (curr != NULL) {
337 netaddr *addrP = curr->addr;
338
339 // iterate through each address on the interface
340 while (addrP != NULL) {
341
342 if (family == addrP->family) {
343 if (family == AF_INET) {
344 int address1 = htonl(
345 ((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr);
346 int address2 = getInetAddress_addr(env, iaObj);
347
348 if (address1 == address2) {
349 match = JNI_TRUE;
350 break;
351 }
352 }
353
354 #if defined(AF_INET6)
355 if (family == AF_INET6) {
356 jbyte *bytes = (jbyte *)&(
357 ((struct sockaddr_in6*)addrP->addr)->sin6_addr);
358 jbyte caddr[16];
359 int i;
360 getInet6Address_ipaddress(env, iaObj, (char *)caddr);
361 i = 0;
362 while (i < 16) {
363 if (caddr[i] != bytes[i]) {
364 break;
365 }
366 i++;
367 }
368 if (i >= 16) {
369 match = JNI_TRUE;
370 break;
371 }
372 }
373 #endif
374 }
375
376 if (match) {
377 break;
378 }
379 addrP = addrP->next;
380 }
381
382 if (match) {
383 break;
384 }
385 curr = curr->next;
386 }
387
388 // if found create a NetworkInterface
389 if (match) {
390 obj = createNetworkInterface(env, curr);
391 }
392
393 freeif(ifs);
394 return obj;
395 }
396
397 /*
398 * Class: java_net_NetworkInterface
399 * Method: getAll
400 * Signature: ()[Ljava/net/NetworkInterface;
401 */
402 JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll
403 (JNIEnv *env, jclass cls)
404 {
405 netif *ifs, *curr;
406 jobjectArray netIFArr;
407 jint arr_index, ifCount;
408
409 ifs = enumInterfaces(env);
410 if (ifs == NULL) {
411 return NULL;
412 }
413
414 // count the interface
415 ifCount = 0;
416 curr = ifs;
417 while (curr != NULL) {
418 ifCount++;
419 curr = curr->next;
420 }
421
422 // allocate a NetworkInterface array
423 netIFArr = (*env)->NewObjectArray(env, ifCount, cls, NULL);
424 if (netIFArr == NULL) {
425 freeif(ifs);
426 return NULL;
427 }
428
429 // Iterate through the interfaces, create a NetworkInterface instance
430 // for each array element and populate the object.
431 curr = ifs;
432 arr_index = 0;
433 while (curr != NULL) {
434 jobject netifObj;
435
436 netifObj = createNetworkInterface(env, curr);
437 if (netifObj == NULL) {
438 freeif(ifs);
439 return NULL;
440 }
441
442 // put the NetworkInterface into the array
443 (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);
444
445 curr = curr->next;
446 }
447
448 freeif(ifs);
449 return netIFArr;
450 }
451
452 /*
453 * Class: java_net_NetworkInterface
454 * Method: isUp0
455 * Signature: (Ljava/lang/String;I)Z
456 */
457 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0
458 (JNIEnv *env, jclass cls, jstring name, jint index)
459 {
460 int ret = getFlags0(env, name);
461 return ((ret & IFF_UP) && (ret & IFF_RUNNING)) ? JNI_TRUE : JNI_FALSE;
462 }
463
464 /*
465 * Class: java_net_NetworkInterface
466 * Method: isP2P0
467 * Signature: (Ljava/lang/String;I)Z
468 */
494 (JNIEnv *env, jclass cls, jstring name, jint index)
495 {
496 int ret = getFlags0(env, name);
497 return (ret & IFF_MULTICAST) ? JNI_TRUE : JNI_FALSE;
498 }
499
500 /*
501 * Class: java_net_NetworkInterface
502 * Method: getMacAddr0
503 * Signature: ([bLjava/lang/String;I)[b
504 */
505 JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0
506 (JNIEnv *env, jclass cls, jbyteArray addrArray, jstring name, jint index)
507 {
508 jint addr;
509 jbyte caddr[4];
510 struct in_addr iaddr;
511 jbyteArray ret = NULL;
512 unsigned char mac[16];
513 int len;
514 int sock;
515 jboolean isCopy;
516 const char* name_utf;
517
518 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
519 if (name_utf == NULL) {
520 if (!(*env)->ExceptionCheck(env))
521 JNU_ThrowOutOfMemoryError(env, NULL);
522 return NULL;
523 }
524 if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
525 (*env)->ReleaseStringUTFChars(env, name, name_utf);
526 return NULL;
527 }
528
529 if (!IS_NULL(addrArray)) {
530 (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
531 addr = ((caddr[0]<<24) & 0xff000000);
532 addr |= ((caddr[1] <<16) & 0xff0000);
533 addr |= ((caddr[2] <<8) & 0xff00);
534 addr |= (caddr[3] & 0xff);
535 iaddr.s_addr = htonl(addr);
536 len = getMacAddress(env, sock, name_utf, &iaddr, mac);
537 } else {
538 len = getMacAddress(env, sock, name_utf, NULL, mac);
539 }
540 if (len > 0) {
541 ret = (*env)->NewByteArray(env, len);
542 if (IS_NULL(ret)) {
543 /* we may have memory to free at the end of this */
544 goto fexit;
545 }
546 (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *)(mac));
547 }
548 fexit:
549 // release the UTF string and interface list
550 (*env)->ReleaseStringUTFChars(env, name, name_utf);
551
552 close(sock);
553 return ret;
554 }
555
556 /*
557 * Class: java_net_NetworkInterface
558 * Method: getMTU0
559 * Signature: ([bLjava/lang/String;I)I
560 */
561 JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0
562 (JNIEnv *env, jclass cls, jstring name, jint index)
563 {
564 jboolean isCopy;
565 int ret = -1;
566 int sock;
567 const char* name_utf = NULL;
568
569 if (name != NULL) {
570 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
571 } else {
572 JNU_ThrowNullPointerException(env, "network interface name is NULL");
573 return ret;
574 }
575 if (name_utf == NULL) {
576 if (!(*env)->ExceptionCheck(env))
577 JNU_ThrowOutOfMemoryError(env, NULL);
578 return ret;
579 }
580
581 if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
582 (*env)->ReleaseStringUTFChars(env, name, name_utf);
583 return JNI_FALSE;
584 }
585
586 ret = getMTU(env, sock, name_utf);
587
588 (*env)->ReleaseStringUTFChars(env, name, name_utf);
589
590 close(sock);
591 return ret;
592 }
593
594 /*** Private methods definitions ****/
595
596 static int getFlags0(JNIEnv *env, jstring name) {
597 jboolean isCopy;
598 int ret, sock;
599 const char* name_utf;
600 int flags = 0;
601
602 if (name != NULL) {
603 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
604 } else {
605 JNU_ThrowNullPointerException(env, "network interface name is NULL");
606 return -1;
607 }
608
609 if (name_utf == NULL) {
610 if (!(*env)->ExceptionCheck(env))
611 JNU_ThrowOutOfMemoryError(env, NULL);
612 return -1;
613 }
614 if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
615 (*env)->ReleaseStringUTFChars(env, name, name_utf);
616 return -1;
617 }
618
619 ret = getFlags(sock, name_utf, &flags);
620
631 }
632
633 /*
634 * Creates a NetworkInterface object, populates the name, the index, and
635 * populates the InetAddress array based on the IP addresses for this
636 * interface.
637 */
638 static jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
639 jobject netifObj;
640 jobject name;
641 jobjectArray addrArr;
642 jobjectArray bindArr;
643 jobjectArray childArr;
644 netaddr *addrs;
645 jint addr_index, addr_count, bind_index;
646 jint child_count, child_index;
647 netaddr *addrP;
648 netif *childP;
649 jobject tmp;
650
651 // Create a NetworkInterface object and populate it
652 netifObj = (*env)->NewObject(env, ni_class, ni_ctrID);
653 CHECK_NULL_RETURN(netifObj, NULL);
654 name = (*env)->NewStringUTF(env, ifs->name);
655 CHECK_NULL_RETURN(name, NULL);
656 (*env)->SetObjectField(env, netifObj, ni_nameID, name);
657 (*env)->SetObjectField(env, netifObj, ni_descID, name);
658 (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);
659 (*env)->SetBooleanField(env, netifObj, ni_virutalID,
660 ifs->virtual ? JNI_TRUE : JNI_FALSE);
661
662 //Count the number of address on this interface
663 addr_count = 0;
664 addrP = ifs->addr;
665 while (addrP != NULL) {
666 addr_count++;
667 addrP = addrP->next;
668 }
669
670 // Create the array of InetAddresses
671 addrArr = (*env)->NewObjectArray(env, addr_count, ia_class, NULL);
672 if (addrArr == NULL) {
673 return NULL;
674 }
675
676 bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL);
677 if (bindArr == NULL) {
678 return NULL;
679 }
680 addrP = ifs->addr;
681 addr_index = 0;
682 bind_index = 0;
683 while (addrP != NULL) {
684 jobject iaObj = NULL;
685 jobject ibObj = NULL;
686
687 if (addrP->family == AF_INET) {
688 iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
689 if (iaObj) {
690 setInetAddress_addr(env, iaObj, htonl(
695 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
696 if (ibObj) {
697 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
698 if (addrP->brdcast) {
699 jobject ia2Obj = NULL;
700 ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
701 if (ia2Obj) {
702 setInetAddress_addr(env, ia2Obj, htonl(
703 ((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
704 (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
705 } else {
706 return NULL;
707 }
708 }
709 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
710 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
711 } else {
712 return NULL;
713 }
714 }
715
716 #if defined(AF_INET6)
717 if (addrP->family == AF_INET6) {
718 int scope=0;
719 iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
720 if (iaObj) {
721 jboolean ret = setInet6Address_ipaddress(env, iaObj,
722 (char *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
723 if (ret == JNI_FALSE) {
724 return NULL;
725 }
726
727 scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
728
729 if (scope != 0) { /* zero is default value, no need to set */
730 setInet6Address_scopeid(env, iaObj, scope);
731 setInet6Address_scopeifname(env, iaObj, netifObj);
732 }
733 } else {
734 return NULL;
735 }
736 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
737 if (ibObj) {
738 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
739 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
740 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
741 } else {
742 return NULL;
743 }
744 }
745 #endif
746
747 (*env)->SetObjectArrayElement(env, addrArr, addr_index++, iaObj);
748 addrP = addrP->next;
749 }
750
751 // See if there is any virtual interface attached to this one.
752 child_count = 0;
753 childP = ifs->childs;
754 while (childP) {
755 child_count++;
756 childP = childP->next;
757 }
758
759 childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL);
760 if (childArr == NULL) {
761 return NULL;
762 }
763
764 // Create the NetworkInterface instances for the sub-interfaces as well.
765 child_index = 0;
766 childP = ifs->childs;
767 while(childP) {
768 tmp = createNetworkInterface(env, childP);
769 if (tmp == NULL) {
770 return NULL;
771 }
772 (*env)->SetObjectField(env, tmp, ni_parentID, netifObj);
773 (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp);
774 childP = childP->next;
775 }
776 (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
777 (*env)->SetObjectField(env, netifObj, ni_bindsID, bindArr);
778 (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
779
780 // return the NetworkInterface
781 return netifObj;
782 }
783
784 /*
785 * Enumerates all interfaces
786 */
787 static netif *enumInterfaces(JNIEnv *env) {
788 netif *ifs;
789 int sock;
790
791 // Enumerate IPv4 addresses
792 sock = openSocket(env, AF_INET);
793 if (sock < 0 && (*env)->ExceptionOccurred(env)) {
794 return NULL;
795 }
796
797 ifs = enumIPv4Interfaces(env, sock, NULL);
798 close(sock);
799
800 if (ifs == NULL && (*env)->ExceptionOccurred(env)) {
801 return NULL;
802 }
803
804 // return partial list if an exception occurs in the middle of process ???
805
806 // If IPv6 is available then enumerate IPv6 addresses.
807 #if defined(AF_INET6)
808
809 // User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
810 // so we have to call ipv6_available()
811 if (ipv6_available()) {
812
813 sock = openSocket(env, AF_INET6);
814 if (sock < 0 && (*env)->ExceptionOccurred(env)) {
815 freeif(ifs);
816 return NULL;
817 }
818
819 ifs = enumIPv6Interfaces(env, sock, ifs);
820 close(sock);
821
822 if ((*env)->ExceptionOccurred(env)) {
823 freeif(ifs);
824 return NULL;
825 }
826
827 }
828 #endif
829
830 return ifs;
831 }
832
833 /*
834 * Frees an interface list (including any attached addresses).
835 */
836 static void freeif(netif *ifs) {
837 netif *currif = ifs;
838 netif *child = NULL;
839
840 while (currif != NULL) {
841 netaddr *addrP = currif->addr;
842 while (addrP != NULL) {
843 netaddr *next = addrP->next;
844 free(addrP);
845 addrP = next;
846 }
847
848 // Don't forget to free the sub-interfaces.
849 if (currif->childs != NULL) {
850 freeif(currif->childs);
851 }
852
853 ifs = currif->next;
854 free(currif);
855 currif = ifs;
856 }
857 }
858
859 static netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
860 struct sockaddr *ifr_addrP,
861 struct sockaddr *ifr_broadaddrP,
862 int family, short prefix)
863 {
864 netif *currif = ifs, *parent;
865 netaddr *addrP;
866
867 #ifdef LIFNAMSIZ
868 int ifnam_size = LIFNAMSIZ;
869 char name[LIFNAMSIZ], vname[LIFNAMSIZ];
870 #else
871 int ifnam_size = IFNAMSIZ;
872 char name[IFNAMSIZ], vname[IFNAMSIZ];
873 #endif
874
875 char *name_colonP;
876 int isVirtual = 0;
877 int addr_size;
878 int flags = 0;
879
880 // If the interface name is a logical interface then we remove the unit
881 // number so that we have the physical interface (eg: hme0:1 -> hme0).
882 // NetworkInterface currently doesn't have any concept of physical vs.
883 // logical interfaces.
884 strncpy(name, if_name, ifnam_size);
885 name[ifnam_size - 1] = '\0';
886 *vname = 0;
887
888 // Create and populate the netaddr node. If allocation fails
889 // return an un-updated list.
890
891 // Allocate for addr and brdcast at once
892
893 #if defined(AF_INET6)
894 addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in)
895 : sizeof(struct sockaddr_in6);
896 #else
897 addr_size = sizeof(struct sockaddr_in);
898 #endif
899
900 CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr) + 2 * addr_size);
901 addrP->addr = (struct sockaddr *)((char *)addrP + sizeof(netaddr));
902 memcpy(addrP->addr, ifr_addrP, addr_size);
903
904 addrP->family = family;
905 addrP->mask = prefix;
906 addrP->next = 0;
907
908 // for IPv4 add broadcast address
909 if (family == AF_INET && ifr_broadaddrP != NULL) {
910 addrP->brdcast = (struct sockaddr *)
911 ((char *)addrP + sizeof(netaddr) + addr_size);
912 memcpy(addrP->brdcast, ifr_broadaddrP, addr_size);
913 } else {
914 addrP->brdcast = NULL;
915 }
916
917 // Deal with virtual interface with colon notation e.g. eth0:1
918 name_colonP = strchr(name, ':');
919 if (name_colonP != NULL) {
920 // This is a virtual interface. If we are able to access the parent
921 // we need to create a new entry if it doesn't exist yet *and* update
922 // the 'parent' interface with the new records.
923 *name_colonP = 0;
924 if (getFlags(sock, name, &flags) < 0 || flags < 0) {
925 // failed to access parent interface do not create parent.
926 // We are a virtual interface with no parent.
927 isVirtual = 1;
928 *name_colonP = ':';
929 } else {
930 // Got access to parent, so create it if necessary.
931 // Save original name to vname and truncate name by ':'
932 memcpy(vname, name, sizeof(vname) );
933 vname[name_colonP - name] = ':';
934 }
935 }
936
937 // Check if this is a "new" interface. Use the interface name for
938 // matching because index isn't supported on Solaris 2.6 & 7.
939 while (currif != NULL) {
940 if (strcmp(name, currif->name) == 0) {
941 break;
942 }
943 currif = currif->next;
944 }
945
946 // If "new" then create an netif structure and insert it into the list.
947 if (currif == NULL) {
948 CHECKED_MALLOC3(currif, netif *, sizeof(netif) + ifnam_size);
949 currif->name = (char *)currif + sizeof(netif);
950 strncpy(currif->name, name, ifnam_size);
951 currif->name[ifnam_size - 1] = '\0';
952 currif->index = getIndex(sock, name);
953 currif->addr = NULL;
954 currif->childs = NULL;
955 currif->virtual = isVirtual;
956 currif->next = ifs;
957 ifs = currif;
958 }
959
960 // Finally insert the address on the interface
961 addrP->next = currif->addr;
962 currif->addr = addrP;
963
964 parent = currif;
965
966 // Deal with the virtual interface now.
967 if (vname[0]) {
968 netaddr *tmpaddr;
969
970 currif = parent->childs;
971
972 while (currif != NULL) {
973 if (strcmp(vname, currif->name) == 0) {
974 break;
975 }
976 currif = currif->next;
977 }
978
979 if (currif == NULL) {
980 CHECKED_MALLOC3(currif, netif *, sizeof(netif) + ifnam_size);
981 currif->name = (char *)currif + sizeof(netif);
982 strncpy(currif->name, vname, ifnam_size);
983 currif->name[ifnam_size - 1] = '\0';
984 currif->index = getIndex(sock, vname);
985 currif->addr = NULL;
986 // Need to duplicate the addr entry?
987 currif->virtual = 1;
988 currif->childs = NULL;
989 currif->next = parent->childs;
990 parent->childs = currif;
991 }
992
993 CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr) + 2 * addr_size);
994 memcpy(tmpaddr, addrP, sizeof(netaddr));
995 if (addrP->addr != NULL) {
996 tmpaddr->addr = (struct sockaddr *)
997 ((char*)tmpaddr + sizeof(netaddr));
998 memcpy(tmpaddr->addr, addrP->addr, addr_size);
999 }
1000
1001 if (addrP->brdcast != NULL) {
1002 tmpaddr->brdcast = (struct sockaddr *)
1003 ((char *)tmpaddr + sizeof(netaddr) + addr_size);
1004 memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
1005 }
1006
1247 * Try to get the interface index.
1248 */
1249 static int getIndex(int sock, const char *name) {
1250 struct ifreq if2;
1251 memset((char *)&if2, 0, sizeof(if2));
1252 strncpy(if2.ifr_name, name, sizeof(if2.ifr_name) - 1);
1253
1254 if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
1255 return -1;
1256 }
1257
1258 return if2.ifr_ifindex;
1259 }
1260
1261 /*
1262 * Gets the Hardware address (usually MAC address) for the named interface.
1263 * On return puts the data in buf, and returns the length, in byte, of the
1264 * MAC address. Returns -1 if there is no hardware address on that interface.
1265 */
1266 static int getMacAddress
1267 (JNIEnv *env, int sock, const char *ifname, const struct in_addr *addr,
1268 unsigned char *buf)
1269 {
1270 static struct ifreq ifr;
1271 int i;
1272 memset((char *)&ifr, 0, sizeof(ifr));
1273 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
1274 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
1275 JNU_ThrowByNameWithMessageAndLastError
1276 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFHWADDR) failed");
1277 return -1;
1278 }
1279
1280 memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1281
1282 // all bytes to 0 means no hardware address
1283 for (i = 0; i < IFHWADDRLEN; i++) {
1284 if (buf[i] != 0)
1285 return IFHWADDRLEN;
1286 }
1287
1288 return -1;
1289 }
1290
1291 static int getMTU(JNIEnv *env, int sock, const char *ifname) {
1292 struct ifreq if2;
1293 memset((char *)&if2, 0, sizeof(if2));
1294 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1295
1296 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1297 JNU_ThrowByNameWithMessageAndLastError
1298 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed");
1299 return -1;
1510 free(buf);
1511 return ifs;
1512 }
1513
1514 #endif /* AF_INET6 */
1515
1516 /*
1517 * Try to get the interface index.
1518 */
1519 static int getIndex(int sock, const char *name) {
1520 int index = if_nametoindex(name);
1521 return (index == 0) ? -1 : index;
1522 }
1523
1524 /*
1525 * Gets the Hardware address (usually MAC address) for the named interface.
1526 * On return puts the data in buf, and returns the length, in byte, of the
1527 * MAC address. Returns -1 if there is no hardware address on that interface.
1528 */
1529 static int getMacAddress
1530 (JNIEnv *env, int sock, const char *ifname, const struct in_addr *addr,
1531 unsigned char *buf)
1532 {
1533 int size;
1534 struct kinfo_ndd *nddp;
1535 void *end;
1536
1537 size = getkerninfo(KINFO_NDD, 0, 0, 0);
1538 if (size == 0) {
1539 return -1;
1540 }
1541
1542 if (size < 0) {
1543 perror("getkerninfo 1");
1544 return -1;
1545 }
1546
1547 nddp = (struct kinfo_ndd *)malloc(size);
1548
1549 if (!nddp) {
1550 JNU_ThrowOutOfMemoryError(env,
1569 }
1570
1571 return -1;
1572 }
1573
1574 static int getMTU(JNIEnv *env, int sock, const char *ifname) {
1575 struct ifreq if2;
1576 memset((char *)&if2, 0, sizeof(if2));
1577 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1578
1579 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1580 JNU_ThrowByNameWithMessageAndLastError
1581 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed");
1582 return -1;
1583 }
1584
1585 return if2.ifr_mtu;
1586 }
1587
1588 static int getFlags(int sock, const char *ifname, int *flags) {
1589 struct ifreq if2;
1590 memset((char *)&if2, 0, sizeof(if2));
1591 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1592
1593 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
1594 return -1;
1595 }
1596
1597 if (sizeof(if2.ifr_flags) == sizeof(short)) {
1598 *flags = (if2.ifr_flags & 0xffff);
1599 } else {
1600 *flags = if2.ifr_flags;
1601 }
1602 return 0;
1603 }
1604
1605 #endif /* _AIX */
1606
1607 /** Solaris **/
1608 #if defined(__solaris__)
1609
1610 #if defined(AF_INET6)
1611 /*
1612 * Opens a socket for further ioctl calls. Tries AF_INET socket first and
1613 * if it fails return AF_INET6 socket.
1614 */
1615 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1616 int sock, alreadyV6 = 0;
1617 struct lifreq if2;
1618
1619 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1620 if (errno == EPROTONOSUPPORT) {
1621 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1622 JNU_ThrowByNameWithMessageAndLastError
1817 /*
1818 * Solaris specific DLPI code to get hardware address from a device.
1819 * Unfortunately, at least up to Solaris X, you have to have special
1820 * privileges (i.e. be root).
1821 */
1822 static int getMacFromDevice
1823 (JNIEnv *env, const char *ifname, unsigned char *retbuf)
1824 {
1825 char style1dev[MAXPATHLEN];
1826 int fd;
1827 dl_phys_addr_req_t dlpareq;
1828 dl_phys_addr_ack_t *dlpaack;
1829 struct strbuf msg;
1830 char buf[128];
1831 int flags = 0;
1832
1833 // Device is in /dev. e.g.: /dev/bge0
1834 strcpy(style1dev, DEV_PREFIX);
1835 strcat(style1dev, ifname);
1836 if ((fd = open(style1dev, O_RDWR)) < 0) {
1837 // Can't open it. We probably are missing the privilege.
1838 // We'll have to try something else
1839 return 0;
1840 }
1841
1842 dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
1843 dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
1844
1845 msg.buf = (char *)&dlpareq;
1846 msg.len = DL_PHYS_ADDR_REQ_SIZE;
1847
1848 if (putmsg(fd, &msg, NULL, 0) < 0) {
1849 JNU_ThrowByNameWithMessageAndLastError
1850 (env, JNU_JAVANETPKG "SocketException", "putmsg() failed");
1851 return -1;
1852 }
1853
1854 dlpaack = (dl_phys_addr_ack_t *)buf;
1855
1856 msg.buf = (char *)buf;
1857 msg.len = 0;
1858 msg.maxlen = sizeof (buf);
1859 if (getmsg(fd, &msg, NULL, &flags) < 0) {
1861 (env, JNU_JAVANETPKG "SocketException", "getmsg() failed");
1862 return -1;
1863 }
1864
1865 if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
1866 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1867 "Couldn't obtain phys addr\n");
1868 return -1;
1869 }
1870
1871 memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
1872 return dlpaack->dl_addr_length;
1873 }
1874
1875 /*
1876 * Gets the Hardware address (usually MAC address) for the named interface.
1877 * On return puts the data in buf, and returns the length, in byte, of the
1878 * MAC address. Returns -1 if there is no hardware address on that interface.
1879 */
1880 static int getMacAddress
1881 (JNIEnv *env, int sock, const char *ifname, const struct in_addr *addr,
1882 unsigned char *buf)
1883 {
1884 struct lifreq if2;
1885 int len, i;
1886
1887 // First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
1888 // try the old way.
1889 memset((char *)&if2, 0, sizeof(if2));
1890 strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1891
1892 if (ioctl(sock, SIOCGLIFHWADDR, &if2) != -1) {
1893 struct sockaddr_dl *sp;
1894 sp = (struct sockaddr_dl *)&if2.lifr_addr;
1895 memcpy(buf, &sp->sdl_data[0], sp->sdl_alen);
1896 return sp->sdl_alen;
1897 }
1898
1899 // On Solaris we have to use DLPI, but it will only work if we have
1900 // privileged access (i.e. root). If that fails, we try a lookup
1901 // in the ARP table, which requires an IPv4 address.
1902 if ((len = getMacFromDevice(env, ifname, buf)) == 0) {
1903 // DLPI failed - trying to do arp lookup
1904
1905 struct arpreq arpreq;
1906 struct sockaddr_in *sin;
1907 struct sockaddr_in ipAddr;
1908
1909 if (addr == NULL) {
1910 // No IPv4 address for that interface, so can't do an ARP lookup.
1911 return -1;
1912 }
1913
1914 len = 6; //???
1915
1916 sin = (struct sockaddr_in *)&arpreq.arp_pa;
1917 memset((char *)&arpreq, 0, sizeof(struct arpreq));
1918 ipAddr.sin_port = 0;
1919 ipAddr.sin_family = AF_INET;
1920 memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
1921 memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
1922 arpreq.arp_flags= ATF_PUBL;
1923
1924 if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
1925 return -1;
1926 }
1927
1928 memcpy(buf, &arpreq.arp_ha.sa_data[0], len);
1929 }
1930
1931 // all bytes to 0 means no hardware address
1932 for (i = 0; i < len; i++) {
1933 if (buf[i] != 0)
1934 return len;
1935 }
1936
1937 return -1;
1938 }
1939
1940 static int getMTU(JNIEnv *env, int sock, const char *ifname) {
1941 struct lifreq if2;
1942 memset((char *)&if2, 0, sizeof(if2));
1943 strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1944
1945 if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
1946 JNU_ThrowByNameWithMessageAndLastError
1947 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFMTU) failed");
1948 return -1;
1949 }
2096 return (index == 0) ? -1 : index;
2097 #else
2098 struct ifreq if2;
2099 memset((char *)&if2, 0, sizeof(if2));
2100 strncpy(if2.ifr_name, name, sizeof(if2.ifr_name) - 1);
2101
2102 if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
2103 return -1;
2104 }
2105
2106 return if2.ifr_index;
2107 #endif
2108 }
2109
2110 /*
2111 * Gets the Hardware address (usually MAC address) for the named interface.
2112 * On return puts the data in buf, and returns the length, in byte, of the
2113 * MAC address. Returns -1 if there is no hardware address on that interface.
2114 */
2115 static int getMacAddress
2116 (JNIEnv *env, int sock, const char *ifname, const struct in_addr *addr,
2117 unsigned char *buf)
2118 {
2119 struct ifaddrs *ifa0, *ifa;
2120 struct sockaddr *saddr;
2121 int i;
2122
2123 // Grab the interface list
2124 if (!getifaddrs(&ifa0)) {
2125 // Cycle through the interfaces
2126 for (i = 0, ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next, i++) {
2127 saddr = ifa->ifa_addr;
2128 // Link layer contains the MAC address
2129 if (saddr->sa_family == AF_LINK && !strcmp(ifname, ifa->ifa_name)) {
2130 struct sockaddr_dl *sadl = (struct sockaddr_dl *) saddr;
2131 // Check the address is the correct length
2132 if (sadl->sdl_alen == ETHER_ADDR_LEN) {
2133 memcpy(buf, (sadl->sdl_data + sadl->sdl_nlen), ETHER_ADDR_LEN);
2134 freeifaddrs(ifa0);
2135 return ETHER_ADDR_LEN;
2136 }
2137 }
2138 }
2139 freeifaddrs(ifa0);
2140 }
2141
2142 return -1;
2143 }
2144
2145 static int getMTU(JNIEnv *env, int sock, const char *ifname) {
2146 struct ifreq if2;
2147 memset((char *)&if2, 0, sizeof(if2));
2148 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
2149
2150 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
2151 JNU_ThrowByNameWithMessageAndLastError
|
63 #include <net/if_var.h>
64 #include <net/if_dl.h>
65 #include <netinet/in_var.h>
66 #include <ifaddrs.h>
67 #endif
68 #endif
69
70 #include "jvm.h"
71 #include "jni_util.h"
72 #include "net_util.h"
73
74 #if defined(__linux__)
75 #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
76 #elif defined(__solaris__)
77 #ifndef SIOCGLIFHWADDR
78 #define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq)
79 #endif
80 #define DEV_PREFIX "/dev/"
81 #endif
82
83 #ifdef LIFNAMSIZ
84 #define IFNAMESIZE LIFNAMSIZ
85 #else
86 #define IFNAMESIZE IFNAMSIZ
87 #endif
88
89 #define CHECKED_MALLOC3(_pointer, _type, _size) \
90 do { \
91 _pointer = (_type)malloc(_size); \
92 if (_pointer == NULL) { \
93 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); \
94 return ifs; /* return untouched list */ \
95 } \
96 } while(0)
97
98 typedef struct _netaddr {
99 struct sockaddr *addr;
100 struct sockaddr *brdcast;
101 short mask;
102 int family; /* to make searches simple */
103 struct _netaddr *next;
104 } netaddr;
105
106 typedef struct _netif {
107 char *name;
108 int index;
147 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs);
148
149 #if defined(AF_INET6)
150 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
151 #endif
152
153 static netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
154 struct sockaddr *ifr_addrP,
155 struct sockaddr *ifr_broadaddrP,
156 int family, short prefix);
157 static void freeif(netif *ifs);
158
159 static int openSocket(JNIEnv *env, int proto);
160 static int openSocketWithFallback(JNIEnv *env, const char *ifname);
161
162 static short translateIPv4AddressToPrefix(struct sockaddr_in *addr);
163 static short translateIPv6AddressToPrefix(struct sockaddr_in6 *addr);
164
165 static int getIndex(int sock, const char *ifname);
166 static int getFlags(int sock, const char *ifname, int *flags);
167 static int getMacAddress(JNIEnv *env, const char *ifname,
168 const struct in_addr *addr, unsigned char *buf);
169 static int getMTU(JNIEnv *env, int sock, const char *ifname);
170
171 #if defined(__solaris__)
172 static int getMacFromDevice(JNIEnv *env, const char *ifname,
173 unsigned char *retbuf);
174 #endif
175
176 /******************* Java entry points *****************************/
177
178 /*
179 * Class: java_net_NetworkInterface
180 * Method: init
181 * Signature: ()V
182 */
183 JNIEXPORT void JNICALL Java_java_net_NetworkInterface_init
184 (JNIEnv *env, jclass cls)
185 {
186 ni_class = (*env)->FindClass(env, "java/net/NetworkInterface");
187 CHECK_NULL(ni_class);
226 CHECK_NULL(ni_ib4maskID);
227 ni_defaultIndexID = (*env)->GetStaticFieldID(env, ni_class, "defaultIndex",
228 "I");
229 CHECK_NULL(ni_defaultIndexID);
230 initInetAddressIDs(env);
231 }
232
233 /*
234 * Class: java_net_NetworkInterface
235 * Method: getByName0
236 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
237 */
238 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0
239 (JNIEnv *env, jclass cls, jstring name)
240 {
241 netif *ifs, *curr;
242 jboolean isCopy;
243 const char* name_utf;
244 jobject obj = NULL;
245
246 if (name != NULL) {
247 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
248 } else {
249 JNU_ThrowNullPointerException(env, "network interface name is NULL");
250 return NULL;
251 }
252
253 if (name_utf == NULL) {
254 if (!(*env)->ExceptionCheck(env))
255 JNU_ThrowOutOfMemoryError(env, NULL);
256 return NULL;
257 }
258
259 ifs = enumInterfaces(env);
260 if (ifs == NULL) {
261 return NULL;
262 }
263
264 // search the list of interfaces based on name
265 curr = ifs;
266 while (curr != NULL) {
267 if (strcmp(name_utf, curr->name) == 0) {
268 break;
269 }
270 curr = curr->next;
271 }
272
273 // if found create a NetworkInterface
274 if (curr != NULL) {
275 obj = createNetworkInterface(env, curr);
276 }
277
278 // release the UTF string and interface list
279 (*env)->ReleaseStringUTFChars(env, name, name_utf);
280 freeif(ifs);
281
282 return obj;
283 }
284
285 /*
286 * Class: java_net_NetworkInterface
287 * Method: getByIndex0
288 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
289 */
290 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
291 (JNIEnv *env, jclass cls, jint index)
292 {
293 netif *ifs, *curr;
294 jobject obj = NULL;
295
296 if (index <= 0) {
297 return NULL;
298 }
299
300 ifs = enumInterfaces(env);
301 if (ifs == NULL) {
302 return NULL;
303 }
304
305 // search the list of interfaces based on index
306 curr = ifs;
307 while (curr != NULL) {
308 if (index == curr->index) {
309 break;
310 }
311 curr = curr->next;
312 }
313
314 // if found create a NetworkInterface
315 if (curr != NULL) {
316 obj = createNetworkInterface(env, curr);
317 }
318
319 // release the interface list
320 freeif(ifs);
321
322 return obj;
323 }
324
325 /*
326 * Class: java_net_NetworkInterface
327 * Method: getByInetAddress0
328 * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
329 */
330 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
331 (JNIEnv *env, jclass cls, jobject iaObj)
332 {
333 netif *ifs, *curr;
334 #if defined(AF_INET6)
335 int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6;
336 #else
337 int family = AF_INET;
338 #endif
339 jobject obj = NULL;
340 jboolean match = JNI_FALSE;
341
342 ifs = enumInterfaces(env);
343 if (ifs == NULL) {
344 return NULL;
345 }
346
347 curr = ifs;
348 while (curr != NULL) {
349 netaddr *addrP = curr->addr;
350
351 // iterate through each address on the interface
352 while (addrP != NULL) {
353
354 if (family == addrP->family) {
355 if (family == AF_INET) {
356 int address1 = htonl(
357 ((struct sockaddr_in *)addrP->addr)->sin_addr.s_addr);
358 int address2 = getInetAddress_addr(env, iaObj);
359
360 if (address1 == address2) {
361 match = JNI_TRUE;
362 break;
363 }
364 }
365 #if defined(AF_INET6)
366 if (family == AF_INET6) {
367 jbyte *bytes = (jbyte *)&(
368 ((struct sockaddr_in6*)addrP->addr)->sin6_addr);
369 jbyte caddr[16];
370 int i;
371 getInet6Address_ipaddress(env, iaObj, (char *)caddr);
372 i = 0;
373 while (i < 16) {
374 if (caddr[i] != bytes[i]) {
375 break;
376 }
377 i++;
378 }
379 if (i >= 16) {
380 match = JNI_TRUE;
381 break;
382 }
383 }
384 #endif
385 }
386
387 if (match) {
388 break;
389 }
390 addrP = addrP->next;
391 }
392
393 if (match) {
394 break;
395 }
396 curr = curr->next;
397 }
398
399 // if found create a NetworkInterface
400 if (match) {
401 obj = createNetworkInterface(env, curr);
402 }
403
404 // release the interface list
405 freeif(ifs);
406
407 return obj;
408 }
409
410 /*
411 * Class: java_net_NetworkInterface
412 * Method: getAll
413 * Signature: ()[Ljava/net/NetworkInterface;
414 */
415 JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll
416 (JNIEnv *env, jclass cls)
417 {
418 netif *ifs, *curr;
419 jobjectArray netIFArr;
420 jint arr_index, ifCount;
421
422 ifs = enumInterfaces(env);
423 if (ifs == NULL) {
424 return NULL;
425 }
426
427 // count the interfaces
428 ifCount = 0;
429 curr = ifs;
430 while (curr != NULL) {
431 ifCount++;
432 curr = curr->next;
433 }
434
435 // allocate a NetworkInterface array
436 netIFArr = (*env)->NewObjectArray(env, ifCount, cls, NULL);
437 if (netIFArr == NULL) {
438 freeif(ifs);
439 return NULL;
440 }
441
442 // iterate through the interfaces, create a NetworkInterface instance
443 // for each array element and populate the object
444 curr = ifs;
445 arr_index = 0;
446 while (curr != NULL) {
447 jobject netifObj;
448
449 netifObj = createNetworkInterface(env, curr);
450 if (netifObj == NULL) {
451 freeif(ifs);
452 return NULL;
453 }
454
455 // put the NetworkInterface into the array
456 (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);
457
458 curr = curr->next;
459 }
460
461 // release the interface list
462 freeif(ifs);
463
464 return netIFArr;
465 }
466
467 /*
468 * Class: java_net_NetworkInterface
469 * Method: isUp0
470 * Signature: (Ljava/lang/String;I)Z
471 */
472 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0
473 (JNIEnv *env, jclass cls, jstring name, jint index)
474 {
475 int ret = getFlags0(env, name);
476 return ((ret & IFF_UP) && (ret & IFF_RUNNING)) ? JNI_TRUE : JNI_FALSE;
477 }
478
479 /*
480 * Class: java_net_NetworkInterface
481 * Method: isP2P0
482 * Signature: (Ljava/lang/String;I)Z
483 */
509 (JNIEnv *env, jclass cls, jstring name, jint index)
510 {
511 int ret = getFlags0(env, name);
512 return (ret & IFF_MULTICAST) ? JNI_TRUE : JNI_FALSE;
513 }
514
515 /*
516 * Class: java_net_NetworkInterface
517 * Method: getMacAddr0
518 * Signature: ([bLjava/lang/String;I)[b
519 */
520 JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0
521 (JNIEnv *env, jclass cls, jbyteArray addrArray, jstring name, jint index)
522 {
523 jint addr;
524 jbyte caddr[4];
525 struct in_addr iaddr;
526 jbyteArray ret = NULL;
527 unsigned char mac[16];
528 int len;
529 jboolean isCopy;
530 const char *name_utf;
531
532 if (name != NULL) {
533 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
534 } else {
535 JNU_ThrowNullPointerException(env, "network interface name is NULL");
536 return NULL;
537 }
538
539 if (name_utf == NULL) {
540 if (!(*env)->ExceptionCheck(env))
541 JNU_ThrowOutOfMemoryError(env, NULL);
542 return NULL;
543 }
544
545 if (!IS_NULL(addrArray)) {
546 (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
547 addr = ((caddr[0]<<24) & 0xff000000);
548 addr |= ((caddr[1] <<16) & 0xff0000);
549 addr |= ((caddr[2] <<8) & 0xff00);
550 addr |= (caddr[3] & 0xff);
551 iaddr.s_addr = htonl(addr);
552 len = getMacAddress(env, name_utf, &iaddr, mac);
553 } else {
554 len = getMacAddress(env, name_utf, NULL, mac);
555 }
556
557 if (len > 0) {
558 ret = (*env)->NewByteArray(env, len);
559 if (!IS_NULL(ret)) {
560 (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *)(mac));
561 }
562 }
563
564 // release the UTF string and interface list
565 (*env)->ReleaseStringUTFChars(env, name, name_utf);
566
567 return ret;
568 }
569
570 /*
571 * Class: java_net_NetworkInterface
572 * Method: getMTU0
573 * Signature: ([bLjava/lang/String;I)I
574 */
575 JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0
576 (JNIEnv *env, jclass cls, jstring name, jint index)
577 {
578 jboolean isCopy;
579 int sock, ret = -1;
580 const char* name_utf = NULL;
581
582 if (name != NULL) {
583 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
584 } else {
585 JNU_ThrowNullPointerException(env, "network interface name is NULL");
586 return ret;
587 }
588
589 if (name_utf == NULL) {
590 if (!(*env)->ExceptionCheck(env))
591 JNU_ThrowOutOfMemoryError(env, NULL);
592 return ret;
593 }
594
595 if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
596 (*env)->ReleaseStringUTFChars(env, name, name_utf);
597 return JNI_FALSE;
598 }
599
600 ret = getMTU(env, sock, name_utf);
601
602 (*env)->ReleaseStringUTFChars(env, name, name_utf);
603
604 close(sock);
605 return ret;
606 }
607
608 /*** Private methods definitions ****/
609
610 static int getFlags0(JNIEnv *env, jstring name) {
611 jboolean isCopy;
612 int ret, sock, flags = 0;
613 const char *name_utf;
614
615 if (name != NULL) {
616 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
617 } else {
618 JNU_ThrowNullPointerException(env, "network interface name is NULL");
619 return -1;
620 }
621
622 if (name_utf == NULL) {
623 if (!(*env)->ExceptionCheck(env))
624 JNU_ThrowOutOfMemoryError(env, NULL);
625 return -1;
626 }
627 if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
628 (*env)->ReleaseStringUTFChars(env, name, name_utf);
629 return -1;
630 }
631
632 ret = getFlags(sock, name_utf, &flags);
633
644 }
645
646 /*
647 * Creates a NetworkInterface object, populates the name, the index, and
648 * populates the InetAddress array based on the IP addresses for this
649 * interface.
650 */
651 static jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
652 jobject netifObj;
653 jobject name;
654 jobjectArray addrArr;
655 jobjectArray bindArr;
656 jobjectArray childArr;
657 netaddr *addrs;
658 jint addr_index, addr_count, bind_index;
659 jint child_count, child_index;
660 netaddr *addrP;
661 netif *childP;
662 jobject tmp;
663
664 // create a NetworkInterface object and populate it
665 netifObj = (*env)->NewObject(env, ni_class, ni_ctrID);
666 CHECK_NULL_RETURN(netifObj, NULL);
667 name = (*env)->NewStringUTF(env, ifs->name);
668 CHECK_NULL_RETURN(name, NULL);
669 (*env)->SetObjectField(env, netifObj, ni_nameID, name);
670 (*env)->SetObjectField(env, netifObj, ni_descID, name);
671 (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);
672 (*env)->SetBooleanField(env, netifObj, ni_virutalID,
673 ifs->virtual ? JNI_TRUE : JNI_FALSE);
674
675 // count the number of addresses on this interface
676 addr_count = 0;
677 addrP = ifs->addr;
678 while (addrP != NULL) {
679 addr_count++;
680 addrP = addrP->next;
681 }
682
683 // create the array of InetAddresses
684 addrArr = (*env)->NewObjectArray(env, addr_count, ia_class, NULL);
685 if (addrArr == NULL) {
686 return NULL;
687 }
688
689 bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL);
690 if (bindArr == NULL) {
691 return NULL;
692 }
693 addrP = ifs->addr;
694 addr_index = 0;
695 bind_index = 0;
696 while (addrP != NULL) {
697 jobject iaObj = NULL;
698 jobject ibObj = NULL;
699
700 if (addrP->family == AF_INET) {
701 iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
702 if (iaObj) {
703 setInetAddress_addr(env, iaObj, htonl(
708 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
709 if (ibObj) {
710 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
711 if (addrP->brdcast) {
712 jobject ia2Obj = NULL;
713 ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
714 if (ia2Obj) {
715 setInetAddress_addr(env, ia2Obj, htonl(
716 ((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
717 (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
718 } else {
719 return NULL;
720 }
721 }
722 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
723 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
724 } else {
725 return NULL;
726 }
727 }
728 #if defined(AF_INET6)
729 if (addrP->family == AF_INET6) {
730 int scope=0;
731 iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
732 if (iaObj) {
733 jboolean ret = setInet6Address_ipaddress(env, iaObj,
734 (char *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
735 if (ret == JNI_FALSE) {
736 return NULL;
737 }
738
739 scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
740
741 if (scope != 0) { /* zero is default value, no need to set */
742 setInet6Address_scopeid(env, iaObj, scope);
743 setInet6Address_scopeifname(env, iaObj, netifObj);
744 }
745 } else {
746 return NULL;
747 }
748 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
749 if (ibObj) {
750 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
751 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
752 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
753 } else {
754 return NULL;
755 }
756 }
757 #endif
758
759 (*env)->SetObjectArrayElement(env, addrArr, addr_index++, iaObj);
760 addrP = addrP->next;
761 }
762
763 // see if there is any virtual interface attached to this one.
764 child_count = 0;
765 childP = ifs->childs;
766 while (childP) {
767 child_count++;
768 childP = childP->next;
769 }
770
771 childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL);
772 if (childArr == NULL) {
773 return NULL;
774 }
775
776 // create the NetworkInterface instances for the sub-interfaces as well
777 child_index = 0;
778 childP = ifs->childs;
779 while(childP) {
780 tmp = createNetworkInterface(env, childP);
781 if (tmp == NULL) {
782 return NULL;
783 }
784 (*env)->SetObjectField(env, tmp, ni_parentID, netifObj);
785 (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp);
786 childP = childP->next;
787 }
788 (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
789 (*env)->SetObjectField(env, netifObj, ni_bindsID, bindArr);
790 (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
791
792 // return the NetworkInterface
793 return netifObj;
794 }
795
796 /*
797 * Enumerates all interfaces
798 */
799 static netif *enumInterfaces(JNIEnv *env) {
800 netif *ifs = NULL;
801 int sock;
802
803 sock = openSocket(env, AF_INET);
804 if (sock < 0 && (*env)->ExceptionOccurred(env)) {
805 return NULL;
806 }
807
808 // enumerate IPv4 addresses
809 ifs = enumIPv4Interfaces(env, sock, NULL);
810 close(sock);
811
812 // return partial list if an exception occurs in the middle of process ???
813 if (ifs == NULL && (*env)->ExceptionOccurred(env)) {
814 return NULL;
815 }
816
817 // If IPv6 is available then enumerate IPv6 addresses.
818 #if defined(AF_INET6)
819 // User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
820 // so we have to call ipv6_available()
821 if (ipv6_available()) {
822 sock = openSocket(env, AF_INET6);
823 if (sock < 0 && (*env)->ExceptionOccurred(env)) {
824 freeif(ifs);
825 return NULL;
826 }
827
828 ifs = enumIPv6Interfaces(env, sock, ifs);
829 close(sock);
830
831 if ((*env)->ExceptionOccurred(env)) {
832 freeif(ifs);
833 return NULL;
834 }
835 }
836 #endif
837
838 return ifs;
839 }
840
841 /*
842 * Frees an interface list (including any attached addresses).
843 */
844 static void freeif(netif *ifs) {
845 netif *currif = ifs;
846 netif *child = NULL;
847
848 while (currif != NULL) {
849 netaddr *addrP = currif->addr;
850 while (addrP != NULL) {
851 netaddr *next = addrP->next;
852 free(addrP);
853 addrP = next;
854 }
855
856 // don't forget to free the sub-interfaces
857 if (currif->childs != NULL) {
858 freeif(currif->childs);
859 }
860
861 ifs = currif->next;
862 free(currif);
863 currif = ifs;
864 }
865 }
866
867 static netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
868 struct sockaddr *ifr_addrP,
869 struct sockaddr *ifr_broadaddrP,
870 int family, short prefix)
871 {
872 netif *currif = ifs, *parent;
873 netaddr *addrP;
874 char name[IFNAMESIZE], vname[IFNAMESIZE];
875 char *name_colonP;
876 int isVirtual = 0;
877 int addr_size;
878
879 // If the interface name is a logical interface then we remove the unit
880 // number so that we have the physical interface (eg: hme0:1 -> hme0).
881 // NetworkInterface currently doesn't have any concept of physical vs.
882 // logical interfaces.
883 strncpy(name, if_name, IFNAMESIZE);
884 name[IFNAMESIZE - 1] = '\0';
885 *vname = 0;
886
887 // Create and populate the netaddr node. If allocation fails
888 // return an un-updated list.
889
890 // Allocate for addr and brdcast at once
891
892 #if defined(AF_INET6)
893 addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in)
894 : sizeof(struct sockaddr_in6);
895 #else
896 addr_size = sizeof(struct sockaddr_in);
897 #endif
898
899 CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr) + 2 * addr_size);
900 addrP->addr = (struct sockaddr *)((char *)addrP + sizeof(netaddr));
901 memcpy(addrP->addr, ifr_addrP, addr_size);
902
903 addrP->family = family;
904 addrP->mask = prefix;
905 addrP->next = 0;
906
907 // for IPv4 add broadcast address
908 if (family == AF_INET && ifr_broadaddrP != NULL) {
909 addrP->brdcast = (struct sockaddr *)
910 ((char *)addrP + sizeof(netaddr) + addr_size);
911 memcpy(addrP->brdcast, ifr_broadaddrP, addr_size);
912 } else {
913 addrP->brdcast = NULL;
914 }
915
916 // Deal with virtual interface with colon notation e.g. eth0:1
917 name_colonP = strchr(name, ':');
918 if (name_colonP != NULL) {
919 int flags = 0;
920 // This is a virtual interface. If we are able to access the parent
921 // we need to create a new entry if it doesn't exist yet *and* update
922 // the 'parent' interface with the new records.
923 *name_colonP = 0;
924 if (getFlags(sock, name, &flags) < 0 || flags < 0) {
925 // failed to access parent interface do not create parent.
926 // We are a virtual interface with no parent.
927 isVirtual = 1;
928 *name_colonP = ':';
929 } else {
930 // Got access to parent, so create it if necessary.
931 // Save original name to vname and truncate name by ':'
932 memcpy(vname, name, sizeof(vname));
933 vname[name_colonP - name] = ':';
934 }
935 }
936
937 // Check if this is a "new" interface. Use the interface name for
938 // matching because index isn't supported on Solaris 2.6 & 7.
939 while (currif != NULL) {
940 if (strcmp(name, currif->name) == 0) {
941 break;
942 }
943 currif = currif->next;
944 }
945
946 // If "new" then create a netif structure and insert it into the list.
947 if (currif == NULL) {
948 CHECKED_MALLOC3(currif, netif *, sizeof(netif) + IFNAMESIZE);
949 currif->name = (char *)currif + sizeof(netif);
950 strncpy(currif->name, name, IFNAMESIZE);
951 currif->name[IFNAMESIZE - 1] = '\0';
952 currif->index = getIndex(sock, name);
953 currif->addr = NULL;
954 currif->childs = NULL;
955 currif->virtual = isVirtual;
956 currif->next = ifs;
957 ifs = currif;
958 }
959
960 // Finally insert the address on the interface
961 addrP->next = currif->addr;
962 currif->addr = addrP;
963
964 parent = currif;
965
966 // Deal with the virtual interface now.
967 if (vname[0]) {
968 netaddr *tmpaddr;
969
970 currif = parent->childs;
971
972 while (currif != NULL) {
973 if (strcmp(vname, currif->name) == 0) {
974 break;
975 }
976 currif = currif->next;
977 }
978
979 if (currif == NULL) {
980 CHECKED_MALLOC3(currif, netif *, sizeof(netif) + IFNAMESIZE);
981 currif->name = (char *)currif + sizeof(netif);
982 strncpy(currif->name, vname, IFNAMESIZE);
983 currif->name[IFNAMESIZE - 1] = '\0';
984 currif->index = getIndex(sock, vname);
985 currif->addr = NULL; // Need to duplicate the addr entry?
986 currif->virtual = 1;
987 currif->childs = NULL;
988 currif->next = parent->childs;
989 parent->childs = currif;
990 }
991
992 CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr) + 2 * addr_size);
993 memcpy(tmpaddr, addrP, sizeof(netaddr));
994 if (addrP->addr != NULL) {
995 tmpaddr->addr = (struct sockaddr *)
996 ((char*)tmpaddr + sizeof(netaddr));
997 memcpy(tmpaddr->addr, addrP->addr, addr_size);
998 }
999
1000 if (addrP->brdcast != NULL) {
1001 tmpaddr->brdcast = (struct sockaddr *)
1002 ((char *)tmpaddr + sizeof(netaddr) + addr_size);
1003 memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
1004 }
1005
1246 * Try to get the interface index.
1247 */
1248 static int getIndex(int sock, const char *name) {
1249 struct ifreq if2;
1250 memset((char *)&if2, 0, sizeof(if2));
1251 strncpy(if2.ifr_name, name, sizeof(if2.ifr_name) - 1);
1252
1253 if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
1254 return -1;
1255 }
1256
1257 return if2.ifr_ifindex;
1258 }
1259
1260 /*
1261 * Gets the Hardware address (usually MAC address) for the named interface.
1262 * On return puts the data in buf, and returns the length, in byte, of the
1263 * MAC address. Returns -1 if there is no hardware address on that interface.
1264 */
1265 static int getMacAddress
1266 (JNIEnv *env, const char *ifname, const struct in_addr *addr,
1267 unsigned char *buf)
1268 {
1269 static struct ifreq ifr;
1270 int i, sock;
1271
1272 if ((sock = openSocketWithFallback(env, ifname)) < 0) {
1273 return -1;
1274 }
1275
1276 memset((char *)&ifr, 0, sizeof(ifr));
1277 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
1278 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
1279 JNU_ThrowByNameWithMessageAndLastError
1280 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFHWADDR) failed");
1281 close(sock);
1282 return -1;
1283 }
1284
1285 close(sock);
1286 memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1287
1288 // all bytes to 0 means no hardware address
1289 for (i = 0; i < IFHWADDRLEN; i++) {
1290 if (buf[i] != 0)
1291 return IFHWADDRLEN;
1292 }
1293
1294 return -1;
1295 }
1296
1297 static int getMTU(JNIEnv *env, int sock, const char *ifname) {
1298 struct ifreq if2;
1299 memset((char *)&if2, 0, sizeof(if2));
1300 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1301
1302 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1303 JNU_ThrowByNameWithMessageAndLastError
1304 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed");
1305 return -1;
1516 free(buf);
1517 return ifs;
1518 }
1519
1520 #endif /* AF_INET6 */
1521
1522 /*
1523 * Try to get the interface index.
1524 */
1525 static int getIndex(int sock, const char *name) {
1526 int index = if_nametoindex(name);
1527 return (index == 0) ? -1 : index;
1528 }
1529
1530 /*
1531 * Gets the Hardware address (usually MAC address) for the named interface.
1532 * On return puts the data in buf, and returns the length, in byte, of the
1533 * MAC address. Returns -1 if there is no hardware address on that interface.
1534 */
1535 static int getMacAddress
1536 (JNIEnv *env, const char *ifname, const struct in_addr *addr,
1537 unsigned char *buf)
1538 {
1539 int size;
1540 struct kinfo_ndd *nddp;
1541 void *end;
1542
1543 size = getkerninfo(KINFO_NDD, 0, 0, 0);
1544 if (size == 0) {
1545 return -1;
1546 }
1547
1548 if (size < 0) {
1549 perror("getkerninfo 1");
1550 return -1;
1551 }
1552
1553 nddp = (struct kinfo_ndd *)malloc(size);
1554
1555 if (!nddp) {
1556 JNU_ThrowOutOfMemoryError(env,
1575 }
1576
1577 return -1;
1578 }
1579
1580 static int getMTU(JNIEnv *env, int sock, const char *ifname) {
1581 struct ifreq if2;
1582 memset((char *)&if2, 0, sizeof(if2));
1583 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1584
1585 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1586 JNU_ThrowByNameWithMessageAndLastError
1587 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed");
1588 return -1;
1589 }
1590
1591 return if2.ifr_mtu;
1592 }
1593
1594 static int getFlags(int sock, const char *ifname, int *flags) {
1595 struct ifreq if2;
1596 memset((char *)&if2, 0, sizeof(if2));
1597 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1598
1599 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
1600 return -1;
1601 }
1602
1603 if (sizeof(if2.ifr_flags) == sizeof(short)) {
1604 *flags = (if2.ifr_flags & 0xffff);
1605 } else {
1606 *flags = if2.ifr_flags;
1607 }
1608 return 0;
1609 }
1610
1611 #endif /* _AIX */
1612
1613 /** Solaris **/
1614 #if defined(__solaris__)
1615
1616 #if defined(AF_INET6)
1617 /*
1618 * Opens a socket for further ioctl calls. Tries AF_INET socket first and
1619 * if it fails return AF_INET6 socket.
1620 */
1621 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1622 int sock, alreadyV6 = 0;
1623 struct lifreq if2;
1624
1625 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1626 if (errno == EPROTONOSUPPORT) {
1627 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1628 JNU_ThrowByNameWithMessageAndLastError
1823 /*
1824 * Solaris specific DLPI code to get hardware address from a device.
1825 * Unfortunately, at least up to Solaris X, you have to have special
1826 * privileges (i.e. be root).
1827 */
1828 static int getMacFromDevice
1829 (JNIEnv *env, const char *ifname, unsigned char *retbuf)
1830 {
1831 char style1dev[MAXPATHLEN];
1832 int fd;
1833 dl_phys_addr_req_t dlpareq;
1834 dl_phys_addr_ack_t *dlpaack;
1835 struct strbuf msg;
1836 char buf[128];
1837 int flags = 0;
1838
1839 // Device is in /dev. e.g.: /dev/bge0
1840 strcpy(style1dev, DEV_PREFIX);
1841 strcat(style1dev, ifname);
1842 if ((fd = open(style1dev, O_RDWR)) < 0) {
1843 // Can't open it. We probably are missing the privilege.
1844 // We'll have to try something else
1845 return 0;
1846 }
1847
1848 dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
1849 dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
1850
1851 msg.buf = (char *)&dlpareq;
1852 msg.len = DL_PHYS_ADDR_REQ_SIZE;
1853
1854 if (putmsg(fd, &msg, NULL, 0) < 0) {
1855 JNU_ThrowByNameWithMessageAndLastError
1856 (env, JNU_JAVANETPKG "SocketException", "putmsg() failed");
1857 return -1;
1858 }
1859
1860 dlpaack = (dl_phys_addr_ack_t *)buf;
1861
1862 msg.buf = (char *)buf;
1863 msg.len = 0;
1864 msg.maxlen = sizeof (buf);
1865 if (getmsg(fd, &msg, NULL, &flags) < 0) {
1867 (env, JNU_JAVANETPKG "SocketException", "getmsg() failed");
1868 return -1;
1869 }
1870
1871 if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
1872 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1873 "Couldn't obtain phys addr\n");
1874 return -1;
1875 }
1876
1877 memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
1878 return dlpaack->dl_addr_length;
1879 }
1880
1881 /*
1882 * Gets the Hardware address (usually MAC address) for the named interface.
1883 * On return puts the data in buf, and returns the length, in byte, of the
1884 * MAC address. Returns -1 if there is no hardware address on that interface.
1885 */
1886 static int getMacAddress
1887 (JNIEnv *env, const char *ifname, const struct in_addr *addr,
1888 unsigned char *buf)
1889 {
1890 struct lifreq if2;
1891 int len, i, sock;
1892
1893 if ((sock = openSocketWithFallback(env, ifname)) < 0) {
1894 return -1;
1895 }
1896
1897 // First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
1898 // try the old way.
1899 memset((char *)&if2, 0, sizeof(if2));
1900 strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1901
1902 if (ioctl(sock, SIOCGLIFHWADDR, &if2) != -1) {
1903 struct sockaddr_dl *sp;
1904 sp = (struct sockaddr_dl *)&if2.lifr_addr;
1905 memcpy(buf, &sp->sdl_data[0], sp->sdl_alen);
1906 close(sock);
1907 return sp->sdl_alen;
1908 }
1909
1910 // On Solaris we have to use DLPI, but it will only work if we have
1911 // privileged access (i.e. root). If that fails, we try a lookup
1912 // in the ARP table, which requires an IPv4 address.
1913 if (((len = getMacFromDevice(env, ifname, buf)) == 0) && (addr != NULL)) {
1914 struct arpreq arpreq;
1915 struct sockaddr_in *sin;
1916 struct sockaddr_in ipAddr;
1917
1918 len = 6; //???
1919
1920 sin = (struct sockaddr_in *)&arpreq.arp_pa;
1921 memset((char *)&arpreq, 0, sizeof(struct arpreq));
1922 ipAddr.sin_port = 0;
1923 ipAddr.sin_family = AF_INET;
1924 memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
1925 memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
1926 arpreq.arp_flags= ATF_PUBL;
1927
1928 if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
1929 close(sock);
1930 return -1;
1931 }
1932
1933 memcpy(buf, &arpreq.arp_ha.sa_data[0], len);
1934 }
1935 close(sock);
1936
1937 // all bytes to 0 means no hardware address
1938 for (i = 0; i < len; i++) {
1939 if (buf[i] != 0)
1940 return len;
1941 }
1942
1943 return -1;
1944 }
1945
1946 static int getMTU(JNIEnv *env, int sock, const char *ifname) {
1947 struct lifreq if2;
1948 memset((char *)&if2, 0, sizeof(if2));
1949 strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1950
1951 if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
1952 JNU_ThrowByNameWithMessageAndLastError
1953 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFMTU) failed");
1954 return -1;
1955 }
2102 return (index == 0) ? -1 : index;
2103 #else
2104 struct ifreq if2;
2105 memset((char *)&if2, 0, sizeof(if2));
2106 strncpy(if2.ifr_name, name, sizeof(if2.ifr_name) - 1);
2107
2108 if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
2109 return -1;
2110 }
2111
2112 return if2.ifr_index;
2113 #endif
2114 }
2115
2116 /*
2117 * Gets the Hardware address (usually MAC address) for the named interface.
2118 * On return puts the data in buf, and returns the length, in byte, of the
2119 * MAC address. Returns -1 if there is no hardware address on that interface.
2120 */
2121 static int getMacAddress
2122 (JNIEnv *env, const char *ifname, const struct in_addr *addr,
2123 unsigned char *buf)
2124 {
2125 struct ifaddrs *ifa0, *ifa;
2126 struct sockaddr *saddr;
2127 int i;
2128
2129 // grab the interface list
2130 if (!getifaddrs(&ifa0)) {
2131 // cycle through the interfaces
2132 for (i = 0, ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next, i++) {
2133 saddr = ifa->ifa_addr;
2134 // link layer contains the MAC address
2135 if (saddr->sa_family == AF_LINK && !strcmp(ifname, ifa->ifa_name)) {
2136 struct sockaddr_dl *sadl = (struct sockaddr_dl *) saddr;
2137 // check the address has the correct length
2138 if (sadl->sdl_alen == ETHER_ADDR_LEN) {
2139 memcpy(buf, (sadl->sdl_data + sadl->sdl_nlen), ETHER_ADDR_LEN);
2140 freeifaddrs(ifa0);
2141 return ETHER_ADDR_LEN;
2142 }
2143 }
2144 }
2145 freeifaddrs(ifa0);
2146 }
2147
2148 return -1;
2149 }
2150
2151 static int getMTU(JNIEnv *env, int sock, const char *ifname) {
2152 struct ifreq if2;
2153 memset((char *)&if2, 0, sizeof(if2));
2154 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
2155
2156 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
2157 JNU_ThrowByNameWithMessageAndLastError
|