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,