/* RxRPC remote transport endpoint management
 *
 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

#include <linux/module.h>
#include <linux/net.h>
#include <linux/skbuff.h>
#include <linux/udp.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/icmp.h>
#include <linux/slab.h>
#include <net/sock.h>
#include <net/af_rxrpc.h>
#include <net/ip.h>
#include <net/route.h>
#include "ar-internal.h"

static LIST_HEAD(rxrpc_peers);
static DEFINE_RWLOCK(rxrpc_peer_lock);
static DECLARE_WAIT_QUEUE_HEAD(rxrpc_peer_wq);

static void rxrpc_destroy_peer(struct work_struct *work);

/*
 * assess the MTU size for the network interface through which this peer is
 * reached
 */
static void rxrpc_assess_MTU_size(struct rxrpc_peer *peer)
{
	struct rtable *rt;
	struct flowi4 fl4;

	peer->if_mtu = 1500;

	rt = ip_route_output_ports(&init_net, &fl4, NULL,
				   peer->srx.transport.sin.sin_addr.s_addr, 0,
				   htons(7000), htons(7001),
				   IPPROTO_UDP, 0, 0);
	if (IS_ERR(rt)) {
		_leave(" [route err %ld]", PTR_ERR(rt));
		return;
	}

	peer->if_mtu = dst_mtu(&rt->dst);
	dst_release(&rt->dst);

	_leave(" [if_mtu %u]", peer->if_mtu);
}

/*
 * allocate a new peer
 */
static struct rxrpc_peer *rxrpc_alloc_peer(struct sockaddr_rxrpc *srx,
					   gfp_t gfp)
{
	struct rxrpc_peer *peer;

	_enter("");

	peer = kzalloc(sizeof(struct rxrpc_peer), gfp);
	if (peer) {
		INIT_WORK(&peer->destroyer, &rxrpc_destroy_peer);
		INIT_LIST_HEAD(&peer->link);
		INIT_LIST_HEAD(&peer->error_targets);
		spin_lock_init(&peer->lock);
		atomic_set(&peer->usage, 1);
		peer->debug_id = atomic_inc_return(&rxrpc_debug_id);
		memcpy(&peer->srx, srx, sizeof(*srx));

		rxrpc_assess_MTU_size(peer);
		peer->mtu = peer->if_mtu;

		if (srx->transport.family == AF_INET) {
			peer->hdrsize = sizeof(struct iphdr);
			switch (srx->transport_type) {
			case SOCK_DGRAM:
				peer->hdrsize += sizeof(struct udphdr);
				break;
			default:
				BUG();
				break;
			}
		} else {
			BUG();
		}

		peer->hdrsize += sizeof(struct rxrpc_header);
		peer->maxdata = peer->mtu - peer->hdrsize;
	}

	_leave(" = %p", peer);
	return peer;
}

/*
 * obtain a remote transport endpoint for the specified address
 */
struct rxrpc_peer *rxrpc_get_peer(struct sockaddr_rxrpc *srx, gfp_t gfp)
{
	struct rxrpc_peer *peer, *candidate;
	const char *new = "old";
	int usage;

	_enter("{%d,%d,%pI4+%hu}",
	       srx->transport_type,
	       srx->transport_len,
	       &srx->transport.sin.sin_addr,
	       ntohs(srx->transport.sin.sin_port));

	/* search the peer list first */
	read_lock_bh(&rxrpc_peer_lock);
	list_for_each_entry(peer, &rxrpc_peers, link) {
		_debug("check PEER %d { u=%d t=%d l=%d }",
		       peer->debug_id,
		       atomic_read(&peer->usage),
		       peer->srx.transport_type,
		       peer->srx.transport_len);

		if (atomic_read(&peer->usage) > 0 &&
		    peer->srx.transport_type == srx->transport_type &&
		    peer->srx.transport_len == srx->transport_len &&
		    memcmp(&peer->srx.transport,
			   &srx->transport,
			   srx->transport_len) == 0)
			goto found_extant_peer;
	}
	read_unlock_bh(&rxrpc_peer_lock);

	/* not yet present - create a candidate for a new record and then
	 * redo the search */
	candidate = rxrpc_alloc_peer(srx, gfp);
	if (!candidate) {
		_leave(" = -ENOMEM");
		return ERR_PTR(-ENOMEM);
	}

	write_lock_bh(&rxrpc_peer_lock);

	list_for_each_entry(peer, &rxrpc_peers, link) {
		if (atomic_read(&peer->usage) > 0 &&
		    peer->srx.transport_type == srx->transport_type &&
		    peer->srx.transport_len == srx->transport_len &&
		    memcmp(&peer->srx.transport,
			   &srx->transport,
			   srx->transport_len) == 0)
			goto found_extant_second;
	}

