Message ID | 1244730452-19704-5-git-send-email-jlayton@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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 <jlayton@redhat.com> > --- > 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 > linux-cifs-client@lists.samba.org > https://lists.samba.org/mailman/listinfo/linux-cifs-client >
On Thu, 11 Jun 2009 16:13:05 +0100 (BST) "David Holder" <david@erion.co.uk> wrote: > 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 > Yep. Users will be able to use text interface names assuming they have mount.cifs installed. getaddrinfo will convert textual interface names to numeric ones already, so we don't really need to do much special for this. This support will depend on a mount.cifs patch too (sorry, should have made that clear when I posted the kernel patchset). The mount.cifs patch is similar, but slightly different from the one posted yesterday. FWIW, when I was testing today, my mount string was: mount -t cifs -o sec=none //fe80::21d:7dff:fe9c:3c86%eth0/scratch /mnt/cifs ...and it worked just fine. I'll send the mount.cifs patch along in a little while...
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; } /*****************************************************************************
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 <jlayton@redhat.com> --- fs/cifs/connect.c | 6 ++++-- fs/cifs/dns_resolve.c | 4 ++-- fs/cifs/netmisc.c | 34 ++++++++++++++++++++++++++++------ 3 files changed, 34 insertions(+), 10 deletions(-)