/*
 * 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.
 *
 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
 */
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/slab.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <net/rose.h>

static void rose_ftimer_expiry(unsigned long);
static void rose_t0timer_expiry(unsigned long);

static void rose_transmit_restart_confirmation(struct rose_neigh *neigh);
static void rose_transmit_restart_request(struct rose_neigh *neigh);

void rose_start_ftimer(struct rose_neigh *neigh)
{
	del_timer(&neigh->ftimer);

	neigh->ftimer.data     = (unsigned long)neigh;
	neigh->ftimer.function = &rose_ftimer_expiry;
	neigh->ftimer.expires  =
		jiffies + msecs_to_jiffies(sysctl_rose_link_fail_timeout);

	add_timer(&neigh->ftimer);
}

static void rose_start_t0timer(struct rose_neigh *neigh)
{
	del_timer(&neigh->t0timer);

	neigh->t0timer.data     = (unsigned long)neigh;
	neigh->t0timer.function = &rose_t0timer_expiry;
	neigh->t0timer.expires  =
		jiffies + msecs_to_jiffies(sysctl_rose_restart_request_timeout);

	add_timer(&neigh->t0timer);
}

void rose_stop_ftimer(struct rose_neigh *neigh)
{
	del_timer(&neigh->ftimer);
}

void rose_stop_t0timer(struct rose_neigh *neigh)
{
	del_timer(&neigh->t0timer);
}

int rose_ftimer_running(struct rose_neigh *neigh)
{
	return timer_pending(&neigh->ftimer);
}

static int rose_t0timer_running(struct rose_neigh *neigh)
{
	return timer_pending(&neigh->t0timer);
}

static void rose_ftimer_expiry(unsigned long param)
{
}

static void rose_t0timer_expiry(unsigned long param)
{
	struct rose_neigh *neigh = (struct rose_neigh *)param;

	rose_transmit_restart_request(neigh);

	neigh->dce_mode = 0;

	rose_start_t0timer(neigh);
}

/*
 *	Interface to ax25_send_frame. Changes my level 2 callsign depending
 *	on whether we have a global ROSE callsign or use the default port
 *	callsign.
 */
static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh)
{
	ax25_address *rose_call;
	ax25_cb *ax25s;

	if (ax25cmp(&rose_callsign, &null_ax25_address) == 0)
		rose_call = (ax25_address *)neigh->dev->dev_addr;
	else
		rose_call = &rose_callsign;

	ax25s = neigh->ax25;
	neigh->ax25 = ax25_send_frame(skb, 260, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);
	if (ax25s)
		ax25_cb_put(ax25s);

	return neigh->ax25 != NULL;
}

/*
 *	Interface to ax25_link_up. Changes my level 2 callsign depending
 *	on whether we have a global ROSE callsign or use the default port
 *	callsign.
 */
static int rose_link_up(struct rose_neigh *neigh)
{
	ax25_address *rose_call;
	ax25_cb *ax25s;

	if (ax25cmp(&rose_callsign, &null_ax25_address) == 0)
		rose_call = (ax25_address *)neigh->dev->dev_addr;
	else
		rose_call = &rose_callsign;

	ax25s = neigh->ax25;
	neigh->ax25 = ax25_find_cb(rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);
	if (ax25s)
		ax25_cb_put(ax25s);

	return neigh->ax25 != NULL;
}

/*
 *	This handles all restart and diagnostic frames.
 */
void rose_link_rx_restart(struct sk_buff *skb, struct rose_neigh *neigh, unsigned short frametype)
{
	struct sk_buff *skbn;

	switch (frametype) {
	case ROSE_RESTART_REQUEST:
		rose_stop_t0timer(neigh);
		neigh->restarted = 1;
		neigh->dce_mode  = (skb->data[3] == ROSE_DTE_ORIGINATED);
		rose_transmit_restart_confirmation(neigh);
		break;

	case ROSE_RESTART_CONFIRMATION:
		rose_stop_t0timer(neigh);
		neigh->restarted = 1;
		break;

	case ROSE_DIAGNOSTIC:
		pr_warn("ROSE: received diagnostic #%d - %3ph\n", skb->data[3],
			skb->data + 4);
		break;

	default:
		printk(KERN_WARNING "ROSE: received unknown %02X with LCI 000\n", frametype);
		break;
	}

	if (neigh->restarted) {
		while ((skbn = skb_dequeue(&neigh->queue)) != NULL)
			if (!rose_send_frame(skbn, neigh))
				kfree_skb(skbn);
	}
}

/*
 *	This routine is called when a Restart Request is needed
 */
static void rose_transmit_restart_request(struct rose_neigh *neigh)
{
	struct sk_buff *skb;
	unsigned char *dptr;
	int len;

	len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 3;

	if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
		return;

	skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN);

	dptr = skb_put(skb, ROSE_MIN_LEN + 3);

	*dptr++ = AX25_P_ROSE;
	*dptr++ = ROSE_GFI;
	*dptr++ = 0x00;
	*dptr++ = ROSE_RESTART_REQUEST;
	*dptr++ = ROSE_DTE_ORIGINATED;
	*dptr++ = 0;

	if (!rose_send_frame(skb, neigh))
		kfree_skb(skb);
}

/*
 * This routine is called when a Restart Confirmation is needed
 */
static void rose_transmit_restart_confirmation(struct rose_neigh *neigh)
{
	struct sk_buff *skb;
	unsigned char *dptr;
	int len;

	len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 1;

	if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
		return;

	skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN);

	dptr = skb_put(skb, ROSE_MIN_LEN + 1);

	*dptr++ = AX25_P_ROSE;
	*dptr++ = ROSE_GFI;
	*dptr++ = 0x00;
	*dptr++ = ROSE_RESTART_CONFIRMATION;

	if (!rose_send_frame(skb, neigh))
		kfree_skb(skb);
}

/*
 * This routine is called when a Clear Request is needed outside of the context
 * of a connected socket.
 */
void rose_transmit_clear_request(struct rose_neigh *neigh, unsigned int lci, unsigned char cause, unsigned char diagnostic)
{
	struct sk_buff *skb;
	unsigned char *dptr;
	int len;

	len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 3;

	if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
		return;

	skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN);

	dptr = skb_put(skb, ROSE_MIN_LEN + 3);

	*dptr++ = AX25_P_ROSE;
	*dptr++ = ((lci >> 8) & 0x0F) | ROSE_GFI;
	*dptr++ = ((lci >> 0) & 0xFF);
	*dptr++ = ROSE_CLEAR_REQUEST;
	*dptr++ = cause;
	*dptr++ = diagnostic;

	if (!rose_send_frame(skb, neigh))
		kfree_skb(skb);
}

void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh)
{
	unsigned char *dptr;

	if (neigh->loopback) {
		rose_loopback_queue(skb, neigh);
		return;
	}

	if (!rose_link_up(neigh))
		neigh->restarted = 0;

	dptr = skb_push(skb, 1);
	*dptr++ = AX25_P_ROSE;

	if (neigh->restarted) {
		if (!rose_send_frame(skb, neigh))
			kfree_skb(skb);
	} else {
		skb_queue_tail(&neigh->queue, skb);

		if (!rose_t0timer_running(neigh)) {
			rose_transmit_restart_request(neigh);
			neigh->dce_mode = 0;
			rose_start_t0timer(neigh);
		}
	}
}