	/* we can now add the new candidate to the list */
	peer = candidate;
	candidate = NULL;
	usage = atomic_read(&peer->usage);

	list_add_tail(&peer->link, &rxrpc_peers);
	write_unlock_bh(&rxrpc_peer_lock);
	new = "new";

success:
	_net("PEER %s %d {%d,%u,%pI4+%hu}",
	     new,
	     peer->debug_id,
	     peer->srx.transport_type,
	     peer->srx.transport.family,
	     &peer->srx.transport.sin.sin_addr,
	     ntohs(peer->srx.transport.sin.sin_port));

	_leave(" = %p {u=%d}", peer, usage);
	return peer;

	/* we found the peer in the list immediately */
found_extant_peer:
	usage = atomic_inc_return(&peer->usage);
	read_unlock_bh(&rxrpc_peer_lock);
	goto success;

	/* we found the peer on the second time through the list */
found_extant_second:
	usage = atomic_inc_return(&peer->usage);
	write_unlock_bh(&rxrpc_peer_lock);
	kfree(candidate);
	goto success;
}

/*
 * find the peer associated with a packet
 */
struct rxrpc_peer *rxrpc_find_peer(struct rxrpc_local *local,
				   __be32 addr, __be16 port)
{
	struct rxrpc_peer *peer;

	_enter("");

	/* search the peer list */
	read_lock_bh(&rxrpc_peer_lock);

	if (local->srx.transport.family == AF_INET &&
	    local->srx.transport_type == SOCK_DGRAM
	    ) {
		list_for_each_entry(peer, &rxrpc_peers, link) {
			if (atomic_read(&peer->usage) > 0 &&
			    peer->srx.transport_type == SOCK_DGRAM &&
			    peer->srx.transport.family == AF_INET &&
			    peer->srx.transport.sin.sin_port == port &&
			    peer->srx.transport.sin.sin_addr.s_addr == addr)
				goto found_UDP_peer;
		}

		goto new_UDP_peer;
	}

	read_unlock_bh(&rxrpc_peer_lock);
	_leave(" = -EAFNOSUPPORT");
	return ERR_PTR(-EAFNOSUPPORT);

found_UDP_peer:
	_net("Rx UDP DGRAM from peer %d", peer->debug_id);
	atomic_inc(&peer->usage);
	read_unlock_bh(&rxrpc_peer_lock);
	_leave(" = %p", peer);
	return peer;

new_UDP_peer:
	_net("Rx UDP DGRAM from NEW peer %d", peer->debug_id);
	read_unlock_bh(&rxrpc_peer_lock);
	_leave(" = -EBUSY [new]");
	return ERR_PTR(-EBUSY);
}

/*
 * release a remote transport endpoint
 */
void rxrpc_put_peer(struct rxrpc_peer *peer)
{
	_enter("%p{u=%d}", peer, atomic_read(&peer->usage));

	ASSERTCMP(atomic_read(&peer->usage), >, 0);

	if (likely(!atomic_dec_and_test(&peer->usage))) {
		_leave(" [in use]");
		return;
	}

	rxrpc_queue_work(&peer->destroyer);
	_leave("");
}

/*
 * destroy a remote transport endpoint
 */
static void rxrpc_destroy_peer(struct work_struct *work)
{
	struct rxrpc_peer *peer =
		container_of(work, struct rxrpc_peer, destroyer);

	_enter("%p{%d}", peer, atomic_read(&peer->usage));

	write_lock_bh(&rxrpc_peer_lock);
	list_del(&peer->link);
	write_unlock_bh(&rxrpc_peer_lock);

	_net("DESTROY PEER %d", peer->debug_id);
	kfree(peer);

	if (list_empty(&rxrpc_peers))
		wake_up_all(&rxrpc_peer_wq);
	_leave("");
}

/*
 * preemptively destroy all the peer records from a transport endpoint rather
 * than waiting for them to time out
 */
void __exit rxrpc_destroy_all_peers(void)
{
	DECLARE_WAITQUEUE(myself,current);

	_enter("");

	/* we simply have to wait for them to go away */
	if (!list_empty(&rxrpc_peers)) {
		set_current_state(TASK_UNINTERRUPTIBLE);
		add_wait_queue(&rxrpc_peer_wq, &myself);

		while (!list_empty(&rxrpc_peers)) {
			schedule();
			set_current_state(TASK_UNINTERRUPTIBLE);
		}

		remove_wait_queue(&rxrpc_peer_wq, &myself);
		set_current_state(TASK_RUNNING);
	}

	_leave("");
}
