diff options
Diffstat (limited to 'fs/lockd/mon.c')
-rw-r--r-- | fs/lockd/mon.c | 113 |
1 files changed, 87 insertions, 26 deletions
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 908b23fadd05..e4d563543b11 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c | |||
@@ -18,6 +18,8 @@ | |||
18 | 18 | ||
19 | #define NLMDBG_FACILITY NLMDBG_MONITOR | 19 | #define NLMDBG_FACILITY NLMDBG_MONITOR |
20 | 20 | ||
21 | #define XDR_ADDRBUF_LEN (20) | ||
22 | |||
21 | static struct rpc_clnt * nsm_create(void); | 23 | static struct rpc_clnt * nsm_create(void); |
22 | 24 | ||
23 | static struct rpc_program nsm_program; | 25 | static struct rpc_program nsm_program; |
@@ -147,28 +149,55 @@ nsm_create(void) | |||
147 | 149 | ||
148 | /* | 150 | /* |
149 | * XDR functions for NSM. | 151 | * XDR functions for NSM. |
152 | * | ||
153 | * See http://www.opengroup.org/ for details on the Network | ||
154 | * Status Monitor wire protocol. | ||
150 | */ | 155 | */ |
151 | 156 | ||
152 | static __be32 * | 157 | static __be32 *xdr_encode_nsm_string(__be32 *p, char *string) |
153 | xdr_encode_common(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) | ||
154 | { | 158 | { |
155 | char buffer[20], *name; | 159 | size_t len = strlen(string); |
156 | 160 | ||
157 | /* | 161 | if (len > SM_MAXSTRLEN) |
158 | * Use the dotted-quad IP address of the remote host as | 162 | len = SM_MAXSTRLEN; |
159 | * identifier. Linux statd always looks up the canonical | 163 | return xdr_encode_opaque(p, string, len); |
160 | * hostname first for whatever remote hostname it receives, | 164 | } |
161 | * so this works alright. | 165 | |
162 | */ | 166 | /* |
163 | if (nsm_use_hostnames) { | 167 | * "mon_name" specifies the host to be monitored. |
164 | name = argp->mon_name; | 168 | * |
165 | } else { | 169 | * Linux uses a text version of the IP address of the remote |
166 | sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr)); | 170 | * host as the host identifier (the "mon_name" argument). |
171 | * | ||
172 | * Linux statd always looks up the canonical hostname first for | ||
173 | * whatever remote hostname it receives, so this works alright. | ||
174 | */ | ||
175 | static __be32 *xdr_encode_mon_name(__be32 *p, struct nsm_args *argp) | ||
176 | { | ||
177 | char buffer[XDR_ADDRBUF_LEN + 1]; | ||
178 | char *name = argp->mon_name; | ||
179 | |||
180 | if (!nsm_use_hostnames) { | ||
181 | snprintf(buffer, XDR_ADDRBUF_LEN, | ||
182 | NIPQUAD_FMT, NIPQUAD(argp->addr)); | ||
167 | name = buffer; | 183 | name = buffer; |
168 | } | 184 | } |
169 | if (!(p = xdr_encode_string(p, name)) | 185 | |
170 | || !(p = xdr_encode_string(p, utsname()->nodename))) | 186 | return xdr_encode_nsm_string(p, name); |
187 | } | ||
188 | |||
189 | /* | ||
190 | * The "my_id" argument specifies the hostname and RPC procedure | ||
191 | * to be called when the status manager receives notification | ||
192 | * (via the SM_NOTIFY call) that the state of host "mon_name" | ||
193 | * has changed. | ||
194 | */ | ||
195 | static __be32 *xdr_encode_my_id(__be32 *p, struct nsm_args *argp) | ||
196 | { | ||
197 | p = xdr_encode_nsm_string(p, utsname()->nodename); | ||
198 | if (!p) | ||
171 | return ERR_PTR(-EIO); | 199 | return ERR_PTR(-EIO); |
200 | |||
172 | *p++ = htonl(argp->prog); | 201 | *p++ = htonl(argp->prog); |
173 | *p++ = htonl(argp->vers); | 202 | *p++ = htonl(argp->vers); |
174 | *p++ = htonl(argp->proc); | 203 | *p++ = htonl(argp->proc); |
@@ -176,18 +205,48 @@ xdr_encode_common(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) | |||
176 | return p; | 205 | return p; |
177 | } | 206 | } |
178 | 207 | ||
179 | static int | 208 | /* |
180 | xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) | 209 | * The "mon_id" argument specifies the non-private arguments |
210 | * of an SM_MON or SM_UNMON call. | ||
211 | */ | ||
212 | static __be32 *xdr_encode_mon_id(__be32 *p, struct nsm_args *argp) | ||
181 | { | 213 | { |
182 | p = xdr_encode_common(rqstp, p, argp); | 214 | p = xdr_encode_mon_name(p, argp); |
183 | if (IS_ERR(p)) | 215 | if (!p) |
184 | return PTR_ERR(p); | 216 | return ERR_PTR(-EIO); |
185 | 217 | ||
186 | /* Surprise - there may even be room for an IPv6 address now */ | 218 | return xdr_encode_my_id(p, argp); |
219 | } | ||
220 | |||
221 | /* | ||
222 | * The "priv" argument may contain private information required | ||
223 | * by the SM_MON call. This information will be supplied in the | ||
224 | * SM_NOTIFY call. | ||
225 | * | ||
226 | * Linux provides the raw IP address of the monitored host, | ||
227 | * left in network byte order. | ||
228 | */ | ||
229 | static __be32 *xdr_encode_priv(__be32 *p, struct nsm_args *argp) | ||
230 | { | ||
187 | *p++ = argp->addr; | 231 | *p++ = argp->addr; |
188 | *p++ = 0; | 232 | *p++ = 0; |
189 | *p++ = 0; | 233 | *p++ = 0; |
190 | *p++ = 0; | 234 | *p++ = 0; |
235 | |||
236 | return p; | ||
237 | } | ||
238 | |||
239 | static int | ||
240 | xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) | ||
241 | { | ||
242 | p = xdr_encode_mon_id(p, argp); | ||
243 | if (IS_ERR(p)) | ||
244 | return PTR_ERR(p); | ||
245 | |||
246 | p = xdr_encode_priv(p, argp); | ||
247 | if (IS_ERR(p)) | ||
248 | return PTR_ERR(p); | ||
249 | |||
191 | rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); | 250 | rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); |
192 | return 0; | 251 | return 0; |
193 | } | 252 | } |
@@ -195,7 +254,7 @@ xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) | |||
195 | static int | 254 | static int |
196 | xdr_encode_unmon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) | 255 | xdr_encode_unmon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) |
197 | { | 256 | { |
198 | p = xdr_encode_common(rqstp, p, argp); | 257 | p = xdr_encode_mon_id(p, argp); |
199 | if (IS_ERR(p)) | 258 | if (IS_ERR(p)) |
200 | return PTR_ERR(p); | 259 | return PTR_ERR(p); |
201 | rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); | 260 | rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); |
@@ -220,9 +279,11 @@ xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp) | |||
220 | } | 279 | } |
221 | 280 | ||
222 | #define SM_my_name_sz (1+XDR_QUADLEN(SM_MAXSTRLEN)) | 281 | #define SM_my_name_sz (1+XDR_QUADLEN(SM_MAXSTRLEN)) |
223 | #define SM_my_id_sz (3+1+SM_my_name_sz) | 282 | #define SM_my_id_sz (SM_my_name_sz+3) |
224 | #define SM_mon_id_sz (1+XDR_QUADLEN(20)+SM_my_id_sz) | 283 | #define SM_mon_name_sz (1+XDR_QUADLEN(SM_MAXSTRLEN)) |
225 | #define SM_mon_sz (SM_mon_id_sz+4) | 284 | #define SM_mon_id_sz (SM_mon_name_sz+SM_my_id_sz) |
285 | #define SM_priv_sz (XDR_QUADLEN(SM_PRIV_SIZE)) | ||
286 | #define SM_mon_sz (SM_mon_id_sz+SM_priv_sz) | ||
226 | #define SM_monres_sz 2 | 287 | #define SM_monres_sz 2 |
227 | #define SM_unmonres_sz 1 | 288 | #define SM_unmonres_sz 1 |
228 | 289 | ||