/*
 * Copyright (C) 1996, 1999 Olaf Kirch
 * Modified by Jeffrey A. Uphoff, 1997-1999.
 * Modified by H.J. Lu, 1998.
 * Modified by Lon Hohberger, Oct. 2000
 *   - Bugfix handling client responses.
 *   - Paranoia on NOTIFY_CALLBACK case
 *
 * NSM for Linux.
 */

/*
 * After reboot, notify all hosts on our notify list. In order not to
 * hang statd with delivery to dead hosts, we perform all RPC calls in
 * parallel.
 *
 * It would have been nice to use the portmapper's rmtcall feature,
 * but that's not possible for security reasons (the portmapper would
 * have to forward the call with root privs for most statd's, which
 * it won't if it's worth its money).
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_rmt.h>
#include <time.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>

#include "sm_inter.h"
#include "statd.h"
#include "notlist.h"
#include "ha-callout.h"

#include "nsm.h"
#include "nfsrpc.h"

#if SIZEOF_SOCKLEN_T - 0 == 0
#define socklen_t int
#endif

static int		sockfd = -1;	/* notify socket */

/*
 * Initialize socket used to notify lockd of peer reboots.
 *
 * Returns the file descriptor of the new socket if successful;
 * otherwise returns -1 and logs an error.
 *
 * Lockd rejects such requests if the source port is not privileged.
 * statd_get_socket() must be invoked while statd still holds root
 * privileges in order for the socket to acquire a privileged source
 * port.
 */
int
statd_get_socket(void)
{
	struct sockaddr_in	sin;
	struct servent *se;
	int loopcnt = 100;

	if (sockfd >= 0)
		return sockfd;

	while (loopcnt-- > 0) {

		if (sockfd >= 0) close(sockfd);

		if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
			xlog(L_ERROR, "%s: Can't create socket: %m", __func__);
			return -1;
		}


		memset(&sin, 0, sizeof(sin));
		sin.sin_family = AF_INET;
		sin.sin_addr.s_addr = INADDR_ANY;

		if (bindresvport(sockfd, &sin) < 0) {
			xlog(D_GENERAL, "%s: can't bind to reserved port",
					__func__);
			break;
		}
		se = getservbyport(sin.sin_port, "udp");
		if (se == NULL)
			break;
		/* rather not use that port, try again */
	}
	FD_SET(sockfd, &SVC_FDSET);
	return sockfd;
}

static notify_list *
recv_rply(u_long *portp)
{
	char			msgbuf[NSM_MAXMSGSIZE];
	ssize_t			msglen;
	notify_list		*lp = NULL;
	XDR			xdr;
	struct sockaddr_in	sin;
	socklen_t		alen = (socklen_t)sizeof(sin);
	uint32_t		xid;

	memset(msgbuf, 0, sizeof(msgbuf));
	msglen = recvfrom(sockfd, msgbuf, sizeof(msgbuf), 0,
				(struct sockaddr *)(char *)&sin, &alen);
	if (msglen == (ssize_t)-1) {
		xlog_warn("%s: recvfrom failed: %m", __func__);
		return NULL;
	}

	memset(&xdr, 0, sizeof(xdr));
	xdrmem_create(&xdr, msgbuf, (unsigned int)msglen, XDR_DECODE);
	xid = nsm_parse_reply(&xdr);
	if (xid == 0)
		goto done;
	if (sin.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
		struct in_addr addr = sin.sin_addr;
		char buf[INET_ADDRSTRLEN];

		xlog_warn("%s: Unrecognized reply from %s", __func__,
				inet_ntop(AF_INET, &addr, buf,
						(socklen_t)sizeof(buf)));
		goto done;
	}

	for (lp = notify; lp != NULL; lp = lp->next) {
		/* LH - this was a bug... it should have been checking
		 * the xid from the response message from the client,
		 * not the static, internal xid */
		if (lp->xid != xid)
			continue;
		if (lp->port == 0)
			*portp = nsm_recv_getport(&xdr);
		break;
	}

done:
	xdr_destroy(&xdr);
	return lp;
}

/*
 * Notify operation for a single list entry
 */
static int
process_entry(notify_list *lp)
{
	struct sockaddr_in	sin;

	if (NL_TIMES(lp) == 0) {
		xlog(D_GENERAL, "%s: Cannot notify localhost, giving up",
				__func__);
		return 0;
	}

	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port   = lp->port;
	/* LH - moved address into switch */

	/* __FORCE__ loopback for callbacks to lockd ... */
	/* Just in case we somehow ignored it thus far */
	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

	if (sin.sin_port == 0)
		lp->xid = nsm_xmit_getport(sockfd, &sin,
					(rpcprog_t)NL_MY_PROG(lp),
					(rpcvers_t)NL_MY_VERS(lp));
	else {
		struct mon m;

		memcpy(m.priv, NL_PRIV(lp), SM_PRIV_SIZE);

		m.mon_id.mon_name = NL_MON_NAME(lp);
		m.mon_id.my_id.my_name = NULL;
		m.mon_id.my_id.my_prog = NL_MY_PROG(lp);
		m.mon_id.my_id.my_vers = NL_MY_VERS(lp);
		m.mon_id.my_id.my_proc = NL_MY_PROC(lp);

		lp->xid = nsm_xmit_nlmcall(sockfd,
				(struct sockaddr *)(char *)&sin,
				(socklen_t)sizeof(sin), &m, NL_STATE(lp));
	}
	if (lp->xid == 0) {
		xlog_warn("%s: failed to notify port %d",
				__func__, ntohs(lp->port));
	}
	NL_TIMES(lp) -= 1;

	return 1;
}

/*
 * Process a datagram received on the notify socket
 */
int
process_reply(FD_SET_TYPE *rfds)
{
	notify_list		*lp;
	u_long			port;

	if (sockfd == -1 || !FD_ISSET(sockfd, rfds))
		return 0;

	if (!(lp = recv_rply(&port)))
		return 1;

	if (lp->port == 0) {
		if (port != 0) {
			lp->port = htons((unsigned short) port);
			process_entry(lp);
			NL_WHEN(lp) = time(NULL) + NOTIFY_TIMEOUT;
			nlist_remove(&notify, lp);
			nlist_insert_timer(&notify, lp);
			return 1;
		}
		xlog_warn("%s: service %d not registered on localhost",
			__func__, NL_MY_PROG(lp));
	} else {
		xlog(D_GENERAL, "%s: Callback to %s (for %d) succeeded",
			__func__, NL_MY_NAME(lp), NL_MON_NAME(lp));
	}
	nlist_free(&notify, lp);
	return 1;
}

/*
 * Process a notify list, either for notifying remote hosts after reboot
 * or for calling back (local) statd clients when the remote has notified
 * us of a crash. 
 */
int
process_notify_list(void)
{
	notify_list	*entry;
	time_t		now;

	while ((entry = notify) != NULL && NL_WHEN(entry) < time(&now)) {
		if (process_entry(entry)) {
			NL_WHEN(entry) = time(NULL) + NOTIFY_TIMEOUT;
			nlist_remove(&notify, entry);
			nlist_insert_timer(&notify, entry);
		} else {
			xlog(L_ERROR,
				"%s: Can't callback %s (%d,%d), giving up",
					__func__,
					NL_MY_NAME(entry),
					NL_MY_PROG(entry),
					NL_MY_VERS(entry));
			nlist_free(&notify, entry);
		}
	}

	return 1;
}
