
/*
 * Copyright (c) 1997 by Procom Technology,Inc.
 *
 * This program can be redistributed or modified under the terms of the 
 * GNU General Public License as published by the Free Software Foundation.
 * This program is distributed without any warranty or implied warranty
 * of merchantability or fitness for a particular purpose.
 *
 * See the GNU General Public License for more details.
 *
 */
 
/* NetBEUI data structures */
 
#ifndef __LINUX_NETBEUI_H
#define __LINUX_NETBEUI_H

#include <asm/byteorder.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/if_tr.h>
#include <linux/if_ether.h>
#include <linux/dextab.h>
#include <linux/af_netb.h>


/* 
 * NetBIOS frame commands - listed by functionality 
 */

#define ADD_GROUP_NAME_QUERY	0x00
#define ADD_NAME_QUERY		0x01
#define ADD_NAME_RESPONSE	0x0D
#define NAME_IN_CONFLICT	0x02

#define NAME_QUERY		0x0A
#define NAME_RECOGNIZED		0x0E
#define SESSION_ALIVE		0x1F
#define SESSION_CONFIRM		0x17
#define SESSION_END		0x18
#define SESSION_INITIALIZE	0x19

#define DATA_ACK		0x14
#define DATA_FIRST_MIDDLE	0x15
#define DATAGRAM		0x08
#define DATAGRAM_BROADCAST	0x09
#define DATA_ONLY_LAST		0x16
#define NO_RECEIVE		0x1A
#define RECEIVE_CONTINUE	0x1C
#define RECEIVE_OUTSTANDING	0x1B

#define STATUS_QUERY		0x03
#define STATUS_RESPONSE		0x0F
#define TERMINATE_TRACE		0x07
#define TERMINATE_TRACE2	0x13

#define NB_MAX_COMMAND_CODE	0x1F
#define NB_MIN_COMMAND_LEN	0x0B


extern u8 nb_command_header_len[];


/* 
 * NetBIOS name service constants 
 */

typedef enum { 
	NB_NAME_INITIAL = 0, 
	NB_NAME_ADDWAIT, 
	NB_NAME_COLLIDED,
	NB_NAME_ACQUIRED 
} name_state_t;

typedef enum {
	NB_NAME_ADD_NAME = 0,
	NB_NAME_RETRY_TIMEOUT,
	NB_NAME_RESPONSE_TIMEOUT,
	NB_NAME_ADD_NAME_RESPONSE1,
	NB_NAME_ADD_NAME_RESPONSE2,
	NB_NAME_ADD_NAME_QUERY,
	NB_NAME_NAME_CONFLICT,
	NB_NAME_REMOVE_NAME
} name_event_t;


/*
 * NetBIOS query service constants 
 */

#define NB_QURY_MAX_CACHE_ENTRIES	50
#define NB_QURY_CACHE_LIVING_TIME	(5*60*HZ)

typedef enum { 
	NB_QURY_INITIAL = 0, 
	NB_QURY_QRYWAIT,
	NB_QURY_FINDWAIT,
	NB_QURY_RECOGNIZED
} query_state_t;

typedef enum {
	NB_QURY_NAME_QUERY = 0,
	NB_QURY_NAME_FIND,
	NB_QURY_RETRY_TIMEOUT,
	NB_QURY_RESPONSE_TIMEOUT,
	NB_QURY_NAME_RECOGNIZED,
	NB_QURY_END_QUERY
} query_event_t;

#define CALL_TT(data2)		((data2 & 0xFF00) >> 8)
#define CALL_SS(data2)  	(data2 & 0x00FF)
#define CALL_DATA2(tt,ss)	(((tt << 8) & 0xFF00) | (ss & 0x00FF))


/* 
 * NetBIOS session service constants 
 */ 

typedef enum { 
	NB_SESS_INITIAL = 0, 
	NB_SESS_CALLWAIT,
	NB_SESS_CONFWAIT,
	NB_SESS_LISTENWAIT,
	NB_SESS_INITWAIT,
	NB_SESS_CONNECTED,
	NB_SESS_DISCWAIT,
	NB_SESS_CONTWAIT,
	NB_SESS_STANDWAIT,
	NB_SESS_ACKWAIT,
	NB_SESS_RSRCWAIT,
	NB_SESS_NORMAL
} session_state_t;

