/*
 *	AX.25 release 027
 *
 *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
 *	releases, misbehave and/or generally screw up. It might even work. 
 *
 *	This code REQUIRES 1.3.0 or higher/ NET3.024
 *
 *	This module:
 *		This module 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.
 *
 *	Other kernels modules in this kit are generally BSD derived. See the copyright headers.
 *
 *
 *	History
 *	AX.25 006	Alan(GW4PTS)		Nearly died of shock - its working 8-)
 *	AX.25 007	Alan(GW4PTS)		Removed the silliest bugs
 *	AX.25 008	Alan(GW4PTS)		Cleaned up, fixed a few state machine problems, added callbacks
 *	AX.25 009	Alan(GW4PTS)		Emergency patch kit to fix memory corruption
 * 	AX.25 010	Alan(GW4PTS)		Added RAW sockets/Digipeat.
 *	AX.25 011	Alan(GW4PTS)		RAW socket and datagram fixes (thanks) - Raw sendto now gets PID right
 *						datagram sendto uses correct target address.
 *	AX.25 012	Alan(GW4PTS)		Correct incoming connection handling, send DM to failed connects.
 *						Use skb->data not skb+1. Support sk->priority correctly.
 *						Correct receive on SOCK_DGRAM.
 *	AX.25 013	Alan(GW4PTS)		Send DM to all unknown frames, missing initialiser fixed
 *						Leave spare SSID bits set (DAMA etc) - thanks for bug report,
 *						removed device registration (its not used or needed). Clean up for
 *						gcc 2.5.8. PID to AX25_P_
 *	AX.25 014	Alan(GW4PTS)		Cleanup and NET3 merge
 *	AX.25 015	Alan(GW4PTS)		Internal test version.
 *	AX.25 016	Alan(GW4PTS)		Semi Internal version for PI card
 *						work.
 *	AX.25 017	Alan(GW4PTS)		Fixed some small bugs reported by
 *						G4KLX
 *	AX.25 018	Alan(GW4PTS)		Fixed a small error in SOCK_DGRAM
 *	AX.25 019	Alan(GW4PTS)		Clean ups for the non INET kernel and device ioctls in AX.25
 *	AX.25 020	Jonathan(G4KLX)		/proc support and other changes.
 *	AX.25 021	Alan(GW4PTS)		Added AX25_T1, AX25_N2, AX25_T3 as requested.
 *	AX.25 022	Jonathan(G4KLX)		More work on the ax25 auto router and /proc improved (again)!
 *			Alan(GW4PTS)		Added TIOCINQ/OUTQ
 *
 *	To do:
 *		Support use as digipeater, including an on/off ioctl
 *		Restructure the ax25_input code to be cleaner/faster and copy only when needed
 *		Consider better arbitary protocol support.
 *		NETROM!!! - This will need the kernel layering done and someone to provide 
 *		legally obtained docs, or efficient good netrom code for references. Don't say
 *		KA9Q - the KA9Q netrom code is broken, the Wampes code is ok but too inefficient,
 *		and both raise possible copyright complexities
 */
 
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include "ax25.h"
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include "sock.h"
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/termios.h>	/* For TIOCINQ/OUTQ */
#include <linux/mm.h>
#include <linux/interrupt.h>

#include "ip.h"
#include "arp.h"

#ifdef CONFIG_NETROM
#include "netrom.h"
#endif

#ifdef CONFIG_AX25

/**********************************************************************************************************************\
*														       *
*						Handlers for the socket list.					       *
*														       *
\**********************************************************************************************************************/

static ax25_socket *volatile ax25_socket_list=NULL;

/* ax25 -> ascii conversion */

char *ax2asc(ax25_address *a)
{
	static char buf[11];
	char c, *s;
	int n;

	for (n = 0, s = buf; n < 6; n++)
	{
		c = (a->ax25_call[n] >> 1) & 0x7F;

		if (c != ' ') *s++ = c;
	}
	
	*s++ = '-';

	if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9)
	{
		*s++ = '1';
		n -= 10;
	}
	
	*s++ = n + '0';
	*s++ = '\0';

	return(buf);

}

/* Compare two ax.25 addresses */

int ax25cmp(ax25_address *a, ax25_address *b)
{
	int ct=0;
	while(ct<6)
	{
		if((a->ax25_call[ct]&0xFE)!=(b->ax25_call[ct]&0xFE))	/* Clean off repeater bits */
			return 1;
		ct++;
	}
 	if((a->ax25_call[ct]&0x1E)==(b->ax25_call[ct]&0x1E))	/* SSID without control bit */
 		return 0;
 	return 2;			/* Partial match */
}

/*
 *	Note: Sockets may not be removed _during_ an interrupt or inet_bh
 *	handler using this technique. They can be added although we do not
 *	use this facility.
 */
 
static void ax25_remove_socket(ax25_socket *sk)
{
	ax25_socket *s;
	
	cli();
	s=ax25_socket_list;
	if(s==sk)
	{
		ax25_socket_list=s->next;
		sti();
		return;
	}
	while(s && s->next)
	{
		if(s->next==sk)
		{
			s->next=sk->next;
			sti();
			return;
		}
		s=s->next;
	}
	sti();
}

static void ax25_insert_socket(ax25_socket *sk)
{
	cli();
	sk->next=ax25_socket_list;
	ax25_socket_list=sk;
	sti();
}

static ax25_socket *ax25_find_listener(ax25_address *addr, int type)
{
	ax25_socket *s;
	s=ax25_socket_list;
	while(s)
	{
		if(ax25cmp(&s->opt.ax25.source_addr,addr)==0 && s->type==type && s->state==TCP_LISTEN)
		{
			return(s);
		}
		s=s->next;
	}
	return(NULL);
}

