/* * Support routines to free netif and netaddr lists */ void free_netif(netif *netifP) { netif *curr = netifP; while (curr != NULL) { if (curr->name != NULL) free(curr->name); if (curr->displayName != NULL) free(curr->displayName); if (curr->addrs != NULL) free_netaddr (curr->addrs); netifP = netifP->next; free(curr); curr = netifP; } }
/* * Create a NetworkInterface object, populate the name and index, and * populate the InetAddress array based on the IP addresses for this * interface. */ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) { jobject netifObj; jobject name, displayName; jobjectArray addrArr, bindsArr, childArr; netaddr *addrs; jint addr_index; int netaddrCount=ifs->naddrs; netaddr *netaddrP=ifs->addrs; jint bind_index; /* * Create a NetworkInterface object and populate it */ netifObj = (*env)->NewObject(env, ni_class, ni_ctor); name = (*env)->NewStringUTF(env, ifs->name); if (ifs->dNameIsUnicode) { displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName, (jsize)wcslen ((PWCHAR)ifs->displayName)); } else { displayName = (*env)->NewStringUTF(env, ifs->displayName); } if (netifObj == NULL || name == NULL || displayName == NULL) { return NULL; } (*env)->SetObjectField(env, netifObj, ni_nameID, name); (*env)->SetObjectField(env, netifObj, ni_displayNameID, displayName); (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index); /* * Get the IP addresses for this interface if necessary * Note that 0 is a valid number of addresses. */ if (netaddrCount < 0) { netaddrCount = enumAddresses_win(env, ifs, &netaddrP); if (netaddrCount == -1) { return NULL; } } addrArr = (*env)->NewObjectArray(env, netaddrCount, ni_iacls, NULL); if (addrArr == NULL) { return NULL; } bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL); if (bindsArr == NULL) { free_netaddr(netaddrP); return NULL; } addrs = netaddrP; addr_index = 0; bind_index = 0; while (addrs != NULL) { jobject iaObj, ia2Obj; jobject ibObj = NULL; if (addrs->addr.him.sa_family == AF_INET) { iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4Ctor); if (iaObj == NULL) { return NULL; } /* default ctor will set family to AF_INET */ setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr)); ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj == NULL) { free_netaddr(netaddrP); return NULL; } (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4Ctor); if (ia2Obj == NULL) { free_netaddr(netaddrP); return NULL; } setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr)); (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj); (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); } else /* AF_INET6 */ { int scope; iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID); if (iaObj) { int ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); if (ret == JNI_FALSE) { return NULL; } scope = addrs->addr.him6.sin6_scope_id; if (scope != 0) { /* zero is default value, no need to set */ setInet6Address_scopeid(env, iaObj, scope); setInet6Address_scopeifname(env, iaObj, netifObj); } ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj == NULL) { free_netaddr(netaddrP); return NULL; } (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); } } (*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj); addrs = addrs->next; addr_index++; } (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr); (*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr); /* * Windows doesn't have virtual interfaces, so child array * is always empty. */ childArr = (*env)->NewObjectArray(env, 0, ni_class, NULL); if (childArr == NULL) { return NULL; } (*env)->SetObjectField(env, netifObj, ni_childsID, childArr); /* return the NetworkInterface */ return netifObj; }
/* * Create a NetworkInterface object, populate the name and index, and * populate the InetAddress array based on the IP addresses for this * interface. */ jobject createNetworkInterface(JNIEnv *env, netif *ifs, int netaddrCount, netaddr *netaddrP) { jobject netifObj; jobject name, displayName; jobjectArray addrArr; netaddr *addrs; jint addr_index; /* * Create a NetworkInterface object and populate it */ netifObj = (*env)->NewObject(env, ni_class, ni_ctor); name = (*env)->NewStringUTF(env, ifs->name); if (ifs->dNameIsUnicode) { displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName, wcslen ((PWCHAR)ifs->displayName)); } else { displayName = (*env)->NewStringUTF(env, ifs->displayName); } if (netifObj == NULL || name == NULL || displayName == NULL) { return NULL; } (*env)->SetObjectField(env, netifObj, ni_nameID, name); (*env)->SetObjectField(env, netifObj, ni_displayNameID, displayName); (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index); /* * Get the IP addresses for this interface if necessary * Note that 0 is a valid number of addresses. */ if (netaddrCount < 0) { netaddrCount = (*enumAddresses_fn)(env, ifs, &netaddrP); if ((*env)->ExceptionOccurred(env)) { free_netaddr(netaddrP); return NULL; } } addrArr = (*env)->NewObjectArray(env, netaddrCount, ni_iacls, NULL); if (addrArr == NULL) { free_netaddr(netaddrP); return NULL; } addrs = netaddrP; addr_index = 0; while (addrs != NULL) { jobject iaObj; if (addrs->addr.him.sa_family == AF_INET) { iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4Ctor); if (iaObj == NULL) { free_netaddr(netaddrP); return NULL; } /* default ctor will set family to AF_INET */ (*env)->SetIntField(env, iaObj, ni_iaAddr, ntohl(addrs->addr.him4.sin_addr.s_addr)); } else /* AF_INET6 */ { int scope; iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID); if (iaObj) { jbyteArray ipaddress = (*env)->NewByteArray(env, 16); if (ipaddress == NULL) { return NULL; } (*env)->SetByteArrayRegion(env, ipaddress, 0, 16, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); scope = addrs->addr.him6.sin6_scope_id; if (scope != 0) { /* zero is default value, no need to set */ (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj); } (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress); } } (*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj); addrs = addrs->next; addr_index++; } (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr); free_netaddr(netaddrP); /* return the NetworkInterface */ return netifObj; }
/* * Enumerate the IP addresses on an interface using the IP helper library * routine GetIfAddrTable and matching based on the index name. There are * more efficient routines but we use GetIfAddrTable because it's avaliable * on 98 and NT. * * Returns the count of addresses, or -1 if error. If no error occurs then * netaddrPP will return a list of netaddr structures with the IP addresses. */ int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP) { MIB_IPADDRTABLE *tableP; ULONG size; DWORD ret; DWORD i; netaddr *netaddrP; int count = 0; unsigned long mask; /* * Use GetIpAddrTable to enumerate the IP Addresses */ size = sizeof(MIB_IPADDRTABLE); tableP = (MIB_IPADDRTABLE *)malloc(size); if (tableP == NULL) { JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); return -1; } ret = GetIpAddrTable(tableP, &size, FALSE); if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) { MIB_IPADDRTABLE * newTableP = (MIB_IPADDRTABLE *)realloc(tableP, size); if (newTableP == NULL) { free(tableP); JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); return -1; } tableP = newTableP; ret = GetIpAddrTable(tableP, &size, FALSE); } if (ret != NO_ERROR) { if (tableP) { free(tableP); } JNU_ThrowByName(env, "java/lang/Error", "IP Helper Library GetIpAddrTable function failed"); return -1; } /* * Iterate through the table to find the addresses with the * matching dwIndex. Ignore 0.0.0.0 addresses. */ count = 0; netaddrP = NULL; i = 0; while (i<tableP->dwNumEntries) { if (tableP->table[i].dwIndex == netifP->dwIndex && tableP->table[i].dwAddr != 0) { netaddr *curr = (netaddr *)malloc(sizeof(netaddr)); if (curr == NULL) { JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); free_netaddr(netaddrP); free(tableP); return -1; } curr->addr.him4.sin_family = AF_INET; curr->addr.him4.sin_addr.s_addr = tableP->table[i].dwAddr; /* * Get netmask / broadcast address */ switch (netifP->ifType) { case MIB_IF_TYPE_ETHERNET: case MIB_IF_TYPE_TOKENRING: case MIB_IF_TYPE_FDDI: case MIB_IF_TYPE_LOOPBACK: case IF_TYPE_IEEE80211: /** * Contrary to what it seems to indicate, dwBCastAddr doesn't * contain the broadcast address but 0 or 1 depending on whether * the broadcast address should set the bits of the host part * to 0 or 1. * Yes, I know it's stupid, but what can I say, it's MSFTs API. */ curr->brdcast.him4.sin_family = AF_INET; if (tableP->table[i].dwBCastAddr == 1) curr->brdcast.him4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask) | (0xffffffff ^ tableP->table[i].dwMask); else curr->brdcast.him4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask); mask = ntohl(tableP->table[i].dwMask); curr->mask = 0; while (mask) { mask <<= 1; curr->mask++; } break; case MIB_IF_TYPE_PPP: case MIB_IF_TYPE_SLIP: default: /** * these don't have broadcast/subnet */ curr->mask = -1; break; } curr->next = netaddrP; netaddrP = curr; count++; } i++; } *netaddrPP = netaddrP; free(tableP); return count; }
/* * Enumerate the IP addresses on an interface using the IP helper library * routine GetIfAddrTable and matching based on the index name. There are * more efficient routines but we use GetIfAddrTable because it's avaliable * on 98 and NT. * * Returns the count of addresses, or -1 if error. If no error occurs then * netaddrPP will return a list of netaddr structures with the IP addresses. */ int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP) { MIB_IPADDRTABLE *tableP; ULONG size; DWORD ret; DWORD i; netaddr *netaddrP; int count = 0; /* * Use GetIpAddrTable to enumerate the IP Addresses */ size = sizeof(MIB_IPADDRTABLE); tableP = (MIB_IPADDRTABLE *)malloc(size); ret = (*GetIpAddrTable_fn)(&tableP, &size, FALSE); if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) { tableP = (MIB_IPADDRTABLE *)realloc(tableP, size); ret = (*GetIpAddrTable_fn)(tableP, &size, FALSE); } if (ret != NO_ERROR) { if (tableP) { free(tableP); } JNU_ThrowByName(env, "java/lang/Error", "IP Helper Library GetIpAddrTable function failed"); return -1; } /* * Iterate through the table to find the addresses with the * matching dwIndex. Ignore 0.0.0.0 addresses. */ count = 0; netaddrP = NULL; i = 0; while (i<tableP->dwNumEntries) { if (tableP->table[i].dwIndex == netifP->dwIndex && tableP->table[i].dwAddr != 0) { netaddr *curr = (netaddr *)malloc(sizeof(netaddr)); if (curr == NULL) { JNU_ThrowOutOfMemoryError(env, "heap allocation failure"); free_netaddr(netaddrP); free(tableP); return -1; } curr->addr.him4.sin_family = AF_INET; curr->addr.him4.sin_addr.s_addr = tableP->table[i].dwAddr; curr->next = netaddrP; netaddrP = curr; count++; } i++; } *netaddrPP = netaddrP; free(tableP); return count; }