/*
 *
 *			   IPSEC for Linux
 *		         Preliminary Release
 * 
 *	 Copyright (C) 1996, 1997, John Ioannidis <ji@hol.gr>
 * 
 * Changes by Angelos D. Keromytis and Niels Provos
 * ported from OpenBSD 2.2 by Petr Novak, <pn@i.cz>
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 *
 */

/*
 * $Id: ipsec_xform.h,v 0.5 1997/06/03 04:24:48 ji Rel $
 *
 * $Log: ipsec_xform.h,v $
 * Revision 0.5  1997/06/03 04:24:48  ji
 * Added ESP-3DES-MD5-96
 *
 * Revision 0.4  1997/01/15 01:28:15  ji
 * Added new transforms.
 *
 * Revision 0.3  1996/11/20 14:39:04  ji
 * Minor cleanups.
 * Rationalized debugging code.
 *
 * Revision 0.2  1996/11/02 00:18:33  ji
 * First limited release.
 *
 *
 */

/*
 * Definitions relevant to IPSEC transformations.
 */

struct expiration
{
	__u32             exp_timeout;
	struct in_addr    exp_dst;
	__u32             exp_spi;
	__u8              exp_sproto;
	struct expiration *exp_next;
	struct expiration *exp_prev;
};

struct flow
{
    struct flow     *flow_next;         /* Next in flow chain */
    struct flow     *flow_prev;         /* Previous in flow chain */
    struct tdb      *flow_sa;           /* Pointer to the SA */
    struct in_addr   flow_src;          /* Source address */
    struct in_addr   flow_srcmask;      /* Source netmask */
    struct in_addr   flow_dst;          /* Destination address */
    struct in_addr   flow_dstmask;      /* Destination netmask */
    __u16            flow_sport;        /* Source port, if applicable */
    __u16            flow_dport;        /* Destination port, if applicable */
    __u16            flow_proto;        /* Transport protocol, if applicable */
    __u8             foo[3];            /* Alignment */
};

struct tdb				/* tunnel descriptor block */
{
	struct tdb	*tdb_hnext;	/* next in hash chain */
	struct tdb	*tdb_onext;	/* next in output */
	struct tdb	*tdb_inext;	/* next in input (prev!) */
	struct xformsw	*tdb_xform;	/* transformation to use */
	__u32		tdb_spi;	/* SPI to use (in network order)*/
	__u32		tdb_flags;	/* Flags related to this TDB */
#define TDBF_UNIQUE        0x00001      /* This should not be used by others */
#define TDBF_TIMER         0x00002      /* Absolute expiration timer in use */
#define TDBF_BYTES         0x00004      /* Check the byte counters */
#define TDBF_PACKETS       0x00008      /* Check the packet counters */
#define TDBF_INVALID       0x00010      /* This SPI is not valid yet/anymore */
#define TDBF_FIRSTUSE      0x00020      /* Expire after first use */
#define TDBF_TUNNELING     0x00040      /* Do IP-in-IP encapsulation */
#define TDBF_SOFT_TIMER    0x00080      /* Soft expiration */
#define TDBF_SOFT_BYTES    0x00100      /* Soft expiration */
#define TDBF_SOFT_PACKETS  0x00200      /* Soft expiration */
#define TDBF_SOFT_FIRSTUSE 0x00400      /* Soft expiration */
#define TDBF_SAME_TTL      0x00800	/* Keep the packet TTL, in tunneling */
	__u64		tdb_exp_packets; /* Expire after so many packets s|r */
	__u64		tdb_soft_packets; /* Expiration warning */
	__u64		tdb_cur_packets; /* Current number of packets s|r'ed */
	__u64		tdb_exp_bytes;	/* Expire after so many bytes passed */
	__u64		tdb_soft_bytes;	/* Expiration warning */
	__u64		tdb_cur_bytes;	/* Current count of bytes */
	__u64		tdb_exp_timeout; /* When does the SPI expire */
	__u64		tdb_soft_timeout; /* Send a soft-expire warning */
	__u64		tdb_established; /* When was the SPI established */
	__u64		tdb_first_use;	/* When was it first used */
	__u64		tdb_soft_first_use; /* Soft warning */
	__u64		tdb_exp_first_use; /* Expire if tdb_first_use +
					      tdb_exp_first_use <= curtime */
	struct in_addr	tdb_dst;	/* dest address for this SPI */
	struct in_addr	tdb_src;	/* source address for this SPI,
					 * used when tunneling */
	struct in_addr	tdb_osrc;
	struct in_addr	tdb_odst;	/* Source and destination addresses
					 * of outter IP header if we're doing
					 * tunneling */
	caddr_t		tdb_xdata;	/* transformation data (opaque) */
	struct flow	*tdb_flow;	/* Which flows use this SA */
	
	__u8		tdb_ttl;	/* TTL used in tunneling */
	__u8		tdb_sproto;	/* IPSec protocol */
	__u16		tdb_satype;	/* Alignment */
	__u32		tdb_epoch;	/* Used by the kernfs interface */
	__u8		*tdb_confname;	/* Used by the kernfs interface */
	__u8		*tdb_authname;	/* Used by the kernfs interface */
};

#define TDB_HASHMOD	257

struct xformsw
{
	u_short		xf_type;	/* Unique ID of xform */
	u_short		xf_flags;	/* secondary type reall) */
	char		*xf_name;	/* human-readable name */
	int		(*xf_attach)(void);	/* called at config time */
	int		(*xf_init)(struct tdb *tdbp, struct xformsw *xsp, struct encap_msghdr *em);	/* xform initialization */
	int		(*xf_zeroize)(struct tdb *);	/* termination */
	int		(*xf_print)(void *, char *);	/* /proc printing */
	int		(*xf_room)(struct tdb *, int, int, int *, int *); /* required head/tail room  */
	struct sk_buff 	*(*xf_input)(struct sk_buff *, struct tdb *);	/* called when packet received */
	int		(*xf_output)(struct sk_buff *, struct tdb *); /* called when packet sent */
};