static ax25_socket *ax25_find_socket(ax25_address *my_addr, ax25_address *dest_addr, int type)
{
	ax25_socket *s;
	s=ax25_socket_list;
	while(s)
	{
		if(ax25cmp(&s->opt.ax25.source_addr,my_addr)==0 && ax25cmp(&s->opt.ax25.dest_addr,dest_addr)==0 && s->type==type)
		{
			return(s);
		}
		s=s->next;
	}
	return(NULL);
}


/*
 *	Look for any matching address - RAW sockets can bind to arbitary names
 */
 
static ax25_socket *ax25_addr_match(ax25_address *addr)
{
	ax25_socket *s=ax25_socket_list;
	while(s)
	{
		if(ax25cmp(&s->opt.ax25.source_addr,addr)==0 && s->type==SOCK_RAW)
			return s;
		s=s->next;
	}
	return NULL;
}

static void ax25_send_to_raw(ax25_socket *sk, sk_buff *skb, int proto)
{
	sk_buff *copy;
	
	while(sk!=NULL)
	{
		if(sk->type==SOCK_RAW && sk->protocol==proto && sk->rmem_alloc<=sk->rcvbuf)
		{
			copy=skb_clone(skb,GFP_ATOMIC);
			if(copy==NULL)
				return;
			copy->sk=sk;
			sk->rmem_alloc+=copy->mem_len;
			skb_queue_tail(&sk->receive_queue,copy);
			if(!sk->dead)
				sk->data_ready(sk,skb->len-2);
		}
		sk=sk->next;
	}
}	

/*
 *	This is only called from user mode. Thus it protects itself against
 *	interrupt users but doesn't worry about being called during work.
 *	Once it is removed from the queue no interrupt or bottom half will
 *	touch it and we are (fairly 8-) ) safe.
 */
 
void ax25_destroy_socket(ax25_socket *sk)	/* Not static as its used by the timer */
{
	sk_buff *skb;
	
	KILL_TIMER(sk);
	
	ax25_remove_socket(sk);
	ax25_init_vars(sk);			/* Flush the retransmit queue and send queue */
	
	while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
	{
		if(skb->sk!=sk)			/* A pending connection */
		{
			skb->sk->dead=1;	/* Queue the unaccepted socket for death */
			SET_TIMER(skb->sk);
			skb->sk->opt.ax25.state=DISCONNECTED;
		}
		kfree_skb(skb,FREE_READ);
	}
	
	if(sk->opt.ax25.digipeat!=NULL)
		kfree_s(sk->opt.ax25.digipeat,sizeof(ax25_digi));
	
	kfree_s(sk,sizeof(*sk));
}

/*******************************************************************************************************************\
*														    *
*		Driver encapsulation support: Moved out of SLIP because a) it should be here 			    *
*									b) for HDLC cards			    *
*														    *
\*******************************************************************************************************************/

/*
 *	Shove an AX.25 UI header on an IP packet and handle ARP
 */

#ifdef CONFIG_INET
 
int ax25_encapsulate(unsigned char *buff,struct device *dev, unsigned short type, void *daddr,
		void *saddr, unsigned len, sk_buff *skb)
{
  	/* header is an AX.25 UI frame from us to them */
  	
  	*buff++=0;	/* KISS DATA */
  	
	if(daddr)
		memcpy(buff,daddr,dev->addr_len);		/* Address specified */
  	buff[6]&=~LAPB_C;
  	buff[6]&=~LAPB_E;
  	buff[6]|=SSID_SPARE;
  	buff+=7;
  	if(saddr)
  		memcpy(buff,saddr,dev->addr_len);
  	else
  		memcpy(buff,dev->dev_addr,dev->addr_len);
  	buff[6]&=~LAPB_C;
  	buff[6]|=LAPB_E|SSID_SPARE;
  	buff+=7;
  	*buff++=LAPB_UI;	/* UI */
  	/* Append a suitable AX.25 PID */
  	switch(type)
  	{
  		case ETH_P_IP:
  			*buff++=AX25_P_IP;	/* AX25 IP */
 			break;
  		case ETH_P_ARP:
  			*buff++=AX25_P_ARP;
  			break;
  		default:
  			*buff++=0;
 	}
	
	if(daddr)  	
	  	return (17);

	return(-17);	/* Unfinished header */
}

int ax25_rebuild_header(unsigned char *bp, struct device *dev, unsigned long dest, sk_buff *skb)
{
  	if(arp_find(bp+1,dest,dev,dev->pa_addr,skb))
  		return 1;
  	bp[7]&=~LAPB_C;
  	bp[7]&=~LAPB_E;
  	bp[7]|=SSID_SPARE;
  	bp[14]&=~LAPB_C;
  	bp[14]|=LAPB_E;
  	bp[14]|=SSID_SPARE;
  	return(0);
}	

#endif

/*******************************************************************************************************************\
*														    *
*		Routing rules for AX.25: Basically iterate over the active interfaces 				    *
*														    *
\*******************************************************************************************************************/

struct protocol *ax25rtr_get_dev(ax25_address *addr)
{
	struct device *dev;
	
	for(dev=dev_base;dev;dev=dev->next)
	{
		if((dev->flags & IFF_UP) && dev->hard_header_len==17 && dev->type == 3) /* Active kiss ax25 mode */
		{
			if(ax25cmp(addr,(ax25_address *)dev->dev_addr)==0)
				return(dev->mac_protocol);
		}
	}
	return NULL;
}

/*******************************************************************************************************************\
*													            *
*	      Handling for system calls applied via the various interfaces to an AX25 socket object		    *
*														    *
\*******************************************************************************************************************/
 
static int ax25_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
	switch(cmd)
	{
		/* FIXME : TIOCINQ */
		default:
			return(-EINVAL);
	}
}

