/*
 *
 *			   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
 *
 */

/*
 * IPSEC <> netlink interface
 */


#define PFENCAP_VERSION_0	0
#define PFENCAP_VERSION_1	1

/*
 * SENT_HDRLEN is the length of the "header"
 * SENT_*_LEN are the lengths of various forms of sen_data
 * SENT_*_OFF are the offsets in the sen_data array of various fields
 */

#define SENT_HDRLEN	(2 * sizeof(__u8) + sizeof(__u16))

#define SENT_IP4_SRCOFF	(0)
#define SENT_IP4_DSTOFF (sizeof (struct in_addr))

#define SENT_IP4_LEN	20
#define SENT_IPSP_LEN	20

/*
 * Tunnel descriptors are setup and torn down using a socket of the 
 * AF_ENCAP domain. The following defines the messages that can
 * be sent down that socket.
 */
struct encap_msghdr
{
    __u16	em_msglen;		/* message length */
    __u8	em_version;		/* for future expansion */
    __u8	em_type;		/* message type */
    __u32   foo;                    /* Alignment to 64 bit */
    union
    {
	struct
	{
		struct sockaddr_encap Eaddr;
		struct sockaddr_encap Emask;
		struct in_addr Dst;
		__u32 Spi;
		__u8  Sproto;
	} Ert;

	/* 
	 * This is used to set/change the attributes of an SPI. If oSrc and
	 * oDst are set to non-zero values, the SPI will also do IP-in-IP
	 * encapsulation (tunneling). If only one of them is set, an error
	 * is returned. Both zero implies transport mode.
	 */
	struct
	{
	    __u32      Spi;		/* SPI */
	    __s32      Alg;		/* Algorithm to use */
	    struct in_addr Dst;		/* Destination address */
	    struct in_addr Src;		/* This is used to set our source
					 * address when the outgoing packet
				         * does not have a source address 
					 * (is zero). */
	    struct in_addr oSrc;	 /* Outter header source address */
	    struct in_addr oDst;	 /* Same, for destination address */
	    __u64      First_Use_Hard; /* Expire relative to first use */
	    __u64      First_Use_Soft;
	    __u64      Expire_Hard;	/* Expire at fixed point in time */
	    __u64      Expire_Soft;
	    __u64      Bytes_Hard;	/* Expire after bytes recved/sent */
	    __u64      Bytes_Soft;
	    __u64      Packets_Hard; /* Expire after packets recved/sent */
	    __u64      Packets_Soft;
	    __s32      TTL;		/* When tunneling, what TTL to use.
					 * If set to IP4_SAME_TTL, the ttl
					 * from the encapsulated packet will
					 * be copied. If set to IP4_DEFAULT_TTL,
					 * the system default TTL will be used.
					 * If set to anything else, then the
					 * ttl used will be TTL % 256 */
	    __u16      Satype;
	    __u8       Sproto;	/* ESP or AH */
	    __u8	   Foo;		/* Alignment */
	    __u8       Dat[1];	/* Data */
	} Xfm;

	/*
 	 * For expiration notifications, the kernel fills in
	 * Notification_Type, Spi, Dst and Sproto, Src and Satype.
  	 * No direct response is expected.
	 *
 	 * For SA Requests, the kernel fills in
	 * Notification_Type, MsgID, Dst, Satype, (and optionally
	 * Protocol, Src, Sport, Dport and UserID).
 	 *
	 */
	struct				/* kernel->userland notifications */
	{
	    __u32      Notification_Type;
	    __u32      MsgID;	/* Request ID */
	    __u32      Spi;		
	    struct in_addr Dst;		/* Peer */
	    struct in_addr Src;		/* Might have our local address */
	    __u16      Sport;	/* Source port */
            __u16      Dport;	/* Destination port */
	    __u8       Protocol;	/* Transport protocol */
	    __u8       Sproto;	/* IPsec protocol */
	    __u16      Satype;	/* SA type */
	    __u32      Foo;		/* Alignment */
	    __u8       UserID[1];	/* Might be used to indicate user */
	} Notify;

	/* Link two SPIs */
	struct
	{
	    __u32        Spi;	/* SPI */
	    __u32        Spi2;
	    struct in_addr   Dst;	/* Dest */
	    struct in_addr   Dst2;
	    __u8	     Sproto; 	/* IPsec protocol */
	    __u8	     Sproto2;
	} Rel;

	/* Enable/disable an SA for a session */
	struct
	{
	    __u32      Spi;
	    struct in_addr Dst;
	    struct in_addr iSrc;	/* Source... */
	    struct in_addr iDst;	/* ...and destination in inner IP */
	    struct in_addr iSmask;	/* Source netmask */
	    struct in_addr iDmask;	/* Destination netmask */
	    __u16	   Sport; 	/* Source port, if applicable */
	    __u16	   Dport;	/* Destination port, if applicable */
	    __u8       Protocol;	/* Transport mode for which protocol */
	    __u8 	   Sproto;	/* IPsec protocol */
	    __u16	   Flags;
	    __u32      Spi2;	/* Used in REPLACESPI... */
	    struct in_addr Dst2;	/* ...to specify which SPI is... */
	    __u8       Sproto2;	/* ...replaced. */
	} Ena;

	/* For general use: (in)validate, delete (chain), reserve */
	struct 
	{
	    __u32       Spi;
	    struct in_addr  Dst;
	    __u8	    Sproto;
	} Gen;
    } Eu;
};

