First attempt at a GTP1 implementation
diff --git a/gtp/gtp.h b/gtp/gtp.h
index d21cbb4..123339b 100644
--- a/gtp/gtp.h
+++ b/gtp/gtp.h
@@ -89,6 +89,55 @@
 /* 242-254 For future use. */
 #define GTP_GPDU            255 /* G-PDU */
 
+
+/* GTP information element cause codes from 29.060 v3.9.0 7.7 */
+/*                                                            */
+#define GTPCAUSE_REQ_IMSI                   0 /* Request IMSI */
+#define GTPCAUSE_REQ_IMEI                   1 /* Request IMEI */
+#define GTPCAUSE_REQ_IMSI_IMEI              2 /* Request IMSI and IMEI */
+#define GTPCAUSE_NO_ID_NEEDED               3 /* No identity needed */
+#define GTPCAUSE_MS_REFUSES_X               4 /* MS refuses */
+#define GTPCAUSE_MS_NOT_RESP_X              5 /* MS is not GPRS responding */
+#define GTPCAUSE_006                        6 /* For future use 6-48 */
+#define GTPCAUSE_049                       49 /* Cause values reserved for GPRS charging protocol use (See GTP' in GSM 12.15) 49-63 */
+#define GTPCAUSE_064                       64 /* For future use 64-127 */
+#define GTPCAUSE_ACC_REQ                  128 /* Request accepted */
+#define GTPCAUSE_129                      129 /* For future use 129-176 */
+#define GTPCAUSE_177                      177 /* Cause values reserved for GPRS charging protocol use (See GTP' In GSM 12.15) 177-191 */
+#define GTPCAUSE_NON_EXIST                192 /* Non-existent */
+#define GTPCAUSE_INVALID_MESSAGE          193 /* Invalid message format */
+#define GTPCAUSE_IMSI_NOT_KNOWN           194 /* IMSI not known */
+#define GTPCAUSE_MS_DETACHED              195 /* MS is GPRS detached */
+#define GTPCAUSE_MS_NOT_RESP              196 /* MS is not GPRS responding */
+#define GTPCAUSE_MS_REFUSES               197 /* MS refuses */
+#define GTPCAUSE_198                      198 /* For future use */
+#define GTPCAUSE_NO_RESOURCES             199 /* No resources available */
+#define GTPCAUSE_NOT_SUPPORTED            200 /* Service not supported */
+#define GTPCAUSE_MAN_IE_INCORRECT         201 /* Mandatory IE incorrect */
+#define GTPCAUSE_MAN_IE_MISSING           202 /* Mandatory IE missing */
+#define GTPCAUSE_OPT_IE_INCORRECT         203 /* Optional IE incorrect */
+#define GTPCAUSE_SYS_FAIL                 204 /* System failure */
+#define GTPCAUSE_ROAMING_REST             205 /* Roaming Restriction */
+#define GTPCAUSE_PTIMSI_MISMATCH          206 /* P-TMSI signature mismatch */
+#define GTPCAUSE_CONN_SUSP                207 /* GPRS connection suspended */
+#define GTPCAUSE_AUTH_FAIL                208 /* Authentication failure */
+#define GTPCAUSE_USER_AUTH_FAIL           209 /* User authentication failed */
+#define GTPCAUSE_CONTEXT_NOT_FOUND        210 /* Context not found */
+#define GTPCAUSE_ADDR_OCCUPIED            211 /* All dynamic PDP addresses are occupied */
+#define GTPCAUSE_NO_MEMORY                212 /* No memory is available */
+#define GTPCAUSE_RELOC_FAIL               213 /* Relocation failure */
+#define GTPCAUSE_UNKNOWN_MAN_EXTHEADER    214 /* Unknown mandatory extension header */
+#define GTPCAUSE_SEM_ERR_TFT              215 /* Semantic error in the TFT operation */
+#define GTPCAUSE_SYN_ERR_TFT              216 /* Syntactic error in the TFT operation */
+#define GTPCAUSE_SEM_ERR_FILTER           217 /* Semantic errors in packet filter(s) */
+#define GTPCAUSE_SYN_ERR_FILTER           218 /* Syntactic errors in packet filter(s) */
+#define GTPCAUSE_MISSING_APN              219 /* Missing or unknown APN*/
+#define GTPCAUSE_UNKNOWN_PDP              220 /* Unknown PDP address or PDP type */
+#define GTPCAUSE_221                      221 /* For Future Use 221-240 */
+#define GTPCAUSE_241                      241 /* Cause Values Reserved For Gprs Charging Protocol Use (See Gtp' In Gsm 12.15) 241-255 */
+
+
+
 /* GTP 0 header. 
  * Explanation to some of the fields:
  * SNDCP NPDU Number flag = 0 except for inter SGSN handover situations
@@ -100,49 +149,49 @@
  * Tunnel ID is IMSI+NSAPI. Unique identifier of PDP context. Is somewhat
  *   redundant because the header also includes flow. */
 
