/*
 *	NET3:	Implementation of protocol layer support routines.
 *
 *		Alan Cox, <A.Cox@swansea.ac.uk / gw4pts@gw4pts.ampr.org>
 *
 *	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.
 */
 
#ifndef _LINUX_NETPROTOCOL_H
#define _LINUX_NETPROTOCOL_H

/*
 *	Hook entries. We have these so we can do multiple binds easily.
 */
 
struct binding
{
	struct protocol *owner;
	struct binding *next;
	struct binding *next_demul;
	int usage;
	unsigned char key[8];
	unsigned char keysize;
	unsigned char copying;
};

/*
 *	This is for now very incomplete and just holds the bits we use.
 */
 
struct protocol
{
	struct protocol *next;
	char *name;
	unsigned short base_header_space;
	unsigned short base_tail_space;
	unsigned short header_space;
	unsigned short tail_space;
	int (*output)(struct protocol *self, sk_buff *skb, int type, int subid, void *saddr, void *daddr, void *protoopts);
#ifdef CONFIG_FAST_PATH	
	int (*fast_output)(sk_buff *skb, char *dp, int priority, int count);
	int (*build_fast_headers)(struct device *dev,int slot, char *dp, int type, int subid, void *saddr, void *daddr, void *protoopts);
#endif	
	int (*input)(struct protocol *self, struct protocol *p,sk_buff *skb, void *saddr, void *daddr);
	int (*bh_input)(struct protocol *self, struct protocol *p,sk_buff *skb, void *saddr, void *daddr);
	int (*control_event)(struct protocol *proto, struct protocol *src, int event, void *arg);
	int (*get_binding)(int protocol, int subid, unsigned char *key);
	struct binding *upper;
	struct binding *lower;
	struct protocol *stream_up;
	struct protocol *stream_down;
	int flags;
#define PF_TEMP		1	
	struct binding *demultiplex[16];
	void *user;		/* User pointer */
	struct device  *device;	/* Device this instance is attached to (if any) */
};
	
#define CTL_HEAD_CHANGE_BELOW	1
#define CTL_DISCONNECT_BELOW	2
#define CTL_BOUND_BELOW		3
#define CTL_TAIL_CHANGE_BELOW	4
#define CTL_DISCONNECT_ABOVE	128
#define CTL_BOUND_ABOVE		129

#ifdef __KERNEL__
/*
 *	Control functions
 */
 
/* 
 *	Bind protocols: These will become private to protocol.c once it is all completed.
 */
extern void protocol_unhook_lower(struct protocol *us, struct protocol *lower, unsigned char *key, int keysize);
extern void protocol_unhook_upper(struct protocol *us, struct protocol *upper, unsigned char *key, int keysize);
extern struct binding *protocol_hook_lower(struct protocol *us, struct protocol *lower, unsigned char *key, int keysize);
extern struct binding *protocol_hook_upper(struct protocol *us, struct protocol *upper, unsigned char *key, int keysize);
/*
 *	Register and find protocols. These are publically available facilities
 */
extern void protocol_register(struct protocol *proto);
extern int protocol_unregister(struct protocol *proto);
extern struct protocol *protocol_find(char *name);
extern struct protocol *protocol_find_instance(char *name, struct device *dev);
extern struct protocol *protocol_clone(struct protocol *proto);
extern struct protocol *protocol_clone_keep(struct protocol *proto);
extern void protocol_delete(struct protocol *proto);
/*
 *	Pass control messages up and down the protocol layers.
 */
extern void protocol_inform_lower(struct protocol *self, int op, void *arg);
extern void protocol_inform_upper(struct protocol *self, int op, void *arg);
/*
 *	Layer binding.
 */
extern int protocol_bind(struct protocol *lower, struct protocol *upper, int proto, int subid);
extern void protocol_unbind(struct protocol *lower, struct protocol *upper, int proto, int subid);
/*
 *	Default event handler
 */
extern int default_protocol_control(struct protocol *self, struct protocol *src, int op, void *arg);
/*
 *	Utilities (will be going inline)
 */
extern unsigned short protocol_size(struct protocol *p);
extern void protocol_adjust(sk_buff *skb, struct protocol *proto);
/*
 *	Demultiplexors
 */
extern void protocol_demultiplex_add(struct protocol *lower, struct binding *self);
extern void protocol_demultiplex_remove(struct protocol *lower, struct protocol *self, unsigned char *key,int keylen);
extern struct binding *protocol_byte_demultiplex(struct protocol *self, unsigned char *key);
extern struct binding *protocol_demultiplex(struct protocol *self, unsigned char *key);
extern struct binding *protocol_byte_next(struct binding *p, unsigned char *key);
extern struct binding *protocol_next(struct binding *p, unsigned char *key);
/*
 *	Input support
 */
extern int protocol_pass_demultiplex(struct protocol *self, void *key, sk_buff *skb, void *saddr, void *daddr);
extern int protocol_defer(struct protocol *pr, struct protocol *lower, sk_buff *skb, void *saddr, void *daddr);
extern void net_bh(void *tmp);
/*
 *	Output support
 */
#ifdef CONFIG_FAST_PATH 
extern int protocol_default_build_fast(struct device *dev, int slot, char *dp, int type, int subid, void *saddr, void *daddr, void *protoopts);
extern int protocol_default_fast_output(sk_buff *skb, char *dp, int priority, int count);
#endif
#endif
#endif