1/*
2 * linux/fs/lockd/mon.c
3 *
4 * The kernel statd client.
5 *
6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
7 */
8
9#include <linux/types.h>
10#include <linux/utsname.h>
11#include <linux/kernel.h>
12#include <linux/ktime.h>
13#include <linux/slab.h>
14
15#include <linux/sunrpc/clnt.h>
16#include <linux/sunrpc/xprtsock.h>
17#include <linux/sunrpc/svc.h>
18#include <linux/lockd/lockd.h>
19
20#include <asm/unaligned.h>
21
22#define NLMDBG_FACILITY		NLMDBG_MONITOR
23#define NSM_PROGRAM		100024
24#define NSM_VERSION		1
25
26enum {
27	NSMPROC_NULL,
28	NSMPROC_STAT,
29	NSMPROC_MON,
30	NSMPROC_UNMON,
31	NSMPROC_UNMON_ALL,
32	NSMPROC_SIMU_CRASH,
33	NSMPROC_NOTIFY,
34};
35
36struct nsm_args {
37	struct nsm_private	*priv;
38	u32			prog;		/* RPC callback info */
39	u32			vers;
40	u32			proc;
41
42	char			*mon_name;
43};
44
45struct nsm_res {
46	u32			status;
47	u32			state;
48};
49
50static struct rpc_program	nsm_program;
51static				LIST_HEAD(nsm_handles);
52static				DEFINE_SPINLOCK(nsm_lock);
53
54/*
55 * Local NSM state
56 */
57u32	__read_mostly		nsm_local_state;
58int	__read_mostly		nsm_use_hostnames;
59
60static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm)
61{
62	return (struct sockaddr *)&nsm->sm_addr;
63}
64
65static struct rpc_clnt *nsm_create(void)
66{
67	struct sockaddr_in sin = {
68		.sin_family		= AF_INET,
69		.sin_addr.s_addr	= htonl(INADDR_LOOPBACK),
70	};
71	struct rpc_create_args args = {
72		.protocol		= XPRT_TRANSPORT_UDP,
73		.address		= (struct sockaddr *)&sin,
74		.addrsize		= sizeof(sin),
75		.servername		= "rpc.statd",
76		.program		= &nsm_program,
77		.version		= NSM_VERSION,
78		.authflavor		= RPC_AUTH_NULL,
79		.flags			= RPC_CLNT_CREATE_NOPING,
80	};
81
82	return rpc_create(&args);
83}
84
85static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
86{
87	struct rpc_clnt	*clnt;
88	int		status;
89	struct nsm_args args = {
90		.priv		= &nsm->sm_priv,
91		.prog		= NLM_PROGRAM,
92		.vers		= 3,
93		.proc		= NLMPROC_NSM_NOTIFY,
94		.mon_name	= nsm->sm_mon_name,
95	};
96	struct rpc_message msg = {
97		.rpc_argp	= &args,
98		.rpc_resp	= res,
99	};
100
101	clnt = nsm_create();
102	if (IS_ERR(clnt)) {
103		status = PTR_ERR(clnt);
104		dprintk("lockd: failed to create NSM upcall transport, "
105				"status=%d\n", status);
106		goto out;
107	}
108
109	memset(res, 0, sizeof(*res));
110
111	msg.rpc_proc = &clnt->cl_procinfo[proc];
112	status = rpc_call_sync(clnt, &msg, 0);
113	if (status < 0)
114		dprintk("lockd: NSM upcall RPC failed, status=%d\n",
115				status);
116	else
117		status = 0;
118	rpc_shutdown_client(clnt);
119 out:
120	return status;
121}
122
123/**
124 * nsm_monitor - Notify a peer in case we reboot
125 * @host: pointer to nlm_host of peer to notify
126 *
127 * If this peer is not already monitored, this function sends an
128 * upcall to the local rpc.statd to record the name/address of
129 * the peer to notify in case we reboot.
130 *
131 * Returns zero if the peer is monitored by the local rpc.statd;
132 * otherwise a negative errno value is returned.
133 */
134int nsm_monitor(const struct nlm_host *host)
135{
136	struct nsm_handle *nsm = host->h_nsmhandle;
137	struct nsm_res	res;
138	int		status;
139
140	dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
141
142	if (nsm->sm_monitored)
143		return 0;
144
145	/*
146	 * Choose whether to record the caller_name or IP address of
147	 * this peer in the local rpc.statd's database.
148	 */
149	nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
150
151	status = nsm_mon_unmon(nsm, NSMPROC_MON, &res);
152	if (unlikely(res.status != 0))
153		status = -EIO;
154	if (unlikely(status < 0)) {
155		printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name);
156		return status;
157	}
158
159	nsm->sm_monitored = 1;
160	if (unlikely(nsm_local_state != res.state)) {
161		nsm_local_state = res.state;
162		dprintk("lockd: NSM state changed to %d\n", nsm_local_state);
163	}
164	return 0;
165}
166
167/**
168 * nsm_unmonitor - Unregister peer notification
169 * @host: pointer to nlm_host of peer to stop monitoring
170 *
171 * If this peer is monitored, this function sends an upcall to
172 * tell the local rpc.statd not to send this peer a notification
173 * when we reboot.
174 */
175void nsm_unmonitor(const struct nlm_host *host)
176{
177	struct nsm_handle *nsm = host->h_nsmhandle;
178	struct nsm_res	res;
179	int status;
180
181	if (atomic_read(&nsm->sm_count) == 1
182	 && nsm->sm_monitored && !nsm->sm_sticky) {
183		dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
184
185		status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res);
186		if (res.status != 0)
187			status = -EIO;
188		if (status < 0)
189			printk(KERN_NOTICE "lockd: cannot unmonitor %s\n",
190					nsm->sm_name);
191		else
192			nsm->sm_monitored = 0;
193	}
194}
195
196static struct nsm_handle *nsm_lookup_hostname(const char *hostname,
197					      const size_t len)
198{
199	struct nsm_handle *nsm;
200
201	list_for_each_entry(nsm, &nsm_handles, sm_link)
202		if (strlen(nsm->sm_name) == len &&
203		    memcmp(nsm->sm_name, hostname, len) == 0)
204			return nsm;
205	return NULL;
206}
207
208static struct nsm_handle *nsm_lookup_addr(const struct sockaddr *sap)
209{
210	struct nsm_handle *nsm;
211
212	list_for_each_entry(nsm, &nsm_handles, sm_link)
213		if (rpc_cmp_addr(nsm_addr(nsm), sap))
214			return nsm;
215	return NULL;
216}
217
218static struct nsm_handle *nsm_lookup_priv(const struct nsm_private *priv)
219{
220	struct nsm_handle *nsm;
221
222	list_for_each_entry(nsm, &nsm_handles, sm_link)
223		if (memcmp(nsm->sm_priv.data, priv->data,
224					sizeof(priv->data)) == 0)
225			return nsm;
226	return NULL;
227}
228
229/*
230 * Construct a unique cookie to match this nsm_handle to this monitored
231 * host.  It is passed to the local rpc.statd via NSMPROC_MON, and
232 * returned via NLMPROC_SM_NOTIFY, in the "priv" field of these
233 * requests.
234 *
235 * The NSM protocol requires that these cookies be unique while the
236 * system is running.  We prefer a stronger requirement of making them
237 * unique across reboots.  If user space bugs cause a stale cookie to
238 * be sent to the kernel, it could cause the wrong host to lose its
239 * lock state if cookies were not unique across reboots.
240 *
241 * The cookies are exposed only to local user space via loopback.  They
242 * do not appear on the physical network.  If we want greater security
243 * for some reason, nsm_init_private() could perform a one-way hash to
244 * obscure the contents of the cookie.
245 */
246static void nsm_init_private(struct nsm_handle *nsm)
247{
248	u64 *p = (u64 *)&nsm->sm_priv.data;
249	struct timespec ts;
250	s64 ns;
251
252	ktime_get_ts(&ts);
253	ns = timespec_to_ns(&ts);
254	put_unaligned(ns, p);
255	put_unaligned((unsigned long)nsm, p + 1);
256}
257
258static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap,
259					    const size_t salen,
260					    const char *hostname,
261					    const size_t hostname_len)
262{
263	struct nsm_handle *new;
264
265	new = kzalloc(sizeof(*new) + hostname_len + 1, GFP_KERNEL);
266	if (unlikely(new == NULL))
267		return NULL;
268
269	atomic_set(&new->sm_count, 1);
270	new->sm_name = (char *)(new + 1);
271	memcpy(nsm_addr(new), sap, salen);
272	new->sm_addrlen = salen;
273	nsm_init_private(new);
274
275	if (rpc_ntop(nsm_addr(new), new->sm_addrbuf,
276					sizeof(new->sm_addrbuf)) == 0)
277		(void)snprintf(new->sm_addrbuf, sizeof(new->sm_addrbuf),
278				"unsupported address family");
279	memcpy(new->sm_name, hostname, hostname_len);
280	new->sm_name[hostname_len] = '\0';
281
282	return new;
283}
284
285/**
286 * nsm_get_handle - Find or create a cached nsm_handle
287 * @sap: pointer to socket address of handle to find
288 * @salen: length of socket address
289 * @hostname: pointer to C string containing hostname to find
290 * @hostname_len: length of C string
291 *
292 * Behavior is modulated by the global nsm_use_hostnames variable.
293 *
294 * Returns a cached nsm_handle after bumping its ref count, or
295 * returns a fresh nsm_handle if a handle that matches @sap and/or
296 * @hostname cannot be found in the handle cache.  Returns NULL if
297 * an error occurs.
298 */
299struct nsm_handle *nsm_get_handle(const struct sockaddr *sap,
300				  const size_t salen, const char *hostname,
301				  const size_t hostname_len)
302{
303	struct nsm_handle *cached, *new = NULL;
304
305	if (hostname && memchr(hostname, '/', hostname_len) != NULL) {
306		if (printk_ratelimit()) {
307			printk(KERN_WARNING "Invalid hostname \"%.*s\" "
308					    "in NFS lock request\n",
309				(int)hostname_len, hostname);
310		}
311		return NULL;
312	}
313
314retry:
315	spin_lock(&nsm_lock);
316
317	if (nsm_use_hostnames && hostname != NULL)
318		cached = nsm_lookup_hostname(hostname, hostname_len);
319	else
320		cached = nsm_lookup_addr(sap);
321
322	if (cached != NULL) {
323		atomic_inc(&cached->sm_count);
324		spin_unlock(&nsm_lock);
325		kfree(new);
326		dprintk("lockd: found nsm_handle for %s (%s), "
327				"cnt %d\n", cached->sm_name,
328				cached->sm_addrbuf,
329				atomic_read(&cached->sm_count));
330		return cached;
331	}
332
333	if (new != NULL) {
334		list_add(&new->sm_link, &nsm_handles);
335		spin_unlock(&nsm_lock);
336		dprintk("lockd: created nsm_handle for %s (%s)\n",
337				new->sm_name, new->sm_addrbuf);
338		return new;
339	}
340
341	spin_unlock(&nsm_lock);
342
343	new = nsm_create_handle(sap, salen, hostname, hostname_len);
344	if (unlikely(new == NULL))
345		return NULL;
346	goto retry;
347}
348
349/**
350 * nsm_reboot_lookup - match NLMPROC_SM_NOTIFY arguments to an nsm_handle
351 * @info: pointer to NLMPROC_SM_NOTIFY arguments
352 *
353 * Returns a matching nsm_handle if found in the nsm cache. The returned
354 * nsm_handle's reference count is bumped. Otherwise returns NULL if some
355 * error occurred.
356 */
357struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info)
358{
359	struct nsm_handle *cached;
360
361	spin_lock(&nsm_lock);
362
363	cached = nsm_lookup_priv(&info->priv);
364	if (unlikely(cached == NULL)) {
365		spin_unlock(&nsm_lock);
366		dprintk("lockd: never saw rebooted peer '%.*s' before\n",
367				info->len, info->mon);
368		return cached;
369	}
370
371	atomic_inc(&cached->sm_count);
372	spin_unlock(&nsm_lock);
373
374	dprintk("lockd: host %s (%s) rebooted, cnt %d\n",
375			cached->sm_name, cached->sm_addrbuf,
376			atomic_read(&cached->sm_count));
377	return cached;
378}
379
380/**
381 * nsm_release - Release an NSM handle
382 * @nsm: pointer to handle to be released
383 *
384 */
385void nsm_release(struct nsm_handle *nsm)
386{
387	if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
388		list_del(&nsm->sm_link);
389		spin_unlock(&nsm_lock);
390		dprintk("lockd: destroyed nsm_handle for %s (%s)\n",
391				nsm->sm_name, nsm->sm_addrbuf);
392		kfree(nsm);
393	}
394}
395
396/*
397 * XDR functions for NSM.
398 *
399 * See http://www.opengroup.org/ for details on the Network
400 * Status Monitor wire protocol.
401 */
402
403static int encode_nsm_string(struct xdr_stream *xdr, const char *string)
404{
405	const u32 len = strlen(string);
406	__be32 *p;
407
408	if (unlikely(len > SM_MAXSTRLEN))
409		return -EIO;
410	p = xdr_reserve_space(xdr, sizeof(u32) + len);
411	if (unlikely(p == NULL))
412		return -EIO;
413	xdr_encode_opaque(p, string, len);
414	return 0;
415}
416
417/*
418 * "mon_name" specifies the host to be monitored.
419 */
420static int encode_mon_name(struct xdr_stream *xdr, const struct nsm_args *argp)
421{
422	return encode_nsm_string(xdr, argp->mon_name);
423}
424
425/*
426 * The "my_id" argument specifies the hostname and RPC procedure
427 * to be called when the status manager receives notification
428 * (via the NLMPROC_SM_NOTIFY call) that the state of host "mon_name"
429 * has changed.
430 */
431static int encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp)
432{
433	int status;
434	__be32 *p;
435
436	status = encode_nsm_string(xdr, utsname()->nodename);
437	if (unlikely(status != 0))
438		return status;
439	p = xdr_reserve_space(xdr, 3 * sizeof(u32));
440	if (unlikely(p == NULL))
441		return -EIO;
442	*p++ = htonl(argp->prog);
443	*p++ = htonl(argp->vers);
444	*p++ = htonl(argp->proc);
445	return 0;
446}
447
448/*
449 * The "mon_id" argument specifies the non-private arguments
450 * of an NSMPROC_MON or NSMPROC_UNMON call.
451 */
452static int encode_mon_id(struct xdr_stream *xdr, const struct nsm_args *argp)
453{
454	int status;
455
456	status = encode_mon_name(xdr, argp);
457	if (unlikely(status != 0))
458		return status;
459	return encode_my_id(xdr, argp);
460}
461
462/*
463 * The "priv" argument may contain private information required
464 * by the NSMPROC_MON call. This information will be supplied in the
465 * NLMPROC_SM_NOTIFY call.
466 */
467static int encode_priv(struct xdr_stream *xdr, const struct nsm_args *argp)
468{
469	__be32 *p;
470
471	p = xdr_reserve_space(xdr, SM_PRIV_SIZE);
472	if (unlikely(p == NULL))
473		return -EIO;
474	xdr_encode_opaque_fixed(p, argp->priv->data, SM_PRIV_SIZE);
475	return 0;
476}
477
478static int xdr_enc_mon(struct rpc_rqst *req, __be32 *p,
479		       const struct nsm_args *argp)
480{
481	struct xdr_stream xdr;
482	int status;
483
484	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
485	status = encode_mon_id(&xdr, argp);
486	if (unlikely(status))
487		return status;
488	return encode_priv(&xdr, argp);
489}
490
491static int xdr_enc_unmon(struct rpc_rqst *req, __be32 *p,
492			 const struct nsm_args *argp)
493{
494	struct xdr_stream xdr;
495
496	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
497	return encode_mon_id(&xdr, argp);
498}
499
500static int xdr_dec_stat_res(struct rpc_rqst *rqstp, __be32 *p,
501			    struct nsm_res *resp)
502{
503	struct xdr_stream xdr;
504
505	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
506	p = xdr_inline_decode(&xdr, 2 * sizeof(u32));
507	if (unlikely(p == NULL))
508		return -EIO;
509	resp->status = ntohl(*p++);
510	resp->state = ntohl(*p);
511
512	dprintk("lockd: xdr_dec_stat_res status %d state %d\n",
513			resp->status, resp->state);
514	return 0;
515}
516
517static int xdr_dec_stat(struct rpc_rqst *rqstp, __be32 *p,
518			struct nsm_res *resp)
519{
520	struct xdr_stream xdr;
521
522	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
523	p = xdr_inline_decode(&xdr, sizeof(u32));
524	if (unlikely(p == NULL))
525		return -EIO;
526	resp->state = ntohl(*p);
527
528	dprintk("lockd: xdr_dec_stat state %d\n", resp->state);
529	return 0;
530}
531
532#define SM_my_name_sz	(1+XDR_QUADLEN(SM_MAXSTRLEN))
533#define SM_my_id_sz	(SM_my_name_sz+3)
534#define SM_mon_name_sz	(1+XDR_QUADLEN(SM_MAXSTRLEN))
535#define SM_mon_id_sz	(SM_mon_name_sz+SM_my_id_sz)
536#define SM_priv_sz	(XDR_QUADLEN(SM_PRIV_SIZE))
537#define SM_mon_sz	(SM_mon_id_sz+SM_priv_sz)
538#define SM_monres_sz	2
539#define SM_unmonres_sz	1
540
541static struct rpc_procinfo	nsm_procedures[] = {
542[NSMPROC_MON] = {
543		.p_proc		= NSMPROC_MON,
544		.p_encode	= (kxdrproc_t)xdr_enc_mon,
545		.p_decode	= (kxdrproc_t)xdr_dec_stat_res,
546		.p_arglen	= SM_mon_sz,
547		.p_replen	= SM_monres_sz,
548		.p_statidx	= NSMPROC_MON,
549		.p_name		= "MONITOR",
550	},
551[NSMPROC_UNMON] = {
552		.p_proc		= NSMPROC_UNMON,
553		.p_encode	= (kxdrproc_t)xdr_enc_unmon,
554		.p_decode	= (kxdrproc_t)xdr_dec_stat,
555		.p_arglen	= SM_mon_id_sz,
556		.p_replen	= SM_unmonres_sz,
557		.p_statidx	= NSMPROC_UNMON,
558		.p_name		= "UNMONITOR",
559	},
560};
561
562static struct rpc_version	nsm_version1 = {
563		.number		= 1,
564		.nrprocs	= ARRAY_SIZE(nsm_procedures),
565		.procs		= nsm_procedures
566};
567
568static struct rpc_version *	nsm_version[] = {
569	[1] = &nsm_version1,
570};
571
572static struct rpc_stat		nsm_stats;
573
574static struct rpc_program	nsm_program = {
575		.name		= "statd",
576		.number		= NSM_PROGRAM,
577		.nrvers		= ARRAY_SIZE(nsm_version),
578		.version	= nsm_version,
579		.stats		= &nsm_stats
580};
581