From patchwork Fri Mar 21 11:08:49 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 332575 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from ganesha.gnumonks.org (ganesha.gnumonks.org [IPv6:2001:780:45:1d:225:90ff:fe52:c662]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 6E38E2C00A8 for ; Fri, 21 Mar 2014 22:13:26 +1100 (EST) Received: from localhost ([127.0.0.1] helo=ganesha.gnumonks.org) by ganesha.gnumonks.org with esmtp (Exim 4.72) (envelope-from ) id 1WQxNy-0000zS-Ue; Fri, 21 Mar 2014 12:13:15 +0100 Received: from mail.us.es ([193.147.175.20]) by ganesha.gnumonks.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.72) (envelope-from ) id 1WQxJr-0000Mh-CH for openbsc@lists.osmocom.org; Fri, 21 Mar 2014 12:09:02 +0100 Received: (qmail 663 invoked from network); 21 Mar 2014 12:08:58 +0100 Received: from unknown (HELO us.es) (192.168.2.12) by us.es with SMTP; 21 Mar 2014 12:08:58 +0100 Received: (qmail 1653 invoked by uid 507); 21 Mar 2014 11:08:58 -0000 X-Qmail-Scanner-Diagnostics: from 127.0.0.1 by antivirus2 (envelope-from , uid 501) with qmail-scanner-2.10 (clamdscan: 0.98.1/18655. spamassassin: 3.3.2. Clear:RC:1(127.0.0.1):SA:0(-97.6/7.5):. Processed in 3.003556 secs); 21 Mar 2014 11:08:58 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on antivirus2 X-Spam-Level: X-Spam-Status: No, score=-97.6 required=7.5 tests=BAYES_50,RCVD_IN_BRBL, RCVD_IN_BRBL_LASTEXT,RCVD_IN_PBL,RCVD_IN_RP_RNBL,RCVD_IN_SORBS_DUL, RDNS_DYNAMIC, SMTPAUTH_US, USER_IN_WHITELIST autolearn=disabled version=3.3.2 X-Spam-ASN: AS12715 188.76.0.0/16 X-Envelope-From: pablo@gnumonks.org Received: from unknown (HELO antivirus2) (127.0.0.1) by us.es with SMTP; 21 Mar 2014 11:08:55 -0000 Received: from 192.168.1.13 (192.168.1.13) by antivirus2 (F-Secure/fsigk_smtp/412/antivirus2); Fri, 21 Mar 2014 12:08:55 +0100 (CET) X-Virus-Status: clean(F-Secure/fsigk_smtp/412/antivirus2) Received: (qmail 17832 invoked from network); 21 Mar 2014 12:08:55 +0100 Received: from 176.146.76.188.dynamic.jazztel.es (HELO localhost.localdomain) (pneira@us.es@188.76.146.176) by mail.us.es with SMTP; 21 Mar 2014 12:08:55 +0100 From: pablo@gnumonks.org To: openbsc@lists.osmocom.org Subject: [PATCH openggsn v2] gtp: fix endianness in teid field of GTPv0 header Date: Fri, 21 Mar 2014 12:08:49 +0100 Message-Id: <1395400129-21471-1-git-send-email-pablo@gnumonks.org> X-Mailer: git-send-email 1.7.10.4 X-Spam-Score: -2.2 (--) Cc: holger@freyther.de, laforge@gnumonks.org X-BeenThere: openbsc@lists.osmocom.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Development of the OpenBSC GSM base station controller List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: openbsc-bounces@lists.osmocom.org Errors-To: openbsc-bounces@lists.osmocom.org From: Pablo Neira Ayuso 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);