#define ENABLE_FLAG_REPLACE    	1
#define ENABLE_FLAG_LOCAL      	2

#define ENCAP_MSG_FIXED_LEN    	(2 * sizeof(__u32))

#define NOTIFY_SOFT_EXPIRE     	0	/* Soft expiration of SA */
#define NOTIFY_HARD_EXPIRE     	1	/* Hard expiration of SA */
#define NOTIFY_REQUEST_SA      	2	/* Establish an SA */

#define NOTIFY_SATYPE_CONF	0	/* SA should do encryption */
#define NOTIFY_SATYPE_AUTH	1	/* SA should do authentication */
#define NOTIFY_SATYPE_TUNNEL	2	/* SA should use tunneling */

#define em_ena_spi	  Eu.Ena.Spi
#define em_ena_dst	  Eu.Ena.Dst
#define em_ena_isrc	  Eu.Ena.iSrc
#define em_ena_idst	  Eu.Ena.iDst
#define em_ena_ismask	  Eu.Ena.iSmask
#define em_ena_idmask	  Eu.Ena.iDmask
#define em_ena_sport	  Eu.Ena.Sport
#define em_ena_dport	  Eu.Ena.Dport
#define em_ena_protocol   Eu.Ena.Protocol
#define em_ena_sproto	  Eu.Ena.Sproto
#define em_ena_flags	  Eu.Ena.Flags

#define em_gen_spi        Eu.Gen.Spi
#define em_gen_dst        Eu.Gen.Dst
#define em_gen_sproto	  Eu.Gen.Sproto

#define em_not_type       Eu.Notify.Notification_Type
#define em_not_spi        Eu.Notify.Spi
#define em_not_dst        Eu.Notify.Dst
#define em_not_satype     Eu.Notify.Satype
#define em_not_userid     Eu.Notify.UserID
#define em_not_msgid      Eu.Notify.MsgID
#define em_not_sport      Eu.Notify.Sport
#define em_not_dport      Eu.Notify.Dport
#define em_not_protocol   Eu.Notify.Protocol
#define em_not_sproto	  Eu.Notify.Sproto

#define em_spi	          Eu.Xfm.Spi
#define em_dst	          Eu.Xfm.Dst
#define em_src	          Eu.Xfm.Src
#define em_osrc	          Eu.Xfm.oSrc
#define em_odst	          Eu.Xfm.oDst
#define em_alg	          Eu.Xfm.Alg
#define em_dat	          Eu.Xfm.Dat
#define em_first_use_hard Eu.Xfm.First_Use_Hard
#define em_first_use_soft Eu.Xfm.First_Use_Soft
#define em_expire_hard    Eu.Xfm.Expire_Hard
#define em_expire_soft    Eu.Xfm.Expire_Soft
#define em_bytes_hard     Eu.Xfm.Bytes_Hard
#define em_bytes_soft     Eu.Xfm.Bytes_Soft
#define em_packets_hard   Eu.Xfm.Packets_Hard
#define em_packets_soft   Eu.Xfm.Packets_Soft
#define em_ttl		  Eu.Xfm.TTL
#define em_sproto	  Eu.Xfm.Sproto
#define em_satype         Eu.Xfm.Satype

#define em_rel_spi	  Eu.Rel.Spi
#define em_rel_spi2	  Eu.Rel.Spi2
#define em_rel_dst	  Eu.Rel.Dst
#define em_rel_dst2	  Eu.Rel.Dst2
#define em_rel_sproto	  Eu.Rel.Sproto
#define em_rel_sproto2	  Eu.Rel.Sproto2

#define em_eaddr Eu.Ert.Eaddr
#define em_emask Eu.Ert.Emask
#define em_erdst Eu.Ert.Dst
#define em_erspi Eu.Ert.Spi
#define em_ersproto Eu.Ert.Sproto

#define EMT_SETSPI	1		/* Set SPI properties */
#define EMT_GRPSPIS	2		/* Group SPIs */
#define EMT_DELSPI	3		/* delete an SPI */
#define EMT_DELSPICHAIN 4		/* delete an SPI chain starting from */
#define EMT_RESERVESPI  5		/* Give us an SPI */
#define EMT_ENABLESPI   6		/* Enable an SA */
#define EMT_DISABLESPI  7		/* Disable an SA */
#define EMT_NOTIFY      8		/* kernel->userland key mgmt not. */
#define EMT_REPLACESPI  10		/* Replace all uses of an SA */
#define	EMT_SETEROUTE	11
#define	EMT_DELEROUTE	12
#define	EMT_TESTROUTE	13

/* Total packet lengths */
#define EMT_SETSPI_FLEN	      104
#define EMT_GRPSPIS_FLEN      26
#define EMT_GENLEN            17
#define EMT_DELSPI_FLEN       EMT_GENLEN
#define EMT_DELSPICHAIN_FLEN  EMT_GENLEN
#define EMT_RESERVESPI_FLEN   EMT_GENLEN
#define EMT_NOTIFY_FLEN       40
#define EMT_ENABLESPI_FLEN    49
#define EMT_DISABLESPI_FLEN   EMT_ENABLESPI_FLEN
#define EMT_REPLACESPI_FLEN   EMT_ENABLESPI_FLEN

extern int ipsec_callback(struct sk_buff *skb);

#ifdef DEBUG_IPSEC_NETLINK

extern int debug_netlink;

#define DB_NL_TDBCB	0x0001

#endif
