Inet6Address: Remove special handling for ll addresses with no scope_id set.
If a scope_id is specified, use it. If no scope_id is specified, don't
try and figure it out from the main routing table.
bug: 26787010
Change-Id: I8298297f4f3478426003e7267bd505959bfab097
diff --git a/ojluni/src/main/java/java/net/Inet6Address.java b/ojluni/src/main/java/java/net/Inet6Address.java
index ca19211..a46223d 100755
--- a/ojluni/src/main/java/java/net/Inet6Address.java
+++ b/ojluni/src/main/java/java/net/Inet6Address.java
@@ -177,12 +177,6 @@
public static final InetAddress LOOPBACK = new Inet6Address("localhost",
new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 0);
-
- /*
- * cached scope_id - for link-local address use only.
- */
- private transient int cached_scope_id = 0;
-
/**
* Holds a 128-bit (16 bytes) IPv6 address.
*
diff --git a/ojluni/src/main/native/Inet6Address.c b/ojluni/src/main/native/Inet6Address.c
index 274fd31..2dfc38f 100755
--- a/ojluni/src/main/native/Inet6Address.c
+++ b/ojluni/src/main/native/Inet6Address.c
@@ -38,7 +38,6 @@
jclass ia6_class;
jfieldID ia6_ipaddressID;
jfieldID ia6_scopeidID;
-jfieldID ia6_cachedscopeidID;
jfieldID ia6_scopeidsetID;
jfieldID ia6_scopeifnameID;
jfieldID ia6_scopeifnamesetID;
@@ -59,8 +58,6 @@
CHECK_NULL(ia6_ipaddressID);
ia6_scopeidID = (*env)->GetFieldID(env, ia6_class, "scope_id", "I");
CHECK_NULL(ia6_scopeidID);
- ia6_cachedscopeidID = (*env)->GetFieldID(env, ia6_class, "cached_scope_id", "I");
- CHECK_NULL(ia6_cachedscopeidID);
ia6_scopeidsetID = (*env)->GetFieldID(env, ia6_class, "scope_id_set", "Z");
CHECK_NULL(ia6_scopeidID);
ia6_scopeifnameID = (*env)->GetFieldID(env, ia6_class, "scope_ifname", "Ljava/net/NetworkInterface;");
diff --git a/ojluni/src/main/native/Inet6AddressImpl.c b/ojluni/src/main/native/Inet6AddressImpl.c
index e0ad5d3..27f03ce 100755
--- a/ojluni/src/main/native/Inet6AddressImpl.c
+++ b/ojluni/src/main/native/Inet6AddressImpl.c
@@ -291,17 +291,14 @@
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
him6.sin6_family = AF_INET6;
-#ifdef __linux__
- if (scope > 0)
- him6.sin6_scope_id = scope;
- else
- him6.sin6_scope_id = getDefaultIPv6Interface( &(him6.sin6_addr));
- len = sizeof(struct sockaddr_in6);
-#else
+
+ // Android-change: Don't try and figure out a default scope ID if one isn't
+ // set. It's only useful for link local addresses anyway, and callers are
+ // expected to call isReachable with a specific NetworkInterface if they
+ // want to query the reachability of an address that's local to that IF.
if (scope > 0)
him6.sin6_scope_id = scope;
len = sizeof(struct sockaddr_in6);
-#endif
/*
* If a network interface was specified, let's create the address
* for it.
diff --git a/ojluni/src/main/native/net_util.h b/ojluni/src/main/native/net_util.h
index 8538d8e..61302e2f 100755
--- a/ojluni/src/main/native/net_util.h
+++ b/ojluni/src/main/native/net_util.h
@@ -95,7 +95,6 @@
extern jclass ia6_class;
extern jfieldID ia6_ipaddressID;
extern jfieldID ia6_scopeidID;
-extern jfieldID ia6_cachedscopeidID;
extern jfieldID ia6_scopeidsetID;
extern jfieldID ia6_scopeifnameID;
extern jfieldID ia6_scopeifnamesetID;
diff --git a/ojluni/src/main/native/net_util_md.c b/ojluni/src/main/native/net_util_md.c
index 660cc1c..27a45ad 100755
--- a/ojluni/src/main/native/net_util_md.c
+++ b/ojluni/src/main/native/net_util_md.c
@@ -551,41 +551,6 @@
printf ("\n");
}
-static jboolean needsLoopbackRoute (struct in6_addr* dest_addr) {
- int byte_count;
- int extra_bits, i;
- struct loopback_route *ptr;
-
- if (loRoutes == 0) {
- initLoopbackRoutes();
- }
-
- for (ptr = loRoutes, i=0; i<nRoutes; i++, ptr++) {
- struct in6_addr *target_addr=&ptr->addr;
- int dest_plen = ptr->plen;
- byte_count = dest_plen >> 3;
- extra_bits = dest_plen & 0x3;
-
- if (byte_count > 0) {
- if (memcmp(target_addr, dest_addr, byte_count)) {
- continue; /* no match */
- }
- }
-
- if (extra_bits > 0) {
- unsigned char c1 = ((unsigned char *)target_addr)[byte_count];
- unsigned char c2 = ((unsigned char *)&dest_addr)[byte_count];
- unsigned char mask = 0xff << (8 - extra_bits);
- if ((c1 & mask) != (c2 & mask)) {
- continue;
- }
- }
- return JNI_TRUE;
- }
- return JNI_FALSE;
-}
-
-
static void initLoopbackRoutes() {
FILE *f;
char srcp[8][5];
@@ -763,25 +728,6 @@
fclose (f);
}
-/* return the scope_id (interface index) of the
- * interface corresponding to the given address
- * returns 0 if no match found
- */
-
-static int getLocalScopeID (char *addr) {
- struct localinterface *lif;
- int i;
- if (localifs == 0) {
- initLocalIfs();
- }
- for (i=0, lif=localifs; i<nifs; i++, lif++) {
- if (memcmp (addr, lif->localaddr, 16) == 0) {
- return lif->index;
- }
- }
- return 0;
-}
-
void initLocalAddrTable () {
initLoopbackRoutes();
initLocalIfs();
@@ -860,80 +806,17 @@
/* MMM: Come back to this! */
#endif
- /*
- * On Linux if we are connecting to a link-local address
- * we need to specify the interface in the scope_id (2.4 kernel only)
- *
- * If the scope was cached the we use the cached value. If not cached but
- * specified in the Inet6Address we use that, but we first check if the
- * address needs to be routed via the loopback interface. In this case,
- * we override the specified value with that of the loopback interface.
- * If no cached value exists and no value was specified by user, then
- * we try to determine a value ffrom the routing table. In all these
- * cases the used value is cached for further use.
- */
-#ifdef __linux__
- if (IN6_IS_ADDR_LINKLOCAL(&(him6->sin6_addr))) {
- int cached_scope_id = 0, scope_id = 0;
- int old_kernel = kernelIsV22();
-
- if (ia6_cachedscopeidID && !old_kernel) {
- cached_scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);
- /* if cached value exists then use it. Otherwise, check
- * if scope is set in the address.
- */
- if (!cached_scope_id) {
- if (ia6_scopeidID) {
- scope_id = (int)(*env)->GetIntField(env,iaObj,ia6_scopeidID);
- }
- if (scope_id != 0) {
- /* check user-specified value for loopback case
- * that needs to be overridden
- */
- if (kernelIsV24() && needsLoopbackRoute (&him6->sin6_addr)) {
- cached_scope_id = lo_scope_id;
- (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
- }
- } else {
- /*
- * Otherwise consult the IPv6 routing tables to
- * try determine the appropriate interface.
- */
- if (kernelIsV24()) {
- cached_scope_id = getDefaultIPv6Interface( &(him6->sin6_addr) );
- } else {
- cached_scope_id = getLocalScopeID( (char *)&(him6->sin6_addr) );
- if (cached_scope_id == 0) {
- cached_scope_id = getDefaultIPv6Interface( &(him6->sin6_addr) );
- }
- }
- (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
- }
- }
- }
-
- /*
- * If we have a scope_id use the extended form
- * of sockaddr_in6.
- */
-
- if (!old_kernel) {
- struct sockaddr_in6 *him6 =
- (struct sockaddr_in6 *)him;
- him6->sin6_scope_id = cached_scope_id != 0 ?
- cached_scope_id : scope_id;
- *len = sizeof(struct sockaddr_in6);
- }
- }
-#else
- /* handle scope_id for solaris */
-
+ // Android-changed: Don't try and figure out scope_ids for link local
+ // addresses. Use them only if they're set in java (say, if the Inet6Address
+ // was constructed with a specific scope_id or NetworkInterface).
if (family != IPv4) {
if (ia6_scopeidID) {
- him6->sin6_scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_scopeidID);
+ int scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_scopeidID);
+ if (scope_id > 0) {
+ him6->sin6_scope_id = scope_id;
+ }
}
}
-#endif
} else
#endif /* AF_INET6 */
{
@@ -1085,158 +968,6 @@
}
/*
- * Determine the default interface for an IPv6 address.
- *
- * 1. Scans /proc/net/ipv6_route for a matching route
- * (eg: fe80::/10 or a route for the specific address).
- * This will tell us the interface to use (eg: "eth0").
- *
- * 2. Lookup /proc/net/if_inet6 to map the interface
- * name to an interface index.
- *
- * Returns :-
- * -1 if error
- * 0 if no matching interface
- * >1 interface index to use for the link-local address.
- */
-#if defined(__linux__) && defined(AF_INET6)
-int getDefaultIPv6Interface(struct in6_addr *target_addr) {
- FILE *f;
- char srcp[8][5];
- char hopp[8][5];
- int dest_plen, src_plen, use, refcnt, metric;
- unsigned long flags;
- char dest_str[40];
- struct in6_addr dest_addr;
- char device[16];
- jboolean match = JNI_FALSE;
-
- /*
- * Scan /proc/net/ipv6_route looking for a matching
- * route.
- */
- if ((f = fopen("/proc/net/ipv6_route", "r")) == NULL) {
- return -1;
- }
- while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
- "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
- "%4s%4s%4s%4s%4s%4s%4s%4s "
- "%08x %08x %08x %08lx %8s",
- dest_str, &dest_str[5], &dest_str[10], &dest_str[15],
- &dest_str[20], &dest_str[25], &dest_str[30], &dest_str[35],
- &dest_plen,
- srcp[0], srcp[1], srcp[2], srcp[3],
- srcp[4], srcp[5], srcp[6], srcp[7],
- &src_plen,
- hopp[0], hopp[1], hopp[2], hopp[3],
- hopp[4], hopp[5], hopp[6], hopp[7],
- &metric, &use, &refcnt, &flags, device) == 31) {
-
- /*
- * Some routes should be ignored
- */
- if ( (dest_plen < 0 || dest_plen > 128) ||
- (src_plen != 0) ||
- (flags & (RTF_POLICY | RTF_FLOW)) ||
- ((flags & RTF_REJECT) && dest_plen == 0) ) {
- continue;
- }
-
- /*
- * Convert the destination address
- */
- dest_str[4] = ':';
- dest_str[9] = ':';
- dest_str[14] = ':';
- dest_str[19] = ':';
- dest_str[24] = ':';
- dest_str[29] = ':';
- dest_str[34] = ':';
- dest_str[39] = '\0';
-
- if (inet_pton(AF_INET6, dest_str, &dest_addr) < 0) {
- /* not an Ipv6 address */
- continue;
- } else {
- /*
- * The prefix len (dest_plen) indicates the number of bits we
- * need to match on.
- *
- * dest_plen / 8 => number of bytes to match
- * dest_plen % 8 => number of additional bits to match
- *
- * eg: fe80::/10 => match 1 byte + 2 additional bits in the
- * the next byte.
- */
- int byte_count = dest_plen >> 3;
- int extra_bits = dest_plen & 0x3;
-
- if (byte_count > 0) {
- if (memcmp(target_addr, &dest_addr, byte_count)) {
- continue; /* no match */
- }
- }
-
- if (extra_bits > 0) {
- unsigned char c1 = ((unsigned char *)target_addr)[byte_count];
- unsigned char c2 = ((unsigned char *)&dest_addr)[byte_count];
- unsigned char mask = 0xff << (8 - extra_bits);
- if ((c1 & mask) != (c2 & mask)) {
- continue;
- }
- }
-
- /*
- * We have a match
- */
- match = JNI_TRUE;
- break;
- }
- }
- fclose(f);
-
- /*
- * If there's a match then we lookup the interface
- * index.
- */
- if (match) {
- char devname[21];
- char addr6p[8][5];
- int plen, scope, dad_status, if_idx;
-
- if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) {
- while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
- addr6p[0], addr6p[1], addr6p[2], addr6p[3],
- addr6p[4], addr6p[5], addr6p[6], addr6p[7],
- &if_idx, &plen, &scope, &dad_status, devname) == 13) {
-
- if (strcmp(devname, device) == 0) {
- /*
- * Found - so just return the index
- */
- fclose(f);
- return if_idx;
- }
- }
- fclose(f);
- } else {
- /*
- * Couldn't open /proc/net/if_inet6
- */
- return -1;
- }
- }
-
- /*
- * If we get here it means we didn't there wasn't any
- * route or we couldn't get the index of the interface.
- */
- return 0;
-}
-#endif
-
-
-/*
* Wrapper for getsockopt system routine - does any necessary
* pre/post processing to deal with OS specific oddies :-
*
diff --git a/ojluni/src/main/native/net_util_md.h b/ojluni/src/main/native/net_util_md.h
index c72a07b..cc0c033 100755
--- a/ojluni/src/main/native/net_util_md.h
+++ b/ojluni/src/main/native/net_util_md.h
@@ -77,10 +77,6 @@
#endif
-#if defined(__linux__) && defined(AF_INET6)
-int getDefaultIPv6Interface(struct in6_addr *target_addr);
-#endif
-
/* needed from libsocket on Solaris 8 */