static int ax25_setsockopt(struct socket *sock, int level, int optname,
	char *optval, int optlen)
{
	ax25_socket *sk;
	int err,opt;
	
	sk=sock->protocol;
	
	if(level==SOL_SOCKET)
		return sock_setsockopt(sk,level,optname,optval,optlen);
	if(level!=SOL_AX25)
		return(-EOPNOTSUPP);
	if(optval==NULL)
		return(-EINVAL);
	err=verify_area(VERIFY_READ,optval,sizeof(int));
	if(err)
		return err;
	opt=get_fs_long((unsigned long *)optval);
	
	switch(optname)
	{
		case AX25_WINDOW:
			if(opt<1||opt>7)
				return -EINVAL;
			sk->window=opt;
			return 0;
			
		case AX25_T1:
			sk->opt.ax25.t1=opt;
			return 0;
			
		case AX25_N2:
			if(opt<1||opt>31)
				return -EINVAL;
			sk->opt.ax25.n2=opt;
			return 0;
			
		case AX25_T3:
			sk->opt.ax25.t3=opt;
			return 0;
	
		default:
			return(-ENOPROTOOPT);
	}
}

static int ax25_getsockopt(struct socket *sock, int level, int optname,
	char *optval, int *optlen)
{
	ax25_socket *sk;
	int val=0;
	int err;
	
	sk=sock->protocol;

	if(level==SOL_SOCKET)
		return sock_getsockopt(sk,level,optname,optval,optlen);
	
	if(level!=SOL_AX25)
		return(-EOPNOTSUPP);
	
	switch(optname)
	{
		case AX25_WINDOW:
			val=sk->window;
			break;
			
		case AX25_T1:
			val=sk->opt.ax25.t1;
			break;
			
		case AX25_N2:
			val=sk->opt.ax25.n2;
			break;
			
		case AX25_T3:
			val=sk->opt.ax25.t3;
			break;
	
		default:
			return(-ENOPROTOOPT);
	}
	err=verify_area(VERIFY_WRITE,optlen,sizeof(int));
	if(err)
		return err;
	put_fs_long(sizeof(int),(unsigned long *)optlen);
	err=verify_area(VERIFY_WRITE,optval,sizeof(int));
	put_fs_long(val,(unsigned long *)optval);
	return(0);
}

static int ax25_listen(struct socket *sock, int backlog)
{
	ax25_socket *sk;
	
	sk=sock->protocol;
	if(sk->type==SOCK_SEQPACKET && sk->state!=TCP_LISTEN)
	{
		sk->max_ack_backlog=backlog;
		sk->state=TCP_LISTEN;
		return 0;
	}
	return -EOPNOTSUPP;
}

static void def_callback1(struct sock *sk)
{
	if(!sk->dead)
		wake_up_interruptible(sk->sleep);
}

static void def_callback2(struct sock *sk, int len)
{
	if(!sk->dead)
		wake_up_interruptible(sk->sleep);
}

static int ax25_create(struct socket *sock, int protocol)
{
	ax25_socket *sk;
	sk=(ax25_socket *)kmalloc(sizeof(*sk),GFP_ATOMIC);
	if(sk==NULL)
		return(-ENOMEM);
	sk->type=sock->type;
	switch(sock->type)
	{
		case SOCK_DGRAM:
			break;
		case SOCK_SEQPACKET:
			break;
		case SOCK_RAW:
			break;
		default:
			kfree_s((void *)sk,sizeof(*sk));
			return(-ESOCKTNOSUPPORT);
	}
	sk->opt.ax25.retxqi=0;
	sk->opt.ax25.lastrxnr=0;
	ax25_init_vars(sk);
	sk->protocol=protocol;
	sk->dead=0;
	sk->opt.ax25.digipeat=NULL;
	sk->next=NULL;
	sk->broadcast=0;
	sk->rcvbuf=SK_RMEM_MAX;
	sk->sndbuf=SK_WMEM_MAX;
	sk->wmem_alloc=0;
	sk->rmem_alloc=0;
	sk->inuse=0;
	sk->debug=0;
	sk->prot=NULL;	/* So we use default free mechanisms */
	sk->err=0;
	sk->localroute=0;
	skb_queue_head_init(&sk->receive_queue);
	skb_queue_head_init(&sk->write_queue);
	sk->send_head=NULL;
	skb_queue_head_init(&sk->back_log);
	sk->state=TCP_CLOSE;
	sk->window=4;
	sk->priority=SOPRI_NORMAL;
	sk->ack_backlog=0;
	sk->shutdown=0;
	
	sk->opt.ax25.t1=DEFAULT_T1;
	sk->opt.ax25.n2=DEFAULT_N2;
	sk->opt.ax25.t3=DEFAULT_T3;
	init_timer(&sk->timer);

	sk->state_change=def_callback1;
	sk->data_ready=def_callback2;
	sk->write_space=def_callback1;
	sk->error_report=def_callback1;

	memset(&sk->opt.ax25.dest_addr,'\0',sizeof(sk->opt.ax25.dest_addr));
	memset(&sk->opt.ax25.source_addr,'\0',sizeof(sk->opt.ax25.source_addr));
	sk->mtu=AX25_MTU;	/* 256 */

	if(sock!=NULL)
	{
		sock->protocol=(void *)sk;
		sk->sleep=sock->wait;
	}
	
	sk->zapped=1;
	return(0);
}