typedef enum {
	NB_SESS_CALL = 0,
	NB_SESS_LISTEN,
	NB_SESS_CONFIRM,
	NB_SESS_REJECT,
	NB_SESS_CONNECT,
	NB_SESS_TIMEOUT,
	NB_SESS_ABORT,
	NB_SESS_HANGUP,
	NB_SESS_END,
	NB_SESS_FIRST_MIDDLE_CONT,
	NB_SESS_FIRST_MIDDLE,
	NB_SESS_CONTINUE,
	NB_SESS_NONBLOCK,
	NB_SESS_PAUSE,
	NB_SESS_PAUSE2, 
	NB_SESS_RESTART,
	NB_SESS_ONLY_LAST_ACK,
	NB_SESS_ONLY_LAST,
	NB_SESS_DATA_ACKED,
	NB_SESS_RESOURCE,
	NB_SESS_CONN_RETRY,
	NB_SESS_NORM_RETRY,
	NB_SESS_ABORT_SEND,
} session_event_t;

typedef enum {
	NB_RECV_NORMAL= 0,
	NB_RECV_NO_RECEIVE,
	NB_RECV_RECEIVE_OUTSTANDING
} input_state_t;

#define NB_VERSION_1xx	0
#define NB_VERSION_2xx	1

#define NB_NACK_NONE	0
#define NB_NACK_ABLE	1

#define NB_ORIGIN_CONNECTED 1
#define NB_ORIGIN_NORMAL    2

typedef void (* abort_owner_cbt)   (void *owner, void *session);
typedef void (* session_ready_cbt) (void *owner, void *session);

#define IS_ABLE_TO_HANDLE_NACK(hdr)	(hdr->data1 & 0x80)
#define NETBIOS_VERSION(hdr)		(hdr->data1 & 0x01)
#define TR_FRAME_LF(hdr)		(((hdr->data1) & 0x0E) >> 1)

#define RECEIVE_CONTINUE_REQUESTED(hdr) (hdr->data1 & 0x01)
#define NACK_INDICATOR(hdr)		(hdr->data1 & 0x02)
#define ACK_WITH_DATA_ALLOWED(hdr)  	(hdr->data1 & 0x04)
#define ACK_WITH_DATA_INCLUDED(hdr)	(hdr->data1 & 0x08)

#define REQUEST_RECEIVE_CONTINUE(hdr)	(hdr->data1 |= 0x01)
#define INDICATE_NACK(hdr)		(hdr->data1 |= 0x02)
#define ALLOW_ACK_WITH_DATA(hdr)	(hdr->data1 |= 0x04)
#define INCLUDE_ACK_WITH_DATA(hdr)	(hdr->data1 |= 0x08)

#define RESYNCH_INDICATOR(hdr)		(hdr->data2)

#define ACK_FLAG			0x80000000


/* NetBIOS link manager constants */
typedef enum {
	NB_LINK_INITIAL= 0,
	NB_LINK_CONNWAIT,
	NB_LINK_UP
} link_state_t;

typedef enum {
	NB_LINK_CONN_INDICATE= 0,
	NB_LINK_CONN_REQUEST,
	NB_LINK_DUMMY_CONN,
	NB_LINK_CONN_CONFIRM,
	NB_LINK_CONN_REJECT,
	NB_LINK_RESET_INDICATE,
	NB_LINK_SESSION_ALIVE,
	NB_LINK_DISC_REQUEST,
	NB_LINK_DISC_INDICATE
} link_event_t;



/* 
 * NetBIOS constants 
 */

#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) )
#define MAX(a,b) ( ((a) > (b)) ? (a) : (b) )

#define MAC_ADDR_LEN	6

#define NetBIOS_FUNC_ADDR_4ETH	"\x03\x00\x00\x00\x00\x01"
#define NetBIOS_FUNC_ADDR_4TR	"\xC0\x00\x00\x00\x00\x80"

#define NB_DELIMITER	0xEFFF

#define LLC_I_HEADLEN	4	/* 4 bytes for LLC header of I_frames */
#define NETB_ILEN	0x0E	/* NetBEUI I_frame header length */

#define LLC_UI_HEADLEN  3       /* 3 bytes for LLC header of UI_frames */
#define NETB_UILEN      0x2C    /* NetBEUI UI_frame header length */

#define MAC_B_HEADLEN	MAX(sizeof(struct ethhdr), sizeof(struct trh_hdr))


/* 
 * NetBIOS status service constants 
 */

typedef enum { 
	NBS_STAT_INITIAL = 0, 
	NBS_STAT_RESPWAIT
} status_state_t;

typedef enum {
	NBE_STAT_STATUS_QUERY = 0,
	NBE_STAT_RETRY_TIMEOUT,
	NBE_STAT_RESPONSE_TIMEOUT,
	NBE_STAT_STATUS_RESPONSE,
	NBE_STAT_INCOMP_RESPONSE
} status_event_t;