-struct gtp0_header {            /*    Descriptions from 3GPP 09.60 */
-	u_int8_t  flags;        /* 01 bitfield, with typical values */
-                                /*    000..... Version: 1 (0) */
-                                /*    ...1111. Spare (7) */
-                                /*    .......0 SNDCP N-PDU Number flag (0) */
-	u_int8_t  type;	        /* 02 Message type. T-PDU = 0xff */
-	u_int16_t length;	/* 03 Length (of G-PDU excluding header) */
-	u_int16_t seq;	        /* 05 Sequence Number */
-	u_int16_t flow;	        /* 07 Flow Label ( = 0 for signalling) */
-	u_int8_t  number;	/* 09 SNDCP N-PDU LCC Number ( 0 = 0xff) */
-	u_int8_t  spare1;	/* 10 Spare */
-	u_int8_t  spare2;	/* 11 Spare */
-	u_int8_t  spare3;	/* 12 Spare */
-	u_int64_t tid;		/* 13 Tunnel ID */
-};                              /* 20 */
+struct gtp0_header {    /*    Descriptions from 3GPP 09.60 */
+  u_int8_t  flags;      /* 01 bitfield, with typical values */
+                        /*    000..... Version: 1 (0) */
+                        /*    ...1111. Spare (7) */
+                        /*    .......0 SNDCP N-PDU Number flag (0) */
+  u_int8_t  type;	        /* 02 Message type. T-PDU = 0xff */
+  u_int16_t length;	/* 03 Length (of G-PDU excluding header) */
+  u_int16_t seq;	        /* 05 Sequence Number */
+  u_int16_t flow;	        /* 07 Flow Label ( = 0 for signalling) */
+  u_int8_t  number;	/* 09 SNDCP N-PDU LCC Number ( 0 = 0xff) */
+  u_int8_t  spare1;	/* 10 Spare */
+  u_int8_t  spare2;	/* 11 Spare */
+  u_int8_t  spare3;	/* 12 Spare */
+  u_int64_t tid;	/* 13 Tunnel ID */
+};                      /* 20 */
 
