diff options
| -rw-r--r-- | fs/lockd/clntlock.c | 51 | ||||
| -rw-r--r-- | fs/lockd/svc.c | 30 |
2 files changed, 22 insertions, 59 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index aedc47a264c..1f3b0fc0d35 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c | |||
| @@ -139,55 +139,6 @@ 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 | |||
| 191 | /* | 142 | /* |
| 192 | * The server lockd has called us back to tell us the lock was granted | 143 | * The server lockd has called us back to tell us the lock was granted |
| 193 | */ | 144 | */ |
| @@ -215,7 +166,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock) | |||
| 215 | */ | 166 | */ |
| 216 | if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid) | 167 | if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid) |
| 217 | continue; | 168 | continue; |
| 218 | if (!nlmclnt_cmp_addr(block->b_host, addr)) | 169 | if (!nlm_cmp_addr(nlm_addr(block->b_host), addr)) |
| 219 | continue; | 170 | continue; |
| 220 | if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0) | 171 | if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0) |
| 221 | continue; | 172 | continue; |
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 566932b98fd..abf83881f68 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c | |||
| @@ -193,20 +193,30 @@ lockd(void *vrqstp) | |||
| 193 | return 0; | 193 | return 0; |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | static int create_lockd_listener(struct svc_serv *serv, char *name, | 196 | static int create_lockd_listener(struct svc_serv *serv, const char *name, |
| 197 | unsigned short port) | 197 | const int family, const unsigned short port) |
| 198 | { | 198 | { |
| 199 | struct svc_xprt *xprt; | 199 | struct svc_xprt *xprt; |
| 200 | 200 | ||
| 201 | xprt = svc_find_xprt(serv, name, 0, 0); | 201 | xprt = svc_find_xprt(serv, name, family, 0); |
| 202 | if (xprt == NULL) | 202 | if (xprt == NULL) |
| 203 | return svc_create_xprt(serv, name, PF_INET, | 203 | return svc_create_xprt(serv, name, family, port, |
| 204 | port, SVC_SOCK_DEFAULTS); | 204 | SVC_SOCK_DEFAULTS); |
| 205 | |||
| 206 | svc_xprt_put(xprt); | 205 | svc_xprt_put(xprt); |
| 207 | return 0; | 206 | return 0; |
| 208 | } | 207 | } |
| 209 | 208 | ||
| 209 | static int create_lockd_family(struct svc_serv *serv, const int family) | ||
| 210 | { | ||
| 211 | int err; | ||
| 212 | |||
| 213 | err = create_lockd_listener(serv, "udp", family, nlm_udpport); | ||
| 214 | if (err < 0) | ||
| 215 | return err; | ||
| 216 | |||
| 217 | return create_lockd_listener(serv, "tcp", family, nlm_tcpport); | ||
| 218 | } | ||
| 219 | |||
| 210 | /* | 220 | /* |
| 211 | * Ensure there are active UDP and TCP listeners for lockd. | 221 | * Ensure there are active UDP and TCP listeners for lockd. |
| 212 | * | 222 | * |
| @@ -222,13 +232,15 @@ static int make_socks(struct svc_serv *serv) | |||
| 222 | static int warned; | 232 | static int warned; |
| 223 | int err; | 233 | int err; |
| 224 | 234 | ||
| 225 | err = create_lockd_listener(serv, "udp", nlm_udpport); | 235 | err = create_lockd_family(serv, PF_INET); |
| 226 | if (err < 0) | 236 | if (err < 0) |
| 227 | goto out_err; | 237 | goto out_err; |
| 228 | 238 | ||
| 229 | err = create_lockd_listener(serv, "tcp", nlm_tcpport); | 239 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 230 | if (err < 0) | 240 | err = create_lockd_family(serv, PF_INET6); |
| 241 | if (err < 0 && err != -EAFNOSUPPORT) | ||
| 231 | goto out_err; | 242 | goto out_err; |
| 243 | #endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */ | ||
| 232 | 244 | ||
| 233 | warned = 0; | 245 | warned = 0; |
| 234 | return 0; | 246 | return 0; |