typedef enum {
	NO_RESPONSE = 0,
	INCOMPLETE_RESPONSE,
	USER_BUFFER_OVERFLOW,
	COMPLETED_RESPONSE
} status_rc_t;


/* 
 * NetBIOS name data structure 
 */

struct nb_name
{
	struct nb_name *	next;
	name_state_t volatile  	state;		
	s32 volatile		status;
    
	__u8     		name[NB_NAME_LEN];	
	__u8			reserved;
	__u8			conflicted;
	name_type_t		type;		
	__u8			name_number;
	__u32			users;
	__u32			identifier;

	struct wait_queue *	waitq;
	struct timer_list 	timer;
	struct sk_buff *	skb;
	__u16 			resp_correlator;
	__u16			xmit_correlator;
	__u8 			retries;	
	__u8 			responses;
	__u8			remote_mac[6];
	struct device *		remote_dev;
};
typedef struct nb_name name_t;


/* 
 * NetBIOS Query Data Structure
 */ 

struct nb_query
{
	struct nb_query *	next;
	query_state_t volatile 	state;		
	s32 volatile 		status;
	
	name_t *		calling_name;
	__u8     		called_name[NB_NAME_LEN];	
	__u8			reserved;
	__u8			lsn;
	__u16 			resp_correlator;
	char *			mac_buff;
	struct device **	dev_buff;
	__u8			buff_len;
	__u8			buff_ofs;
	
	__u8			rsn;
	__u8			remote_mac[6];
	struct device *		remote_dev;
	__u16			xmit_correlator;
	__u8			tr_lfb; /* for Token-Ring support */

	struct timer_list 	timer;
	struct sk_buff *	skb;
	__u8 			retries;	
	__u8 			responses;
	struct wait_queue *	waitq;
};
typedef struct nb_query query_t;


/* 
 * NetBIOS Session Data Structure
 */

struct nb_session
{
	struct nb_session *	next;
	struct nb_session *	prev;
	session_state_t volatile state;		
	s32 volatile		status;

	int			link_no;
	void *			owner;
	name_t *		local_name;
	name_type_t		remote_name_type;		
	__u8 			remote_name[NB_NAME_LEN];
	__u8			reserved;
	__u8			lsn;
	__u8			rsn;
	__u8			version;
	__u8			nack_indicator;
	__u8			tr_frame_lf;
	__u16			mtu;
	__u16			llcmac_ihl;
	__u8			urgent_ack;
	__u8			users;
	__u8			zapped;
	struct sk_buff_head 	back_log;
	abort_owner_cbt		abort_owner_callback;
	session_ready_cbt	session_ready_callback;

	struct wait_queue *	waitq;
	struct timer_list 	timer;
	struct sk_buff *	skb;
	struct device * 	remote_dev;
	__u8			remote_mac[6];
	__u16			xmit_correlator;
	__u16			resp_correlator;
	
	__u8			o_nonblock;
	__u8			o_noack;
	__u8			o_aborted;
	__u8			o_no_receive;
	__u8			o_receive_continue;
	__u8			o_receive_outstanding;
	__u8			o_rsrc_origin;
	__u8 *			o_buff;
	__u16			o_buffsize;
	__u16			o_size;
	__u16			o_txed;
	__u16			o_acked;
	__u16			r_acked;
	__u32			o_total;
	__u32			o_ack_correlator;
	
	__u16			i_rcvbuf;
	__u16			i_aborted;
	input_state_t		i_state;
	struct sk_buff_head 	i_skbq;
	__u16			i_notacked;
	__u16			i_size;
	__u32			i_total;
};
typedef struct nb_session session_t;


/* 
 * NetBIOS-LLC link data structure
 */

struct nb_link
{
	link_state_t volatile 	state;		
	s32	volatile 	status;

	__u32 			llc_handle;	
	__u32			link_no;
	__u8			remote_mac[6];	
	struct device *		remote_dev;	
	struct sk_buff_head	skbq;
	__u8			llc_busy;
	__u32			iactivity;
	__u8			keep_alive;
	struct timer_list	timer;
	
	dextab_t		session_table;	
	struct wait_queue *	waitq;
};
typedef struct nb_link link_t;
 

/* 
 * NetBIOS dataGram data structure
 */

struct name_dgrms {
	char				name[NB_NAME_LEN];

	struct sk_buff_head		frameq;
	struct sk_buff		 	*curr_skb;

	volatile unsigned char		connected;
	char				*conn_name;

	struct wait_queue		**waitq;

	struct name_dgrms		**list;
	struct name_dgrms		*next;
	struct name_dgrms		*prev;
};
typedef struct name_dgrms   name_dgrms_t;