-struct gtp1_header_short {      /*     Descriptions from 3GPP 29060 */
-	u_int8_t  flags;        /* 01 bitfield, with typical values */
-                                /*    000..... Version: 1 */
-                                /*    ...1.... Protocol Type: GTP=1, GTP'=0 */
-                                /*    ....1... Spare = 1 */
-                                /*    .....1.. Extension header flag: 1 */
-                                /*    ......1. Sequence number flag: 1 */
-                                /*    .......0 PN: N-PDU Number flag */
-	u_int8_t  type;		/* 02 Message type. T-PDU = 0xff */
-	u_int16_t length;	/* 03 Length (of IP packet or signalling) */
-	u_int64_t tid;		/* 05 - 08 Tunnel ID */
+struct gtp1_header_short { /*    Descriptions from 3GPP 29060 */
+  u_int8_t  flags;         /* 01 bitfield, with typical values */
+                           /*    001..... Version: 1 */
+                           /*    ...1.... Protocol Type: GTP=1, GTP'=0 */
+                           /*    ....0... Spare = 0 */
+                           /*    .....0.. Extension header flag: 0 */
+                           /*    ......0. Sequence number flag: 0 */
+                           /*    .......0 PN: N-PDU Number flag */
+  u_int8_t  type;	   /* 02 Message type. T-PDU = 0xff */
+  u_int16_t length;	   /* 03 Length (of IP packet or signalling) */
+  u_int32_t tei;           /* 05 - 08 Tunnel Endpoint ID */
 };
 
-struct gtp1_header_long {       /*     Descriptions from 3GPP 29060 */
-	u_int8_t  flags;        /* 01 bitfield, with typical values */
-                                /*    000..... Version: 1 */
-                                /*    ...1.... Protocol Type: GTP=1, GTP'=0 */
-                                /*    ....1... Spare = 1 */
-                                /*    .....1.. Extension header flag: 1 */
-                                /*    ......1. Sequence number flag: 1 */
-                                /*    .......0 PN: N-PDU Number flag */
-	u_int8_t  type;		/* 02 Message type. T-PDU = 0xff */
-	u_int16_t length;	/* 03 Length (of IP packet or signalling) */
-	u_int64_t tid;		/* 05 Tunnel ID */
-	u_int16_t seq;	        /* 10 Sequence Number */
-	u_int8_t  npdu;		/* 11 N-PDU Number */
-	u_int8_t  next;		/* 12 Next extension header type. Empty = 0 */
+struct gtp1_header_long {  /*    Descriptions from 3GPP 29060 */
+  u_int8_t  flags;         /* 01 bitfield, with typical values */
+                           /*    001..... Version: 1 */
+                           /*    ...1.... Protocol Type: GTP=1, GTP'=0 */
+                           /*    ....0... Spare = 0 */
+                           /*    .....0.. Extension header flag: 0 */
+                           /*    ......1. Sequence number flag: 1 */
+                           /*    .......0 PN: N-PDU Number flag */
+  u_int8_t  type;	   /* 02 Message type. T-PDU = 0xff */
+  u_int16_t length;	   /* 03 Length (of IP packet or signalling) */
+  u_int32_t tei;	   /* 05 Tunnel Endpoint ID */
+  u_int16_t seq;	   /* 10 Sequence Number */
+  u_int8_t  npdu;	   /* 11 N-PDU Number */
+  u_int8_t  next;	   /* 12 Next extension header type. Empty = 0 */
 };
 
 struct gtp0_packet {
@@ -162,9 +211,9 @@
 
 union gtp_packet {
   u_int8_t flags;
-  struct gtp0_packet       gtp0;
-  struct gtp1_packet_short gtp1s;
-  struct gtp1_packet_long  gtp1l;
+  struct gtp0_packet        gtp0;
+  struct gtp1_packet_short  gtp1s;
+  struct gtp1_packet_long   gtp1l;
 } __attribute__((packed)) h;
 
 
@@ -188,7 +237,9 @@
 struct gsn_t {
   /* Parameters related to the network interface */
 
-  int         fd;       /* File descriptor to network interface */
+  int         fd0;      /* GTP0 file descriptor */
+  int         fd1c;     /* GTP1 control plane file descriptor */
+  int         fd1u;     /* GTP0 user plane file descriptor */
   int       mode;       /* Mode of operation: GGSN or SGSN */
   struct in_addr gsnc;  /* IP address of this gsn for signalling */
   struct in_addr gsnu;  /* IP address of this gsn for user traffic */
@@ -206,9 +257,10 @@
 
   /* Call back functions */
   int (*cb_delete_context) (struct pdp_t*);
-  int (*cb_create_context) (struct pdp_t*);
-  int (*cb_conf) (int type, int cause, struct pdp_t *pdp, void* aid);
-  int (*cb_gpdu) (struct pdp_t* pdp, void* pack, unsigned len);
+  int (*cb_create_context_ind) (struct pdp_t*);
+  int (*cb_unsup_ind) (struct sockaddr_in *peer);
+  int (*cb_conf) (int type, int cause, struct pdp_t *pdp, void* cbp);
+  int (*cb_data_ind) (struct pdp_t* pdp, void* pack, unsigned len);
 
   /* Counters */
   
@@ -247,100 +299,92 @@
 		      uint64_t imsi, uint8_t nsapi);
 extern int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp);
 
-extern int gtp_create_context(struct gsn_t *gsn, struct pdp_t *pdp, void *aid,
-			      struct in_addr* inetaddr);
-extern int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *aid,
-			      struct in_addr* inetaddr);
-extern int gtp_delete_context(struct gsn_t *gsn, struct pdp_t *pdp, void *aid);
+extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp, 
+				  void *cbp, struct in_addr* inetaddr);
 
-extern int 
-gtp_create_context2(struct gsn_t *gsn, void *aid, 
-		    struct in_addr* inetaddr,
-		    int selmode, uint64_t imsi, int nsapi,
-		    uint8_t *qos, int qoslen,
-		    char *apn, int apnlen,
-		    char *msisdn, int msisdnlen,
-		    uint8_t *pco, int pcolen);
+extern int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
+	     int (*cb_create_context_ind) (struct pdp_t* pdp));
 
-extern int gtp_gpdu(struct gsn_t *gsn, struct pdp_t *pdp,
-		    void *pack, unsigned len);
+extern int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, 
+				   int cause);
+
+extern int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, 
+			      void *cbp, struct in_addr* inetaddr);
+
+extern int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, 
+				  void *cbp);
+
+extern int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp,
+			void *pack, unsigned len);
+
+extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
+             int (*cb_data_ind) (struct pdp_t* pdp, void* pack, unsigned len));
+
 
 extern int gtp_fd(struct gsn_t *gsn);
-extern int gtp_decaps(struct gsn_t *gsn);
+extern int gtp_decaps0(struct gsn_t *gsn);
+extern int gtp_decaps1c(struct gsn_t *gsn);
+extern int gtp_decaps1u(struct gsn_t *gsn);
 extern int gtp_retrans(struct gsn_t *gsn);
 extern int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout);
 