static ax25_socket *ax25_make_new(struct sock *osk)
{
	ax25_socket *sk;
	sk=(ax25_socket *)kmalloc(sizeof(*sk),GFP_ATOMIC);
	if(sk==NULL)
		return(NULL);
	sk->type=osk->type;
	switch(osk->type)
	{
		case SOCK_DGRAM:
			break;
		case SOCK_SEQPACKET:

			break;
		default:
			kfree_s((void *)sk,sizeof(*sk));
			return NULL;
	}
	skb_queue_head_init(&sk->write_queue);
	sk->shutdown=0;
	sk->opt.ax25.retxqi=0;
	sk->opt.ax25.lastrxnr=0;
	ax25_init_vars(sk);
	sk->rmem_alloc=0;
	sk->dead=0;
	sk->next=NULL;
	sk->priority=osk->priority;
	sk->broadcast=0;
	sk->protocol=osk->protocol;
	sk->rcvbuf=osk->rcvbuf;
	sk->sndbuf=osk->sndbuf;
	sk->wmem_alloc=0;
	sk->rmem_alloc=0;
	sk->inuse=0;
	sk->dead=0;
	sk->ack_backlog=0;
	sk->prot=NULL;	/* So we use default free mechanisms */
	sk->broadcast=0;
	sk->err=0;
	sk->localroute=0;
	skb_queue_head_init(&sk->receive_queue);
	skb_queue_head_init(&sk->write_queue);
	sk->send_head=NULL;
	skb_queue_head_init(&sk->back_log);
	sk->debug=osk->debug;
	sk->state=TCP_ESTABLISHED;
	sk->window=4;
	sk->opt.ax25.t1=osk->opt.ax25.t1;
	sk->opt.ax25.n2=osk->opt.ax25.n2;
	sk->opt.ax25.t3=osk->opt.ax25.t3;
	init_timer(&sk->timer);

	/* These two are vital! */
	sk->opt.ax25.retxqi=0;
	sk->opt.ax25.lastrxnr=0;

	sk->state_change=def_callback1;
	sk->data_ready=def_callback2;
	sk->write_space=def_callback1;
	sk->error_report=def_callback1;
	
	memset(&sk->opt.ax25.dest_addr,'\0',sizeof(sk->opt.ax25.dest_addr));
	memcpy(&sk->opt.ax25.source_addr,&osk->opt.ax25.source_addr,sizeof(sk->opt.ax25.source_addr));
	
	if(osk->opt.ax25.digipeat!=NULL)
	{
		sk->opt.ax25.digipeat=(ax25_digi *)kmalloc(sizeof(ax25_digi),GFP_ATOMIC);
		if(sk->opt.ax25.digipeat==NULL)
		{
			kfree_s(sk,sizeof(ax25_socket));
			return NULL;
		}
	}
	else
		sk->opt.ax25.digipeat=NULL;
		
	sk->mtu=osk->mtu;
	sk->sleep=osk->sleep;
	sk->zapped=osk->zapped;
	return(sk);
}

static int ax25_dup(struct socket *newsock,struct socket *oldsock)
{
	return(ax25_create(newsock,oldsock->type));
}

static int ax25_release(struct socket *sock, struct socket *peer)
{
	ax25_socket *sk=sock->protocol;
	if(sk==NULL)
		return(0);
	sk->state_change(sk);
	if(sk->state==TCP_ESTABLISHED && sk->type==SOCK_SEQPACKET)
	{
		sk->opt.ax25.state=DISC_SENT;	
		ax25_write_internal(sk,DISC,POLLON,C_COMMAND);
		SET_TIMER(sk);
		sk->dead=1;
	}		
	else
		ax25_destroy_socket(sk);
	sock->protocol=NULL;	
	return(0);
}
		
static int ax25_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
{
	ax25_socket *sk;
	struct sockaddr_ax25 *addr=(struct sockaddr_ax25 *)uaddr;
	struct protocol *proto;
	
	sk=sock->protocol;
	
	if(sk->zapped==0)
		return(-EIO);
		
	if(addr_len!=sizeof(*addr))
		return -EINVAL;
		
#ifdef DONTDO	
	if(ax25_find_socket(&addr->sax25_call,sk->type)!=NULL)
	{
		if(sk->debug)
			printk("AX25: bind failed: in use.\n");
		return(-EADDRINUSE);	   
	}
#endif	
	memcpy(&sk->opt.ax25.source_addr,&addr->sax25_call,sizeof(sk->opt.ax25.source_addr));

	if((proto=ax25rtr_get_dev(&sk->opt.ax25.source_addr))==NULL)
	{
		if(sk->debug)
			printk("AX25 bind failed: no device.\n");
		return(-EADDRNOTAVAIL);
	}
	ax25_insert_socket(sk);
	sk->zapped=0;
	if(sk->debug)
		printk("AX25: socket is bound.\n");
	return(0);
}