/* 
 * NetBIOS socket supplement structures
 */

struct netbeui_sock {
	int			protocol;
	volatile nbso_state_t 	state;
	struct proto_ops	*prot;
	struct socket		*socket;
	volatile int		owner;

	name_t			*name;
	session_t		*session;
	session_t		*acked_backlog_list;
	int			max_acked_backlog;
	volatile struct timeval	sto;
	volatile struct timeval	rto;
	volatile unsigned short	shutdown;

	volatile char 		broadcast;
	struct sockaddr_netbeui	dg_conn_name;
	name_dgrms_t		*dg_namep;

	int			error;
	struct timeval		stamp;
	struct wait_queue **	waitq;
};


/*
 * NetBIOS status data structure
 */ 

struct nb_status
{
	struct nb_status 	*next;

	__u8     		*called_name;
	char			*user_sbuff;
	int			sbuff_len;

	status_rc_t		resp_status;

	volatile status_state_t	state;
	__u8 			retries;	
	int			len_rx_info;
	__u8			no_rx_names;
	__u8			overflowed;
	__u16 			resp_correlator;

	__u8			unicast;
	__u8			remote_mac[MAC_ADDR_LEN];

	struct sk_buff		*tx_skb;
	struct sk_buff		*rx_skb;
	volatile unsigned char	locked;

	struct timer_list 	timer;
	struct wait_queue	*waitq;
};
typedef struct nb_status status_t;



/*
 * NetBIOS datagram packet header 
 */

struct nb_dgram
{
	__u16			length;
	__u16			delimiter;
	__u8			command;
	__u8			data1;
	__u16			data2;
	__u16			xmit_correlator;
	__u16			resp_correlator;
	__u8			dest_name[NB_NAME_LEN];
	__u8			source_name[NB_NAME_LEN];
};
typedef struct nb_dgram dgram_t;


/*
 * NetBIOS session packet header
 */ 

struct nb_packet
{
	__u16			length;
	__u16			delimiter;
	__u8			command;
	__u8			data1;
	__u16			data2;
	__u16			xmit_correlator;
	__u16			resp_correlator;
	__u8			dest_num;
	__u8			source_num;
};
typedef	struct nb_packet packet_t;


/*
 * NetBIOS Configuration Definitions
 */

typedef struct netbeui_config config_t;

extern config_t netbios_config;

#define NB_INACTIVITY_TIMEOUT	(netbios_config.inactivity_timeout * HZ)
#define NB_TRANSMIT_TIMEOUT	(netbios_config.transmit_timeout * (HZ/2))
#define NB_TRANSMIT_COUNT	(netbios_config.transmit_count)
#define NB_RESOURCE_TIMEOUT	(netbios_config.resource_timeout * (HZ/10))
#define NB_DATA_ACK_TIMEOUT	(netbios_config.data_ack_timeout * (HZ/10))


/*
 * Common functions interface
 */ 

extern inline char *
NB_FUNCADDR (struct device *dev);

extern unsigned char
nbcm_apt_dev (struct device *dev);

extern inline int
MAC_HEADLEN (struct device *dev);

extern inline int
LLCMAC_I_HEADLEN (struct device *dev);

extern inline int
LLCMAC_UI_HEADLEN (int mac_hlen);

extern inline int
LLCMAC_UIB_HEADLEN (void);

extern inline int
CALC_DG_SKBLEN (int mac_hlen, int user_datalen);



/*
 * LLC supplement interface
 */

extern int	nbll_attach_session(session_t *session, struct device *dev, unsigned char *remote_mac);
extern int	nbll_link_session(int link_no, unsigned char session_no);
extern int	nbll_isend( int link_no, struct sk_buff *skb);
extern int 	nbll_uisend( unsigned char *remote_maccaddr, struct sk_buff *skb);

extern void	nbll_detach_session(int link_no, unsigned char session_no);
extern int	nbll_drop_link(int link_no);

extern dextab_t * nbll_get_link_table(void);
extern dextab_t * nbll_get_session_table(int link_no);

extern void	nbll_test( void);

 
/*
 * Name service interface
 */

extern unsigned char *	DEV_NAME_NUMBER_1(struct device *dev);
extern int	VALIDATE_NAME(char *name);
extern void	nbns_init_name_number_1(struct device *adapters[]);
extern name_t * nbns_name_number_1(void);

extern int	nbns_add_name( char *name, name_type_t type, name_t **out_name);
extern name_t *	nbns_use_name( name_t *nb_name);
extern name_t *	nbns_find_name( char *nb_name);
extern void	nbns_del_name( name_t *nb_name);
extern void	nbns_del_identifier( unsigned long id);