#define XF_IP4		1		/* IP inside IP */
#define XF_OLD_AH	2		/* RFCs 1828 & 1852 */
#define XF_OLD_ESP	3		/* RFCs 1829 & 1851 */
#define XF_NEW_AH	4		/* AH HMAC 96bits */
#define XF_NEW_ESP	5		/* ESP + auth 96bits + replay counter */

/* Supported key hash algorithms */
#define ALG_AUTH_MD5	1
#define ALG_AUTH_SHA1	2
#define ALG_AUTH_RMD160 3

/* Supported encryption algorithms */
#define ALG_ENC_DES	1
#define ALG_ENC_3DES	2
#define ALG_ENC_BLF     3
#define ALG_ENC_CAST    4

#if 0
#define XF_IP4		1		/* IP inside IP */
#define XF_AHMD5	2		/* AH MD5 */
#define XF_AHSHA	3		/* AH SHA */
#define XF_ESPDES	4		/* ESP DES-CBC */
#define XF_ESP3DES	5		/* ESP DES3-CBC */
#define XF_AHHMACMD5	6		/* AH-HMAC-MD5 with opt replay prot */
#define XF_AHHMACSHA1	7		/* AH-HMAC-SHA1 with opt replay prot */
#define XF_ESPDESMD5	8
#define XF_ESP3DESMD5	9
#define	XF_ESP3DESMD596	10	/* triple DES, HMAC-MD-5 with 96-bits of authentication */
#define	XF_ESPDESMD596	11	/* HMAC-MD-5 with 96-bits of authentication */
#endif

#define XFT_AUTH	0x0001
#define XFT_CONF	0x0100

#define	IPSEC_ZEROES_SIZE	64

#ifdef	__KERNEL__
extern unsigned char ipseczeroes[IPSEC_ZEROES_SIZE];

struct tdb *tdbh[TDB_HASHMOD];
extern struct xformsw xformsw[], *xformswNXFORMSW;

/* TDB management routines */
extern struct tdb *gettdb(u_long, struct in_addr, __u8);
extern __u32 reserve_spi(__u32, struct in_addr, __u8, int *);
extern void puttdb(struct tdb *);
extern int tdb_delete(struct tdb *, int);
extern int tdb_init(struct tdb *, struct encap_msghdr *);

/* Flow management routines */
extern struct flow *get_flow(void);
extern void put_flow(struct flow *, struct tdb *);
extern void delete_flow(struct flow *, struct tdb *);
extern struct flow *find_flow(struct in_addr, struct in_addr, struct in_addr,
                              struct in_addr, __u8, __u16, __u16,
                              struct tdb *);
extern struct flow *find_global_flow(struct in_addr, struct in_addr,
                                     struct in_addr, struct in_addr, __u8,
                                     __u16, __u16);

/* XF_IP4 */
extern int ipe4_attach(void);
extern int ipe4_init(struct tdb *, struct xformsw *, struct encap_msghdr *);
extern int ipe4_zeroize(struct tdb *);
extern int ipe4_print(void *, char *);
extern int ipe4_room(struct tdb *, int, int, int *, int *);
extern struct sk_buff *ipe4_input(struct sk_buff *, struct tdb *);
extern int ipe4_output(struct sk_buff *, struct tdb *);

/* XF_OLD_AH */
extern int ah_old_attach(void);
extern int ah_old_init(struct tdb *, struct xformsw *, struct encap_msghdr *);
extern int ah_old_zeroize(struct tdb *);
extern int ah_old_print(void *, char *);
extern int ah_old_room(struct tdb *, int, int, int *, int *);
extern struct sk_buff *ah_old_input(struct sk_buff *, struct tdb *);
extern int ah_old_output(struct sk_buff *, struct tdb *);

/* XF_NEW_AH */
extern int ah_new_attach(void);
extern int ah_new_init(struct tdb *, struct xformsw *, struct encap_msghdr *);
extern int ah_new_zeroize(struct tdb *);
extern int ah_new_print(void *, char *);
extern int ah_new_room(struct tdb *, int, int, int *, int *);
extern struct sk_buff *ah_new_input(struct sk_buff *, struct tdb *);
extern int ah_new_output(struct sk_buff *, struct tdb *);

/* XF_OLD_ESP */
extern int esp_old_attach(void);
extern int esp_old_init(struct tdb *, struct xformsw *, struct encap_msghdr *);
extern int esp_old_zeroize(struct tdb *);
extern int esp_old_print(void *, char *);
extern int esp_old_room(struct tdb *, int, int, int *, int *);
extern struct sk_buff *esp_old_input(struct sk_buff *, struct tdb *);
extern int esp_old_output(struct sk_buff *, struct tdb *);

/* XF_NEW_ESP */
extern int esp_new_attach(void);
extern int esp_new_init(struct tdb *, struct xformsw *, struct encap_msghdr *);
extern int esp_new_zeroize(struct tdb *);
extern int esp_new_print(void *, char *);
extern int esp_new_room(struct tdb *, int, int, int *, int *);
extern struct sk_buff *esp_new_input(struct sk_buff *, struct tdb *);
extern int esp_new_output(struct sk_buff *, struct tdb *);

/* Replay window (common to NEW_AH and NEW_ESP) */
extern int checkreplaywindow32(__u32, __u32, __u32 *, __u32, __u32 *);

#ifdef DEBUG_IPSEC_XFORM

extern int debug_xform;

#define DB_XF_INIT	0x0001

#endif
#endif /* __KERNEL__ */
