blob: 2b14026f99fe82d3ad237ed5370912a010e9cc5a [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 (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002425 if (gsn->cb_delete_context)
2426 gsn->cb_delete_context(pdp);
2427 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2428 pdp->nodata = 1;
2429 } else {
2430 gtp_freepdp(gsn, pdp);
2431 }
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002432 }
2433
2434 return 0;
2435}
2436
Oliver Smith1cde2c12019-05-13 11:35:03 +02002437/* API: Send Delete PDP Context Request. PDP CTX shall be free'd by user at any
2438 point in time later than this function through a call to pdp_freepdp(pdp), but
2439 it must be freed no later than during cb_conf(GTP_DELETE_PDP_REQ, pdp) */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002440int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2441 int teardown)
2442{
Harald Weltebed35df2011-11-02 13:06:18 +01002443 union gtp_packet packet;
2444 unsigned int length =
2445 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2446 struct in_addr addr;
2447 struct pdp_t *linked_pdp;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002448 int count;
jjako2c381332003-10-21 19:09:53 +00002449
Harald Weltebed35df2011-11-02 13:06:18 +01002450 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2451 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002452 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002453 return EOF;
jjako2c381332003-10-21 19:09:53 +00002454 }
jjako2c381332003-10-21 19:09:53 +00002455
Harald Weltebed35df2011-11-02 13:06:18 +01002456 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002457 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002458 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002459 return EOF;
2460 }
2461
2462 if (!teardown) {
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002463 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002464 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002465 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002466 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002467 return EOF;
2468 }
2469 }
2470
2471 if (pdp->version == 1) {
2472 if (teardown)
2473 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2474 0xff);
2475
2476 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2477 }
2478
2479 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2480
Harald Weltebed35df2011-11-02 13:06:18 +01002481 return 0;
jjako2c381332003-10-21 19:09:53 +00002482}
jjako08d331d2003-10-13 20:33:30 +00002483
jjako52c24142002-12-16 13:33:51 +00002484/* Send Delete PDP Context Response */
2485int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002486 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002487 void *pack, unsigned len,
2488 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002489 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002490{
Harald Weltebed35df2011-11-02 13:06:18 +01002491 union gtp_packet packet;
Harald Weltebed35df2011-11-02 13:06:18 +01002492 unsigned int length =
2493 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00002494
Harald Weltebed35df2011-11-02 13:06:18 +01002495 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002496
Harald Weltebed35df2011-11-02 13:06:18 +01002497 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2498 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002499
Harald Weltebed35df2011-11-02 13:06:18 +01002500 if (cause == GTPCAUSE_ACC_REQ) {
2501 if ((teardown) || (version == 0)) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002502 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002503 } else {
2504 /* If we end up here (no teardown) it means we still
2505 have at least another pdp context active for this
2506 PDN connection (since last DeleteReq should come
2507 with teardown enabled). If the ctx to delete is a
2508 secondary ctx, simply free it. If it's the primary
2509 ctx, mark it as nodata but don't free it since we
2510 need it to hold data linked together and we'll
2511 require it later to tear down the entire tree. Still,
2512 we announce its deletion through cb_delete_context
2513 because we don't want user to release its related
2514 data and not use it anymore.
2515 */
Harald Weltebed35df2011-11-02 13:06:18 +01002516 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002517 if (gsn->cb_delete_context)
2518 gsn->cb_delete_context(pdp);
2519 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2520 pdp->nodata = 1;
2521 } else {
2522 gtp_freepdp(gsn, pdp);
2523 }
Harald Weltebed35df2011-11-02 13:06:18 +01002524 }
jjako2c381332003-10-21 19:09:53 +00002525 }
Harald Weltebed35df2011-11-02 13:06:18 +01002526 /* if (cause == GTPCAUSE_ACC_REQ) */
2527 return 0;
jjako52c24142002-12-16 13:33:51 +00002528}
2529
2530/* Handle Delete PDP Context Request */
2531int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002532 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002533 void *pack, unsigned len)
2534{
2535 struct pdp_t *pdp = NULL;
2536 struct pdp_t *linked_pdp = NULL;
2537 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002538
Harald Weltebed35df2011-11-02 13:06:18 +01002539 uint16_t seq = get_seq(pack);
2540 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002541
Harald Weltebed35df2011-11-02 13:06:18 +01002542 uint8_t nsapi;
2543 uint8_t teardown = 0;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002544 int count;
jjako52c24142002-12-16 13:33:51 +00002545
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002546 /* Is this a duplicate ? */
2547 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002548 return 0; /* We allready send off response once */
2549 }
jjako2c381332003-10-21 19:09:53 +00002550
Harald Weltebed35df2011-11-02 13:06:18 +01002551 /* Find the linked context in question */
2552 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2553 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002554 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002555 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002556 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2557 NULL, NULL, GTPCAUSE_NON_EXIST,
2558 teardown);
2559 }
jjako2c381332003-10-21 19:09:53 +00002560
Harald Weltebed35df2011-11-02 13:06:18 +01002561 /* If version 0 this is also the secondary context */
2562 if (version == 0)
2563 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002564
Harald Weltebed35df2011-11-02 13:06:18 +01002565 /* Decode information elements */
2566 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2567 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002568 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2569 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002570 if (0 == version)
2571 return EOF;
2572 else
2573 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2574 len, NULL, NULL,
2575 GTPCAUSE_INVALID_MESSAGE,
2576 teardown);
2577 }
2578
2579 if (version == 1) {
2580 /* NSAPI (mandatory) */
2581 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2582 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002583 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2584 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002585 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2586 len, NULL, NULL,
2587 GTPCAUSE_MAN_IE_MISSING,
2588 teardown);
2589 }
2590
2591 /* Find the context in question */
2592 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2593 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002594 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2595 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002596 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2597 len, NULL, NULL,
2598 GTPCAUSE_NON_EXIST,
2599 teardown);
2600 }
2601
2602 /* Teardown (conditional) */
2603 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2604
2605 if (!teardown) {
Pau Espin Pedrol742a6b52019-05-30 13:36:10 +02002606 /* TS 29.060 section 7.3.5: If a GSN receives a Delete PDP context
2607 * without a Teardown Indicator or with a Teardown Indicator with
2608 * value set to "0" and only that PDP context is active for a PDN
2609 * connection, then the GSN shall ignore the message. (Note:
2610 * This is symptom of a race condition. The reliable delivery of
2611 * signalling messages will eventually lead to a consistent
2612 * situation, allowing the teardown of the PDP context.)
2613 */
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002614 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002615 if (count <= 1) {
Pau Espin Pedrold1bd6fc2018-07-13 19:11:45 +02002616 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2617 "Ignoring CTX DEL without teardown and count=%d\n",
2618 count);
Harald Weltebed35df2011-11-02 13:06:18 +01002619 return 0; /* 29.060 7.3.5 Ignore message */
2620 }
2621 }
2622 }
2623
2624 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2625 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002626}
2627
jjako52c24142002-12-16 13:33:51 +00002628/* Handle Delete PDP Context Response */
2629int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002630 struct sockaddr_in *peer, void *pack, unsigned len)
2631{
2632 union gtpie_member *ie[GTPIE_SIZE];
2633 uint8_t cause;
2634 void *cbp = NULL;
2635 uint8_t type = 0;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002636 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002637 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002638
Harald Weltebed35df2011-11-02 13:06:18 +01002639 /* Remove packet from queue */
2640 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2641 return EOF;
jjako52c24142002-12-16 13:33:51 +00002642
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002643 /* Find the context in question. It may not be available if gtp_delete_context_req
2644 * was used and as a result the PDP ctx was already freed */
2645 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2646 gsn->err_unknownpdp++;
2647 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
Oliver Smith1cde2c12019-05-13 11:35:03 +02002648 "Unknown PDP context: %u (expected if gtp_delete_context_req is used or pdp ctx was freed manually before response)\n",
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002649 get_tei(pack));
2650 if (gsn->cb_conf)
2651 gsn->cb_conf(type, EOF, NULL, cbp);
2652 return EOF;
2653 }
2654
Harald Weltebed35df2011-11-02 13:06:18 +01002655 /* Decode information elements */
2656 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2657 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002658 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2659 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002660 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002661 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002662 return EOF;
2663 }
2664
2665 /* Extract cause value (mandatory) */
2666 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2667 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002668 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2669 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002670 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002671 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002672 return EOF;
2673 }
2674
2675 /* Check the cause value (again) */
2676 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2677 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002678 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2679 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002680 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002681 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002682 return EOF;
2683 }
2684
2685 /* Callback function to notify application */
2686 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002687 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002688
2689 return 0;
jjako52c24142002-12-16 13:33:51 +00002690}
2691
Harald Welte54d082e2017-08-12 22:43:21 +02002692/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002693static int gtp_error_ind_resp(struct gsn_t *gsn, uint8_t version,
jjako08d331d2003-10-13 20:33:30 +00002694 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002695 void *pack, unsigned len)
2696{
Harald Weltebed35df2011-11-02 13:06:18 +01002697 union gtp_packet packet;
2698 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2699
Harald Welte54d082e2017-08-12 22:43:21 +02002700 if (version == 1) {
2701 /* Mandatory 7.7.13 TEI Data I */
2702 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2703 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2704
2705 /* Mandatory 7.7.32 GSN Address */
2706 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2707 sizeof(gsn->gsnu), &gsn->gsnu);
2708 }
2709
Harald Weltebed35df2011-11-02 13:06:18 +01002710 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2711 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002712}
2713
2714/* Handle Error Indication */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002715static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002716 struct sockaddr_in *peer, void *pack, unsigned len)
2717{
Harald Welte37d5b152017-08-12 23:58:29 +02002718 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002719 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002720
Harald Weltebed35df2011-11-02 13:06:18 +01002721 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002722 if (version == 0) {
2723 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
2724 gsn->err_unknownpdp++;
2725 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2726 "Unknown PDP context\n");
2727 return EOF;
2728 }
2729 } else if (version == 1) {
2730 /* we have to look-up based on the *peer* TEID */
2731 int hlen = get_hlen(pack);
2732 uint32_t teid_gn;
2733
2734 /* Decode information elements */
2735 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2736 gsn->invalid++;
2737 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2738 "Invalid message format\n");
2739 return EOF;
2740 }
2741
2742 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2743 gsn->missing++;
2744 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2745 "Missing mandatory information field\n");
2746 return EOF;
2747 }
2748
2749 if (pdp_getgtp1_peer_d(&pdp, peer, teid_gn)) {
2750 gsn->err_unknownpdp++;
2751 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2752 return EOF;
2753 }
Harald Weltebed35df2011-11-02 13:06:18 +01002754 }
jjako52c24142002-12-16 13:33:51 +00002755
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002756 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2757 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002758
Harald Weltebd228242017-11-06 03:16:49 +09002759 /* This is obvious from above code, given the semantics of the
2760 * functions above, but Coverity doesn't figure this out, so
2761 * let's make it clear. It's good style anyway in case above
2762 * code should ever change. */
2763 OSMO_ASSERT(pdp);
2764
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002765 gtp_freepdp(gsn, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002766 return 0;
jjako52c24142002-12-16 13:33:51 +00002767}
2768
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002769static int gtp_gpdu_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002770 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2771{
jjako08d331d2003-10-13 20:33:30 +00002772
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002773 int hlen;
jjako52c24142002-12-16 13:33:51 +00002774
Harald Weltebed35df2011-11-02 13:06:18 +01002775 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002776
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002777 switch (version) {
2778 case 0:
Harald Weltebed35df2011-11-02 13:06:18 +01002779 if (pdp_getgtp0
2780 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2781 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002782 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002783 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002784 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2785 len);
2786 }
2787 hlen = GTP0_HEADER_SIZE;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002788 break;
2789 case 1:
Harald Weltebed35df2011-11-02 13:06:18 +01002790 if (pdp_getgtp1
2791 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2792 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002793 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002794 len, "Unknown PDP context, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002795 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2796 len);
2797 }
jjako08d331d2003-10-13 20:33:30 +00002798
Harald Weltebed35df2011-11-02 13:06:18 +01002799 /* Is this a long or a short header ? */
2800 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2801 hlen = GTP1_HEADER_SIZE_LONG;
2802 else
2803 hlen = GTP1_HEADER_SIZE_SHORT;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002804 break;
2805 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002806 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002807 "Unknown version: %d\n", version);
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002808 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002809 }
jjako08d331d2003-10-13 20:33:30 +00002810
Harald Weltebed35df2011-11-02 13:06:18 +01002811 /* If the GPDU was not from the peer GSN tell him to delete context */
2812 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2813 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002814 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002815 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2816 }
jjako52c24142002-12-16 13:33:51 +00002817
Harald Weltebed35df2011-11-02 13:06:18 +01002818 /* Callback function */
2819 if (gsn->cb_data_ind != 0)
2820 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2821
2822 return 0;
jjako52c24142002-12-16 13:33:51 +00002823}
2824
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002825/* Receives GTP packet and sends off for further processing
jjako52c24142002-12-16 13:33:51 +00002826 * Function will check the validity of the header. If the header
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002827 * is not valid the packet is either dropped or a version not
2828 * supported is returned to the peer.
jjako52c24142002-12-16 13:33:51 +00002829 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002830int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002831{
Harald Weltebed35df2011-11-02 13:06:18 +01002832 unsigned char buffer[PACKET_MAX];
2833 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002834 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002835 int status;
2836 struct gtp0_header *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002837 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002838 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002839
Harald Weltebed35df2011-11-02 13:06:18 +01002840 /* TODO: Need strategy of userspace buffering and blocking */
2841 /* Currently read is non-blocking and send is blocking. */
2842 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002843
Harald Weltebed35df2011-11-02 13:06:18 +01002844 while (1) { /* Loop until no more to read */
2845 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002846 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002847 return -1;
2848 }
2849 peerlen = sizeof(peer);
2850 if ((status =
2851 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2852 (struct sockaddr *)&peer, &peerlen)) < 0) {
2853 if (errno == EAGAIN)
2854 return 0;
2855 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002856 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002857 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002858 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2859 status, status ? strerror(errno) : "No error");
2860 return -1;
2861 }
jjako1db1c812003-07-06 20:53:57 +00002862
Harald Weltebed35df2011-11-02 13:06:18 +01002863 /* Need at least 1 byte in order to check version */
2864 if (status < (1)) {
2865 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002866 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2867 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002868 continue;
2869 }
jjako08d331d2003-10-13 20:33:30 +00002870
Harald Weltebed35df2011-11-02 13:06:18 +01002871 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002872
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002873 version = GTPHDR_F_GET_VER(pheader->flags);
2874
Harald Weltebed35df2011-11-02 13:06:18 +01002875 /* Version should be gtp0 (or earlier) */
2876 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2877 /* GTP 0 messages. If other version message is received we reply that we */
2878 /* only support version 0, implying that this is the only version */
2879 /* supported on this port */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002880 if (version > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002881 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01002882 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2883 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002884 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2885 continue;
2886 }
2887
2888 /* Check length of gtp0 packet */
2889 if (status < GTP0_HEADER_SIZE) {
2890 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002891 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2892 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002893 continue; /* Silently discard 29.60: 11.1.2 */
2894 }
2895
2896 /* Check packet length field versus length of packet */
2897 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2898 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002899 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002900 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002901 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002902 continue; /* Silently discard */
2903 }
2904
2905 if ((gsn->mode == GTP_MODE_GGSN) &&
2906 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002907 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002908 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002909 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002910 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002911 "Unexpected GTPv0 Signalling Message '%s'\n",
2912 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002913 continue; /* Silently discard 29.60: 11.1.4 */
2914 }
2915
2916 if ((gsn->mode == GTP_MODE_SGSN) &&
2917 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002918 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002919 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002920 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002921 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002922 "Unexpected GTPv0 Signalling Message '%s'\n",
2923 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002924 continue; /* Silently discard 29.60: 11.1.4 */
2925 }
2926
2927 switch (pheader->type) {
2928 case GTP_ECHO_REQ:
2929 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2930 break;
2931 case GTP_ECHO_RSP:
2932 gtp_echo_conf(gsn, version, &peer, buffer, status);
2933 break;
2934 case GTP_NOT_SUPPORTED:
2935 gtp_unsup_ind(gsn, &peer, buffer, status);
2936 break;
2937 case GTP_CREATE_PDP_REQ:
2938 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2939 status);
2940 break;
2941 case GTP_CREATE_PDP_RSP:
2942 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2943 status);
2944 break;
2945 case GTP_UPDATE_PDP_REQ:
2946 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2947 status);
2948 break;
2949 case GTP_UPDATE_PDP_RSP:
2950 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2951 status);
2952 break;
2953 case GTP_DELETE_PDP_REQ:
2954 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2955 status);
2956 break;
2957 case GTP_DELETE_PDP_RSP:
2958 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2959 status);
2960 break;
2961 case GTP_ERROR:
2962 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2963 break;
2964 case GTP_GPDU:
2965 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2966 break;
2967 default:
2968 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002969 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2970 "Unknown GTP message type received: %d\n",
2971 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002972 break;
2973 }
2974 }
jjako08d331d2003-10-13 20:33:30 +00002975}
2976
jjako08d331d2003-10-13 20:33:30 +00002977int gtp_decaps1c(struct gsn_t *gsn)
2978{
Harald Weltebed35df2011-11-02 13:06:18 +01002979 unsigned char buffer[PACKET_MAX];
2980 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002981 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002982 int status;
2983 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002984 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002985 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002986
Harald Weltebed35df2011-11-02 13:06:18 +01002987 /* TODO: Need strategy of userspace buffering and blocking */
2988 /* Currently read is non-blocking and send is blocking. */
2989 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002990
Harald Weltebed35df2011-11-02 13:06:18 +01002991 while (1) { /* Loop until no more to read */
2992 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002993 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002994 return -1;
2995 }
2996 peerlen = sizeof(peer);
2997 if ((status =
2998 recvfrom(fd, buffer, sizeof(buffer), 0,
2999 (struct sockaddr *)&peer, &peerlen)) < 0) {
3000 if (errno == EAGAIN)
3001 return 0;
3002 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003003 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003004 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003005 fd, (unsigned long)buffer, sizeof(buffer),
3006 status, status ? strerror(errno) : "No error");
3007 return -1;
3008 }
jjako08d331d2003-10-13 20:33:30 +00003009
Harald Weltebed35df2011-11-02 13:06:18 +01003010 /* Need at least 1 byte in order to check version */
3011 if (status < (1)) {
3012 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003013 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3014 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003015 continue;
3016 }
jjako08d331d2003-10-13 20:33:30 +00003017
Harald Weltebed35df2011-11-02 13:06:18 +01003018 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003019
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003020 version = GTPHDR_F_GET_VER(pheader->flags);
3021
Harald Weltebed35df2011-11-02 13:06:18 +01003022 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003023 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003024 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003025 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3026 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003027 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
3028 /*29.60: 11.1.1 */
3029 continue;
3030 }
jjako08d331d2003-10-13 20:33:30 +00003031
Harald Weltebed35df2011-11-02 13:06:18 +01003032 /* Version must be at least GTP 1 */
3033 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3034 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3035 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003036 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003037 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003038 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3039 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003040 continue;
3041 }
jjako08d331d2003-10-13 20:33:30 +00003042
Harald Weltebed35df2011-11-02 13:06:18 +01003043 /* Check packet flag field */
3044 if (((pheader->flags & 0xf7) != 0x32)) {
3045 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003046 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003047 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003048 continue;
3049 }
jjako2c381332003-10-21 19:09:53 +00003050
Harald Weltebed35df2011-11-02 13:06:18 +01003051 /* Check length of packet */
3052 if (status < GTP1_HEADER_SIZE_LONG) {
3053 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003054 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3055 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003056 continue; /* Silently discard 29.60: 11.1.2 */
3057 }
jjako2c381332003-10-21 19:09:53 +00003058
Harald Weltebed35df2011-11-02 13:06:18 +01003059 /* Check packet length field versus length of packet */
3060 if (status !=
3061 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3062 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003063 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003064 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003065 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003066 continue; /* Silently discard */
3067 }
jjako1db1c812003-07-06 20:53:57 +00003068
Harald Weltebed35df2011-11-02 13:06:18 +01003069 /* Check for extension headers */
3070 /* TODO: We really should cycle through the headers and determine */
3071 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003072 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003073 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003074 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3075 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003076 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3077 status);
jjako1db1c812003-07-06 20:53:57 +00003078
Harald Weltebed35df2011-11-02 13:06:18 +01003079 continue;
3080 }
3081
3082 if ((gsn->mode == GTP_MODE_GGSN) &&
3083 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003084 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003085 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003086 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003087 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003088 "Unexpected GTPv1 Signalling Message '%s'\n",
3089 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003090 continue; /* Silently discard 29.60: 11.1.4 */
3091 }
3092
3093 if ((gsn->mode == GTP_MODE_SGSN) &&
3094 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003095 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003096 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003097 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003098 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003099 "Unexpected GTPv1 Signalling Message '%s'\n",
3100 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003101 continue; /* Silently discard 29.60: 11.1.4 */
3102 }
3103
3104 switch (pheader->type) {
3105 case GTP_ECHO_REQ:
3106 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3107 break;
3108 case GTP_ECHO_RSP:
3109 gtp_echo_conf(gsn, version, &peer, buffer, status);
3110 break;
3111 case GTP_NOT_SUPPORTED:
3112 gtp_unsup_ind(gsn, &peer, buffer, status);
3113 break;
3114 case GTP_SUPP_EXT_HEADER:
3115 gtp_extheader_ind(gsn, &peer, buffer, status);
3116 break;
3117 case GTP_CREATE_PDP_REQ:
3118 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3119 status);
3120 break;
3121 case GTP_CREATE_PDP_RSP:
3122 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3123 status);
3124 break;
3125 case GTP_UPDATE_PDP_REQ:
3126 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3127 status);
3128 break;
3129 case GTP_UPDATE_PDP_RSP:
3130 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3131 status);
3132 break;
3133 case GTP_DELETE_PDP_REQ:
3134 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3135 status);
3136 break;
3137 case GTP_DELETE_PDP_RSP:
3138 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3139 status);
3140 break;
3141 case GTP_ERROR:
3142 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3143 break;
3144 default:
3145 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003146 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3147 "Unknown GTP message type received: %u\n",
3148 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003149 break;
3150 }
3151 }
jjako52c24142002-12-16 13:33:51 +00003152}
3153
jjako08d331d2003-10-13 20:33:30 +00003154int gtp_decaps1u(struct gsn_t *gsn)
3155{
Harald Weltebed35df2011-11-02 13:06:18 +01003156 unsigned char buffer[PACKET_MAX];
3157 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003158 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003159 int status;
3160 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003161 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003162 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003163
Harald Weltebed35df2011-11-02 13:06:18 +01003164 /* TODO: Need strategy of userspace buffering and blocking */
3165 /* Currently read is non-blocking and send is blocking. */
3166 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003167
Harald Weltebed35df2011-11-02 13:06:18 +01003168 while (1) { /* Loop until no more to read */
3169 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003170 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003171 return -1;
3172 }
3173 peerlen = sizeof(peer);
3174 if ((status =
3175 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3176 (struct sockaddr *)&peer, &peerlen)) < 0) {
3177 if (errno == EAGAIN)
3178 return 0;
3179 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003180 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003181 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003182 gsn->fd1u, (unsigned long)buffer,
3183 sizeof(buffer), status,
3184 status ? strerror(errno) : "No error");
3185 return -1;
3186 }
jjako08d331d2003-10-13 20:33:30 +00003187
Harald Weltebed35df2011-11-02 13:06:18 +01003188 /* Need at least 1 byte in order to check version */
3189 if (status < (1)) {
3190 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003191 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3192 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003193 continue;
3194 }
jjako08d331d2003-10-13 20:33:30 +00003195
Harald Weltebed35df2011-11-02 13:06:18 +01003196 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003197
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003198 version = GTPHDR_F_GET_VER(pheader->flags);
3199
Harald Weltebed35df2011-11-02 13:06:18 +01003200 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003201 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003202 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003203 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3204 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003205 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3206 continue;
3207 }
jjako08d331d2003-10-13 20:33:30 +00003208
Harald Weltebed35df2011-11-02 13:06:18 +01003209 /* Version must be at least GTP 1 */
3210 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3211 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3212 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003213 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003214 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003215 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3216 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003217 continue;
3218 }
jjako2c381332003-10-21 19:09:53 +00003219
Harald Weltebed35df2011-11-02 13:06:18 +01003220 /* Check packet flag field (allow both with and without sequence number) */
3221 if (((pheader->flags & 0xf5) != 0x30)) {
3222 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003223 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003224 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003225 continue;
3226 }
jjako2c381332003-10-21 19:09:53 +00003227
Harald Weltebed35df2011-11-02 13:06:18 +01003228 /* Check length of packet */
3229 if (status < GTP1_HEADER_SIZE_SHORT) {
3230 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003231 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3232 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003233 continue; /* Silently discard 29.60: 11.1.2 */
3234 }
3235
3236 /* Check packet length field versus length of packet */
3237 if (status !=
3238 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3239 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003240 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003241 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003242 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003243 continue; /* Silently discard */
3244 }
3245
3246 /* Check for extension headers */
3247 /* TODO: We really should cycle through the headers and determine */
3248 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003249 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003250 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003251 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3252 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003253 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3254 status);
3255
3256 continue;
3257 }
3258
3259 switch (pheader->type) {
3260 case GTP_ECHO_REQ:
3261 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3262 break;
3263 case GTP_ECHO_RSP:
3264 gtp_echo_conf(gsn, version, &peer, buffer, status);
3265 break;
3266 case GTP_SUPP_EXT_HEADER:
3267 gtp_extheader_ind(gsn, &peer, buffer, status);
3268 break;
3269 case GTP_ERROR:
3270 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3271 break;
3272 /* Supported header extensions */
3273 case GTP_GPDU:
3274 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3275 break;
3276 default:
3277 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003278 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3279 "Unknown GTP message type received: %u\n",
3280 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003281 break;
3282 }
3283 }
jjako08d331d2003-10-13 20:33:30 +00003284}
3285
Harald Weltebed35df2011-11-02 13:06:18 +01003286int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003287{
Harald Weltebed35df2011-11-02 13:06:18 +01003288 union gtp_packet packet;
3289 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003290 struct msghdr msgh;
3291 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003292 int fd;
jjako52c24142002-12-16 13:33:51 +00003293
Harald Welte471e3492017-09-24 16:12:39 +08003294 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003295 memset(&addr, 0, sizeof(addr));
3296 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003297#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003298 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003299#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003300 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003301
Harald Welte471e3492017-09-24 16:12:39 +08003302 /* prepare msghdr */
3303 memset(&msgh, 0, sizeof(msgh));
3304 msgh.msg_name = &addr;
3305 msgh.msg_namelen = sizeof(addr);
3306 msgh.msg_iov = iov;
3307 msgh.msg_iovlen = ARRAY_SIZE(iov);
3308
3309 /* prepare iovectors */
3310 iov[0].iov_base = &packet;
3311 /* iov[0].iov_len is not known here yet */
3312 iov[1].iov_base = pack;
3313 iov[1].iov_len = len;
3314
Harald Weltebed35df2011-11-02 13:06:18 +01003315 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003316
Harald Welte471e3492017-09-24 16:12:39 +08003317 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003318 addr.sin_port = htons(GTP0_PORT);
3319 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003320
Harald Weltebed35df2011-11-02 13:06:18 +01003321 get_default_gtp(0, GTP_GPDU, &packet);
3322 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003323 if (pdp->tx_gpdu_seq)
3324 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3325 else
3326 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003327 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003328 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003329 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003330
Harald Weltebed35df2011-11-02 13:06:18 +01003331 addr.sin_port = htons(GTP1U_PORT);
3332 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003333
Harald Weltebed35df2011-11-02 13:06:18 +01003334 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003335 if (pdp->tx_gpdu_seq) {
3336 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3337 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3338 GTP1_HEADER_SIZE_LONG);
3339 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3340 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3341 } else {
3342 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3343 packet.gtp1s.h.length = hton16(len);
3344 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3345 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3346 }
Harald Weltebed35df2011-11-02 13:06:18 +01003347 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003348 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003349 return EOF;
3350 }
3351
3352 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003353 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003354 return -1;
3355 }
3356
Harald Welte471e3492017-09-24 16:12:39 +08003357 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003358 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003359 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003360 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003361 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3362 strerror(errno));
3363 return EOF;
3364 }
3365 return 0;
jjako52c24142002-12-16 13:33:51 +00003366}
3367
jjako52c24142002-12-16 13:33:51 +00003368/* ***********************************************************
3369 * Conversion functions
3370 *************************************************************/
3371
jjako52c24142002-12-16 13:33:51 +00003372/* ***********************************************************
3373 * IP address conversion functions
3374 * There exist several types of address representations:
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01003375 * - eua: End User Address. (29.060, 7.7.27, message type 128)
jjako52c24142002-12-16 13:33:51 +00003376 * Used for signalling address to mobile station. Supports IPv4
3377 * IPv6 x.25 etc. etc.
3378 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3379 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3380 * - in_addr: IPv4 address struct.
3381 * - sockaddr_in: Socket API representation of IP address and
3382 * port number.
3383 *************************************************************/
3384
Harald Weltebed35df2011-11-02 13:06:18 +01003385int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3386{
Harald Weltecee75462017-09-24 17:45:05 +08003387 eua->v[0] = PDP_EUA_ORG_IETF;
3388 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003389 if (src) {
3390 eua->l = 6;
3391 memcpy(&eua->v[2], src, 4);
3392 } else {
3393 eua->l = 2;
3394 }
3395 return 0;
jjako52c24142002-12-16 13:33:51 +00003396}
3397
Harald Weltebed35df2011-11-02 13:06:18 +01003398int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3399{
Harald Weltecee75462017-09-24 17:45:05 +08003400 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 +01003401 return -1; /* Not IPv4 address */
3402 memcpy(dst, &eua->v[2], 4);
3403 return 0;
jjako52c24142002-12-16 13:33:51 +00003404}
3405
Harald Weltebed35df2011-11-02 13:06:18 +01003406int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3407{
3408 memset(dst, 0, sizeof(struct in_addr));
3409 if (gsna->l != 4)
3410 return EOF; /* Return if not IPv4 */
3411 memcpy(dst, gsna->v, gsna->l);
3412 return 0;
jjako52c24142002-12-16 13:33:51 +00003413}
3414
Harald Weltebed35df2011-11-02 13:06:18 +01003415int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3416{
3417 memset(gsna, 0, sizeof(struct ul16_t));
3418 gsna->l = 4;
3419 memcpy(gsna->v, src, gsna->l);
3420 return 0;
jjako52c24142002-12-16 13:33:51 +00003421}
Harald Welteb10ee082017-08-12 19:29:16 +02003422
3423/* TS 29.060 has yet again a different encoding for IMSIs than
3424 * what we have in other places, so we cannot use the gsm48
3425 * decoding functions. Also, libgtp uses an uint64_t in
3426 * _network byte order_ to contain BCD digits ?!? */
3427const char *imsi_gtp2str(const uint64_t *imsi)
3428{
Harald Weltea06120d2017-11-06 03:12:54 +09003429 static char buf[sizeof(*imsi)*2+1];
Harald Welteb10ee082017-08-12 19:29:16 +02003430 const uint8_t *imsi8 = (const uint8_t *) imsi;
3431 unsigned int i, j = 0;
3432
3433 for (i = 0; i < sizeof(*imsi); i++) {
3434 uint8_t nibble;
3435
3436 nibble = imsi8[i] & 0xf;
3437 if (nibble == 0xf)
3438 break;
3439 buf[j++] = osmo_bcd2char(nibble);
3440
3441 nibble = imsi8[i] >> 4;
3442 if (nibble == 0xf)
3443 break;
3444 buf[j++] = osmo_bcd2char(nibble);
3445 }
3446
3447 buf[j++] = '\0';
3448 return buf;
3449}