static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
	int addr_len, int flags)
{
	ax25_socket *sk=sock->protocol;
	struct sockaddr_ax25 *addr=(struct sockaddr_ax25 *)uaddr;
	
	if(sk->state==TCP_ESTABLISHED && sock->state == SS_CONNECTING)
	{
		sock->state=SS_CONNECTED;
		return 0;	/* Connect completed during a ERESTARTSYS event */
	}
	
	if(sk->state==TCP_ESTABLISHED && sk->type == SOCK_SEQPACKET)
		return -EISCONN;	/* No reconnect on a seqpacket socket */
		
	sk->state = TCP_CLOSE;	
	sock->state = SS_UNCONNECTED;

	if(addr_len>sizeof(*addr))
	{
		int ct=0;
		int ndigi=addr_len-sizeof(*addr);
		ax25_address *ap=(ax25_address *)(((char *)addr)+sizeof(*addr));
		/* Size is an exact number of digipeaters ? */
		if(ndigi%sizeof(ax25_address))
			return -EINVAL;
		ndigi/=sizeof(ax25_address);
		/* Valid number of digipeaters ? */
		if(ndigi<1||ndigi>6)
			return -EINVAL;
		if(sk->opt.ax25.digipeat==NULL)
		{
			sk->opt.ax25.digipeat=(ax25_digi *)kmalloc(sizeof(ax25_digi),GFP_KERNEL);
			if(sk->opt.ax25.digipeat==NULL)
				return -ENOMEM;
		}
		sk->opt.ax25.digipeat->ndigi=ndigi;
		while(ct<ndigi)
		{
			sk->opt.ax25.digipeat->repeated[ct]=0;
			memcpy(&sk->opt.ax25.digipeat->calls[ct],&ap[ct],sizeof(ax25_address));
			ct++;
		}
		sk->opt.ax25.digipeat->lastrepeat=0;
		addr_len-=ndigi*sizeof(ax25_address);	
	}
	
	if(addr_len!=sizeof(struct sockaddr_ax25))
		return(-EINVAL);
	
	if(sk->opt.ax25.source_addr.ax25_call[0]==0)	/* Must bind first - no autobinding in this */
		return -EINVAL;
		
	if(sk->type==SOCK_SEQPACKET && ax25_find_socket(&sk->opt.ax25.source_addr,&addr->sax25_call,sk->type)!=NULL)
		return -EBUSY;				/* Already such a connection */
		
	memcpy(&sk->opt.ax25.dest_addr,&addr->sax25_call,sizeof(sk->opt.ax25.dest_addr));
	
	/* First the easy one */
	
	if(sk->type!=SOCK_SEQPACKET)
	{
		sock->state = SS_CONNECTED;
		sk->state=TCP_ESTABLISHED;
		return(0);
	}
	

	/* Move to connecting socket, ax.25 lapb WAIT_UA.. */	
	sock->state = SS_CONNECTING;
	sk->state=TCP_SYN_SENT;
	sk->opt.ax25.state=WAIT_UA;
	ax25_write_internal (sk, SABM, POLLOFF, C_COMMAND);
	SET_TIMER(sk);		/* Start going SABM SABM until a UA or a give up and DM */
	
	/* Now the loop */
	
	if(sk->state!=TCP_ESTABLISHED && (flags & O_NONBLOCK))
		return -EINPROGRESS;
		
	cli();	/* To avoid races on the sleep */
	/* A DM or timeout will go to closed, a UA will go to ABM */
	while(sk->state==TCP_SYN_SENT)
	{
		interruptible_sleep_on(sk->sleep);
		if (current->signal & ~current->blocked)
		{
			sti();
			return -ERESTARTSYS;
		}
	}
	if(sk->state!=TCP_ESTABLISHED)	/* Not in ABM, not in WAIT_UA -> failed */
	{
		sti();
		sock->state=SS_UNCONNECTED;
		return -sk->err;	/* Always set at this point */
	}
	
	sock->state=SS_CONNECTED;
	sti();
	
	return 0;
}
	
static int ax25_socketpair(struct socket *sock1, struct socket *sock2)
{
	return(-EOPNOTSUPP);
}

static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
{
	ax25_socket *sk;
	ax25_socket *newsk;
	sk_buff *skb;

	if(newsock->protocol)
		kfree_s(newsock->protocol,sizeof(ax25_socket));
	newsock->protocol=NULL;
	
	sk=sock->protocol;

	if(sk->type!=SOCK_SEQPACKET)
		return -EOPNOTSUPP;
	
	if(sk->state!=TCP_LISTEN)
		return -EINVAL;
		
	/* The write queue this time is holding sockets ready to use
	   hooked into the SABM we saved */
	
	do
	{
		cli();
		skb=skb_dequeue(&sk->receive_queue);
		if(skb==NULL)
		{
			if(flags&O_NONBLOCK)
			{
				sti();
				return 0;
			}
			interruptible_sleep_on(sk->sleep);
			if(current->signal & ~current->blocked) 
			{
				sti();
				return -ERESTARTSYS;
			}
		}
	}
	while(skb==NULL);
	newsk=skb->sk;
	newsk->pair=NULL;
	sti();
	/* Now attach up the new socket */
	sk->ack_backlog--;
	newsock->protocol=newsk;
	return(0);			
}

static int ax25_getname(struct socket *sock, struct sockaddr *uaddr,
	int *uaddr_len, int peer)
{
	ax25_address *addr;
	struct sockaddr_ax25 *sax=(struct sockaddr_ax25 *)uaddr;
	ax25_socket *sk;
	
	sk=sock->protocol;
	
	if(peer)
	{
		if(sk->state!=TCP_ESTABLISHED)
			return -ENOTCONN;
		addr=&sk->opt.ax25.dest_addr;
	}
	else
		addr=&sk->opt.ax25.source_addr;
		
	sax->sax25_family = AF_AX25;
	memcpy(&sax->sax25_call,addr,sizeof(sax->sax25_call));
	*uaddr_len=sizeof(struct sockaddr_ax25);
	return(0);
}
 