extern void	nbns_get_add_name_query( struct sk_buff *skb, unsigned char *remote_mac, int type);
extern void	nbns_get_add_name_response( struct sk_buff *skb, unsigned char *remote_mac);
extern void	nbns_get_name_conflict( struct sk_buff *skb);

extern dextab_t * 	nbns_get_name_table(void);
extern name_t * 	nbns_get_name_list(void);

extern int	nbns_count_names(void);

extern void	nbns_test( void);


/*
 * Query service interface
 */

extern void	nbqs_get_name_recognized( struct sk_buff *skb, unsigned char *remote_mac);

extern int	nbqs_query_name(char *called_name, name_t *calling_name, 
                                unsigned char lsn, unsigned char *rsn, 
                                unsigned char *lfb, unsigned short *xmit_correlator);
extern int	nbqs_find_name(char *called_name, char *mac_buff, 
				struct device **dev_buff, int buff_len);
extern void	nbqs_add_rnc(char *name, struct device *dev, unsigned char *mac);
extern void 	nbqs_delete_rnc(char *name);

extern void	nbqs_test( void);


/*
 * Session service interface
 */

extern void 	nbss_get_name_query(struct sk_buff *skb, unsigned char *remote_mac);
extern void	nbss_deliver_frame(session_t *session, struct sk_buff *skb);

extern int 	nbss_call( name_t * calling_name, char * called_name, void *owner,
           			abort_owner_cbt itf_abort_owner, 
           			session_t **session_ptr);

extern int 	nbss_listen( name_t *nb_name, int backlog, void *owner,
           			abort_owner_cbt itf_abort_owner, 
           			session_ready_cbt itf_session_ready);
extern void 	nbss_end_listen( name_t *nb_name);

extern int	nbss_send(session_t *session, unsigned char *buf,
                                unsigned short size, unsigned char nonblock,
                                unsigned char noack);
extern int	nbss_send_zero(session_t *session, char *buff);
extern void	nbss_abort_send(session_t *session);
extern int	nbss_send_ready(session_t *session);

extern int	nbss_receive(session_t *session, unsigned char *buf,
                                unsigned short size, unsigned char nonblock);
extern void	nbss_abort_receive(session_t *session);
extern int	nbss_receive_ready(session_t *session);
extern int	nbss_trim_data(session_t *session);

extern void	nbss_hangup( session_t *session);
extern void	nbss_abort_session( session_t *session);
extern int	nbss_drop_session (int link_no, int session_no);


extern dextab_t * nbss_get_session_table(int link_no);

extern void	nbss_test(char *service_name);


/*
 * DataGram service interface
 */

extern void
nbdg_set_dgbc_mtu (void);

extern int
nbdg_remove_unwanted_dgf (name_dgrms_t *namep, int len);

extern void
nbdg_register_peername (name_dgrms_t *namep, char *remote_name);

extern void
nbdg_deregister_peername (name_dgrms_t *namep);

extern int
nbdg_add_name (char *local_name, struct wait_queue **wq, name_dgrms_t **namep);

extern void
nbdg_del_name (name_dgrms_t *namep);

extern int
nbdg_receive_ready (name_dgrms_t *namep);

extern int
nbdg_send (char *local_name, char *dest_name, name_type_t dest_type, char *buff,                                       int bufflen);
extern int
nbdg_receive (name_dgrms_t *namep, char *source_name, char *dest_name,
					char *buff, int bufflen, int nonblock);

extern void
nbdg_get_datagram (struct sk_buff *skb);

extern void
nbdg_get_datagram_broadcast (struct sk_buff *skb);


/*
 * Socket Supplement Interface
 */

extern int	nbso_init(void);
extern int	nbso_exit(void);


/*
 * Status service interface
 */

void
nbst_init_status (void);

int
nbst_obtain_status (char *called_name, char *status_buff, int *buff_len);

void
nbst_get_status_query (struct sk_buff *skb, unsigned char *remote_mac);

void
nbst_get_status_response (struct sk_buff *skb, unsigned char *remote_mac);


/*
 * PROC entry interface
 */

extern void	proc_init(void);
extern void	proc_clean(void);


/*
 * Configuration system interface
 */ 

extern int	nbcs_setsockopt(struct socket *sock, int optname, void *optval, int optlen);
extern int 	nbcs_getsockopt(struct socket *sock, int optname, void *optval, int *optlen);
extern int 	nbcs_ioctl (unsigned int cmd, void *arg);



#endif __LINUX_NETBEUI_H
