nfsd4: allow nfs4 state startup to fail
[safe/jmp/linux-2.6] / fs / cifs / netmisc.c
index 00e6e35..bd6d689 100644 (file)
@@ -158,25 +158,47 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst)
 /*
  * Try to convert a string to an IPv4 address and then attempt to convert
  * it to an IPv6 address if that fails. Set the family field if either
- * succeeds.
+ * succeeds. If it's an IPv6 address and it has a '%' sign in it, try to
+ * treat the part following it as a numeric sin6_scope_id.
  *
  * Returns 0 on failure.
  */
 int
 cifs_convert_address(char *src, void *dst)
 {
+       int rc;
+       char *pct, *endp;
        struct sockaddr_in *s4 = (struct sockaddr_in *) dst;
-       struct sockaddr_in6 *s6 = (Struct sockaddr_in6 *) dst;
+       struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst;
 
+       /* IPv4 address */
        if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) {
                s4->sin_family = AF_INET;
                return 1;
-       } else if (cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr)) {
-               s6->sin6_family = AF_INET6;
-               return 1;
        }
 
-       return 0;
+       /* temporarily terminate string */
+       pct = strchr(src, '%');
+       if (pct)
+               *pct = '\0';
+
+       rc = cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr);
+
+       /* repair temp termination (if any) and make pct point to scopeid */
+       if (pct)
+               *pct++ = '%';
+
+       if (!rc)
+               return rc;
+
+       s6->sin6_family = AF_INET6;
+       if (pct) {
+               s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0);
+               if (!*pct || *endp)
+                       return 0;
+       }
+
+       return rc;
 }
 
 /*****************************************************************************