--- old/src/java.base/unix/native/libnet/NetworkInterface.c 2016-06-02 12:51:41.000000000 +0100 +++ new/src/java.base/unix/native/libnet/NetworkInterface.c 2016-06-02 12:51:41.000000000 +0100 @@ -135,7 +135,8 @@ #endif static netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs, - struct sockaddr *ifr_addrP, int family, short prefix); + struct sockaddr *ifr_addrP, int family, short prefix, + struct sockaddr *ifr_broadaddrP, struct sockaddr *ifr_netmaskP); static void freeif(netif *ifs); static int openSocket(JNIEnv *env, int proto); @@ -145,6 +146,7 @@ static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name, struct sockaddr *brdcast_store); static short getSubnet(JNIEnv *env, int sock, const char *ifname); +static short computeMaskFromAddress(struct sockaddr *ifr_netmaskP); static int getIndex(int sock, const char *ifname); static int getFlags(int sock, const char *ifname, int *flags); @@ -864,7 +866,8 @@ } netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs, - struct sockaddr *ifr_addrP, int family, short prefix) + struct sockaddr *ifr_addrP, int family, short prefix, + struct sockaddr *ifr_broadaddrP, struct sockaddr *ifr_netmaskP) { netif *currif = ifs, *parent; netaddr *addrP; @@ -913,18 +916,29 @@ addrP->next = 0; if (family == AF_INET) { // Deal with broadcast addr & subnet mask - struct sockaddr *brdcast_to = + if (ifr_broadaddrP != NULL) { // just set it, if already known + addrP->brdcast = (struct sockaddr *) ((char *)addrP + sizeof(netaddr) + addr_size); - addrP->brdcast = getBroadcast(env, sock, name, brdcast_to); - if ((*env)->ExceptionCheck(env) == JNI_TRUE) { - return ifs; + memcpy(addrP->brdcast, ifr_broadaddrP, addr_size); + } else { // otherwise look it up + struct sockaddr *brdcast_to = + (struct sockaddr *) ((char *)addrP + sizeof(netaddr) + addr_size); + addrP->brdcast = getBroadcast(env, sock, name, brdcast_to); + if ((*env)->ExceptionCheck(env) == JNI_TRUE) { + return ifs; + } } - if ((mask = getSubnet(env, sock, name)) != -1) { - addrP->mask = mask; - } else if((*env)->ExceptionCheck(env)) { - return ifs; + + if (ifr_netmaskP != NULL) { // just compute the mask, if already known + addrP->mask = computeMaskFromAddress(ifr_netmaskP); + } else { // otherwise look it up + if ((mask = getSubnet(env, sock, name)) != -1) { + addrP->mask = mask; + } else if((*env)->ExceptionCheck(env)) { + return ifs; + } } - } + } // Deal with virtual interface with colon notation e.g. eth0:1 name_colonP = strchr(name, ':'); @@ -1023,6 +1037,20 @@ return ifs; } +static short computeMaskFromAddress(struct sockaddr *ifr_netmaskP){ + short ret = 0; + unsigned int mask; + + mask = ntohl(((struct sockaddr_in*)ifr_netmaskP)->sin_addr.s_addr); + + while (mask) { + mask <<= 1; + ret++; + } + + return ret; +} + /* * Opens a socket for further ioct calls. proto is one of AF_INET or AF_INET6. */ @@ -1122,13 +1150,38 @@ // Iterate through each interface ifreqP = ifc.ifc_req; + struct sockaddr addr, broadaddr, netmask; for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++, ifreqP++) { -#if defined(_AIX) - if (ifreqP->ifr_addr.sa_family != AF_INET) continue; -#endif + struct sockaddr* broadaddrP = NULL; + struct sockaddr* netmaskP = NULL; + + if ((struct sockaddr *)&(ifreqP->ifr_addr) != NULL && + ((struct sockaddr *)&(ifreqP->ifr_addr))->sa_family != AF_INET) + continue; + + memcpy(&addr, &(ifreqP->ifr_addr), sizeof(struct sockaddr)); + + // set broadaddrP, if applicable + if ((ifreqP->ifr_flags & IFF_POINTOPOINT) == 0 && + ifreqP->ifr_flags & IFF_BROADCAST) { + fprintf(stdout, "\ninside if loop for %s, ", ifreqP->ifr_name); + + if (ioctl(sock, SIOCGIFBRDADDR, ifreqP) == 0) { + memcpy(&broadaddr, &(ifreqP->ifr_broadaddr), sizeof(struct sockaddr)); + broadaddrP = &broadaddr; + } + // restore the address, for subsequent calls + memcpy(&(ifreqP->ifr_addr), &addr, sizeof(struct sockaddr)); + } + + if (ioctl(sock, SIOCGIFNETMASK, ifreqP) == 0) { + memcpy(&netmask, &(ifreqP->ifr_netmask), sizeof(struct sockaddr)); + netmaskP = &netmask; + } + // Add to the list ifs = addif(env, sock, ifreqP->ifr_name, ifs, - (struct sockaddr *)&(ifreqP->ifr_addr), AF_INET, 0); + &addr, AF_INET, 0, broadaddrP, netmaskP); // If an exception occurred then free the list if ((*env)->ExceptionOccurred(env)) { @@ -1177,7 +1230,7 @@ addr.sin6_scope_id = if_idx; ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, - AF_INET6, (short)prefix); + AF_INET6, (short)prefix, NULL, NULL); // If an exception occurred then return the list as is. if ((*env)->ExceptionOccurred(env)) { @@ -1261,7 +1314,8 @@ // Add to the list ifs = addif(env, sock, ifreqP->ifr_name, ifs, - (struct sockaddr *)&(ifreqP->ifr_addr), AF_INET6, 0); + (struct sockaddr *)&(ifreqP->ifr_addr), + AF_INET6, 0, NULL, NULL); // If an exception occurred then free the list if ((*env)->ExceptionOccurred(env)) { @@ -1346,14 +1400,7 @@ return -1; } - mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr); - ret = 0; - while (mask) { - mask <<= 1; - ret++; - } - - return ret; + return computeMaskFromAddress(&(if2.ifr_addr)); } /* @@ -1596,7 +1643,7 @@ // add to the list ifs = addif(env, sock,ifr->lifr_name, ifs, (struct sockaddr *)&(ifr->lifr_addr), family, - (short)ifr->lifr_addrlen); + (short)ifr->lifr_addrlen, NULL, NULL); // If an exception occurred we return immediately if ((*env)->ExceptionOccurred(env)) { @@ -1674,15 +1721,7 @@ return -1; } - mask = ntohl(((struct sockaddr_in*)&(if2.lifr_addr))->sin_addr.s_addr); - ret = 0; - - while (mask) { - mask <<= 1; - ret++; - } - - return ret; + return computeMaskFromAddress(&(if2.lifr_addr)); } @@ -1889,13 +1928,21 @@ } for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) { + struct sockaddr* ifa_broadaddr = NULL; // Skip non-AF_INET entries. if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET) continue; + // set ifa_broadaddr, if there is one + if ((ifa->ifa_flags & IFF_POINTOPOINT) == 0 && + ifa->ifa_flags & IFF_BROADCAST) { + ifa_broadaddr = ifa->ifa_broadaddr; + } + // Add to the list. - ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET, 0); + ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET, 0, + ifa_broadaddr, ifa->ifa_netmask); // If an exception occurred then free the list. if ((*env)->ExceptionOccurred(env)) { @@ -1972,7 +2019,7 @@ // Add to the list. sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr; ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET6, - (short)prefix(&sin6->sin6_addr, sizeof(struct in6_addr))); + (short)prefix(&sin6->sin6_addr, sizeof(struct in6_addr)), NULL, NULL); // If an exception occurred then free the list. if ((*env)->ExceptionOccurred(env)) { @@ -2059,14 +2106,7 @@ return -1; } - mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr); - ret = 0; - while (mask) { - mask <<= 1; - ret++; - } - - return ret; + return computeMaskFromAddress(&(if2.ifr_addr)); } /*