[PATCH openggsn v2] gtp: fix endianness in teid field of GTPv0 header

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.

pablo at gnumonks.org pablo at gnumonks.org
Fri Mar 21 11:08:49 UTC 2014


From: Pablo Neira Ayuso <pablo at gnumonks.org>

This field needs to be in network byte order as well. This problem
may manifest if you use ggsn and sgsn with different endianness.
It also show up when using the gtp kernel mode since the downlink
packets are using network byte order in the 64-bits teid field,
which osmo-sgsn / libgtp doesn't expect.
---
v2: Add function to encapsulate the code to access and to build
    the teid as Holger suggested.

Tested with and without gtp kernel support.
If no objections, I'll push this to master.

 gtp/gtp.c |   34 +++++++++++++---------------------
 gtp/pdp.c |    6 ++++++
 gtp/pdp.h |    2 ++
 3 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/gtp/gtp.c b/gtp/gtp.c
index 3cc0c0b..6185634 100644
--- a/gtp/gtp.c
+++ b/gtp/gtp.c
@@ -250,7 +250,7 @@ static uint64_t get_tid(void *pack)
 	union gtp_packet *packet = (union gtp_packet *)pack;
 
 	if ((packet->flags & 0xe0) == 0x00) {	/* Version 0 */
-		return packet->gtp0.h.tid;
+		return be64toh(packet->gtp0.h.tid);
 	}
 	return 0;
 }
@@ -425,10 +425,10 @@ int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
 		addr.sin_port = htons(GTP0_PORT);
 		packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
 		packet->gtp0.h.seq = hton16(gsn->seq_next);
-		if (pdp)
+		if (pdp) {
 			packet->gtp0.h.tid =
-			    (pdp->imsi & 0x0fffffffffffffffull) +
-			    ((uint64_t) pdp->nsapi << 60);
+				htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
+		}
 		if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
 			    || (packet->gtp0.h.type == GTP_ERROR)))
 			packet->gtp0.h.flow = hton16(pdp->flru);
@@ -581,7 +581,7 @@ int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
 	if ((packet->flags & 0xe0) == 0x00) {	/* Version 0 */
 		packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
 		packet->gtp0.h.seq = hton16(seq);
-		packet->gtp0.h.tid = tid;
+		packet->gtp0.h.tid = htobe64(tid);
 		if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
 			    (packet->gtp0.h.type == GTP_ERROR)))
 			packet->gtp0.h.flow = hton16(pdp->flru);
@@ -1329,12 +1329,9 @@ int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
 	memset(pdp, 0, sizeof(struct pdp_t));
 
 	if (version == 0) {
-		pdp->imsi =
-		    ((union gtp_packet *)pack)->gtp0.
-		    h.tid & 0x0fffffffffffffffull;
-		pdp->nsapi =
-		    (((union gtp_packet *)pack)->gtp0.
-		     h.tid & 0xf000000000000000ull) >> 60;
+		uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
+
+		pdp_set_imsi_nsapi(pdp, tid);
 	}
 
 	pdp->seq = seq;
@@ -2051,12 +2048,9 @@ int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
 	/* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
 	/* we have to use the tunnel endpoint identifier */
 	if (version == 0) {
-		imsi =
-		    ((union gtp_packet *)pack)->gtp0.
-		    h.tid & 0x0fffffffffffffffull;
-		nsapi =
-		    (((union gtp_packet *)pack)->gtp0.
-		     h.tid & 0xf000000000000000ull) >> 60;
+		uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
+
+		pdp_set_imsi_nsapi(pdp, tid);
 
 		/* Find the context in question */
 		if (pdp_getimsi(&pdp, imsi, nsapi)) {
@@ -2645,7 +2639,7 @@ int gtp_error_ind_conf(struct gsn_t *gsn, int version,
 	struct pdp_t *pdp;
 
 	/* Find the context in question */
-	if (pdp_tidget(&pdp, ((union gtp_packet *)pack)->gtp0.h.tid)) {
+	if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
 		gsn->err_unknownpdp++;
 		gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
 			    "Unknown PDP context");
@@ -3196,9 +3190,7 @@ int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
 		packet.gtp0.h.length = hton16(len);
 		packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
 		packet.gtp0.h.flow = hton16(pdp->flru);
-		packet.gtp0.h.tid =
-		    (pdp->imsi & 0x0fffffffffffffffull) +
-		    ((uint64_t) pdp->nsapi << 60);
+		packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
 
 		if (len > sizeof(union gtp_packet) - sizeof(struct gtp0_header)) {
 			gsn->err_memcpy++;
diff --git a/gtp/pdp.c b/gtp/pdp.c
index dfb91ea..dc21bf8 100644
--- a/gtp/pdp.c
+++ b/gtp/pdp.c
@@ -370,6 +370,12 @@ uint64_t pdp_gettid(uint64_t imsi, uint8_t nsapi)
 	return (imsi & 0x0fffffffffffffffull) + ((uint64_t) nsapi << 60);
 }
 
+void pdp_set_imsi_nsapi(struct pdp_t *pdp, uint64_t teid)
+{
+	pdp->imsi = teid & 0x0fffffffffffffffull;
+	pdp->nsapi = (teid & 0xf000000000000000ull) >> 60;
+}
+
 int ulcpy(void *dst, void *src, size_t size)
 {
 	if (((struct ul255_t *)src)->l <= size) {
diff --git a/gtp/pdp.h b/gtp/pdp.h
index b069a6f..6e30467 100644
--- a/gtp/pdp.h
+++ b/gtp/pdp.h
@@ -242,6 +242,8 @@ int pdp_tidset(struct pdp_t *pdp, uint64_t tid);
 int pdp_tiddel(struct pdp_t *pdp);
 int pdp_tidget(struct pdp_t **pdp, uint64_t tid);
 
+void pdp_set_imsi_nsapi(struct pdp_t *pdp, uint64_t teid);
+
 /*
 int pdp_iphash(void* ipif, struct ul66_t *eua);
 int pdp_ipset(struct pdp_t *pdp, void* ipif, struct ul66_t *eua);
-- 
1.7.10.4





More information about the OpenBSC mailing list