/*
 * Enough portmapper functionality that mount doesn't hang trying
 * to start lockd.  Enables nfsroot with locking functionality.
 *
 * Note: the kernel will only speak to the local portmapper
 * using RPC over UDP.
 */

#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>

#include "dummypmap.h"
#include "sunrpc.h"

extern const char *progname;

struct portmap_args {
	uint32_t program;
	uint32_t version;
	uint32_t proto;
	uint32_t port;
};

struct portmap_call {
	struct rpc_call rpc;
	struct portmap_args args;
};

struct portmap_reply {
	struct rpc_reply rpc;
	uint32_t port;
};

static int bind_portmap(void)
{
	int sock = socket(PF_INET, SOCK_DGRAM, 0);
	struct sockaddr_in sin;

	if (sock < 0)
		return -1;

	memset(&sin, 0, sizeof sin);
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = htonl(0x7f000001);	/* 127.0.0.1 */
	sin.sin_port = htons(RPC_PMAP_PORT);
	if (bind(sock, (struct sockaddr *)&sin, sizeof sin) < 0) {
		int err = errno;
		close(sock);
		errno = err;
		return -1;
	}

	return sock;
}

static const char *protoname(uint32_t proto)
{
	switch (ntohl(proto)) {
	case IPPROTO_TCP:
		return "tcp";
	case IPPROTO_UDP:
		return "udp";
	default:
		return NULL;
	}
}

static void *get_auth(struct rpc_auth *auth)
{
	switch (ntohl(auth->flavor)) {
	case AUTH_NULL:
	/* Fallthrough */
	case AUTH_UNIX:
		return (char *)&auth->body + ntohl(auth->len);
	default:
		return NULL;
	}
}

static int check_unix_cred(struct rpc_auth *cred)
{
	uint32_t len;
	int quad_len;
	uint32_t node_name_len;
	int quad_name_len;
	uint32_t *base;
	uint32_t *pos;
	int ret = -1;

	len = ntohl(cred->len);
	quad_len = (len + 3) >> 2;
	if (quad_len < 6)
		/* Malformed creds */
		goto out;

	base = pos = cred->body;

	/* Skip timestamp */
	pos++;

	/* Skip node name: only localhost can succeed. */
	node_name_len = ntohl(*pos++);
	quad_name_len = (node_name_len + 3) >> 2;
	if (pos + quad_name_len + 3 > base + quad_len)
		/* Malformed creds */
		goto out;
	pos += quad_name_len;

	/* uid must be 0 */
	if (*pos++ != 0)
		goto out;

	/* gid must be 0 */
	if (*pos++ != 0)
		goto out;

	/* Skip remaining gids */
	ret = 0;

out:
	return ret;
}

static int check_cred(struct rpc_auth *cred)
{
	switch (ntohl(cred->flavor)) {
	case AUTH_NULL:
		return 0;
	case AUTH_UNIX:
		return check_unix_cred(cred);
	default:
		return -1;
	}
}

static int check_vrf(struct rpc_auth *vrf)
{
	return (vrf->flavor == htonl(AUTH_NULL)) ? 0 : -1;
}

static int dummy_portmap(int sock, FILE *portmap_file)
{
	struct sockaddr_in sin;
	int pktlen, addrlen;
	unsigned char pkt[65536];	/* Max UDP packet size */
	/* RPC UDP packets do not include TCP fragment size */
	struct rpc_call *rpc = (struct rpc_call *) &pkt[-4];
	struct rpc_auth *cred;
	struct rpc_auth *vrf;
	struct portmap_args *args;
	struct portmap_reply rply;

	for (;;) {
		addrlen = sizeof sin;
		pktlen = recvfrom(sock, &pkt, sizeof pkt, 0,
				  (struct sockaddr *)&sin, &addrlen);

		if (pktlen < 0) {
			if (errno == EINTR)
				continue;

			return -1;
		}

		/* +4 to skip the TCP fragment header */
		if (pktlen + 4 < sizeof(struct portmap_call))
			continue;	/* Bad packet */

		if (rpc->hdr.udp.msg_type != htonl(RPC_CALL))
			continue;	/* Bad packet */

		memset(&rply, 0, sizeof rply);

		rply.rpc.hdr.udp.xid = rpc->hdr.udp.xid;
		rply.rpc.hdr.udp.msg_type = htonl(RPC_REPLY);

		cred = (struct rpc_auth *) &rpc->cred_flavor;
		if (rpc->rpc_vers != htonl(2)) {
			rply.rpc.reply_state = htonl(REPLY_DENIED);
			/* state <- RPC_MISMATCH == 0 */
		} else if (rpc->program != htonl(PORTMAP_PROGRAM)) {
			rply.rpc.reply_state = htonl(PROG_UNAVAIL);
		} else if (rpc->prog_vers != htonl(2)) {
			rply.rpc.reply_state = htonl(PROG_MISMATCH);
		} else if (!(vrf = get_auth(cred)) ||
			   (char *)vrf > (char *)pkt + pktlen - 8 - sizeof(*args) ||
			   !(args = get_auth(vrf)) ||
			   (char *)args > (char *)pkt + pktlen - sizeof(*args) ||
			   check_cred(cred) || check_vrf(vrf)) {
			/* Can't deal with credentials data; the kernel
			   won't send them */
			rply.rpc.reply_state = htonl(SYSTEM_ERR);
		} else {
			switch (ntohl(rpc->proc)) {
			case PMAP_PROC_NULL:
				break;
			case PMAP_PROC_SET:
				if (args->proto == htonl(IPPROTO_TCP) ||
				    args->proto == htonl(IPPROTO_UDP)) {
					if (portmap_file)
						fprintf(portmap_file,
							"%u %u %s %u\n",
							ntohl(args->program),
							ntohl(args->version),
							protoname(args->proto),
							ntohl(args->port));
					rply.port = htonl(1);	/* TRUE = success */
				}
				break;
			case PMAP_PROC_UNSET:
				rply.port = htonl(1);	/* TRUE = success */
				break;
			case PMAP_PROC_GETPORT:
				break;
			case PMAP_PROC_DUMP:
				break;
			default:
				rply.rpc.reply_state = htonl(PROC_UNAVAIL);
				break;
			}
		}

		sendto(sock, &rply.rpc.hdr.udp, sizeof rply - 4, 0,
		       (struct sockaddr *)&sin, addrlen);
	}
}

pid_t start_dummy_portmap(const char *file)
{
	FILE *portmap_filep;
	int sock;
	pid_t spoof_portmap;

	portmap_filep = fopen(file, "w");
	if (!portmap_filep) {
		fprintf(stderr, "%s: cannot write portmap file: %s\n",
			progname, file);
		return -1;
	}

	sock = bind_portmap();
	if (sock == -1) {
		if (errno == EINVAL || errno == EADDRINUSE)
			return 0;	/* Assume not needed */
		else {
			fclose(portmap_filep);
			fprintf(stderr, "%s: portmap spoofing failed\n",
				progname);
			return -1;
		}
	}

	spoof_portmap = fork();
	if (spoof_portmap == -1) {
		fclose(portmap_filep);
		fprintf(stderr, "%s: cannot fork\n", progname);
		return -1;
	} else if (spoof_portmap == 0) {
		/* Child process */
		dummy_portmap(sock, portmap_filep);
		_exit(255);	/* Error */
	} else {
		/* Parent process */
		close(sock);
		return spoof_portmap;
	}
}
