Re: [PATCH 4/5] cifs: have cifs parse scope_id outof IPv6 addresses and use it
"David Holder" <[email protected]>
| Newsgroups | gmane.linux.file-systems.cifs |
|---|---|
| Message-ID | <[email protected]> |
Jeff, Great to see this going into the code. Do you plan to allow for textual interface names after the %? You can use getnameinfo() with the NI_NUMERICHOST flag to convert the textual interface name and IPv6 address to numeric format or just use if_nametoindex(). Regards, David > This patch has CIFS look for a '%' in an IPv6 address. If one is > present then it will try to treat that value as a numeric interface > index suitable for stuffing into the sin6_scope_id field. > > This should allow people to mount servers on IPv6 link-local addresses. > > Signed-off-by: Jeff Layton <[email protected]> > --- > fs/cifs/connect.c | 6 ++++-- > fs/cifs/dns_resolve.c | 4 ++-- > fs/cifs/netmisc.c | 34 ++++++++++++++++++++++++++++------ > 3 files changed, 34 insertions(+), 10 deletions(-) > > diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c > index 6a91b5f..c9e489c 100644 > --- a/fs/cifs/connect.c > +++ b/fs/cifs/connect.c > @@ -1374,8 +1374,10 @@ cifs_find_tcp_session(struct sockaddr_storage > *addr) > server->addr.sockAddr.sin_addr.s_addr)) > continue; > else if (addr->ss_family == AF_INET6 && > - !ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, > - &addr6->sin6_addr)) > + (!ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, > + &addr6->sin6_addr) || > + server->addr.sockAddr6.sin6_scope_id != > + addr6->sin6_scope_id)) > continue; > > ++server->srv_count; > diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c > index 91b5500..8794814 100644 > --- a/fs/cifs/dns_resolve.c > +++ b/fs/cifs/dns_resolve.c > @@ -35,7 +35,7 @@ > * 0 - name is not IP > */ > static int > -is_ip(const char *name) > +is_ip(char *name) > { > struct sockaddr_storage ss; > > @@ -57,7 +57,7 @@ dns_resolver_instantiate(struct key *key, const void > *data, > ip[datalen] = '\0'; > > /* make sure this looks like an address */ > - if (!is_ip((const char *) ip)) { > + if (!is_ip(ip)) { > kfree(ip); > return -EINVAL; > } > diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c > index 00e6e35..bd6d689 100644 > --- a/fs/cifs/netmisc.c > +++ b/fs/cifs/netmisc.c > @@ -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; > } > > /***************************************************************************** > -- > 1.6.0.6 > > _______________________________________________ > linux-cifs-client mailing list > [email protected] > https://lists.samba.org/mailman/listinfo/linux-cifs-client >