diff options
Diffstat (limited to 'fs/lockd/clntlock.c')
| -rw-r--r-- | fs/lockd/clntlock.c | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 1f3b0fc0d351..aedc47a264c1 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c | |||
| @@ -139,6 +139,55 @@ int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout) | |||
| 139 | return 0; | 139 | return 0; |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 143 | static const struct in6_addr *nlmclnt_map_v4addr(const struct sockaddr *sap, | ||
| 144 | struct in6_addr *addr_mapped) | ||
| 145 | { | ||
| 146 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; | ||
| 147 | |||
| 148 | switch (sap->sa_family) { | ||
| 149 | case AF_INET6: | ||
| 150 | return &((const struct sockaddr_in6 *)sap)->sin6_addr; | ||
| 151 | case AF_INET: | ||
| 152 | ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, addr_mapped); | ||
| 153 | return addr_mapped; | ||
| 154 | } | ||
| 155 | |||
| 156 | return NULL; | ||
| 157 | } | ||
| 158 | |||
| 159 | /* | ||
| 160 | * If lockd is using a PF_INET6 listener, all incoming requests appear | ||
| 161 | * to come from AF_INET6 remotes. The address of AF_INET remotes are | ||
| 162 | * mapped to AF_INET6 automatically by the network layer. In case the | ||
| 163 | * user passed an AF_INET server address at mount time, ensure both | ||
| 164 | * addresses are AF_INET6 before comparing them. | ||
| 165 | */ | ||
| 166 | static int nlmclnt_cmp_addr(const struct nlm_host *host, | ||
| 167 | const struct sockaddr *sap) | ||
| 168 | { | ||
| 169 | const struct in6_addr *addr1; | ||
| 170 | const struct in6_addr *addr2; | ||
| 171 | struct in6_addr addr1_mapped; | ||
| 172 | struct in6_addr addr2_mapped; | ||
| 173 | |||
| 174 | addr1 = nlmclnt_map_v4addr(nlm_addr(host), &addr1_mapped); | ||
| 175 | if (likely(addr1 != NULL)) { | ||
| 176 | addr2 = nlmclnt_map_v4addr(sap, &addr2_mapped); | ||
| 177 | if (likely(addr2 != NULL)) | ||
| 178 | return ipv6_addr_equal(addr1, addr2); | ||
| 179 | } | ||
| 180 | |||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | #else /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */ | ||
| 184 | static int nlmclnt_cmp_addr(const struct nlm_host *host, | ||
| 185 | const struct sockaddr *sap) | ||
| 186 | { | ||
| 187 | return nlm_cmp_addr(nlm_addr(host), sap); | ||
| 188 | } | ||
| 189 | #endif /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */ | ||
| 190 | |||
| 142 | /* | 191 | /* |
| 143 | * The server lockd has called us back to tell us the lock was granted | 192 | * The server lockd has called us back to tell us the lock was granted |
| 144 | */ | 193 | */ |
| @@ -166,7 +215,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock) | |||
| 166 | */ | 215 | */ |
| 167 | if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid) | 216 | if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid) |
| 168 | continue; | 217 | continue; |
| 169 | if (!nlm_cmp_addr(nlm_addr(block->b_host), addr)) | 218 | if (!nlmclnt_cmp_addr(block->b_host, addr)) |
| 170 | continue; | 219 | continue; |
| 171 | if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0) | 220 | if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0) |
| 172 | continue; | 221 | continue; |