-/*
-extern int gtp_set_cb_newpdp(struct gsn_t *gsn, 
-			     int (*cb) (struct pdp_t*));
-extern int gtp_set_cb_freepdp(struct gsn_t *gsn, 
-			      int (*cb) (struct pdp_t*));
-extern int gtp_set_cb_create_pdp_ind(struct gsn_t *gsn, 
-				     int (*cb) (struct pdp_t*));
-extern int gtp_set_cb_create_pdp_conf(struct gsn_t *gsn, 
-				      int (*cb) (struct pdp_t*, int));
-extern int gtp_set_cb_update_pdp_conf(struct gsn_t *gsn, 
-				      int (*cb) (struct pdp_t*, int, int));
-extern int gtp_set_cb_delete_pdp_ind(struct gsn_t *gsn, 
-				     int (*cb) (struct pdp_t*));
-extern int gtp_set_cb_delete_pdp_conf(struct gsn_t *gsn, 
-				      int (*cb) (struct pdp_t*, int));
-*/
-
 extern int gtp_set_cb_delete_context(struct gsn_t *gsn, 
 	     int (*cb_delete_context) (struct pdp_t* pdp));
-extern int gtp_set_cb_create_context(struct gsn_t *gsn,
-	     int (*cb_create_context) (struct pdp_t* pdp));
+/*extern int gtp_set_cb_create_context(struct gsn_t *gsn,
+  int (*cb_create_context) (struct pdp_t* pdp)); */
+
+extern int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
+				int (*cb) (struct sockaddr_in *peer));
+
+
 extern int gtp_set_cb_conf(struct gsn_t *gsn,
-             int (*cb) (int type, int cause, struct pdp_t* pdp, void *aid));
-extern int gtp_set_cb_gpdu(struct gsn_t *gsn,
-	     int (*cb_gpdu) (struct pdp_t* pdp, void* pack, unsigned len));
+             int (*cb) (int type, int cause, struct pdp_t* pdp, void *cbp));
 
 
 /* Internal functions (not part of the API */
 
-extern int gtp_echo_req(struct gsn_t *gsn, struct in_addr *inetaddrs);
-extern int gtp_echo_resp(struct gsn_t *gsn, struct sockaddr_in *peer,
+extern int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
+			struct in_addr *inetaddrs);
+extern int gtp_echo_resp(struct gsn_t *gsn, int version, 
+			 struct sockaddr_in *peer, int fd,
 			 void *pack, unsigned len);
-extern int gtp_echo_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
+extern int gtp_echo_ind(struct gsn_t *gsn, int version, 
+			struct sockaddr_in *peer, int fd, 
 			void *pack, unsigned len);
-extern int gtp_echo_conf(struct gsn_t *gsn, struct sockaddr_in *peer,
+extern int gtp_echo_conf(struct gsn_t *gsn, int version, 
+			 struct sockaddr_in *peer,
 			 void *pack, unsigned len);
 
-extern int gtp_unsup_resp(struct gsn_t *gsn, struct sockaddr_in *peer,
-			  void *pack, unsigned len);
-extern int gtp_unsup_conf(struct gsn_t *gsn, struct sockaddr_in *peer,
-			  void *pack, unsigned len);
+extern int gtp_unsup_req(struct gsn_t *gsn, int version, 
+			 struct sockaddr_in *peer,
+			 int fd, void *pack, unsigned len);
+extern int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
+			 void *pack, unsigned len);
 
-extern int gtp_create_pdp_req(struct gsn_t *gsn, int version, void *aid,
-			      struct in_addr* inetaddr, struct pdp_t *pdp);
-
-extern int gtp_create_pdp_resp(struct gsn_t *gsn, int version,
-			       struct sockaddr_in *peer, 
-			       void *pack, unsigned len, 
+extern int gtp_create_pdp_resp(struct gsn_t *gsn, int version, 
 			       struct pdp_t *pdp, uint8_t cause);
 
 extern int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
-			      struct sockaddr_in *peer, 
+			      struct sockaddr_in *peer, int fd,
 			      void *pack, unsigned len);
 
 extern int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
 			       struct sockaddr_in *peer,
 			       void *pack, unsigned len);
 
-extern int gtp_update_pdp_req(struct gsn_t *gsn, int version, void *aid,
+extern int gtp_update_pdp_req(struct gsn_t *gsn, int version, void *cbp,
 			      struct in_addr* inetaddr, struct pdp_t *pdp);
 
-extern int gtp_delete_pdp_req(struct gsn_t *gsn, int version, void *aid,
+extern int gtp_delete_pdp_req(struct gsn_t *gsn, int version, void *cbp,
 			      struct pdp_t *pdp);
 
 extern int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
-			       struct sockaddr_in *peer, 
+			       struct sockaddr_in *peer, int fd,
 			       void *pack, unsigned len, 
 			       struct pdp_t *pdp, uint8_t cause);
 
 extern int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
-			      struct sockaddr_in *peer, 
+			      struct sockaddr_in *peer, int fd,
 			      void *pack, unsigned len);
 
 extern int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,