blob: 5dde6b502fbfb67d2cf428b8b69dced74fab1870 [file] [log] [blame]
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001/*
Harald Welte632e8432017-09-05 18:12:14 +02002 * OsmoGGSN - Gateway GPRS Support Node
jjako0fe0df02004-09-17 11:30:40 +00003 * Copyright (C) 2002, 2003, 2004 Mondru AB.
Harald Welte632e8432017-09-05 18:12:14 +02004 * Copyright (C) 2010-2011, 2016-2017 Harald Welte <laforge@gnumonks.org>
5 * Copyright (C) 2015-2017 sysmocom - s.f.m.c. GmbH
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01006 *
jjako52c24142002-12-16 13:33:51 +00007 * The contents of this file may be used under the terms of the GNU
8 * General Public License Version 2, provided that the above copyright
9 * notice and this permission notice is included in all copies or
10 * substantial portions of the software.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +010011 *
jjako52c24142002-12-16 13:33:51 +000012 */
13
14/*
15 * gtp.c: Contains all GTP functionality. Should be able to handle multiple
Pau Espin Pedrol732131d2018-01-25 17:23:09 +010016 * tunnels in the same program.
jjako52c24142002-12-16 13:33:51 +000017 *
18 * TODO:
19 * - Do we need to handle fragmentation?
20 */
21
jjako52c24142002-12-16 13:33:51 +000022#ifdef __linux__
23#define _GNU_SOURCE 1
24#endif
25
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +010026#include <osmocom/core/logging.h>
27#include <osmocom/core/utils.h>
28
Holger Hans Peter Freyther5816bcf2014-04-04 11:43:09 +020029#if defined(__FreeBSD__)
30#include <sys/endian.h>
31#endif
32
jjako0fe0df02004-09-17 11:30:40 +000033#include "../config.h"
34#ifdef HAVE_STDINT_H
35#include <stdint.h>
36#endif
jjako52c24142002-12-16 13:33:51 +000037
jjako52c24142002-12-16 13:33:51 +000038#include <stdio.h>
39#include <stdarg.h>
40#include <stdlib.h>
41#include <sys/time.h>
42#include <sys/types.h>
43#include <sys/socket.h>
44#include <netinet/in.h>
45#include <arpa/inet.h>
46#include <sys/stat.h>
47#include <time.h>
48#include <unistd.h>
49#include <string.h>
50#include <errno.h>
51#include <fcntl.h>
Alexander Huemerdb852a12015-11-06 20:59:01 +010052#include <inttypes.h>
jjako52c24142002-12-16 13:33:51 +000053
54#include <arpa/inet.h>
55
jjakobae2cd42004-01-09 12:04:39 +000056/* #include <stdint.h> ISO C99 types */
jjako52c24142002-12-16 13:33:51 +000057
58#include "pdp.h"
59#include "gtp.h"
60#include "gtpie.h"
61#include "queue.h"
62
Harald Welte95848ba2011-11-02 18:17:50 +010063/* According to section 14.2 of 3GPP TS 29.006 version 6.9.0 */
64#define N3_REQUESTS 5
65
66#define T3_REQUEST 3
67
jjako1db1c812003-07-06 20:53:57 +000068/* Error reporting functions */
69
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +010070#define GTP_LOGPKG(pri, peer, pack, len, fmt, args...) \
71 logp2(DLGTP, pri, __FILE__, __LINE__, 0, \
72 "Packet from %s:%u, length: %d content: %s: " fmt, \
73 inet_ntoa((peer)->sin_addr), htons((peer)->sin_port), \
74 len, osmo_hexdump((const uint8_t *) pack, len), \
75 ##args);
jjako1db1c812003-07-06 20:53:57 +000076
Neels Hofmeyr9b097382015-10-12 14:00:19 +020077#define LOGP_WITH_ADDR(ss, level, addr, fmt, args...) \
78 LOGP(ss, level, "addr(%s:%d) " fmt, \
79 inet_ntoa((addr).sin_addr), htons((addr).sin_port), \
80 ##args);
81
jjako52c24142002-12-16 13:33:51 +000082/* API Functions */
83
Harald Weltebed35df2011-11-02 13:06:18 +010084const char *gtp_version()
jjako52c24142002-12-16 13:33:51 +000085{
Harald Weltebed35df2011-11-02 13:06:18 +010086 return VERSION;
jjako52c24142002-12-16 13:33:51 +000087}
88
Maxe6612772018-01-11 18:25:37 +010089const struct value_string gtp_type_names[] = {
90 { GTP_ECHO_REQ, "Echo Request" },
91 { GTP_ECHO_RSP, "Echo Response" },
92 { GTP_NOT_SUPPORTED, "Version Not Supported" },
93 { GTP_ALIVE_REQ, "Node Alive Request" },
94 { GTP_ALIVE_RSP, "Node Alive Response" },
95 { GTP_REDIR_REQ, "Redirection Request" },
96 { GTP_REDIR_RSP, "Redirection Response" },
97 { GTP_CREATE_PDP_REQ, "Create PDP Context Request" },
98 { GTP_CREATE_PDP_RSP, "Create PDP Context Response" },
99 { GTP_UPDATE_PDP_REQ, "Update PDP Context Request" },
100 { GTP_UPDATE_PDP_RSP, "Update PDP Context Response" },
101 { GTP_DELETE_PDP_REQ, "Delete PDP Context Request" },
102 { GTP_DELETE_PDP_RSP, "Delete PDP Context Response" },
103 { GTP_ERROR, "Error Indication" },
104 { GTP_PDU_NOT_REQ, "PDU Notification Request" },
105 { GTP_PDU_NOT_RSP, "PDU Notification Response" },
106 { GTP_PDU_NOT_REJ_REQ, "PDU Notification Reject Request" },
107 { GTP_PDU_NOT_REJ_RSP, "PDU Notification Reject Response" },
108 { GTP_SUPP_EXT_HEADER, "Supported Extension Headers Notification" },
109 { GTP_SND_ROUTE_REQ, "Send Routeing Information for GPRS Request" },
110 { GTP_SND_ROUTE_RSP, "Send Routeing Information for GPRS Response" },
111 { GTP_FAILURE_REQ, "Failure Report Request" },
112 { GTP_FAILURE_RSP, "Failure Report Response" },
113 { GTP_MS_PRESENT_REQ, "Note MS GPRS Present Request" },
114 { GTP_MS_PRESENT_RSP, "Note MS GPRS Present Response" },
115 { GTP_IDEN_REQ, "Identification Request" },
116 { GTP_IDEN_RSP, "Identification Response" },
117 { GTP_SGSN_CONTEXT_REQ,"SGSN Context Request" },
118 { GTP_SGSN_CONTEXT_RSP,"SGSN Context Response" },
119 { GTP_SGSN_CONTEXT_ACK,"SGSN Context Acknowledge" },
120 { GTP_FWD_RELOC_REQ, "Forward Relocation Request" },
121 { GTP_FWD_RELOC_RSP, "Forward Relocation Response" },
122 { GTP_FWD_RELOC_COMPL, "Forward Relocation Complete" },
123 { GTP_RELOC_CANCEL_REQ,"Relocation Cancel Request" },
124 { GTP_RELOC_CANCEL_RSP,"Relocation Cancel Response" },
125 { GTP_FWD_SRNS, "Forward SRNS Context" },
126 { GTP_FWD_RELOC_ACK, "Forward Relocation Complete Acknowledge" },
127 { GTP_FWD_SRNS_ACK, "Forward SRNS Context Acknowledge" },
128 { GTP_DATA_TRAN_REQ, "Data Record Transfer Request" },
129 { GTP_DATA_TRAN_RSP, "Data Record Transfer Response" },
130 { GTP_GPDU, "G-PDU" },
131 { 0, NULL }
132};
133
jjako52c24142002-12-16 13:33:51 +0000134/* gtp_new */
135/* gtp_free */
136
Harald Weltebed35df2011-11-02 13:06:18 +0100137int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
138 uint64_t imsi, uint8_t nsapi)
139{
Harald Weltee257be12017-08-12 14:55:09 +0200140 int rc;
141 rc = pdp_newpdp(pdp, imsi, nsapi, NULL);
142 if (!rc && *pdp)
143 (*pdp)->gsn = gsn;
144 return rc;
jjako52c24142002-12-16 13:33:51 +0000145}
146
Harald Weltebed35df2011-11-02 13:06:18 +0100147int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp)
148{
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +0200149 if (gsn->cb_delete_context)
150 gsn->cb_delete_context(pdp);
Harald Weltebed35df2011-11-02 13:06:18 +0100151 return pdp_freepdp(pdp);
jjako52c24142002-12-16 13:33:51 +0000152}
153
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +0200154/* Free pdp and all its secondary PDP contexts. Must be called on the primary PDP context. */
155int gtp_freepdp_teardown(struct gsn_t *gsn, struct pdp_t *pdp)
156{
157 int n;
158 struct pdp_t *secondary_pdp;
159 OSMO_ASSERT(!pdp->secondary);
160
161 for (n = 0; n < PDP_MAXNSAPI; n++) {
162 if (pdp->secondary_tei[n]) {
163 if (pdp_getgtp1
164 (&secondary_pdp,
165 pdp->secondary_tei[n])) {
166 LOGP(DLGTP, LOGL_ERROR,
167 "Unknown secondary PDP context\n");
168 continue;
169 }
170 if (pdp != secondary_pdp) {
171 gtp_freepdp(gsn, secondary_pdp);
172 }
173 }
174 }
175
176 return gtp_freepdp(gsn, pdp);
177}
178
jjako52c24142002-12-16 13:33:51 +0000179/* gtp_gpdu */
180
Harald Weltebed35df2011-11-02 13:06:18 +0100181extern int gtp_fd(struct gsn_t *gsn)
182{
183 return gsn->fd0;
jjako52c24142002-12-16 13:33:51 +0000184}
185
186/* gtp_decaps */
187/* gtp_retrans */
188/* gtp_retranstimeout */
189
jjako08d331d2003-10-13 20:33:30 +0000190int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100191 int (*cb) (struct sockaddr_in * peer))
192{
193 gsn->cb_unsup_ind = cb;
194 return 0;
jjako08d331d2003-10-13 20:33:30 +0000195}
196
jjako2c381332003-10-21 19:09:53 +0000197int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100198 int (*cb) (struct sockaddr_in * peer))
199{
200 gsn->cb_extheader_ind = cb;
201 return 0;
jjako2c381332003-10-21 19:09:53 +0000202}
203
jjako08d331d2003-10-13 20:33:30 +0000204/* API: Initialise delete context callback */
205/* Called whenever a pdp context is deleted for any reason */
Harald Weltebed35df2011-11-02 13:06:18 +0100206int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
jjako52c24142002-12-16 13:33:51 +0000207{
Harald Weltebed35df2011-11-02 13:06:18 +0100208 gsn->cb_delete_context = cb;
209 return 0;
jjako52c24142002-12-16 13:33:51 +0000210}
211
jjako52c24142002-12-16 13:33:51 +0000212int gtp_set_cb_conf(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100213 int (*cb) (int type, int cause,
214 struct pdp_t * pdp, void *cbp))
215{
216 gsn->cb_conf = cb;
217 return 0;
jjako52c24142002-12-16 13:33:51 +0000218}
219
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200220static void emit_cb_recovery(struct gsn_t *gsn, struct sockaddr_in * peer,
221 struct pdp_t * pdp, uint8_t recovery)
222{
223 if (gsn->cb_recovery)
224 gsn->cb_recovery(peer, recovery);
225 if (gsn->cb_recovery2)
226 gsn->cb_recovery2(peer, pdp, recovery);
227}
228
Harald Welte629e9862010-12-24 20:58:09 +0100229int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100230 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
231{
232 gsn->cb_recovery = cb;
233 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100234}
235
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200236/* cb_recovery()
237 * pdp may be NULL if Recovery IE was received from a message independent
238 * of any PDP ctx (such as Echo Response), or because pdp ctx is unknown to the
239 * local setup. In case pdp is known, caller may want to keep that pdp alive to
240 * handle subsequent msg cb as this specific pdp ctx is still valid according to
241 * specs.
242 */
243int gtp_set_cb_recovery2(struct gsn_t *gsn,
244 int (*cb_recovery2) (struct sockaddr_in * peer, struct pdp_t * pdp, uint8_t recovery))
245{
246 gsn->cb_recovery2 = cb_recovery2;
247 return 0;
248}
249
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +0100250int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100251 int (*cb_data_ind) (struct pdp_t * pdp,
252 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000253{
Harald Weltebed35df2011-11-02 13:06:18 +0100254 gsn->cb_data_ind = cb_data_ind;
255 return 0;
jjako52c24142002-12-16 13:33:51 +0000256}
257
jjako08d331d2003-10-13 20:33:30 +0000258/**
259 * get_default_gtp()
260 * Generate a GPRS Tunneling Protocol signalling packet header, depending
261 * on GTP version and message type. pdp is used for teid/flow label.
262 * *packet must be allocated by the calling function, and be large enough
263 * to hold the packet header.
264 * returns the length of the header. 0 on error.
265 **/
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100266static unsigned int get_default_gtp(uint8_t version, uint8_t type, void *packet)
Harald Weltebed35df2011-11-02 13:06:18 +0100267{
268 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
269 struct gtp1_header_long *gtp1_default =
270 (struct gtp1_header_long *)packet;
271 switch (version) {
272 case 0:
273 /* Initialise "standard" GTP0 header */
274 memset(gtp0_default, 0, sizeof(struct gtp0_header));
275 gtp0_default->flags = 0x1e;
276 gtp0_default->type = hton8(type);
277 gtp0_default->spare1 = 0xff;
278 gtp0_default->spare2 = 0xff;
279 gtp0_default->spare3 = 0xff;
280 gtp0_default->number = 0xff;
281 return GTP0_HEADER_SIZE;
282 case 1:
283 /* Initialise "standard" GTP1 header */
284 /* 29.060: 8.2: S=1 and PN=0 */
285 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
286 /* and Supported Extension Headers Notification, the S field shall be */
287 /* set to 1 */
288 /* Currently extension headers are not supported */
289 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
Harald Weltefed598f2017-09-24 16:39:22 +0800290 /* No extension, enable sequence, no N-PDU */
291 gtp1_default->flags = GTPHDR_F_VER(1) | GTP1HDR_F_GTP1 | GTP1HDR_F_SEQ;
Harald Weltebed35df2011-11-02 13:06:18 +0100292 gtp1_default->type = hton8(type);
293 return GTP1_HEADER_SIZE_LONG;
294 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100295 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100296 "Unknown GTP packet version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +0100297 return 0;
298 }
jjako52c24142002-12-16 13:33:51 +0000299}
300
jjako08d331d2003-10-13 20:33:30 +0000301/**
302 * get_seq()
303 * Get sequence number of a packet.
304 * Returns 0 on error
305 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100306static uint16_t get_seq(void *pack)
307{
308 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800309 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000310
Harald Weltefed598f2017-09-24 16:39:22 +0800311 if (ver == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +0100312 return ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800313 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100314 return ntoh16(packet->gtp1l.h.seq);
315 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100316 return 0;
317 }
jjako08d331d2003-10-13 20:33:30 +0000318}
319
320/**
321 * get_tid()
322 * Get tunnel identifier of a packet.
323 * Returns 0 on error
324 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100325static uint64_t get_tid(void *pack)
326{
327 union gtp_packet *packet = (union gtp_packet *)pack;
328
Harald Weltefed598f2017-09-24 16:39:22 +0800329 if (GTPHDR_F_GET_VER(packet->flags) == 0) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100330 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100331 }
332 return 0;
jjako08d331d2003-10-13 20:33:30 +0000333}
334
335/**
336 * get_hlen()
337 * Get the header length of a packet.
338 * Returns 0 on error
339 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100340static uint16_t get_hlen(void *pack)
341{
342 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800343 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000344
Harald Weltefed598f2017-09-24 16:39:22 +0800345 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100346 return GTP0_HEADER_SIZE;
Harald Weltefed598f2017-09-24 16:39:22 +0800347 } else if (ver == 1 && (packet->flags & 0x07) == 0) { /* Short version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100348 return GTP1_HEADER_SIZE_SHORT;
Harald Weltefed598f2017-09-24 16:39:22 +0800349 } else if (ver == 1) { /* Version 1 with seq/n-pdu/ext */
350 return GTP1_HEADER_SIZE_LONG;
Harald Weltebed35df2011-11-02 13:06:18 +0100351 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100352 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100353 return 0;
354 }
jjako08d331d2003-10-13 20:33:30 +0000355}
356
357/**
358 * get_tei()
359 * Get the tunnel endpoint identifier (flow label) of a packet.
360 * Returns 0xffffffff on error.
361 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100362static uint32_t get_tei(void *pack)
363{
364 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800365 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000366
Harald Weltefed598f2017-09-24 16:39:22 +0800367 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100368 return ntoh16(packet->gtp0.h.flow);
Harald Weltefed598f2017-09-24 16:39:22 +0800369 } else if (ver == 1) { /* Version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100370 return ntoh32(packet->gtp1l.h.tei);
371 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100372 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100373 return 0xffffffff;
374 }
jjako08d331d2003-10-13 20:33:30 +0000375}
jjakoa7cd2492003-04-11 09:40:12 +0000376
jjako52c24142002-12-16 13:33:51 +0000377/* ***********************************************************
378 * Reliable delivery of signalling messages
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100379 *
jjako52c24142002-12-16 13:33:51 +0000380 * Sequence numbers are used for both signalling messages and
381 * data messages.
382 *
383 * For data messages each tunnel maintains a sequence counter,
384 * which is incremented by one each time a new data message
385 * is sent. The sequence number starts at (0) zero at tunnel
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100386 * establishment, and wraps around at 65535 (29.060 9.3.1.1
jjako52c24142002-12-16 13:33:51 +0000387 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
388 * or can be used to check the validity of the message in the
389 * receiver, or for reordering af packets.
390 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100391 * For signalling messages the sequence number is used by
jjako52c24142002-12-16 13:33:51 +0000392 * signalling messages for which a response is defined. A response
393 * message should copy the sequence from the corresponding request
394 * message. The sequence number "unambiguously" identifies a request
395 * message within a given path, with a path being defined as a set of
396 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
397 * messages shall be responded to, and all response messages associated
398 * with a certain request shall always include the same information"
399 *
400 * We take this to mean that the GSN transmitting a request is free to
401 * choose the sequence number, as long as it is unique within a given path.
402 * It means that we are allowed to count backwards, or roll over at 17
403 * if we prefer that. It also means that we can use the same counter for
404 * all paths. This has the advantage that the transmitted request sequence
405 * numbers are unique within each GSN, and also we dont have to mess around
406 * with path setup and teardown.
407 *
408 * If a response message is lost, the request will be retransmitted, and
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100409 * the receiving GSN will receive a "duplicated" request. The standard
jjako52c24142002-12-16 13:33:51 +0000410 * requires the receiving GSN to send a response, with the same information
411 * as in the original response. For most messages this happens automatically:
412 *
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200413 * Echo: Automatically duplicates the original response
jjako52c24142002-12-16 13:33:51 +0000414 * Create pdp context: The SGSN may send create context request even if
415 * a context allready exist (imsi+nsapi?). This means that the reply will
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200416 automatically duplicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000417 * side effects in the application which is asked twice to validate
418 * the login.
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200419 * Update pdp context: Automatically duplicates the original response???
jjako52c24142002-12-16 13:33:51 +0000420 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
421 * a nonexist reply message.
422 *
423 * The correct solution will be to make a queue containing response messages.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100424 * This queue should be checked whenever a request is received. If the
jjako52c24142002-12-16 13:33:51 +0000425 * response is allready in the queue that response should be transmitted.
426 * It should be possible to find messages in this queue on the basis of
427 * the sequence number and peer GSN IP address (The sequense number is unique
428 * within each path). This need to be implemented by a hash table. Furthermore
429 * it should be possibly to delete messages based on a timeout. This can be
430 * achieved by means of a linked list. The timeout value need to be larger
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100431 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
jjako52c24142002-12-16 13:33:51 +0000432 * set in the peer GSN, so there is no way to know these parameters. On the
433 * other hand the timeout value need to be so small that we do not receive
434 * wraparound sequence numbere before the message is deleted. 60 seconds is
435 * probably not a bad choise.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100436 *
jjako52c24142002-12-16 13:33:51 +0000437 * This queue however is first really needed from gtp1.
438 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100439 * gtp_req:
jjako52c24142002-12-16 13:33:51 +0000440 * Send off a signalling message with appropiate sequence
441 * number. Store packet in queue.
442 * gtp_conf:
443 * Remove an incoming confirmation from the queue
444 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000445 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000446 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000447 * gtp_notification:
448 * Send off a notification message. This is neither a request nor
449 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000450 * gtp_retrans:
451 * Retransmit any outstanding packets which have exceeded
452 * a predefined timeout.
453 *************************************************************/
454
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100455static int gtp_req(struct gsn_t *gsn, uint8_t version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100456 union gtp_packet *packet, int len,
457 struct in_addr *inetaddr, void *cbp)
458{
Harald Weltefed598f2017-09-24 16:39:22 +0800459 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100460 struct sockaddr_in addr;
461 struct qmsg_t *qmsg;
462 int fd;
jjako08d331d2003-10-13 20:33:30 +0000463
Harald Weltebed35df2011-11-02 13:06:18 +0100464 memset(&addr, 0, sizeof(addr));
465 addr.sin_family = AF_INET;
466 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000467#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100468 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000469#endif
jjako52c24142002-12-16 13:33:51 +0000470
Harald Weltefed598f2017-09-24 16:39:22 +0800471 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100472 addr.sin_port = htons(GTP0_PORT);
473 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
474 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100475 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100476 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100477 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100478 }
Harald Weltebed35df2011-11-02 13:06:18 +0100479 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
480 || (packet->gtp0.h.type == GTP_ERROR)))
481 packet->gtp0.h.flow = hton16(pdp->flru);
482 else if (pdp)
483 packet->gtp0.h.flow = hton16(pdp->flrc);
484 fd = gsn->fd0;
Harald Weltefed598f2017-09-24 16:39:22 +0800485 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100486 addr.sin_port = htons(GTP1C_PORT);
487 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
488 packet->gtp1l.h.seq = hton16(gsn->seq_next);
489 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
490 (packet->gtp1l.h.type == GTP_ERROR)))
491 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
492 else if (pdp)
493 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
494 fd = gsn->fd1c;
495 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100496 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100497 return -1;
498 }
jjako52c24142002-12-16 13:33:51 +0000499
Harald Weltebed35df2011-11-02 13:06:18 +0100500 if (sendto(fd, packet, len, 0,
501 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
502 gsn->err_sendto++;
Max14b1b632017-08-21 20:14:59 +0200503 LOGP(DLGTP, LOGL_ERROR, "Sendto(fd=%d, msg=%lx, len=%d, dst=%s) failed: Error = %s\n", fd,
504 (unsigned long)&packet, len, inet_ntoa(addr.sin_addr), strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100505 return -1;
506 }
507
508 /* Use new queue structure */
509 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
510 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100511 LOGP(DLGTP, LOGL_ERROR,
512 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100513 } else {
514 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
515 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100516 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100517 qmsg->retrans = 0; /* No retransmissions so far */
518 qmsg->cbp = cbp;
519 qmsg->type = ntoh8(packet->gtp0.h.type);
520 qmsg->fd = fd;
521 }
522 gsn->seq_next++; /* Count up this time */
523 return 0;
jjako52c24142002-12-16 13:33:51 +0000524}
525
Alexander Couzense1412d92018-09-16 05:10:03 +0200526
527/**
528 * @brief clear the request and response queue. Useful for debugging to reset "some" state.
529 * @param gsn The GGSN instance
530 */
531void gtp_clear_queues(struct gsn_t *gsn)
532{
533 struct qmsg_t *qmsg;
534
535 while (!queue_getfirst(gsn->queue_req, &qmsg)) {
536 queue_freemsg(gsn->queue_req, qmsg);
537 }
538
539 while (!queue_getfirst(gsn->queue_resp, &qmsg)) {
540 queue_freemsg(gsn->queue_resp, qmsg);
541 }
542}
543
jjako52c24142002-12-16 13:33:51 +0000544/* gtp_conf
545 * Remove signalling packet from retransmission queue.
546 * return 0 on success, EOF if packet was not found */
547
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100548static int gtp_conf(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100549 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
550{
Harald Weltefed598f2017-09-24 16:39:22 +0800551 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100552 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000553
Harald Weltefed598f2017-09-24 16:39:22 +0800554 if (ver == 0)
Harald Weltebed35df2011-11-02 13:06:18 +0100555 seq = ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800556 else if (ver == 1 && (packet->gtp1l.h.flags & GTP1HDR_F_SEQ))
Harald Weltebed35df2011-11-02 13:06:18 +0100557 seq = ntoh16(packet->gtp1l.h.seq);
558 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100559 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
560 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100561 return EOF;
562 }
jjako08d331d2003-10-13 20:33:30 +0000563
Harald Weltebed35df2011-11-02 13:06:18 +0100564 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
565 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100566 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
567 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100568 return EOF;
569 }
jjako52c24142002-12-16 13:33:51 +0000570
Harald Weltebed35df2011-11-02 13:06:18 +0100571 return 0;
jjako52c24142002-12-16 13:33:51 +0000572}
573
Harald Weltebed35df2011-11-02 13:06:18 +0100574int gtp_retrans(struct gsn_t *gsn)
575{
576 /* Retransmit any outstanding packets */
577 /* Remove from queue if maxretrans exceeded */
578 time_t now;
579 struct qmsg_t *qmsg;
580 now = time(NULL);
581 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000582
Harald Welte95848ba2011-11-02 18:17:50 +0100583 /* get first element in queue, as long as the timeout of that
584 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100585 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
586 (qmsg->timeout <= now)) {
587 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100588 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100589 if (gsn->cb_conf)
590 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
591 queue_freemsg(gsn->queue_req, qmsg);
592 } else {
593 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
594 (struct sockaddr *)&qmsg->peer,
595 sizeof(struct sockaddr_in)) < 0) {
596 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100597 LOGP(DLGTP, LOGL_ERROR,
598 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100599 gsn->fd0, (unsigned long)&qmsg->p,
600 qmsg->l, strerror(errno));
601 }
602 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100603 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100604 qmsg->retrans++;
605 }
606 }
jjako52c24142002-12-16 13:33:51 +0000607
Harald Weltebed35df2011-11-02 13:06:18 +0100608 /* Also clean up reply timeouts */
609 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
610 (qmsg->timeout < now)) {
611 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
612 queue_freemsg(gsn->queue_resp, qmsg);
613 }
jjako52c24142002-12-16 13:33:51 +0000614
Harald Weltebed35df2011-11-02 13:06:18 +0100615 return 0;
jjako52c24142002-12-16 13:33:51 +0000616}
617
Harald Weltebed35df2011-11-02 13:06:18 +0100618int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
619{
Pau Espin Pedrolceac0782019-05-27 17:39:45 +0200620 time_t now, later, diff;
Harald Weltebed35df2011-11-02 13:06:18 +0100621 struct qmsg_t *qmsg;
Pau Espin Pedrolceac0782019-05-27 17:39:45 +0200622 timeout->tv_usec = 0;
jjako52c24142002-12-16 13:33:51 +0000623
Harald Weltebed35df2011-11-02 13:06:18 +0100624 if (queue_getfirst(gsn->queue_req, &qmsg)) {
625 timeout->tv_sec = 10;
Harald Weltebed35df2011-11-02 13:06:18 +0100626 } else {
627 now = time(NULL);
628 later = qmsg->timeout;
629 timeout->tv_sec = later - now;
Harald Weltebed35df2011-11-02 13:06:18 +0100630 if (timeout->tv_sec < 0)
631 timeout->tv_sec = 0; /* No negative allowed */
632 if (timeout->tv_sec > 10)
633 timeout->tv_sec = 10; /* Max sleep for 10 sec */
634 }
Pau Espin Pedrolceac0782019-05-27 17:39:45 +0200635
636 if (queue_getfirst(gsn->queue_resp, &qmsg)) {
637 /* already set by queue_req, do nothing */
638 } else { /* trigger faster if earlier timeout exists in queue_resp */
639 now = time(NULL);
640 later = qmsg->timeout;
641 diff = later - now;
642 if (diff < 0)
643 diff = 0;
644 if (diff < timeout->tv_sec)
645 timeout->tv_sec = diff;
646 }
647
Harald Weltebed35df2011-11-02 13:06:18 +0100648 return 0;
jjako52c24142002-12-16 13:33:51 +0000649}
650
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100651static int gtp_resp(uint8_t version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000652 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100653 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
654{
Harald Weltefed598f2017-09-24 16:39:22 +0800655 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100656 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000657
Harald Weltefed598f2017-09-24 16:39:22 +0800658 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100659 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
660 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100661 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100662 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
663 (packet->gtp0.h.type == GTP_ERROR)))
664 packet->gtp0.h.flow = hton16(pdp->flru);
665 else if (pdp)
666 packet->gtp0.h.flow = hton16(pdp->flrc);
Harald Weltefed598f2017-09-24 16:39:22 +0800667 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100668 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
669 packet->gtp1l.h.seq = hton16(seq);
670 if (pdp && (fd == gsn->fd1u))
671 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
672 else if (pdp)
673 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
674 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100675 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100676 return -1;
677 }
jjako08d331d2003-10-13 20:33:30 +0000678
Harald Weltebed35df2011-11-02 13:06:18 +0100679 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100680 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100681 return -1;
682 }
jjako52c24142002-12-16 13:33:51 +0000683
Harald Weltebed35df2011-11-02 13:06:18 +0100684 if (sendto(fd, packet, len, 0,
685 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
686 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100687 LOGP(DLGTP, LOGL_ERROR,
688 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100689 (unsigned long)&packet, len, strerror(errno));
690 return -1;
691 }
692
693 /* Use new queue structure */
694 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
695 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100696 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100697 } else {
698 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
699 qmsg->l = len;
700 qmsg->timeout = time(NULL) + 60; /* When to timeout */
701 qmsg->retrans = 0; /* No retransmissions so far */
702 qmsg->cbp = NULL;
703 qmsg->type = 0;
704 qmsg->fd = fd;
705 }
706 return 0;
jjako52c24142002-12-16 13:33:51 +0000707}
708
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100709static int gtp_notification(struct gsn_t *gsn, uint8_t version,
jjako2c381332003-10-21 19:09:53 +0000710 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100711 struct sockaddr_in *peer, int fd, uint16_t seq)
712{
jjako2c381332003-10-21 19:09:53 +0000713
Harald Weltefed598f2017-09-24 16:39:22 +0800714 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100715 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000716
Harald Weltebed35df2011-11-02 13:06:18 +0100717 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000718
Harald Weltebed35df2011-11-02 13:06:18 +0100719 /* In GTP0 notifications are treated as replies. In GTP1 they
720 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000721
Harald Weltebed35df2011-11-02 13:06:18 +0100722 if (fd == gsn->fd1c)
723 addr.sin_port = htons(GTP1C_PORT);
724 else if (fd == gsn->fd1u)
725 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000726
Harald Weltefed598f2017-09-24 16:39:22 +0800727 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100728 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
729 packet->gtp0.h.seq = hton16(seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800730 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100731 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
732 packet->gtp1l.h.seq = hton16(seq);
733 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100734 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100735 return -1;
736 }
737
738 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100739 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100740 return -1;
741 }
742
743 if (sendto(fd, packet, len, 0,
744 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
745 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100746 LOGP(DLGTP, LOGL_ERROR,
747 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100748 (unsigned long)&packet, len, strerror(errno));
749 return -1;
750 }
751 return 0;
jjako2c381332003-10-21 19:09:53 +0000752}
753
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200754static int gtp_duplicate(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +0100755 struct sockaddr_in *peer, uint16_t seq)
756{
757 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000758
Harald Weltebed35df2011-11-02 13:06:18 +0100759 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
760 return EOF; /* Notfound */
761 }
jjakoa7cd2492003-04-11 09:40:12 +0000762
Harald Weltebed35df2011-11-02 13:06:18 +0100763 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100764 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100765 return -1;
766 }
767
768 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
769 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
770 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100771 LOGP(DLGTP, LOGL_ERROR,
772 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100773 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
774 strerror(errno));
775 }
776 return 0;
jjako52c24142002-12-16 13:33:51 +0000777}
778
jjako52c24142002-12-16 13:33:51 +0000779/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100780static void log_restart(struct gsn_t *gsn)
781{
jjako52c24142002-12-16 13:33:51 +0000782 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200783 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000784 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200785 char *filename;
jjako52c24142002-12-16 13:33:51 +0000786
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200787 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
788 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000789
790 /* We try to open file. On failure we will later try to create file */
791 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100792 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100793 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100794 filename);
795 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100796 rc = fscanf(f, "%d", &counter);
797 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100798 LOGP(DLGTP, LOGL_ERROR,
799 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100800 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100801 }
802 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100803 LOGP(DLGTP, LOGL_ERROR,
804 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100805 }
jjako52c24142002-12-16 13:33:51 +0000806 }
Harald Weltebed35df2011-11-02 13:06:18 +0100807
808 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000809 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100810
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200811 /* Keep the umask closely wrapped around our fopen() call in case the
812 * log outputs cause file creation. */
813 i = umask(022);
814 f = fopen(filename, "w");
815 umask(i);
816 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100817 LOGP(DLGTP, LOGL_ERROR,
818 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100819 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200820 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000821 }
822
jjako52c24142002-12-16 13:33:51 +0000823 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100824close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200825 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100826 LOGP(DLGTP, LOGL_ERROR,
827 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200828free_filename:
829 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000830}
831
jjako1db1c812003-07-06 20:53:57 +0000832int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100833 int mode)
jjako52c24142002-12-16 13:33:51 +0000834{
Harald Weltebed35df2011-11-02 13:06:18 +0100835 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000836
Max14b1b632017-08-21 20:14:59 +0200837 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
jjako52c24142002-12-16 13:33:51 +0000838
Harald Weltebed35df2011-11-02 13:06:18 +0100839 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000840
Harald Weltebed35df2011-11-02 13:06:18 +0100841 (*gsn)->statedir = statedir;
842 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000843
Harald Weltebed35df2011-11-02 13:06:18 +0100844 /* Initialise sequence number */
845 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000846
Harald Weltebed35df2011-11-02 13:06:18 +0100847 /* Initialise request retransmit queue */
848 queue_new(&(*gsn)->queue_req);
849 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000850
Harald Weltebed35df2011-11-02 13:06:18 +0100851 /* Initialise pdp table */
852 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000853
Harald Weltebed35df2011-11-02 13:06:18 +0100854 /* Initialise call back functions */
855 (*gsn)->cb_create_context_ind = 0;
856 (*gsn)->cb_delete_context = 0;
857 (*gsn)->cb_unsup_ind = 0;
858 (*gsn)->cb_conf = 0;
859 (*gsn)->cb_data_ind = 0;
860
861 /* Store function parameters */
862 (*gsn)->gsnc = *listen;
863 (*gsn)->gsnu = *listen;
864 (*gsn)->mode = mode;
865
866 /* Create GTP version 0 socket */
867 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
868 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100869 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200870 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100871 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200872 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100873 }
874
875 memset(&addr, 0, sizeof(addr));
876 addr.sin_family = AF_INET;
877 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
878 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000879#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100880 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000881#endif
jjako08d331d2003-10-13 20:33:30 +0000882
Harald Weltebed35df2011-11-02 13:06:18 +0100883 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
884 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200885 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
886 "bind(fd0=%d) failed: Error = %s\n",
887 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200888 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100889 }
jjako08d331d2003-10-13 20:33:30 +0000890
Harald Weltebed35df2011-11-02 13:06:18 +0100891 /* Create GTP version 1 control plane socket */
892 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
893 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100894 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200895 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100896 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200897 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100898 }
899
900 memset(&addr, 0, sizeof(addr));
901 addr.sin_family = AF_INET;
902 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
903 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000904#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100905 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000906#endif
jjako08d331d2003-10-13 20:33:30 +0000907
Harald Weltebed35df2011-11-02 13:06:18 +0100908 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
909 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200910 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
911 "bind(fd1c=%d) failed: Error = %s\n",
912 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200913 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100914 }
jjako08d331d2003-10-13 20:33:30 +0000915
Harald Weltebed35df2011-11-02 13:06:18 +0100916 /* Create GTP version 1 user plane socket */
917 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
918 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100919 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200920 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100921 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200922 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100923 }
924
925 memset(&addr, 0, sizeof(addr));
926 addr.sin_family = AF_INET;
927 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
928 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000929#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100930 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000931#endif
jjako52c24142002-12-16 13:33:51 +0000932
Harald Weltebed35df2011-11-02 13:06:18 +0100933 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
934 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200935 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +0200936 "bind(fd1u=%d) failed: Error = %s\n",
937 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +0200938 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100939 }
940
941 return 0;
jjako52c24142002-12-16 13:33:51 +0000942}
943
Harald Weltebed35df2011-11-02 13:06:18 +0100944int gtp_free(struct gsn_t *gsn)
945{
jjako52c24142002-12-16 13:33:51 +0000946
Harald Weltebed35df2011-11-02 13:06:18 +0100947 /* Clean up retransmit queues */
948 queue_free(gsn->queue_req);
949 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000950
Harald Weltebed35df2011-11-02 13:06:18 +0100951 close(gsn->fd0);
952 close(gsn->fd1c);
953 close(gsn->fd1u);
954
955 free(gsn);
956 return 0;
jjako52c24142002-12-16 13:33:51 +0000957}
958
959/* ***********************************************************
960 * Path management messages
961 * Messages: echo and version not supported.
962 * A path is connection between two UDP/IP endpoints
963 *
964 * A path is either using GTP0 or GTP1. A path can be
965 * established by any kind of GTP message??
966
967 * Which source port to use?
968 * GTP-C request destination port is 2123/3386
969 * GTP-U request destination port is 2152/3386
970 * T-PDU destination port is 2152/3386.
971 * For the above messages the source port is locally allocated.
972 * For response messages src=rx-dst and dst=rx-src.
973 * For simplicity we should probably use 2123+2152/3386 as
974 * src port even for the cases where src can be locally
975 * allocated. This also means that we have to listen only to
976 * the same ports.
977 * For response messages we need to be able to respond to
978 * the relevant src port even if it is locally allocated by
979 * the peer.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100980 *
jjako52c24142002-12-16 13:33:51 +0000981 * The need for path management!
982 * We might need to keep a list of active paths. This might
983 * be in the form of remote IP address + UDP port numbers.
984 * (We will consider a path astablished if we have a context
985 * with the node in question)
986 *************************************************************/
987
988/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000989int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
990 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000991{
Harald Weltebed35df2011-11-02 13:06:18 +0100992 union gtp_packet packet;
993 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
994 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000995}
996
jjako08d331d2003-10-13 20:33:30 +0000997/* Send off an echo reply */
998int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100999 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001000{
Harald Weltebed35df2011-11-02 13:06:18 +01001001 union gtp_packet packet;
1002 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
1003 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1004 gsn->restart_counter);
1005 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
1006 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00001007}
1008
jjako52c24142002-12-16 13:33:51 +00001009/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +01001010int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1011 int fd, void *pack, unsigned len)
1012{
jjako52c24142002-12-16 13:33:51 +00001013
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02001014 /* Check if it was a duplicate request */
1015 if (!gtp_duplicate(gsn, 0, peer, get_seq(pack)))
Harald Weltebed35df2011-11-02 13:06:18 +01001016 return 0;
jjako52c24142002-12-16 13:33:51 +00001017
Harald Weltebed35df2011-11-02 13:06:18 +01001018 /* Send off reply to request */
1019 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +00001020}
1021
1022/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +00001023int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001024 void *pack, unsigned len)
1025{
1026 union gtpie_member *ie[GTPIE_SIZE];
1027 unsigned char recovery;
1028 void *cbp = NULL;
1029 uint8_t type = 0;
1030 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001031
Harald Weltebed35df2011-11-02 13:06:18 +01001032 /* Remove packet from queue */
1033 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1034 return EOF;
jjako52c24142002-12-16 13:33:51 +00001035
Harald Weltebed35df2011-11-02 13:06:18 +01001036 /* Extract information elements into a pointer array */
1037 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1038 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001039 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1040 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001041 if (gsn->cb_conf)
1042 gsn->cb_conf(type, EOF, NULL, cbp);
1043 return EOF;
1044 }
jjako52c24142002-12-16 13:33:51 +00001045
Harald Weltebed35df2011-11-02 13:06:18 +01001046 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1047 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001048 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1049 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001050 if (gsn->cb_conf)
1051 gsn->cb_conf(type, EOF, NULL, cbp);
1052 return EOF;
1053 }
jjako52c24142002-12-16 13:33:51 +00001054
Harald Weltebed35df2011-11-02 13:06:18 +01001055 /* Echo reply packages does not have a cause information element */
1056 /* Instead we return the recovery number in the callback function */
1057 if (gsn->cb_conf)
1058 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +01001059
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001060 emit_cb_recovery(gsn, peer, NULL, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001061
1062 return 0;
jjako52c24142002-12-16 13:33:51 +00001063}
1064
1065/* Send off a Version Not Supported message */
1066/* This message is somewhat special in that it actually is a
1067 * response to some other message with unsupported GTP version
1068 * For this reason it has parameters like a response, and does
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001069 * its own message transmission. No signalling queue is used
jjako52c24142002-12-16 13:33:51 +00001070 * The reply is sent to the peer IP and peer UDP. This means that
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001071 * the peer will be receiving a GTP0 message on a GTP1 port!
jjako52c24142002-12-16 13:33:51 +00001072 * In practice however this will never happen as a GTP0 GSN will
1073 * only listen to the GTP0 port, and therefore will never receive
1074 * anything else than GTP0 */
1075
jjako08d331d2003-10-13 20:33:30 +00001076int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1077 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001078{
Harald Weltebed35df2011-11-02 13:06:18 +01001079 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +00001080
Harald Weltebed35df2011-11-02 13:06:18 +01001081 /* GTP 1 is the highest supported protocol */
1082 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
1083 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +00001084}
1085
1086/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +01001087int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1088 void *pack, unsigned len)
1089{
jjako52c24142002-12-16 13:33:51 +00001090
Harald Weltebed35df2011-11-02 13:06:18 +01001091 if (gsn->cb_unsup_ind)
1092 gsn->cb_unsup_ind(peer);
1093
1094 return 0;
jjako52c24142002-12-16 13:33:51 +00001095}
1096
jjako2c381332003-10-21 19:09:53 +00001097/* Send off an Supported Extension Headers Notification */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001098static int gtp_extheader_req(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
jjako2c381332003-10-21 19:09:53 +00001099 int fd, void *pack, unsigned len)
1100{
Harald Weltebed35df2011-11-02 13:06:18 +01001101 union gtp_packet packet;
1102 unsigned int length =
1103 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +00001104
Harald Weltebed35df2011-11-02 13:06:18 +01001105 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +00001106
Harald Weltebed35df2011-11-02 13:06:18 +01001107 if (version < 1)
1108 return 0;
jjako2c381332003-10-21 19:09:53 +00001109
Harald Weltebed35df2011-11-02 13:06:18 +01001110 /* We report back that we support only PDCP PDU headers */
1111 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
1112 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +00001113
Harald Weltebed35df2011-11-02 13:06:18 +01001114 return gtp_notification(gsn, version, &packet, length,
1115 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +00001116}
1117
1118/* Handle a Supported Extension Headers Notification */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001119static int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001120 void *pack, unsigned len)
1121{
jjako2c381332003-10-21 19:09:53 +00001122
Harald Weltebed35df2011-11-02 13:06:18 +01001123 if (gsn->cb_extheader_ind)
1124 gsn->cb_extheader_ind(peer);
1125
1126 return 0;
jjako2c381332003-10-21 19:09:53 +00001127}
1128
jjako52c24142002-12-16 13:33:51 +00001129/* ***********************************************************
1130 * Session management messages
1131 * Messages: create, update and delete PDP context
1132 *
1133 * Information storage
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001134 * Information storage for each PDP context is defined in
jjako52c24142002-12-16 13:33:51 +00001135 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1136 * PDP-address (IP address), sequence numbers, charging ID.
1137 * For the SGSN it also includes radio related mobility
1138 * information.
1139 *************************************************************/
1140
Harald Welte7b3347b2010-05-15 12:18:46 +02001141/* API: Send Create PDP Context Request (7.3.1) */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001142int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001143 void *cbp)
1144{
1145 union gtp_packet packet;
1146 unsigned int length =
1147 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1148 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001149
Harald Weltebed35df2011-11-02 13:06:18 +01001150 /* TODO: Secondary PDP Context Activation Procedure */
1151 /* In secondary activation procedure the PDP context is identified
1152 by tei in the header. The following fields are omitted: Selection
1153 mode, IMSI, MSISDN, End User Address, Access Point Name and
1154 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001155
Harald Weltebed35df2011-11-02 13:06:18 +01001156 if (pdp->secondary) {
1157 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001158 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001159 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001160 return EOF;
1161 }
1162 }
jjako2c381332003-10-21 19:09:53 +00001163
Harald Weltebed35df2011-11-02 13:06:18 +01001164 if (pdp->version == 0) {
1165 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1166 sizeof(pdp->qos_req0), pdp->qos_req0);
1167 }
jjako52c24142002-12-16 13:33:51 +00001168
Harald Weltebed35df2011-11-02 13:06:18 +01001169 /* Section 7.7.2 */
1170 if (pdp->version == 1) {
1171 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1172 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1173 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1174 }
jjako52c24142002-12-16 13:33:51 +00001175
Harald Weltebed35df2011-11-02 13:06:18 +01001176 /* Section 7.7.3 Routing Area Information */
1177 if (pdp->rai_given == 1)
1178 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1179 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001180
Harald Weltebed35df2011-11-02 13:06:18 +01001181 /* Section 7.7.11 */
1182 if (pdp->norecovery_given == 0)
1183 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1184 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001185
Harald Weltebed35df2011-11-02 13:06:18 +01001186 /* Section 7.7.12 */
1187 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1188 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1189 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001190
Harald Weltebed35df2011-11-02 13:06:18 +01001191 if (pdp->version == 0) {
1192 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1193 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1194 }
jjako08d331d2003-10-13 20:33:30 +00001195
Harald Weltebed35df2011-11-02 13:06:18 +01001196 /* Section 7.7.13 */
1197 if (pdp->version == 1) {
1198 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1199 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001200
Harald Weltebed35df2011-11-02 13:06:18 +01001201 /* Section 7.7.14 */
1202 if (!pdp->teic_confirmed)
1203 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1204 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001205
Harald Weltebed35df2011-11-02 13:06:18 +01001206 /* Section 7.7.17 */
1207 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001208
Harald Weltebed35df2011-11-02 13:06:18 +01001209 /* Section 7.7.17 */
1210 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1211 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1212 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001213
Harald Weltebed35df2011-11-02 13:06:18 +01001214 /* Section 7.7.23 */
1215 if (pdp->cch_pdp) /* Only include charging if flags are set */
1216 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1217 pdp->cch_pdp);
1218 }
jjako9b4971d2004-05-27 20:30:19 +00001219
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001220 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001221 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1222 pdp->traceref);
1223 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1224 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001225
Harald Weltebed35df2011-11-02 13:06:18 +01001226 /* Section 7.7.27 */
1227 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1228 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1229 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001230
Harald Weltebed35df2011-11-02 13:06:18 +01001231 /* Section 7.7.30 */
1232 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1233 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1234 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001235
Harald Weltebed35df2011-11-02 13:06:18 +01001236 /* Section 7.7.31 */
1237 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1238 if (pdp->pco_req.l)
1239 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1240 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001241
Harald Weltebed35df2011-11-02 13:06:18 +01001242 /* Section 7.7.32 */
1243 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1244 pdp->gsnlc.l, pdp->gsnlc.v);
1245 /* Section 7.7.32 */
1246 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1247 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001248
Harald Weltebed35df2011-11-02 13:06:18 +01001249 /* Section 7.7.33 */
1250 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1251 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1252 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001253
Harald Weltebed35df2011-11-02 13:06:18 +01001254 /* Section 7.7.34 */
1255 if (pdp->version == 1)
1256 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1257 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001258
Harald Weltebed35df2011-11-02 13:06:18 +01001259 /* Section 7.7.36 */
1260 if ((pdp->version == 1) && pdp->tft.l)
1261 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1262 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001263
Harald Weltebed35df2011-11-02 13:06:18 +01001264 /* Section 7.7.41 */
1265 if ((pdp->version == 1) && pdp->triggerid.l)
1266 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1267 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001268
Harald Weltebed35df2011-11-02 13:06:18 +01001269 /* Section 7.7.42 */
1270 if ((pdp->version == 1) && pdp->omcid.l)
1271 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1272 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001273
Harald Weltebed35df2011-11-02 13:06:18 +01001274 /* new R7 fields */
1275 if (pdp->rattype_given == 1)
1276 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1277 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001278
Harald Weltebed35df2011-11-02 13:06:18 +01001279 if (pdp->userloc_given == 1)
1280 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1281 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001282
Harald Weltebed35df2011-11-02 13:06:18 +01001283 if (pdp->mstz_given == 1)
1284 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1285 pdp->mstz.l, pdp->mstz.v);
1286
1287 if (pdp->imeisv_given == 1)
1288 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1289 pdp->imeisv.l, pdp->imeisv.v);
1290
1291 /* TODO hisaddr0 */
1292 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1293
1294 return 0;
jjako52c24142002-12-16 13:33:51 +00001295}
1296
jjako08d331d2003-10-13 20:33:30 +00001297/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001298int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1299{
jjako08d331d2003-10-13 20:33:30 +00001300
Harald Weltebed35df2011-11-02 13:06:18 +01001301 /* Now send off a reply to the peer */
1302 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1303
1304 if (cause != GTPCAUSE_ACC_REQ) {
1305 pdp_freepdp(pdp);
1306 }
1307
1308 return 0;
jjako08d331d2003-10-13 20:33:30 +00001309}
1310
1311/* API: Register create context indication callback */
1312int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001313 int (*cb_create_context_ind) (struct pdp_t *
1314 pdp))
jjako52c24142002-12-16 13:33:51 +00001315{
Harald Weltebed35df2011-11-02 13:06:18 +01001316 gsn->cb_create_context_ind = cb_create_context_ind;
1317 return 0;
jjako08d331d2003-10-13 20:33:30 +00001318}
1319
jjako08d331d2003-10-13 20:33:30 +00001320/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001321int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1322 uint8_t cause)
1323{
1324 union gtp_packet packet;
1325 unsigned int length =
1326 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001327
Harald Weltebed35df2011-11-02 13:06:18 +01001328 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001329
Harald Weltebed35df2011-11-02 13:06:18 +01001330 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001331
Harald Weltebed35df2011-11-02 13:06:18 +01001332 if (version == 0)
1333 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1334 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001335
Harald Weltebed35df2011-11-02 13:06:18 +01001336 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1337 pdp->reorder);
1338 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1339 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001340
Harald Weltebed35df2011-11-02 13:06:18 +01001341 if (version == 0) {
1342 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1343 pdp->fllu);
1344 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1345 pdp->fllc);
1346 }
jjako08d331d2003-10-13 20:33:30 +00001347
Harald Weltebed35df2011-11-02 13:06:18 +01001348 if (version == 1) {
1349 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1350 pdp->teid_own);
1351 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1352 pdp->teic_own);
1353 }
jjako08d331d2003-10-13 20:33:30 +00001354
Harald Weltebed35df2011-11-02 13:06:18 +01001355 /* TODO: We use teic_own as charging ID */
1356 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1357 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001358
Harald Weltebed35df2011-11-02 13:06:18 +01001359 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1360 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001361
Harald Weltebed35df2011-11-02 13:06:18 +01001362 if (pdp->pco_neg.l) { /* Optional PCO */
1363 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1364 pdp->pco_neg.l, pdp->pco_neg.v);
1365 }
jjako52c24142002-12-16 13:33:51 +00001366
Harald Weltebed35df2011-11-02 13:06:18 +01001367 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1368 pdp->gsnlc.l, pdp->gsnlc.v);
1369 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1370 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001371
Harald Weltebed35df2011-11-02 13:06:18 +01001372 if (version == 1)
1373 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1374 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001375
Harald Weltebed35df2011-11-02 13:06:18 +01001376 /* TODO: Charging gateway address */
1377 }
jjako52c24142002-12-16 13:33:51 +00001378
Harald Weltebed35df2011-11-02 13:06:18 +01001379 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1380 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001381}
1382
1383/* Handle Create PDP Context Request */
1384int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001385 struct sockaddr_in *peer, int fd,
1386 void *pack, unsigned len)
1387{
1388 struct pdp_t *pdp, *pdp_old;
1389 struct pdp_t pdp_buf;
1390 union gtpie_member *ie[GTPIE_SIZE];
1391 uint8_t recovery;
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001392 bool recovery_recvd = false;
1393 int rc;
jjako52c24142002-12-16 13:33:51 +00001394
Harald Weltebed35df2011-11-02 13:06:18 +01001395 uint16_t seq = get_seq(pack);
1396 int hlen = get_hlen(pack);
1397 uint8_t linked_nsapi = 0;
1398 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001399
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02001400 if (!gtp_duplicate(gsn, version, peer, seq))
Harald Weltebed35df2011-11-02 13:06:18 +01001401 return 0;
jjako08d331d2003-10-13 20:33:30 +00001402
Harald Weltebed35df2011-11-02 13:06:18 +01001403 pdp = &pdp_buf;
1404 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001405
Harald Weltebed35df2011-11-02 13:06:18 +01001406 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001407 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1408
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001409 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001410 }
jjako52c24142002-12-16 13:33:51 +00001411
Harald Weltebed35df2011-11-02 13:06:18 +01001412 pdp->seq = seq;
1413 pdp->sa_peer = *peer;
1414 pdp->fd = fd;
1415 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001416
Harald Weltebed35df2011-11-02 13:06:18 +01001417 /* Decode information elements */
1418 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1419 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001420 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1421 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001422 if (0 == version)
1423 return EOF;
1424 else
1425 return gtp_create_pdp_resp(gsn, version, pdp,
1426 GTPCAUSE_INVALID_MESSAGE);
1427 }
jjako52c24142002-12-16 13:33:51 +00001428
Harald Weltebed35df2011-11-02 13:06:18 +01001429 if (version == 1) {
1430 /* Linked NSAPI (conditional) */
1431 /* If included this is the Secondary PDP Context Activation Procedure */
1432 /* In secondary activation IMSI is not included, so the context must be */
1433 /* identified by the tei */
1434 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001435
Harald Weltebed35df2011-11-02 13:06:18 +01001436 /* Find the primary PDP context */
1437 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1438 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001439 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001440 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001441 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001442 return gtp_create_pdp_resp(gsn, version, pdp,
1443 GTPCAUSE_OPT_IE_INCORRECT);
1444 }
jjako2c381332003-10-21 19:09:53 +00001445
Harald Weltebed35df2011-11-02 13:06:18 +01001446 /* Check that the primary PDP context matches linked nsapi */
1447 if (linked_pdp->nsapi != linked_nsapi) {
1448 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001449 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001450 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001451 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001452 return gtp_create_pdp_resp(gsn, version, pdp,
1453 GTPCAUSE_OPT_IE_INCORRECT);
1454 }
jjako52c24142002-12-16 13:33:51 +00001455
Harald Weltebed35df2011-11-02 13:06:18 +01001456 /* Copy parameters from primary context */
1457 pdp->selmode = linked_pdp->selmode;
1458 pdp->imsi = linked_pdp->imsi;
1459 pdp->msisdn = linked_pdp->msisdn;
1460 pdp->eua = linked_pdp->eua;
1461 pdp->pco_req = linked_pdp->pco_req;
1462 pdp->apn_req = linked_pdp->apn_req;
1463 pdp->teic_gn = linked_pdp->teic_gn;
1464 pdp->secondary = 1;
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001465 } else {
1466 /* Not Secondary PDP Context Activation Procedure */
1467 /* IMSI (conditional): If the MS is emergency attached
1468 and the MS is UICCless, the IMSI cannot be included
1469 in the message and therefore IMSI shall not be
1470 included in the message. */
1471 if (gtpie_gettv0
1472 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1473 gsn->missing++;
1474 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1475 len, "Missing IMSI not supported\n");
1476 return gtp_create_pdp_resp(gsn, version, pdp,
1477 GTPCAUSE_MAN_IE_MISSING);
1478 }
1479 }
1480
1481 /* TEID (mandatory) */
1482 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1483 gsn->missing++;
1484 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1485 len, "Missing mandatory information field\n");
1486 return gtp_create_pdp_resp(gsn, version, pdp,
1487 GTPCAUSE_MAN_IE_MISSING);
1488 }
1489 /* TEIC (conditional) */
1490 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1491 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1492 gsn->missing++;
1493 GTP_LOGPKG(LOGL_ERROR, peer,
1494 pack, len,
1495 "Missing mandatory information field\n");
1496 return gtp_create_pdp_resp(gsn, version, pdp,
1497 GTPCAUSE_MAN_IE_MISSING);
1498 }
1499 }
1500 /* NSAPI (mandatory) */
1501 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1502 gsn->missing++;
1503 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1504 len, "Missing mandatory information field\n");
1505 return gtp_create_pdp_resp(gsn, version, pdp,
1506 GTPCAUSE_MAN_IE_MISSING);
1507 }
1508 /* QoS (mandatory) */
1509 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1510 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1511 gsn->missing++;
1512 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1513 len, "Missing mandatory information field\n");
1514 return gtp_create_pdp_resp(gsn, version, pdp,
1515 GTPCAUSE_MAN_IE_MISSING);
1516 }
1517 /* TFT (conditional) */
1518 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1519 &pdp->tft.v, sizeof(pdp->tft.v))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001520 }
1521 }
1522 /* if (version == 1) */
1523 if (version == 0) {
1524 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1525 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1526 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001527 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1528 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001529 return gtp_create_pdp_resp(gsn, version, pdp,
1530 GTPCAUSE_MAN_IE_MISSING);
1531 }
Harald Weltebed35df2011-11-02 13:06:18 +01001532 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1533 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001534 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1535 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001536 return gtp_create_pdp_resp(gsn, version, pdp,
1537 GTPCAUSE_MAN_IE_MISSING);
1538 }
Harald Weltebed35df2011-11-02 13:06:18 +01001539 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1540 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001541 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1542 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001543 return gtp_create_pdp_resp(gsn, version, pdp,
1544 GTPCAUSE_MAN_IE_MISSING);
1545 }
1546 }
jjako08d331d2003-10-13 20:33:30 +00001547
Harald Weltebed35df2011-11-02 13:06:18 +01001548 /* SGSN address for signalling (mandatory) */
1549 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1550 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1551 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001552 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1553 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001554 return gtp_create_pdp_resp(gsn, version, pdp,
1555 GTPCAUSE_MAN_IE_MISSING);
1556 }
jjako2e840a32003-01-28 16:05:18 +00001557
Harald Weltebed35df2011-11-02 13:06:18 +01001558 /* SGSN address for user traffic (mandatory) */
1559 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1560 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1561 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001562 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1563 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001564 return gtp_create_pdp_resp(gsn, version, pdp,
1565 GTPCAUSE_MAN_IE_MISSING);
1566 }
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001567 /* Recovery (optional) */
1568 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1569 /* we use recovery futher down after announcing new pdp ctx to user */
1570 recovery_recvd = true;
1571 }
jjako52c24142002-12-16 13:33:51 +00001572
Harald Weltebed35df2011-11-02 13:06:18 +01001573 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001574 /* Selection mode (conditional) */
1575 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1576 &pdp->selmode, sizeof(pdp->selmode))) {
1577 gsn->missing++;
1578 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1579 len, "Missing mandatory information field\n");
1580 return gtp_create_pdp_resp(gsn, version, pdp,
1581 GTPCAUSE_MAN_IE_MISSING);
1582 }
1583 /* End User Address (conditional) */
1584 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1585 &pdp->eua.v, sizeof(pdp->eua.v))) {
1586 gsn->missing++;
1587 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1588 len, "Missing mandatory information field\n");
1589 return gtp_create_pdp_resp(gsn, version, pdp,
1590 GTPCAUSE_MAN_IE_MISSING);
1591 }
1592 /* APN */
1593 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1594 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1595 gsn->missing++;
1596 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1597 len, "Missing mandatory information field\n");
1598 return gtp_create_pdp_resp(gsn, version, pdp,
1599 GTPCAUSE_MAN_IE_MISSING);
1600 }
1601 /* Extract protocol configuration options (optional) */
1602 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1603 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1604 }
Harald Weltebed35df2011-11-02 13:06:18 +01001605 /* MSISDN (conditional) */
1606 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1607 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1608 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001609 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1610 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001611 return gtp_create_pdp_resp(gsn, version, pdp,
1612 GTPCAUSE_MAN_IE_MISSING);
1613 }
1614 }
jjako52c24142002-12-16 13:33:51 +00001615
Harald Weltebed35df2011-11-02 13:06:18 +01001616 /* Initialize our own IP addresses */
1617 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1618 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1619
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001620 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001621
1622 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1623 /* Found old pdp with same tid. Now the voodoo begins! */
1624 /* 09.60 / 29.060 allows create on existing context to "steal" */
1625 /* the context which was allready established */
1626 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001627 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001628 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1629 &&
1630 (!memcmp
1631 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1632 && (pdp->selmode == pdp_old->selmode)
1633 && (pdp->msisdn.l == pdp_old->msisdn.l)
1634 &&
1635 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1636 {
1637 /* OK! We are dealing with the same APN. We will copy new
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001638 * parameters to the old pdp and send off confirmation
Harald Weltebed35df2011-11-02 13:06:18 +01001639 * We ignore the following information elements:
1640 * QoS: MS will get originally negotiated QoS.
1641 * End user address (EUA). MS will get old EUA anyway.
1642 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001643 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001644
1645 /* Copy remote flow label */
1646 pdp_old->flru = pdp->flru;
1647 pdp_old->flrc = pdp->flrc;
1648
1649 /* Copy remote tei */
1650 pdp_old->teid_gn = pdp->teid_gn;
1651 pdp_old->teic_gn = pdp->teic_gn;
1652
1653 /* Copy peer GSN address */
1654 pdp_old->gsnrc.l = pdp->gsnrc.l;
1655 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1656 pdp_old->gsnru.l = pdp->gsnru.l;
1657 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1658
1659 /* Copy request parameters */
1660 pdp_old->seq = pdp->seq;
1661 pdp_old->sa_peer = pdp->sa_peer;
1662 pdp_old->fd = pdp->fd = fd;
1663 pdp_old->version = pdp->version = version;
1664
1665 /* Switch to using the old pdp context */
1666 pdp = pdp_old;
1667
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001668 if (recovery_recvd)
1669 emit_cb_recovery(gsn, peer, pdp, recovery);
1670
Harald Weltebed35df2011-11-02 13:06:18 +01001671 /* Confirm to peer that things were "successful" */
1672 return gtp_create_pdp_resp(gsn, version, pdp,
1673 GTPCAUSE_ACC_REQ);
1674 } else { /* This is not the same PDP context. Delete the old one. */
1675
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001676 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001677
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02001678 gtp_freepdp(gsn, pdp_old);
Harald Weltebed35df2011-11-02 13:06:18 +01001679
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001680 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001681 }
1682 }
1683
1684 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
Harald Weltee257be12017-08-12 14:55:09 +02001685 if (pdp)
1686 pdp->gsn = gsn;
Harald Weltebed35df2011-11-02 13:06:18 +01001687
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001688 /* Callback function to validate login */
Harald Weltebed35df2011-11-02 13:06:18 +01001689 if (gsn->cb_create_context_ind != 0)
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001690 rc = gsn->cb_create_context_ind(pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001691 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001692 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1693 "No create_context_ind callback defined\n");
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001694 rc = gtp_create_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001695 GTPCAUSE_NOT_SUPPORTED);
1696 }
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001697 if (recovery_recvd)
1698 emit_cb_recovery(gsn, peer, pdp, recovery);
1699 return rc;
jjako52c24142002-12-16 13:33:51 +00001700}
1701
jjako52c24142002-12-16 13:33:51 +00001702/* Handle Create PDP Context Response */
1703int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001704 struct sockaddr_in *peer, void *pack, unsigned len)
1705{
1706 struct pdp_t *pdp;
1707 union gtpie_member *ie[GTPIE_SIZE];
1708 uint8_t cause, recovery;
1709 void *cbp = NULL;
1710 uint8_t type = 0;
1711 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001712
Harald Weltebed35df2011-11-02 13:06:18 +01001713 /* Remove packet from queue */
1714 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1715 return EOF;
jjako52c24142002-12-16 13:33:51 +00001716
Harald Weltebed35df2011-11-02 13:06:18 +01001717 /* Find the context in question */
1718 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1719 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001720 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001721 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001722 if (gsn->cb_conf)
1723 gsn->cb_conf(type, EOF, NULL, cbp);
1724 return EOF;
1725 }
jjako2c381332003-10-21 19:09:53 +00001726
Harald Weltebed35df2011-11-02 13:06:18 +01001727 /* Register that we have received a valid teic from GGSN */
1728 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001729
Harald Weltebed35df2011-11-02 13:06:18 +01001730 /* Decode information elements */
1731 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1732 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001733 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1734 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001735 if (gsn->cb_conf)
1736 gsn->cb_conf(type, EOF, pdp, cbp);
1737 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1738 pdp_freepdp(pdp); */
1739 return EOF;
1740 }
jjako52c24142002-12-16 13:33:51 +00001741
Harald Weltebed35df2011-11-02 13:06:18 +01001742 /* Extract cause value (mandatory) */
1743 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1744 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001745 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1746 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001747 if (gsn->cb_conf)
1748 gsn->cb_conf(type, EOF, pdp, cbp);
1749 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1750 pdp_freepdp(pdp); */
1751 return EOF;
1752 }
jjako52c24142002-12-16 13:33:51 +00001753
Harald Weltebed35df2011-11-02 13:06:18 +01001754 /* Extract recovery (optional) */
1755 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001756 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001757 }
jjako52c24142002-12-16 13:33:51 +00001758
Harald Weltebed35df2011-11-02 13:06:18 +01001759 /* Extract protocol configuration options (optional) */
1760 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1761 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1762 }
jjako52c24142002-12-16 13:33:51 +00001763
Harald Weltebed35df2011-11-02 13:06:18 +01001764 /* Check all conditional information elements */
1765 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001766
Harald Weltebed35df2011-11-02 13:06:18 +01001767 if (version == 0) {
1768 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1769 &pdp->qos_neg0,
1770 sizeof(pdp->qos_neg0))) {
1771 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001772 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001773 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001774 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001775 if (gsn->cb_conf)
1776 gsn->cb_conf(type, EOF, pdp, cbp);
1777 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1778 pdp_freepdp(pdp); */
1779 return EOF;
1780 }
1781 }
jjako08d331d2003-10-13 20:33:30 +00001782
Harald Weltebed35df2011-11-02 13:06:18 +01001783 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1784 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001785 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001786 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001787 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001788 if (gsn->cb_conf)
1789 gsn->cb_conf(type, EOF, pdp, cbp);
1790 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1791 pdp_freepdp(pdp); */
1792 return EOF;
1793 }
jjako52c24142002-12-16 13:33:51 +00001794
Harald Weltebed35df2011-11-02 13:06:18 +01001795 if (version == 0) {
1796 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1797 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001798 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001799 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001800 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001801 if (gsn->cb_conf)
1802 gsn->cb_conf(type, EOF, pdp, cbp);
1803 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1804 pdp_freepdp(pdp); */
1805 return EOF;
1806 }
jjako52c24142002-12-16 13:33:51 +00001807
Harald Weltebed35df2011-11-02 13:06:18 +01001808 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1809 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001810 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001811 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001812 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001813 if (gsn->cb_conf)
1814 gsn->cb_conf(type, EOF, pdp, cbp);
1815 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1816 pdp_freepdp(pdp); */
1817 return EOF;
1818 }
1819 }
1820
1821 if (version == 1) {
1822 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1823 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001824 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001825 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001826 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001827 if (gsn->cb_conf)
1828 gsn->cb_conf(type, EOF, pdp, cbp);
1829 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1830 pdp_freepdp(pdp); */
1831 return EOF;
1832 }
1833
1834 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1835 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001836 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001837 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001838 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001839 if (gsn->cb_conf)
1840 gsn->cb_conf(type, EOF, pdp, cbp);
1841 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1842 pdp_freepdp(pdp); */
1843 return EOF;
1844 }
1845 }
1846
1847 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1848 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001849 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001850 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001851 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001852 if (gsn->cb_conf)
1853 gsn->cb_conf(type, EOF, pdp, cbp);
1854 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1855 pdp_freepdp(pdp); */
1856 }
1857
1858 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1859 &pdp->eua.v, sizeof(pdp->eua.v))) {
1860 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001861 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001862 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001863 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001864 if (gsn->cb_conf)
1865 gsn->cb_conf(type, EOF, pdp, cbp);
1866 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1867 pdp_freepdp(pdp); */
1868 return EOF;
1869 }
1870
1871 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1872 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1873 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001874 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001875 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001876 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001877 if (gsn->cb_conf)
1878 gsn->cb_conf(type, EOF, pdp, cbp);
1879 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1880 pdp_freepdp(pdp); */
1881 return EOF;
1882 }
1883
1884 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1885 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1886 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001887 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001888 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001889 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001890 if (gsn->cb_conf)
1891 gsn->cb_conf(type, EOF, pdp, cbp);
1892 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1893 pdp_freepdp(pdp); */
1894 return EOF;
1895 }
1896
1897 if (version == 1) {
1898 if (gtpie_gettlv
1899 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1900 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1901 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001902 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001903 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001904 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001905 if (gsn->cb_conf)
1906 gsn->cb_conf(type, EOF, pdp, cbp);
1907 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1908 pdp_freepdp(pdp); */
1909 return EOF;
1910 }
1911 }
1912
1913 }
1914
1915 if (gsn->cb_conf)
1916 gsn->cb_conf(type, cause, pdp, cbp);
1917
1918 return 0;
jjako52c24142002-12-16 13:33:51 +00001919}
1920
jjako08d331d2003-10-13 20:33:30 +00001921/* API: Send Update PDP Context Request */
1922int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001923 struct in_addr *inetaddr)
1924{
1925 union gtp_packet packet;
1926 unsigned int length =
1927 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001928
Harald Weltebed35df2011-11-02 13:06:18 +01001929 if (pdp->version == 0)
1930 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1931 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001932
Harald Weltebed35df2011-11-02 13:06:18 +01001933 /* Include IMSI if updating with unknown teic_gn */
1934 if ((pdp->version == 1) && (!pdp->teic_gn))
1935 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1936 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1937
1938 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1939 gsn->restart_counter);
1940
1941 if (pdp->version == 0) {
1942 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1943 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1944 }
1945
1946 if (pdp->version == 1) {
1947 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1948 pdp->teid_own);
1949
1950 if (!pdp->teic_confirmed)
1951 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1952 pdp->teic_own);
1953 }
1954
1955 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1956
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001957 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001958 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1959 pdp->traceref);
1960 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1961 pdp->tracetype); */
1962
1963 /* TODO if ggsn update message
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001964 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01001965 pdp->eua.l, pdp->eua.v);
1966 */
1967
1968 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1969 pdp->gsnlc.l, pdp->gsnlc.v);
1970 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1971 pdp->gsnlu.l, pdp->gsnlu.v);
1972
1973 if (pdp->version == 1)
1974 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1975 pdp->qos_req.l, pdp->qos_req.v);
1976
1977 if ((pdp->version == 1) && pdp->tft.l)
1978 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1979 pdp->tft.l, pdp->tft.v);
1980
1981 if ((pdp->version == 1) && pdp->triggerid.l)
1982 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1983 pdp->triggerid.l, pdp->triggerid.v);
1984
1985 if ((pdp->version == 1) && pdp->omcid.l)
1986 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1987 pdp->omcid.l, pdp->omcid.v);
1988
Daniel Willmann134a7752016-02-03 18:53:29 +01001989 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001990
1991 return 0;
jjako52c24142002-12-16 13:33:51 +00001992}
1993
jjako08d331d2003-10-13 20:33:30 +00001994/* Send Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001995static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01001996 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001997 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001998 struct pdp_t *pdp, uint8_t cause)
1999{
jjako08d331d2003-10-13 20:33:30 +00002000
Harald Weltebed35df2011-11-02 13:06:18 +01002001 union gtp_packet packet;
2002 unsigned int length =
2003 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00002004
Harald Weltebed35df2011-11-02 13:06:18 +01002005 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00002006
Harald Weltebed35df2011-11-02 13:06:18 +01002007 if (cause == GTPCAUSE_ACC_REQ) {
2008
2009 if (version == 0)
2010 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
2011 sizeof(pdp->qos_neg0), pdp->qos_neg0);
2012
2013 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
2014 gsn->restart_counter);
2015
2016 if (version == 0) {
2017 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
2018 pdp->fllu);
2019 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
2020 pdp->fllc);
2021 }
2022
2023 if (version == 1) {
2024 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2025 pdp->teid_own);
2026
2027 if (!pdp->teic_confirmed)
2028 gtpie_tv4(&packet, &length, GTP_MAX,
2029 GTPIE_TEI_C, pdp->teic_own);
2030 }
2031
2032 /* TODO we use teid_own as charging ID address */
2033 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
2034 pdp->teid_own);
2035
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002036 /* If ggsn
2037 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01002038 pdp->eua.l, pdp->eua.v); */
2039
2040 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2041 pdp->gsnlc.l, pdp->gsnlc.v);
2042 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2043 pdp->gsnlu.l, pdp->gsnlu.v);
2044
2045 if (version == 1)
2046 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2047 pdp->qos_neg.l, pdp->qos_neg.v);
2048
2049 /* TODO: Charging gateway address */
2050 }
2051
2052 return gtp_resp(version, gsn, pdp, &packet, length, peer,
2053 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00002054}
2055
jjako52c24142002-12-16 13:33:51 +00002056/* Handle Update PDP Context Request */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002057static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002058 struct sockaddr_in *peer, int fd,
2059 void *pack, unsigned len)
2060{
2061 struct pdp_t *pdp;
2062 struct pdp_t pdp_backup;
2063 union gtpie_member *ie[GTPIE_SIZE];
2064 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002065
Harald Weltebed35df2011-11-02 13:06:18 +01002066 uint16_t seq = get_seq(pack);
2067 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002068
Harald Weltebed35df2011-11-02 13:06:18 +01002069 uint64_t imsi;
2070 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002071
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002072 /* Is this a duplicate ? */
2073 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002074 return 0; /* We allready send of response once */
2075 }
jjako08d331d2003-10-13 20:33:30 +00002076
Harald Weltebed35df2011-11-02 13:06:18 +01002077 /* Decode information elements */
2078 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2079 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002080 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2081 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002082 if (0 == version)
2083 return EOF;
2084 else
2085 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2086 len, NULL,
2087 GTPCAUSE_INVALID_MESSAGE);
2088 }
jjako08d331d2003-10-13 20:33:30 +00002089
Harald Weltebed35df2011-11-02 13:06:18 +01002090 /* Finding PDP: */
2091 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2092 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2093 /* we have to use the tunnel endpoint identifier */
2094 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002095 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
2096
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01002097 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00002098
Harald Weltebed35df2011-11-02 13:06:18 +01002099 /* Find the context in question */
2100 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2101 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002102 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2103 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002104 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2105 len, NULL,
2106 GTPCAUSE_NON_EXIST);
2107 }
2108 } else if (version == 1) {
2109 /* NSAPI (mandatory) */
2110 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2111 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002112 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2113 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002114 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2115 len, NULL,
2116 GTPCAUSE_MAN_IE_MISSING);
2117 }
jjako08d331d2003-10-13 20:33:30 +00002118
Harald Weltebed35df2011-11-02 13:06:18 +01002119 /* IMSI (conditional) */
2120 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2121 /* Find the context in question */
2122 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2123 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002124 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002125 pack, len, "Unknown PDP context: %u\n",
2126 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002127 return gtp_update_pdp_resp(gsn, version, peer,
2128 fd, pack, len, NULL,
2129 GTPCAUSE_NON_EXIST);
2130 }
2131 } else {
2132 /* Find the context in question */
2133 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2134 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002135 GTP_LOGPKG(LOGL_ERROR, peer,
2136 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002137 return gtp_update_pdp_resp(gsn, version, peer,
2138 fd, pack, len, NULL,
2139 GTPCAUSE_NON_EXIST);
2140 }
2141 }
2142 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002143 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002144 return EOF;
2145 }
jjako08d331d2003-10-13 20:33:30 +00002146
Harald Weltebed35df2011-11-02 13:06:18 +01002147 /* Make a backup copy in case anything is wrong */
2148 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002149
Harald Weltebed35df2011-11-02 13:06:18 +01002150 if (version == 0) {
2151 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2152 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2153 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002154 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2155 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002156 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2157 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2158 len, pdp,
2159 GTPCAUSE_MAN_IE_MISSING);
2160 }
2161 }
jjako52c24142002-12-16 13:33:51 +00002162
Harald Weltebed35df2011-11-02 13:06:18 +01002163 /* Recovery (optional) */
2164 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002165 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002166 }
jjako08d331d2003-10-13 20:33:30 +00002167
Harald Weltebed35df2011-11-02 13:06:18 +01002168 if (version == 0) {
2169 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2170 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002171 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2172 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002173 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2174 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2175 len, pdp,
2176 GTPCAUSE_MAN_IE_MISSING);
2177 }
jjako52c24142002-12-16 13:33:51 +00002178
Harald Weltebed35df2011-11-02 13:06:18 +01002179 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2180 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002181 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2182 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002183 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2184 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2185 len, pdp,
2186 GTPCAUSE_MAN_IE_MISSING);
2187 }
2188 }
jjako52c24142002-12-16 13:33:51 +00002189
Harald Weltebed35df2011-11-02 13:06:18 +01002190 if (version == 1) {
2191 /* TEID (mandatory) */
2192 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2193 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002194 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2195 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002196 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2197 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2198 len, pdp,
2199 GTPCAUSE_MAN_IE_MISSING);
2200 }
jjako52c24142002-12-16 13:33:51 +00002201
Harald Weltebed35df2011-11-02 13:06:18 +01002202 /* TEIC (conditional) */
2203 /* If TEIC is not included it means that we have allready received it */
2204 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2205 /* all updated contexts, or only for one of the linked contexts */
2206 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2207
2208 /* NSAPI (mandatory) */
2209 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2210 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002211 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2212 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002213 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2214 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2215 len, pdp,
2216 GTPCAUSE_MAN_IE_MISSING);
2217 }
2218 }
2219
2220 /* Trace reference (optional) */
2221 /* Trace type (optional) */
2222
2223 /* End User Address (conditional) TODO: GGSN Initiated
2224 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2225 &pdp->eua.v, sizeof(pdp->eua.v))) {
2226 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002227 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002228 "Missing mandatory information field");
2229 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002230 return gtp_update_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01002231 GTPCAUSE_MAN_IE_MISSING);
2232 } */
2233
2234 /* SGSN address for signalling (mandatory) */
2235 /* It is weird that this is mandatory when TEIC is conditional */
2236 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2237 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2238 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002239 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2240 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002241 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2242 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2243 pdp, GTPCAUSE_MAN_IE_MISSING);
2244 }
2245
2246 /* SGSN address for user traffic (mandatory) */
2247 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2248 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2249 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002250 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2251 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002252 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2253 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2254 pdp, GTPCAUSE_MAN_IE_MISSING);
2255 }
2256
2257 if (version == 1) {
2258 /* QoS (mandatory) */
2259 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2260 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2261 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002262 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2263 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002264 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2265 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2266 len, pdp,
2267 GTPCAUSE_MAN_IE_MISSING);
2268 }
2269
2270 /* TFT (conditional) */
2271 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2272 &pdp->tft.v, sizeof(pdp->tft.v))) {
2273 }
2274
2275 /* OMC identity */
2276 }
2277
2278 /* Confirm to peer that things were "successful" */
2279 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2280 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002281}
2282
jjako52c24142002-12-16 13:33:51 +00002283/* Handle Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002284static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002285 struct sockaddr_in *peer, void *pack, unsigned len)
2286{
2287 struct pdp_t *pdp;
2288 union gtpie_member *ie[GTPIE_SIZE];
2289 uint8_t cause, recovery;
2290 void *cbp = NULL;
2291 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002292 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002293
Harald Weltebed35df2011-11-02 13:06:18 +01002294 /* Remove packet from queue */
2295 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2296 return EOF;
jjako52c24142002-12-16 13:33:51 +00002297
Harald Weltebed35df2011-11-02 13:06:18 +01002298 /* Find the context in question */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002299 if (pdp_getgtp1(&pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002300 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002301 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002302 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002303 pdp = NULL;
2304 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002305 }
jjako2c381332003-10-21 19:09:53 +00002306
Harald Weltebed35df2011-11-02 13:06:18 +01002307 /* Register that we have received a valid teic from GGSN */
2308 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002309
Harald Weltebed35df2011-11-02 13:06:18 +01002310 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002311 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002312 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002313 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2314 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002315 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002316 }
jjako52c24142002-12-16 13:33:51 +00002317
Harald Weltebed35df2011-11-02 13:06:18 +01002318 /* Extract cause value (mandatory) */
2319 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002320 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002321 }
jjako52c24142002-12-16 13:33:51 +00002322
Harald Weltebed35df2011-11-02 13:06:18 +01002323 /* Extract recovery (optional) */
2324 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002325 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002326 }
2327
2328 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002329 /* TODO: This does not handle GGSN-initiated update responses */
2330 if (GTPCAUSE_ACC_REQ == cause) {
2331 if (version == 0) {
2332 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2333 &pdp->qos_neg0,
2334 sizeof(pdp->qos_neg0))) {
2335 goto err_missing;
2336 }
2337
2338 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2339 goto err_missing;
2340 }
2341
2342 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2343 goto err_missing;
2344 }
Harald Weltebed35df2011-11-02 13:06:18 +01002345 }
2346
Daniel Willmannd9975522016-02-04 15:38:12 +01002347 if (version == 1) {
2348 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2349 goto err_missing;
2350 }
Harald Weltebed35df2011-11-02 13:06:18 +01002351
Daniel Willmannd9975522016-02-04 15:38:12 +01002352 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2353 goto err_missing;
2354 }
2355 }
2356
2357 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2358 goto err_missing;
2359 }
2360
2361 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2362 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2363 goto err_missing;
2364 }
2365
2366 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2367 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2368 goto err_missing;
2369 }
2370
2371 if (version == 1) {
2372 if (gtpie_gettlv
2373 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2374 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2375 goto err_missing;
2376 }
2377 }
Harald Weltebed35df2011-11-02 13:06:18 +01002378 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002379
2380 if (gsn->cb_conf)
2381 gsn->cb_conf(type, cause, pdp, cbp);
2382 return 0; /* Succes */
2383
2384err_missing:
2385 gsn->missing++;
2386 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2387 "Missing information field\n");
2388err_out:
2389 if (gsn->cb_conf)
2390 gsn->cb_conf(type, EOF, pdp, cbp);
2391 return EOF;
jjako52c24142002-12-16 13:33:51 +00002392}
2393
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002394/* API: Deprecated. Send Delete PDP Context Request And free pdp ctx. */
jjako2c381332003-10-21 19:09:53 +00002395int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002396 int teardown)
2397{
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002398 struct pdp_t *linked_pdp;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002399
2400 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
2401 LOGP(DLGTP, LOGL_ERROR,
2402 "Unknown linked PDP context: %u\n", pdp->teic_own);
2403 return EOF;
2404 }
2405
2406 if (gtp_delete_context_req2(gsn, pdp, cbp, teardown) == EOF)
2407 return EOF;
2408
2409 if (teardown) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002410 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002411 } else {
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002412 /* If we end up here (no teardown) it means we still
2413 have at least another pdp context active for this
2414 PDN connection (since last DeleteReq should come
2415 with teardown enabled). If the ctx to delete is a
2416 secondary ctx, simply free it. If it's the primary
2417 ctx, mark it as nodata but don't free it since we
2418 need it to hold data linked together and we'll
2419 require it later to tear down the entire tree. Still,
2420 we announce its deletion through cb_delete_context
2421 because we don't want user to release its related
2422 data and not use it anymore.
2423 */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002424 if (gsn->cb_delete_context)
2425 gsn->cb_delete_context(pdp);
2426 if (pdp == linked_pdp) {
2427 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2428 linked_pdp->nodata = 1;
2429 } else
2430 pdp_freepdp(pdp);
2431 }
2432
2433 return 0;
2434}
2435
2436/* API: Send Delete PDP Context Request. PDP CTX shall be free'd by user at cb_conf(GTP_DELETE_PDP_RSP) */
2437int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2438 int teardown)
2439{
Harald Weltebed35df2011-11-02 13:06:18 +01002440 union gtp_packet packet;
2441 unsigned int length =
2442 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2443 struct in_addr addr;
2444 struct pdp_t *linked_pdp;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002445 int count;
jjako2c381332003-10-21 19:09:53 +00002446
Harald Weltebed35df2011-11-02 13:06:18 +01002447 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2448 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002449 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002450 return EOF;
jjako2c381332003-10-21 19:09:53 +00002451 }
jjako2c381332003-10-21 19:09:53 +00002452
Harald Weltebed35df2011-11-02 13:06:18 +01002453 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002454 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002455 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002456 return EOF;
2457 }
2458
2459 if (!teardown) {
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002460 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002461 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002462 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002463 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002464 return EOF;
2465 }
2466 }
2467
2468 if (pdp->version == 1) {
2469 if (teardown)
2470 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2471 0xff);
2472
2473 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2474 }
2475
2476 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2477
Harald Weltebed35df2011-11-02 13:06:18 +01002478 return 0;
jjako2c381332003-10-21 19:09:53 +00002479}
jjako08d331d2003-10-13 20:33:30 +00002480
jjako52c24142002-12-16 13:33:51 +00002481/* Send Delete PDP Context Response */
2482int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002483 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002484 void *pack, unsigned len,
2485 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002486 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002487{
Harald Weltebed35df2011-11-02 13:06:18 +01002488 union gtp_packet packet;
Harald Weltebed35df2011-11-02 13:06:18 +01002489 unsigned int length =
2490 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00002491
Harald Weltebed35df2011-11-02 13:06:18 +01002492 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002493
Harald Weltebed35df2011-11-02 13:06:18 +01002494 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2495 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002496
Harald Weltebed35df2011-11-02 13:06:18 +01002497 if (cause == GTPCAUSE_ACC_REQ) {
2498 if ((teardown) || (version == 0)) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002499 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002500 } else {
2501 /* If we end up here (no teardown) it means we still
2502 have at least another pdp context active for this
2503 PDN connection (since last DeleteReq should come
2504 with teardown enabled). If the ctx to delete is a
2505 secondary ctx, simply free it. If it's the primary
2506 ctx, mark it as nodata but don't free it since we
2507 need it to hold data linked together and we'll
2508 require it later to tear down the entire tree. Still,
2509 we announce its deletion through cb_delete_context
2510 because we don't want user to release its related
2511 data and not use it anymore.
2512 */
Harald Weltebed35df2011-11-02 13:06:18 +01002513 if (gsn->cb_delete_context)
2514 gsn->cb_delete_context(pdp);
2515 if (pdp == linked_pdp) {
2516 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2517 0;
2518 linked_pdp->nodata = 1;
2519 } else
2520 pdp_freepdp(pdp);
2521 }
jjako2c381332003-10-21 19:09:53 +00002522 }
Harald Weltebed35df2011-11-02 13:06:18 +01002523 /* if (cause == GTPCAUSE_ACC_REQ) */
2524 return 0;
jjako52c24142002-12-16 13:33:51 +00002525}
2526
2527/* Handle Delete PDP Context Request */
2528int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002529 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002530 void *pack, unsigned len)
2531{
2532 struct pdp_t *pdp = NULL;
2533 struct pdp_t *linked_pdp = NULL;
2534 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002535
Harald Weltebed35df2011-11-02 13:06:18 +01002536 uint16_t seq = get_seq(pack);
2537 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002538
Harald Weltebed35df2011-11-02 13:06:18 +01002539 uint8_t nsapi;
2540 uint8_t teardown = 0;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002541 int count;
jjako52c24142002-12-16 13:33:51 +00002542
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002543 /* Is this a duplicate ? */
2544 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002545 return 0; /* We allready send off response once */
2546 }
jjako2c381332003-10-21 19:09:53 +00002547
Harald Weltebed35df2011-11-02 13:06:18 +01002548 /* Find the linked context in question */
2549 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2550 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002551 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002552 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002553 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2554 NULL, NULL, GTPCAUSE_NON_EXIST,
2555 teardown);
2556 }
jjako2c381332003-10-21 19:09:53 +00002557
Harald Weltebed35df2011-11-02 13:06:18 +01002558 /* If version 0 this is also the secondary context */
2559 if (version == 0)
2560 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002561
Harald Weltebed35df2011-11-02 13:06:18 +01002562 /* Decode information elements */
2563 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2564 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002565 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2566 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002567 if (0 == version)
2568 return EOF;
2569 else
2570 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2571 len, NULL, NULL,
2572 GTPCAUSE_INVALID_MESSAGE,
2573 teardown);
2574 }
2575
2576 if (version == 1) {
2577 /* NSAPI (mandatory) */
2578 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2579 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002580 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2581 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002582 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2583 len, NULL, NULL,
2584 GTPCAUSE_MAN_IE_MISSING,
2585 teardown);
2586 }
2587
2588 /* Find the context in question */
2589 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2590 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002591 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2592 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002593 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2594 len, NULL, NULL,
2595 GTPCAUSE_NON_EXIST,
2596 teardown);
2597 }
2598
2599 /* Teardown (conditional) */
2600 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2601
2602 if (!teardown) {
Pau Espin Pedrol742a6b52019-05-30 13:36:10 +02002603 /* TS 29.060 section 7.3.5: If a GSN receives a Delete PDP context
2604 * without a Teardown Indicator or with a Teardown Indicator with
2605 * value set to "0" and only that PDP context is active for a PDN
2606 * connection, then the GSN shall ignore the message. (Note:
2607 * This is symptom of a race condition. The reliable delivery of
2608 * signalling messages will eventually lead to a consistent
2609 * situation, allowing the teardown of the PDP context.)
2610 */
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002611 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002612 if (count <= 1) {
Pau Espin Pedrold1bd6fc2018-07-13 19:11:45 +02002613 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2614 "Ignoring CTX DEL without teardown and count=%d\n",
2615 count);
Harald Weltebed35df2011-11-02 13:06:18 +01002616 return 0; /* 29.060 7.3.5 Ignore message */
2617 }
2618 }
2619 }
2620
2621 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2622 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002623}
2624
jjako52c24142002-12-16 13:33:51 +00002625/* Handle Delete PDP Context Response */
2626int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002627 struct sockaddr_in *peer, void *pack, unsigned len)
2628{
2629 union gtpie_member *ie[GTPIE_SIZE];
2630 uint8_t cause;
2631 void *cbp = NULL;
2632 uint8_t type = 0;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002633 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002634 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002635
Harald Weltebed35df2011-11-02 13:06:18 +01002636 /* Remove packet from queue */
2637 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2638 return EOF;
jjako52c24142002-12-16 13:33:51 +00002639
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002640 /* Find the context in question. It may not be available if gtp_delete_context_req
2641 * was used and as a result the PDP ctx was already freed */
2642 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2643 gsn->err_unknownpdp++;
2644 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2645 "Unknown PDP context: %u (expected if gtp_delete_context_req is used)\n",
2646 get_tei(pack));
2647 if (gsn->cb_conf)
2648 gsn->cb_conf(type, EOF, NULL, cbp);
2649 return EOF;
2650 }
2651
Harald Weltebed35df2011-11-02 13:06:18 +01002652 /* Decode information elements */
2653 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2654 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002655 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2656 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002657 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002658 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002659 return EOF;
2660 }
2661
2662 /* Extract cause value (mandatory) */
2663 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2664 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002665 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2666 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002667 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002668 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002669 return EOF;
2670 }
2671
2672 /* Check the cause value (again) */
2673 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2674 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002675 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2676 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002677 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002678 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002679 return EOF;
2680 }
2681
2682 /* Callback function to notify application */
2683 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002684 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002685
2686 return 0;
jjako52c24142002-12-16 13:33:51 +00002687}
2688
Harald Welte54d082e2017-08-12 22:43:21 +02002689/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002690static int gtp_error_ind_resp(struct gsn_t *gsn, uint8_t version,
jjako08d331d2003-10-13 20:33:30 +00002691 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002692 void *pack, unsigned len)
2693{
Harald Weltebed35df2011-11-02 13:06:18 +01002694 union gtp_packet packet;
2695 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2696
Harald Welte54d082e2017-08-12 22:43:21 +02002697 if (version == 1) {
2698 /* Mandatory 7.7.13 TEI Data I */
2699 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2700 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2701
2702 /* Mandatory 7.7.32 GSN Address */
2703 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2704 sizeof(gsn->gsnu), &gsn->gsnu);
2705 }
2706
Harald Weltebed35df2011-11-02 13:06:18 +01002707 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2708 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002709}
2710
2711/* Handle Error Indication */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002712static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002713 struct sockaddr_in *peer, void *pack, unsigned len)
2714{
Harald Welte37d5b152017-08-12 23:58:29 +02002715 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002716 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002717
Harald Weltebed35df2011-11-02 13:06:18 +01002718 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002719 if (version == 0) {
2720 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
2721 gsn->err_unknownpdp++;
2722 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2723 "Unknown PDP context\n");
2724 return EOF;
2725 }
2726 } else if (version == 1) {
2727 /* we have to look-up based on the *peer* TEID */
2728 int hlen = get_hlen(pack);
2729 uint32_t teid_gn;
2730
2731 /* Decode information elements */
2732 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2733 gsn->invalid++;
2734 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2735 "Invalid message format\n");
2736 return EOF;
2737 }
2738
2739 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2740 gsn->missing++;
2741 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2742 "Missing mandatory information field\n");
2743 return EOF;
2744 }
2745
2746 if (pdp_getgtp1_peer_d(&pdp, peer, teid_gn)) {
2747 gsn->err_unknownpdp++;
2748 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2749 return EOF;
2750 }
Harald Weltebed35df2011-11-02 13:06:18 +01002751 }
jjako52c24142002-12-16 13:33:51 +00002752
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002753 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2754 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002755
Harald Weltebd228242017-11-06 03:16:49 +09002756 /* This is obvious from above code, given the semantics of the
2757 * functions above, but Coverity doesn't figure this out, so
2758 * let's make it clear. It's good style anyway in case above
2759 * code should ever change. */
2760 OSMO_ASSERT(pdp);
2761
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002762 gtp_freepdp(gsn, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002763 return 0;
jjako52c24142002-12-16 13:33:51 +00002764}
2765
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002766static int gtp_gpdu_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002767 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2768{
jjako08d331d2003-10-13 20:33:30 +00002769
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002770 int hlen;
jjako52c24142002-12-16 13:33:51 +00002771
Harald Weltebed35df2011-11-02 13:06:18 +01002772 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002773
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002774 switch (version) {
2775 case 0:
Harald Weltebed35df2011-11-02 13:06:18 +01002776 if (pdp_getgtp0
2777 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2778 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002779 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002780 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002781 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2782 len);
2783 }
2784 hlen = GTP0_HEADER_SIZE;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002785 break;
2786 case 1:
Harald Weltebed35df2011-11-02 13:06:18 +01002787 if (pdp_getgtp1
2788 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2789 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002790 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002791 len, "Unknown PDP context, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002792 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2793 len);
2794 }
jjako08d331d2003-10-13 20:33:30 +00002795
Harald Weltebed35df2011-11-02 13:06:18 +01002796 /* Is this a long or a short header ? */
2797 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2798 hlen = GTP1_HEADER_SIZE_LONG;
2799 else
2800 hlen = GTP1_HEADER_SIZE_SHORT;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002801 break;
2802 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002803 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002804 "Unknown version: %d\n", version);
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002805 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002806 }
jjako08d331d2003-10-13 20:33:30 +00002807
Harald Weltebed35df2011-11-02 13:06:18 +01002808 /* If the GPDU was not from the peer GSN tell him to delete context */
2809 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2810 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002811 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002812 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2813 }
jjako52c24142002-12-16 13:33:51 +00002814
Harald Weltebed35df2011-11-02 13:06:18 +01002815 /* Callback function */
2816 if (gsn->cb_data_ind != 0)
2817 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2818
2819 return 0;
jjako52c24142002-12-16 13:33:51 +00002820}
2821
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002822/* Receives GTP packet and sends off for further processing
jjako52c24142002-12-16 13:33:51 +00002823 * Function will check the validity of the header. If the header
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002824 * is not valid the packet is either dropped or a version not
2825 * supported is returned to the peer.
jjako52c24142002-12-16 13:33:51 +00002826 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002827int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002828{
Harald Weltebed35df2011-11-02 13:06:18 +01002829 unsigned char buffer[PACKET_MAX];
2830 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002831 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002832 int status;
2833 struct gtp0_header *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002834 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002835 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002836
Harald Weltebed35df2011-11-02 13:06:18 +01002837 /* TODO: Need strategy of userspace buffering and blocking */
2838 /* Currently read is non-blocking and send is blocking. */
2839 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002840
Harald Weltebed35df2011-11-02 13:06:18 +01002841 while (1) { /* Loop until no more to read */
2842 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002843 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002844 return -1;
2845 }
2846 peerlen = sizeof(peer);
2847 if ((status =
2848 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2849 (struct sockaddr *)&peer, &peerlen)) < 0) {
2850 if (errno == EAGAIN)
2851 return 0;
2852 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002853 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002854 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002855 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2856 status, status ? strerror(errno) : "No error");
2857 return -1;
2858 }
jjako1db1c812003-07-06 20:53:57 +00002859
Harald Weltebed35df2011-11-02 13:06:18 +01002860 /* Need at least 1 byte in order to check version */
2861 if (status < (1)) {
2862 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002863 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2864 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002865 continue;
2866 }
jjako08d331d2003-10-13 20:33:30 +00002867
Harald Weltebed35df2011-11-02 13:06:18 +01002868 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002869
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002870 version = GTPHDR_F_GET_VER(pheader->flags);
2871
Harald Weltebed35df2011-11-02 13:06:18 +01002872 /* Version should be gtp0 (or earlier) */
2873 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2874 /* GTP 0 messages. If other version message is received we reply that we */
2875 /* only support version 0, implying that this is the only version */
2876 /* supported on this port */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002877 if (version > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002878 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01002879 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2880 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002881 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2882 continue;
2883 }
2884
2885 /* Check length of gtp0 packet */
2886 if (status < GTP0_HEADER_SIZE) {
2887 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002888 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2889 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002890 continue; /* Silently discard 29.60: 11.1.2 */
2891 }
2892
2893 /* Check packet length field versus length of packet */
2894 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2895 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002896 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002897 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002898 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002899 continue; /* Silently discard */
2900 }
2901
2902 if ((gsn->mode == GTP_MODE_GGSN) &&
2903 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002904 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002905 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002906 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002907 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002908 "Unexpected GTPv0 Signalling Message '%s'\n",
2909 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002910 continue; /* Silently discard 29.60: 11.1.4 */
2911 }
2912
2913 if ((gsn->mode == GTP_MODE_SGSN) &&
2914 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002915 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002916 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002917 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002918 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002919 "Unexpected GTPv0 Signalling Message '%s'\n",
2920 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002921 continue; /* Silently discard 29.60: 11.1.4 */
2922 }
2923
2924 switch (pheader->type) {
2925 case GTP_ECHO_REQ:
2926 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2927 break;
2928 case GTP_ECHO_RSP:
2929 gtp_echo_conf(gsn, version, &peer, buffer, status);
2930 break;
2931 case GTP_NOT_SUPPORTED:
2932 gtp_unsup_ind(gsn, &peer, buffer, status);
2933 break;
2934 case GTP_CREATE_PDP_REQ:
2935 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2936 status);
2937 break;
2938 case GTP_CREATE_PDP_RSP:
2939 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2940 status);
2941 break;
2942 case GTP_UPDATE_PDP_REQ:
2943 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2944 status);
2945 break;
2946 case GTP_UPDATE_PDP_RSP:
2947 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2948 status);
2949 break;
2950 case GTP_DELETE_PDP_REQ:
2951 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2952 status);
2953 break;
2954 case GTP_DELETE_PDP_RSP:
2955 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2956 status);
2957 break;
2958 case GTP_ERROR:
2959 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2960 break;
2961 case GTP_GPDU:
2962 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2963 break;
2964 default:
2965 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002966 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2967 "Unknown GTP message type received: %d\n",
2968 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002969 break;
2970 }
2971 }
jjako08d331d2003-10-13 20:33:30 +00002972}
2973
jjako08d331d2003-10-13 20:33:30 +00002974int gtp_decaps1c(struct gsn_t *gsn)
2975{
Harald Weltebed35df2011-11-02 13:06:18 +01002976 unsigned char buffer[PACKET_MAX];
2977 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002978 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002979 int status;
2980 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002981 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002982 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002983
Harald Weltebed35df2011-11-02 13:06:18 +01002984 /* TODO: Need strategy of userspace buffering and blocking */
2985 /* Currently read is non-blocking and send is blocking. */
2986 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002987
Harald Weltebed35df2011-11-02 13:06:18 +01002988 while (1) { /* Loop until no more to read */
2989 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002990 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002991 return -1;
2992 }
2993 peerlen = sizeof(peer);
2994 if ((status =
2995 recvfrom(fd, buffer, sizeof(buffer), 0,
2996 (struct sockaddr *)&peer, &peerlen)) < 0) {
2997 if (errno == EAGAIN)
2998 return 0;
2999 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003000 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003001 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003002 fd, (unsigned long)buffer, sizeof(buffer),
3003 status, status ? strerror(errno) : "No error");
3004 return -1;
3005 }
jjako08d331d2003-10-13 20:33:30 +00003006
Harald Weltebed35df2011-11-02 13:06:18 +01003007 /* Need at least 1 byte in order to check version */
3008 if (status < (1)) {
3009 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003010 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3011 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003012 continue;
3013 }
jjako08d331d2003-10-13 20:33:30 +00003014
Harald Weltebed35df2011-11-02 13:06:18 +01003015 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003016
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003017 version = GTPHDR_F_GET_VER(pheader->flags);
3018
Harald Weltebed35df2011-11-02 13:06:18 +01003019 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003020 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003021 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003022 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3023 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003024 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
3025 /*29.60: 11.1.1 */
3026 continue;
3027 }
jjako08d331d2003-10-13 20:33:30 +00003028
Harald Weltebed35df2011-11-02 13:06:18 +01003029 /* Version must be at least GTP 1 */
3030 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3031 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3032 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003033 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003034 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003035 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3036 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003037 continue;
3038 }
jjako08d331d2003-10-13 20:33:30 +00003039
Harald Weltebed35df2011-11-02 13:06:18 +01003040 /* Check packet flag field */
3041 if (((pheader->flags & 0xf7) != 0x32)) {
3042 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003043 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003044 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003045 continue;
3046 }
jjako2c381332003-10-21 19:09:53 +00003047
Harald Weltebed35df2011-11-02 13:06:18 +01003048 /* Check length of packet */
3049 if (status < GTP1_HEADER_SIZE_LONG) {
3050 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003051 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3052 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003053 continue; /* Silently discard 29.60: 11.1.2 */
3054 }
jjako2c381332003-10-21 19:09:53 +00003055
Harald Weltebed35df2011-11-02 13:06:18 +01003056 /* Check packet length field versus length of packet */
3057 if (status !=
3058 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3059 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003060 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003061 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003062 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003063 continue; /* Silently discard */
3064 }
jjako1db1c812003-07-06 20:53:57 +00003065
Harald Weltebed35df2011-11-02 13:06:18 +01003066 /* Check for extension headers */
3067 /* TODO: We really should cycle through the headers and determine */
3068 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003069 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003070 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003071 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3072 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003073 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3074 status);
jjako1db1c812003-07-06 20:53:57 +00003075
Harald Weltebed35df2011-11-02 13:06:18 +01003076 continue;
3077 }
3078
3079 if ((gsn->mode == GTP_MODE_GGSN) &&
3080 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003081 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003082 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003083 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003084 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003085 "Unexpected GTPv1 Signalling Message '%s'\n",
3086 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003087 continue; /* Silently discard 29.60: 11.1.4 */
3088 }
3089
3090 if ((gsn->mode == GTP_MODE_SGSN) &&
3091 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003092 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003093 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003094 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003095 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003096 "Unexpected GTPv1 Signalling Message '%s'\n",
3097 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003098 continue; /* Silently discard 29.60: 11.1.4 */
3099 }
3100
3101 switch (pheader->type) {
3102 case GTP_ECHO_REQ:
3103 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3104 break;
3105 case GTP_ECHO_RSP:
3106 gtp_echo_conf(gsn, version, &peer, buffer, status);
3107 break;
3108 case GTP_NOT_SUPPORTED:
3109 gtp_unsup_ind(gsn, &peer, buffer, status);
3110 break;
3111 case GTP_SUPP_EXT_HEADER:
3112 gtp_extheader_ind(gsn, &peer, buffer, status);
3113 break;
3114 case GTP_CREATE_PDP_REQ:
3115 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3116 status);
3117 break;
3118 case GTP_CREATE_PDP_RSP:
3119 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3120 status);
3121 break;
3122 case GTP_UPDATE_PDP_REQ:
3123 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3124 status);
3125 break;
3126 case GTP_UPDATE_PDP_RSP:
3127 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3128 status);
3129 break;
3130 case GTP_DELETE_PDP_REQ:
3131 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3132 status);
3133 break;
3134 case GTP_DELETE_PDP_RSP:
3135 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3136 status);
3137 break;
3138 case GTP_ERROR:
3139 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3140 break;
3141 default:
3142 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003143 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3144 "Unknown GTP message type received: %u\n",
3145 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003146 break;
3147 }
3148 }
jjako52c24142002-12-16 13:33:51 +00003149}
3150
jjako08d331d2003-10-13 20:33:30 +00003151int gtp_decaps1u(struct gsn_t *gsn)
3152{
Harald Weltebed35df2011-11-02 13:06:18 +01003153 unsigned char buffer[PACKET_MAX];
3154 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003155 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003156 int status;
3157 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003158 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003159 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003160
Harald Weltebed35df2011-11-02 13:06:18 +01003161 /* TODO: Need strategy of userspace buffering and blocking */
3162 /* Currently read is non-blocking and send is blocking. */
3163 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003164
Harald Weltebed35df2011-11-02 13:06:18 +01003165 while (1) { /* Loop until no more to read */
3166 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003167 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003168 return -1;
3169 }
3170 peerlen = sizeof(peer);
3171 if ((status =
3172 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3173 (struct sockaddr *)&peer, &peerlen)) < 0) {
3174 if (errno == EAGAIN)
3175 return 0;
3176 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003177 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003178 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003179 gsn->fd1u, (unsigned long)buffer,
3180 sizeof(buffer), status,
3181 status ? strerror(errno) : "No error");
3182 return -1;
3183 }
jjako08d331d2003-10-13 20:33:30 +00003184
Harald Weltebed35df2011-11-02 13:06:18 +01003185 /* Need at least 1 byte in order to check version */
3186 if (status < (1)) {
3187 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003188 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3189 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003190 continue;
3191 }
jjako08d331d2003-10-13 20:33:30 +00003192
Harald Weltebed35df2011-11-02 13:06:18 +01003193 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003194
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003195 version = GTPHDR_F_GET_VER(pheader->flags);
3196
Harald Weltebed35df2011-11-02 13:06:18 +01003197 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003198 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003199 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003200 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3201 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003202 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3203 continue;
3204 }
jjako08d331d2003-10-13 20:33:30 +00003205
Harald Weltebed35df2011-11-02 13:06:18 +01003206 /* Version must be at least GTP 1 */
3207 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3208 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3209 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003210 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003211 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003212 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3213 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003214 continue;
3215 }
jjako2c381332003-10-21 19:09:53 +00003216
Harald Weltebed35df2011-11-02 13:06:18 +01003217 /* Check packet flag field (allow both with and without sequence number) */
3218 if (((pheader->flags & 0xf5) != 0x30)) {
3219 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003220 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003221 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003222 continue;
3223 }
jjako2c381332003-10-21 19:09:53 +00003224
Harald Weltebed35df2011-11-02 13:06:18 +01003225 /* Check length of packet */
3226 if (status < GTP1_HEADER_SIZE_SHORT) {
3227 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003228 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3229 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003230 continue; /* Silently discard 29.60: 11.1.2 */
3231 }
3232
3233 /* Check packet length field versus length of packet */
3234 if (status !=
3235 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3236 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003237 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003238 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003239 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003240 continue; /* Silently discard */
3241 }
3242
3243 /* Check for extension headers */
3244 /* TODO: We really should cycle through the headers and determine */
3245 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003246 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003247 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003248 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3249 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003250 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3251 status);
3252
3253 continue;
3254 }
3255
3256 switch (pheader->type) {
3257 case GTP_ECHO_REQ:
3258 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3259 break;
3260 case GTP_ECHO_RSP:
3261 gtp_echo_conf(gsn, version, &peer, buffer, status);
3262 break;
3263 case GTP_SUPP_EXT_HEADER:
3264 gtp_extheader_ind(gsn, &peer, buffer, status);
3265 break;
3266 case GTP_ERROR:
3267 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3268 break;
3269 /* Supported header extensions */
3270 case GTP_GPDU:
3271 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3272 break;
3273 default:
3274 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003275 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3276 "Unknown GTP message type received: %u\n",
3277 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003278 break;
3279 }
3280 }
jjako08d331d2003-10-13 20:33:30 +00003281}
3282
Harald Weltebed35df2011-11-02 13:06:18 +01003283int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003284{
Harald Weltebed35df2011-11-02 13:06:18 +01003285 union gtp_packet packet;
3286 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003287 struct msghdr msgh;
3288 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003289 int fd;
jjako52c24142002-12-16 13:33:51 +00003290
Harald Welte471e3492017-09-24 16:12:39 +08003291 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003292 memset(&addr, 0, sizeof(addr));
3293 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003294#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003295 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003296#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003297 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003298
Harald Welte471e3492017-09-24 16:12:39 +08003299 /* prepare msghdr */
3300 memset(&msgh, 0, sizeof(msgh));
3301 msgh.msg_name = &addr;
3302 msgh.msg_namelen = sizeof(addr);
3303 msgh.msg_iov = iov;
3304 msgh.msg_iovlen = ARRAY_SIZE(iov);
3305
3306 /* prepare iovectors */
3307 iov[0].iov_base = &packet;
3308 /* iov[0].iov_len is not known here yet */
3309 iov[1].iov_base = pack;
3310 iov[1].iov_len = len;
3311
Harald Weltebed35df2011-11-02 13:06:18 +01003312 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003313
Harald Welte471e3492017-09-24 16:12:39 +08003314 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003315 addr.sin_port = htons(GTP0_PORT);
3316 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003317
Harald Weltebed35df2011-11-02 13:06:18 +01003318 get_default_gtp(0, GTP_GPDU, &packet);
3319 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003320 if (pdp->tx_gpdu_seq)
3321 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3322 else
3323 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003324 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003325 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003326 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003327
Harald Weltebed35df2011-11-02 13:06:18 +01003328 addr.sin_port = htons(GTP1U_PORT);
3329 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003330
Harald Weltebed35df2011-11-02 13:06:18 +01003331 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003332 if (pdp->tx_gpdu_seq) {
3333 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3334 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3335 GTP1_HEADER_SIZE_LONG);
3336 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3337 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3338 } else {
3339 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3340 packet.gtp1s.h.length = hton16(len);
3341 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3342 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3343 }
Harald Weltebed35df2011-11-02 13:06:18 +01003344 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003345 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003346 return EOF;
3347 }
3348
3349 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003350 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003351 return -1;
3352 }
3353
Harald Welte471e3492017-09-24 16:12:39 +08003354 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003355 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003356 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003357 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003358 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3359 strerror(errno));
3360 return EOF;
3361 }
3362 return 0;
jjako52c24142002-12-16 13:33:51 +00003363}
3364
jjako52c24142002-12-16 13:33:51 +00003365/* ***********************************************************
3366 * Conversion functions
3367 *************************************************************/
3368
jjako52c24142002-12-16 13:33:51 +00003369/* ***********************************************************
3370 * IP address conversion functions
3371 * There exist several types of address representations:
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01003372 * - eua: End User Address. (29.060, 7.7.27, message type 128)
jjako52c24142002-12-16 13:33:51 +00003373 * Used for signalling address to mobile station. Supports IPv4
3374 * IPv6 x.25 etc. etc.
3375 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3376 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3377 * - in_addr: IPv4 address struct.
3378 * - sockaddr_in: Socket API representation of IP address and
3379 * port number.
3380 *************************************************************/
3381
Harald Weltebed35df2011-11-02 13:06:18 +01003382int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3383{
Harald Weltecee75462017-09-24 17:45:05 +08003384 eua->v[0] = PDP_EUA_ORG_IETF;
3385 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003386 if (src) {
3387 eua->l = 6;
3388 memcpy(&eua->v[2], src, 4);
3389 } else {
3390 eua->l = 2;
3391 }
3392 return 0;
jjako52c24142002-12-16 13:33:51 +00003393}
3394
Harald Weltebed35df2011-11-02 13:06:18 +01003395int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3396{
Harald Weltecee75462017-09-24 17:45:05 +08003397 if ((eua->l != 6) || (eua->v[0] != PDP_EUA_ORG_IETF) || (eua->v[1] != PDP_EUA_TYPE_v4))
Harald Weltebed35df2011-11-02 13:06:18 +01003398 return -1; /* Not IPv4 address */
3399 memcpy(dst, &eua->v[2], 4);
3400 return 0;
jjako52c24142002-12-16 13:33:51 +00003401}
3402
Harald Weltebed35df2011-11-02 13:06:18 +01003403int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3404{
3405 memset(dst, 0, sizeof(struct in_addr));
3406 if (gsna->l != 4)
3407 return EOF; /* Return if not IPv4 */
3408 memcpy(dst, gsna->v, gsna->l);
3409 return 0;
jjako52c24142002-12-16 13:33:51 +00003410}
3411
Harald Weltebed35df2011-11-02 13:06:18 +01003412int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3413{
3414 memset(gsna, 0, sizeof(struct ul16_t));
3415 gsna->l = 4;
3416 memcpy(gsna->v, src, gsna->l);
3417 return 0;
jjako52c24142002-12-16 13:33:51 +00003418}
Harald Welteb10ee082017-08-12 19:29:16 +02003419
3420/* TS 29.060 has yet again a different encoding for IMSIs than
3421 * what we have in other places, so we cannot use the gsm48
3422 * decoding functions. Also, libgtp uses an uint64_t in
3423 * _network byte order_ to contain BCD digits ?!? */
3424const char *imsi_gtp2str(const uint64_t *imsi)
3425{
Harald Weltea06120d2017-11-06 03:12:54 +09003426 static char buf[sizeof(*imsi)*2+1];
Harald Welteb10ee082017-08-12 19:29:16 +02003427 const uint8_t *imsi8 = (const uint8_t *) imsi;
3428 unsigned int i, j = 0;
3429
3430 for (i = 0; i < sizeof(*imsi); i++) {
3431 uint8_t nibble;
3432
3433 nibble = imsi8[i] & 0xf;
3434 if (nibble == 0xf)
3435 break;
3436 buf[j++] = osmo_bcd2char(nibble);
3437
3438 nibble = imsi8[i] >> 4;
3439 if (nibble == 0xf)
3440 break;
3441 buf[j++] = osmo_bcd2char(nibble);
3442 }
3443
3444 buf[j++] = '\0';
3445 return buf;
3446}