int ax25_input(struct protocol *p, struct protocol *below, sk_buff *skb, void *saddr, void *daddr)
{
	unsigned char *data=skb_data(skb);
	ax25_socket *sk;
	int type=0;
	ax25_digi dp;
	ax25_address src,dest;
	ax25_socket *raw;
	struct device *dev=skb->dev;
	
	skb->sk=NULL;		/* Initially we don't know who its for */
	skb->h.raw = data;
			
	/*
	 *	Parse the address header.
	 */
	 
	data=ax25_parse_addr(skb,skb->len,&src,&dest,&dp,&type);
	if(data==NULL)
	{
		kfree_skb(skb,FREE_READ);
		return(0);
	}
	
	/*
	 *	Send the frame to the AX.25 auto-router
	 */
	 
	ax25_rt_rx_frame(&src,dev);
	
	/*
	 *	Ours perhaps ?
	 */
	 
	 
	if(dp.lastrepeat+1<dp.ndigi)		/* Not yet digipeated completely */
	{
		if(ax25cmp(&dp.calls[dp.lastrepeat+1],(ax25_address *)dev->dev_addr)==0)
		{
			/* We are the digipeater. Mark ourselves as repeated
			   and throw the packet back down to the same protocol/device pair */
			dp.lastrepeat++;
			dp.repeated[(int)dp.lastrepeat]=1;
			build_ax25_addr(skb,&src,&dest,&dp,type);
			p->output(p, skb, ETH_P_AX25, 0, NULL, NULL, NULL);			
		}
		else
			kfree_skb(skb,FREE_READ);
		return(0);
	}

	/* For our addreses ? */
	
	if(
	   (raw=ax25_addr_match(&dest))==NULL &&	/* MUST BE FIRST IF... */
	   ax25cmp(&dest,(ax25_address *)skb->dev->dev_addr)!=0 &&
	   ax25cmp(&dest,(ax25_address *)skb->dev->broadcast)!=0 
#ifdef CONFIG_NETROM	   
	   && ax25cmp(&dest,(ax25_address *)netrom_dev.broadcast)!=0
#endif	   
	)
	{
		kfree_skb(skb,FREE_READ);	/* Someone elses packet (very likely - KISS is almost always
						   promiscuous) */
		return(0);
	}
	
	if((*data&~0x10)==LAPB_UI)	/* UI frame - bypass LAPB processing */
	{
		data++;
		if(raw!=NULL)
			ax25_send_to_raw(raw,skb,(int)*data);
		/*
		 *	This will demultiplex to upper layers (eg NetROM) and to the socket class (PID Text).
		 *	It's ok although perhaps non-obvious to handle AX.25 SOCK_DGRAM this way.
		 */
		if(*data==AX25_P_TEXT)
		{
			/* Find an AX.25 datagram socket */
			sk=ax25_find_socket(&dest,&src,SOCK_DGRAM);
			if(sk!=NULL)
			{
				if(sock_queue_rcv_skb(sk,skb))
					kfree_skb(skb,FREE_READ);
			}
			else
				kfree_skb(skb, FREE_READ);
		}	
		else if(!protocol_pass_demultiplex(&proto_ax25, data++, skb, &src, &dest))
		{
			kfree_skb(skb, FREE_READ);
		}
		return(0);
	}
	
	/* LAPB */
	sk=ax25_find_socket(&dest,&src,SOCK_SEQPACKET);
	if(sk)
	{
		skb->h.raw=data;
		skb->sk=NULL;	/* Dont charge IFrames until they are finally lodged. We don't want to charge
				   for supervisory frames */
		/* Process the frame. If it is queued up internally it returns one otherwise we 
		   free it immediately. This routine itself wakes the user context layers so we
		   do no further work */
		if(ax25_process_rx_frame(sk,skb,type)==0)
			kfree_skb(skb,FREE_READ);
		return(0);
	}	
	else
	{
		ax25_socket *make;	

		if((data[0]&0xEF)!=SABM_CONTROL)
		{
			ax25_return_dm(&src,&dest,&dp);
			kfree_skb(skb,FREE_READ);
			return(0);
		}

		sk=ax25_find_listener(&dest,SOCK_SEQPACKET);
		if(sk==NULL || sk->ack_backlog == sk->max_ack_backlog || (make=ax25_make_new(sk))==NULL)
		{
			ax25_return_dm(&src,&dest,&dp);
			kfree_skb(skb,FREE_READ);
			return(0);
		}
		memcpy(&make->opt.ax25.dest_addr,&src,sizeof(make->opt.ax25.dest_addr));
		
		/*
		 *	Sort out any digipeated paths.
		 */
		 
		if(dp.ndigi && make->opt.ax25.digipeat==NULL && (make->opt.ax25.digipeat=kmalloc(sizeof(ax25_digi),GFP_ATOMIC))==NULL)
		{
			kfree_skb(skb,FREE_READ);
			ax25_destroy_socket(sk);
			return(0);
		}
		if(dp.ndigi==0)
		{
			if(make->opt.ax25.digipeat)
			{
				kfree_s(make->opt.ax25.digipeat,sizeof(ax25_digi));
				make->opt.ax25.digipeat=NULL;
			}
		}
		else
			/* Reverse the source SABM's path */
			ax25_digi_invert(&dp,make->opt.ax25.digipeat);
			
		skb->sk=make;
		make->state=TCP_ESTABLISHED;
		ax25_init_vars(make);
		make->opt.ax25.state=ABM;
		ax25_write_internal(make,UA,POLLON,C_RESPONSE);
		sk->ack_backlog++;
		make->pair=sk;
		ax25_insert_socket(make);
		skb_queue_head(&sk->receive_queue,skb);
		if(!sk->dead)
			sk->data_ready(sk,skb->len-2);
		return 0;
	}
}

static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, int noblock,
	int flags)
{
	ax25_socket *sk=sock->protocol;
	struct sockaddr_ax25 *usax=(struct sockaddr_ax25 *)msg->msg_name;
	unsigned char *uaddr=(unsigned char *)msg->msg_name;
	int err;
	struct sockaddr_ax25 sax;
	sk_buff *skb;
	struct protocol *protocol;
	unsigned char *asmptr;
	int size;
	ax25_digi *dp;
	ax25_digi dtmp;
	int addr_len=msg->msg_namelen;
	
	if(sk->err)
	{
		err=sk->err;
		sk->err=0;
		return -err;
	}

	if(flags)
		return -EINVAL;
		
	if(usax)
	{
		int ndigi=addr_len-sizeof(sax);	
		if(addr_len <sizeof(sax))
			return(-EINVAL);
		/* Trailing digipeaters on address ?? */
		
		if(addr_len>sizeof(sax))
		{
			int ct=0;

			ax25_address *ap=(ax25_address *)(((char *)uaddr)+sizeof(sax));
			/* Size is an exact number of digipeaters ? */
			if(ndigi%sizeof(ax25_address))
				return -EINVAL;
			ndigi/=sizeof(ax25_address);
			/* Valid number of digipeaters ? */
			if(ndigi<1||ndigi>6)
				return -EINVAL;
			/* Copy data into digipeat structure */
			while(ct<ndigi)
			{
				dtmp.repeated[ct]=0;
				memcpy(&dtmp.calls[ct],&ap[ct],sizeof(ax25_address));
				ct++;
			}
			dtmp.lastrepeat=0;
			dtmp.ndigi=ndigi;
			addr_len-=ndigi*sizeof(ax25_address);	
		}
		memcpy(&sax,usax,sizeof(sax));
		if(sk->type==SOCK_SEQPACKET && memcmp(&sk->opt.ax25.dest_addr,&sax.sax25_call,sizeof(sax.sax25_call))!=0)
			return -EISCONN;
		if(sax.sax25_family != AF_AX25)
			return -EINVAL;
		if(ndigi)
			dp=&dtmp;
		else
			dp=NULL;
	}
	else
	{
		if(sk->state!=TCP_ESTABLISHED)
			return -ENOTCONN;
		sax.sax25_family=AF_AX25;
		memcpy(&sax.sax25_call,&sk->opt.ax25.dest_addr,sizeof(sax.sax25_call));
		dp=sk->opt.ax25.digipeat;
	}
	
	if(sk->debug)
		printk("AX.25: sendto: Addresses built.\n");
	/* Build a packet */
	
	if(sk->debug)
		printk("AX.25: sendto: building packet.\n");

	size=len+protocol_size(&proto_ax25);
	skb=sock_alloc_send_skb(sk, size, noblock, &err);
	if(skb==NULL)
		return err;
	protocol_adjust(skb,&proto_ax25);

	if(sk->debug)	
		printk("AX.25: sendto: allocating buffer (%d)\n",size-sizeof(sk_buff));
	skb->sk=sk;
	skb->free=1;

	/* Put on the UI header and address */
	
	asmptr=skb_push(skb,2);
	*asmptr++=LAPB_UI;
	if(sk->type!=SOCK_RAW)
		*asmptr=AX25_P_TEXT;	/* AX.25 */
	else
		*asmptr=sk->protocol;	/* AX.25 raw */
	skb->h.raw=asmptr;
	
	/* Build an AX.25 header */
	build_ax25_addr(skb,&sk->opt.ax25.source_addr,&sax.sax25_call,dp,C_COMMAND);
	/* User data follows immediately after the AX.25 data */
	memcpy_fromiovec(skb_put(skb,len),msg->msg_iov,len);
	if(sk->debug)
		printk("AX.25: Transmitting buffer\n");
	if(sk->type==SOCK_SEQPACKET)
	{
		/* Connected mode sockets go via the LAPB machine */
		if(sk->state!=TCP_ESTABLISHED)
		{
			kfree_skb(skb,FREE_WRITE);
			return -ENOTCONN;
		}
		ax25_output(sk,skb);	/* Shove it onto the queue and kick */
		return len;
	}
	else
	{
		/* Datagram frames go straight out of the door as UI */
		/* Find out where this has to go */
		if((protocol=ax25rtr_get_dev(&sk->opt.ax25.source_addr))==NULL)
		{
			kfree_skb(skb,FREE_WRITE);
			return -ENETUNREACH;
		}
		protocol->output(protocol,skb,ETH_P_AX25,0,NULL,NULL,NULL);
		return len;
	}
}

static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len)
{
	ax25_socket *sk=sock->protocol;
	struct sockaddr_ax25 *sax=(struct sockaddr_ax25 *)msg->msg_name;
	char *addrptr=msg->msg_name;
	sk_buff *skb;
	int er;
	int copied;
	
	if(sk->err)
	{
		er= -sk->err;
		sk->err=0;
		return er;
	}
	
	if(addr_len)
		*addr_len=sizeof(*sax);

	/* This works for seqpacket too. The receiver has ordered the queue for us! We do one quick check first though */
	if(sk->type==SOCK_SEQPACKET && sk->state!=TCP_ESTABLISHED)
		return -ENOTCONN;
	/* Now we can treat all alike */
	skb=skb_recv_datagram(sk,flags,noblock,&er);
	if(skb==NULL)
		return er;
	copied=(size<skb->len)?size:skb->len;
	skb_copy_datagram_iovec(skb,sk->type==SOCK_SEQPACKET?2:0,msg->msg_iov,copied);
	
	if(sax)
	{
		struct sockaddr_ax25 addr;
		ax25_digi digi;
		ax25_address dest;
		int ct=0;
		
		ax25_parse_addr(skb,skb->len,NULL,&dest,&digi,NULL);
		addr.sax25_family=AF_AX25;
		memcpy(&addr.sax25_call,&dest,sizeof(addr.sax25_call));
		memcpy(sax,&addr,sizeof(*sax));
		addrptr+=sizeof(*sax);
		while(ct<digi.ndigi)
		{
			memcpy(addrptr,&digi.calls[ct],7);
			addrptr+=7;
			ct++;
		}
		if(addr_len)
			*addr_len=sizeof(*sax)+7*digi.ndigi;
	}
	skb_free_datagram(skb);
	return(copied);
}		

static int ax25_shutdown(struct socket *sk,int how)
{
	/* FIXME - generate DM and RNR states */
	return -EOPNOTSUPP;
}

static int ax25_select(struct socket *sock , int sel_type, select_table *wait)
{
	return datagram_select(sock->protocol,sel_type,wait);
}

static int ax25_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
{
	
	ax25_socket *sk=sock->protocol;
	int err;
	long amount=0;
			
	switch(cmd)
	{
	
		case TIOCOUTQ:
			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
			if(err)
				return err;
			amount=sk->sndbuf-sk->wmem_alloc;
			if(amount<0)
				amount=0;
			put_fs_long(amount,(unsigned long *)arg);
			return 0;
		case TIOCINQ:
		{
			sk_buff *skb;
			if(sk->state==TCP_LISTEN)
				return -EINVAL;
			/* These two are safe on a single CPU system as only user tasks fiddle here */
			if((skb=skb_peek(&sk->receive_queue))!=NULL)
				amount=skb->len;
			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
			put_fs_long(amount,(unsigned long *)arg);
			return 0;
		}

		case SIOCGSTAMP:
			if (sk)
			{
				if(sk->stamp.tv_sec==0)
					return -ENOENT;
				err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval));
				if(err)
					return err;
					memcpy_tofs((void *)arg,&sk->stamp,sizeof(struct timeval));
				return 0;
			}
			return -EINVAL;
		case SIOCGIFCONF:
		case SIOCGIFFLAGS:
		case SIOCSIFFLAGS:
		case SIOCGIFADDR:
		case SIOCSIFADDR:
		case SIOCGIFDSTADDR:
		case SIOCSIFDSTADDR:
		case SIOCGIFBRDADDR:
		case SIOCSIFBRDADDR:
		case SIOCGIFNETMASK:
		case SIOCSIFNETMASK:
		case SIOCGIFMETRIC:
		case SIOCSIFMETRIC:
		case SIOCGIFMEM:
		case SIOCSIFMEM:
		case SIOCGIFMTU:
		case SIOCSIFMTU:
		case SIOCSIFLINK:
		case SIOCGIFHWADDR:
		case SIOCSIFHWADDR:
		case OLD_SIOCGIFHWADDR:
			return(dev_ioctl(cmd,(void *) arg));

		default:
			return -EINVAL;
	}
	/*NOTREACHED*/
	return(0);
}

int ax25_get_info(char *buffer, char **start, off_t offset, int length)
{
	ax25_socket *sock;
	struct protocol *proto;
	char *devname;
	int len = 0;
	off_t pos = 0;
	off_t begin = 0;
  
	cli();

	len += sprintf(buffer, "dest_addr src_addr  dev st vs vr t1 n2 t3 wnd mtu prot type dead\n");

	for (sock = ax25_socket_list; sock != NULL; sock = sock->next)
	{
		proto = ax25rtr_get_dev(&sock->opt.ax25.source_addr);
		if(proto==NULL)
			devname="[Unknown]";
		else
			devname=proto->name;

		len += sprintf(buffer + len, "%-9s ",
			ax2asc(&sock->opt.ax25.dest_addr));
		len += sprintf(buffer + len, "%-9s %-3s  %d  %d  %d %2d %2d %2d   %d %3d 0x%02X    %d    %d\n",
			ax2asc(&sock->opt.ax25.source_addr), devname, sock->opt.ax25.state,
			sock->opt.ax25.vs, sock->opt.ax25.vr, 
			sock->opt.ax25.t1/PR_SLOWHZ, sock->opt.ax25.n2, sock->opt.ax25.t3/PR_SLOWHZ,
			sock->window, sock->mtu,
			sock->protocol, sock->type, sock->dead);
		
		pos = begin + len;

		if (pos < offset)
		{
			len   = 0;
			begin = pos;
		}
		
		if (pos > offset + length)
			break;
	}

	sti();

	*start = buffer + (offset - begin);
	len   -= (offset - begin);

	if (len > length) len = length;

	return(len);
} 

static struct proto_ops ax25_proto_ops = {
	AF_AX25,
	
	ax25_create,
	ax25_dup,
	ax25_release,
	ax25_bind,
	ax25_connect,
	ax25_socketpair,
	ax25_accept,
	ax25_getname,
	ax25_select,
	ax25_ioctl,
	ax25_listen,
	ax25_shutdown,
	ax25_setsockopt,
	ax25_getsockopt,
	ax25_fcntl,
	ax25_sendmsg,
	ax25_recvmsg
};

/* Called by socket.c on kernel start up */

void ax25_proto_init(struct net_proto *pro)
{
	(void) sock_register(ax25_proto_ops.family, &ax25_proto_ops);
	protocol_register(&proto_ax25);
	printk("NET3: GW4PTS AX.25 for Linux. Version 0.28 ALPHA for Linux NET3.026 (pre Linux 1.3.0)\n");
	printk("Portions (c) Copyright 1984 University Of British Columbia\n");
	printk("Portions (c) Copyright 1990 The Regents of the University Of California\n");
	
}

/*
 *	Not yet re-implemented.
 */
 
static int ax25_get_binding(int proto, int subid, unsigned char *key)
{
	return -1;
}

struct protocol proto_ax25=
{
	NULL,
	"AX.25",
	2+10*7,		/* [ADDR.B][LAPB.B] + Src+Dst+8 digipeaters all of 7 bytes */
	2+10*7,		/* long addresses... */
	0,
	0,
	NULL,/*ax25_mac_output,*/
#ifdef CONFIG_FAST_PATH
	protocol_default_fast_output,
	protocol_default_build_fast,
#endif	
	ax25_input,
	ax25_input,	/* We run AX.25 off the physical interrupt layer on the PI/2 - it works so why not */
	default_protocol_control,
	ax25_get_binding,
	NULL,
	NULL,
	0,
};



#endif
