blob: 547241da9f21f96a260635681c8461e02a698fac [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
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +0200134/* Deprecated, use gtp_pdp_newpdp() instead */
Harald Weltebed35df2011-11-02 13:06:18 +0100135int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
136 uint64_t imsi, uint8_t nsapi)
137{
Harald Weltee257be12017-08-12 14:55:09 +0200138 int rc;
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +0200139 rc = gtp_pdp_newpdp(gsn, pdp, imsi, nsapi, NULL);
Harald Weltee257be12017-08-12 14:55:09 +0200140 return rc;
jjako52c24142002-12-16 13:33:51 +0000141}
142
Harald Weltebed35df2011-11-02 13:06:18 +0100143int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp)
144{
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +0200145 if (gsn->cb_delete_context)
146 gsn->cb_delete_context(pdp);
Harald Weltebed35df2011-11-02 13:06:18 +0100147 return pdp_freepdp(pdp);
jjako52c24142002-12-16 13:33:51 +0000148}
149
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +0200150/* Free pdp and all its secondary PDP contexts. Must be called on the primary PDP context. */
151int gtp_freepdp_teardown(struct gsn_t *gsn, struct pdp_t *pdp)
152{
153 int n;
154 struct pdp_t *secondary_pdp;
155 OSMO_ASSERT(!pdp->secondary);
156
157 for (n = 0; n < PDP_MAXNSAPI; n++) {
158 if (pdp->secondary_tei[n]) {
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +0200159 if (gtp_pdp_getgtp1(gsn, &secondary_pdp,
160 pdp->secondary_tei[n])) {
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +0200161 LOGP(DLGTP, LOGL_ERROR,
162 "Unknown secondary PDP context\n");
163 continue;
164 }
165 if (pdp != secondary_pdp) {
166 gtp_freepdp(gsn, secondary_pdp);
167 }
168 }
169 }
170
171 return gtp_freepdp(gsn, pdp);
172}
173
jjako52c24142002-12-16 13:33:51 +0000174/* gtp_gpdu */
175
Harald Weltebed35df2011-11-02 13:06:18 +0100176extern int gtp_fd(struct gsn_t *gsn)
177{
178 return gsn->fd0;
jjako52c24142002-12-16 13:33:51 +0000179}
180
181/* gtp_decaps */
182/* gtp_retrans */
183/* gtp_retranstimeout */
184
jjako08d331d2003-10-13 20:33:30 +0000185int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100186 int (*cb) (struct sockaddr_in * peer))
187{
188 gsn->cb_unsup_ind = cb;
189 return 0;
jjako08d331d2003-10-13 20:33:30 +0000190}
191
jjako2c381332003-10-21 19:09:53 +0000192int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100193 int (*cb) (struct sockaddr_in * peer))
194{
195 gsn->cb_extheader_ind = cb;
196 return 0;
jjako2c381332003-10-21 19:09:53 +0000197}
198
jjako08d331d2003-10-13 20:33:30 +0000199/* API: Initialise delete context callback */
200/* Called whenever a pdp context is deleted for any reason */
Harald Weltebed35df2011-11-02 13:06:18 +0100201int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
jjako52c24142002-12-16 13:33:51 +0000202{
Harald Weltebed35df2011-11-02 13:06:18 +0100203 gsn->cb_delete_context = cb;
204 return 0;
jjako52c24142002-12-16 13:33:51 +0000205}
206
jjako52c24142002-12-16 13:33:51 +0000207int gtp_set_cb_conf(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100208 int (*cb) (int type, int cause,
209 struct pdp_t * pdp, void *cbp))
210{
211 gsn->cb_conf = cb;
212 return 0;
jjako52c24142002-12-16 13:33:51 +0000213}
214
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200215static void emit_cb_recovery(struct gsn_t *gsn, struct sockaddr_in * peer,
216 struct pdp_t * pdp, uint8_t recovery)
217{
218 if (gsn->cb_recovery)
219 gsn->cb_recovery(peer, recovery);
220 if (gsn->cb_recovery2)
221 gsn->cb_recovery2(peer, pdp, recovery);
Pau Espin Pedrol5d8b2262019-08-22 15:00:00 +0200222 if (gsn->cb_recovery3)
223 gsn->cb_recovery3(gsn, peer, pdp, recovery);
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200224}
225
Harald Welte629e9862010-12-24 20:58:09 +0100226int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100227 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
228{
229 gsn->cb_recovery = cb;
230 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100231}
232
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200233/* cb_recovery()
234 * pdp may be NULL if Recovery IE was received from a message independent
235 * of any PDP ctx (such as Echo Response), or because pdp ctx is unknown to the
236 * local setup. In case pdp is known, caller may want to keep that pdp alive to
237 * handle subsequent msg cb as this specific pdp ctx is still valid according to
238 * specs.
239 */
240int gtp_set_cb_recovery2(struct gsn_t *gsn,
241 int (*cb_recovery2) (struct sockaddr_in * peer, struct pdp_t * pdp, uint8_t recovery))
242{
243 gsn->cb_recovery2 = cb_recovery2;
244 return 0;
245}
246
Pau Espin Pedrol5d8b2262019-08-22 15:00:00 +0200247/* cb_recovery()
248 * pdp may be NULL if Recovery IE was received from a message independent
249 * of any PDP ctx (such as Echo Response), or because pdp ctx is unknown to the
250 * local setup. In case pdp is known, caller may want to keep that pdp alive to
251 * handle subsequent msg cb as this specific pdp ctx is still valid according to
252 * specs.
253 */
254int gtp_set_cb_recovery3(struct gsn_t *gsn,
255 int (*cb_recovery3) (struct gsn_t *gsn, struct sockaddr_in *peer,
256 struct pdp_t *pdp, uint8_t recovery))
257{
258 gsn->cb_recovery3 = cb_recovery3;
259 return 0;
260}
261
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +0100262int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100263 int (*cb_data_ind) (struct pdp_t * pdp,
264 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000265{
Harald Weltebed35df2011-11-02 13:06:18 +0100266 gsn->cb_data_ind = cb_data_ind;
267 return 0;
jjako52c24142002-12-16 13:33:51 +0000268}
269
jjako08d331d2003-10-13 20:33:30 +0000270/**
271 * get_default_gtp()
272 * Generate a GPRS Tunneling Protocol signalling packet header, depending
273 * on GTP version and message type. pdp is used for teid/flow label.
274 * *packet must be allocated by the calling function, and be large enough
275 * to hold the packet header.
276 * returns the length of the header. 0 on error.
277 **/
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100278static unsigned int get_default_gtp(uint8_t version, uint8_t type, void *packet)
Harald Weltebed35df2011-11-02 13:06:18 +0100279{
280 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
281 struct gtp1_header_long *gtp1_default =
282 (struct gtp1_header_long *)packet;
283 switch (version) {
284 case 0:
285 /* Initialise "standard" GTP0 header */
286 memset(gtp0_default, 0, sizeof(struct gtp0_header));
287 gtp0_default->flags = 0x1e;
288 gtp0_default->type = hton8(type);
289 gtp0_default->spare1 = 0xff;
290 gtp0_default->spare2 = 0xff;
291 gtp0_default->spare3 = 0xff;
292 gtp0_default->number = 0xff;
293 return GTP0_HEADER_SIZE;
294 case 1:
295 /* Initialise "standard" GTP1 header */
296 /* 29.060: 8.2: S=1 and PN=0 */
297 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
298 /* and Supported Extension Headers Notification, the S field shall be */
299 /* set to 1 */
300 /* Currently extension headers are not supported */
301 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
Harald Weltefed598f2017-09-24 16:39:22 +0800302 /* No extension, enable sequence, no N-PDU */
303 gtp1_default->flags = GTPHDR_F_VER(1) | GTP1HDR_F_GTP1 | GTP1HDR_F_SEQ;
Harald Weltebed35df2011-11-02 13:06:18 +0100304 gtp1_default->type = hton8(type);
305 return GTP1_HEADER_SIZE_LONG;
306 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100307 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100308 "Unknown GTP packet version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +0100309 return 0;
310 }
jjako52c24142002-12-16 13:33:51 +0000311}
312
jjako08d331d2003-10-13 20:33:30 +0000313/**
314 * get_seq()
315 * Get sequence number of a packet.
316 * Returns 0 on error
317 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100318static uint16_t get_seq(void *pack)
319{
320 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800321 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000322
Harald Weltefed598f2017-09-24 16:39:22 +0800323 if (ver == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +0100324 return ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800325 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100326 return ntoh16(packet->gtp1l.h.seq);
327 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100328 return 0;
329 }
jjako08d331d2003-10-13 20:33:30 +0000330}
331
332/**
333 * get_tid()
334 * Get tunnel identifier of a packet.
335 * Returns 0 on error
336 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100337static uint64_t get_tid(void *pack)
338{
339 union gtp_packet *packet = (union gtp_packet *)pack;
340
Harald Weltefed598f2017-09-24 16:39:22 +0800341 if (GTPHDR_F_GET_VER(packet->flags) == 0) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100342 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100343 }
344 return 0;
jjako08d331d2003-10-13 20:33:30 +0000345}
346
347/**
348 * get_hlen()
349 * Get the header length of a packet.
350 * Returns 0 on error
351 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100352static uint16_t get_hlen(void *pack)
353{
354 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800355 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000356
Harald Weltefed598f2017-09-24 16:39:22 +0800357 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100358 return GTP0_HEADER_SIZE;
Harald Weltefed598f2017-09-24 16:39:22 +0800359 } else if (ver == 1 && (packet->flags & 0x07) == 0) { /* Short version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100360 return GTP1_HEADER_SIZE_SHORT;
Harald Weltefed598f2017-09-24 16:39:22 +0800361 } else if (ver == 1) { /* Version 1 with seq/n-pdu/ext */
362 return GTP1_HEADER_SIZE_LONG;
Harald Weltebed35df2011-11-02 13:06:18 +0100363 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100364 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100365 return 0;
366 }
jjako08d331d2003-10-13 20:33:30 +0000367}
368
369/**
370 * get_tei()
371 * Get the tunnel endpoint identifier (flow label) of a packet.
372 * Returns 0xffffffff on error.
373 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100374static uint32_t get_tei(void *pack)
375{
376 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800377 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000378
Harald Weltefed598f2017-09-24 16:39:22 +0800379 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100380 return ntoh16(packet->gtp0.h.flow);
Harald Weltefed598f2017-09-24 16:39:22 +0800381 } else if (ver == 1) { /* Version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100382 return ntoh32(packet->gtp1l.h.tei);
383 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100384 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100385 return 0xffffffff;
386 }
jjako08d331d2003-10-13 20:33:30 +0000387}
jjakoa7cd2492003-04-11 09:40:12 +0000388
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200389static int queue_timer_retrans(struct gsn_t *gsn)
390{
391 /* Retransmit any outstanding packets */
392 /* Remove from queue if maxretrans exceeded */
393 time_t now;
394 struct qmsg_t *qmsg;
395 now = time(NULL);
396 /*printf("Retrans: New beginning %d\n", (int) now); */
397
398 /* get first element in queue, as long as the timeout of that
399 * element has expired */
400 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
401 (qmsg->timeout <= now)) {
402 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
403 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
404 LOGP(DLGTP, LOGL_NOTICE, "Timeout of seq %" PRIu16 "\n",
405 qmsg->seq);
406 if (gsn->cb_conf)
407 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
408 queue_freemsg(gsn->queue_req, qmsg);
409 } else {
410 LOGP(DLGTP, LOGL_INFO, "Retransmit (%d) of seq %" PRIu16 "\n",
411 qmsg->retrans, qmsg->seq);
412 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
413 (struct sockaddr *)&qmsg->peer,
414 sizeof(struct sockaddr_in)) < 0) {
415 gsn->err_sendto++;
416 LOGP(DLGTP, LOGL_ERROR,
417 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
418 gsn->fd0, (unsigned long)&qmsg->p,
419 qmsg->l, strerror(errno));
420 }
421 queue_back(gsn->queue_req, qmsg);
422 qmsg->timeout = now + T3_REQUEST;
423 qmsg->retrans++;
424 }
425 }
426
427 /* Also clean up reply timeouts */
428 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
429 (qmsg->timeout < now)) {
430 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
431 queue_freemsg(gsn->queue_resp, qmsg);
432 }
433
434 return 0;
435}
436
437static int queue_timer_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
438{
439 time_t now, later, diff;
440 struct qmsg_t *qmsg;
441 timeout->tv_usec = 0;
442
443 if (queue_getfirst(gsn->queue_req, &qmsg)) {
444 timeout->tv_sec = 10;
445 } else {
446 now = time(NULL);
447 later = qmsg->timeout;
448 timeout->tv_sec = later - now;
449 if (timeout->tv_sec < 0)
450 timeout->tv_sec = 0; /* No negative allowed */
451 if (timeout->tv_sec > 10)
452 timeout->tv_sec = 10; /* Max sleep for 10 sec */
453 }
454
455 if (queue_getfirst(gsn->queue_resp, &qmsg)) {
456 /* already set by queue_req, do nothing */
457 } else { /* trigger faster if earlier timeout exists in queue_resp */
458 now = time(NULL);
459 later = qmsg->timeout;
460 diff = later - now;
461 if (diff < 0)
462 diff = 0;
463 if (diff < timeout->tv_sec)
464 timeout->tv_sec = diff;
465 }
466
467 return 0;
468}
469
470static void queue_timer_start(struct gsn_t *gsn)
471{
472 struct timeval next;
473
474 /* Retrieve next retransmission as timeval */
475 queue_timer_retranstimeout(gsn, &next);
476
477 /* re-schedule the timer */
478 osmo_timer_schedule(&gsn->queue_timer, next.tv_sec, next.tv_usec/1000);
479}
480
481/* timer callback for libgtp retransmission and ping */
482static void queue_timer_cb(void *data)
483{
484 struct gsn_t *gsn = data;
485
486 /* do all the retransmissions as needed */
487 queue_timer_retrans(gsn);
488
489 queue_timer_start(gsn);
490}
491
jjako52c24142002-12-16 13:33:51 +0000492/* ***********************************************************
493 * Reliable delivery of signalling messages
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100494 *
jjako52c24142002-12-16 13:33:51 +0000495 * Sequence numbers are used for both signalling messages and
496 * data messages.
497 *
498 * For data messages each tunnel maintains a sequence counter,
499 * which is incremented by one each time a new data message
500 * is sent. The sequence number starts at (0) zero at tunnel
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100501 * establishment, and wraps around at 65535 (29.060 9.3.1.1
jjako52c24142002-12-16 13:33:51 +0000502 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
503 * or can be used to check the validity of the message in the
504 * receiver, or for reordering af packets.
505 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100506 * For signalling messages the sequence number is used by
jjako52c24142002-12-16 13:33:51 +0000507 * signalling messages for which a response is defined. A response
508 * message should copy the sequence from the corresponding request
509 * message. The sequence number "unambiguously" identifies a request
510 * message within a given path, with a path being defined as a set of
511 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
512 * messages shall be responded to, and all response messages associated
513 * with a certain request shall always include the same information"
514 *
515 * We take this to mean that the GSN transmitting a request is free to
516 * choose the sequence number, as long as it is unique within a given path.
517 * It means that we are allowed to count backwards, or roll over at 17
518 * if we prefer that. It also means that we can use the same counter for
519 * all paths. This has the advantage that the transmitted request sequence
520 * numbers are unique within each GSN, and also we dont have to mess around
521 * with path setup and teardown.
522 *
523 * If a response message is lost, the request will be retransmitted, and
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100524 * the receiving GSN will receive a "duplicated" request. The standard
jjako52c24142002-12-16 13:33:51 +0000525 * requires the receiving GSN to send a response, with the same information
526 * as in the original response. For most messages this happens automatically:
527 *
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200528 * Echo: Automatically duplicates the original response
jjako52c24142002-12-16 13:33:51 +0000529 * Create pdp context: The SGSN may send create context request even if
530 * a context allready exist (imsi+nsapi?). This means that the reply will
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200531 automatically duplicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000532 * side effects in the application which is asked twice to validate
533 * the login.
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200534 * Update pdp context: Automatically duplicates the original response???
jjako52c24142002-12-16 13:33:51 +0000535 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
536 * a nonexist reply message.
537 *
538 * The correct solution will be to make a queue containing response messages.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100539 * This queue should be checked whenever a request is received. If the
jjako52c24142002-12-16 13:33:51 +0000540 * response is allready in the queue that response should be transmitted.
541 * It should be possible to find messages in this queue on the basis of
542 * the sequence number and peer GSN IP address (The sequense number is unique
543 * within each path). This need to be implemented by a hash table. Furthermore
544 * it should be possibly to delete messages based on a timeout. This can be
545 * achieved by means of a linked list. The timeout value need to be larger
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100546 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
jjako52c24142002-12-16 13:33:51 +0000547 * set in the peer GSN, so there is no way to know these parameters. On the
548 * other hand the timeout value need to be so small that we do not receive
549 * wraparound sequence numbere before the message is deleted. 60 seconds is
550 * probably not a bad choise.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100551 *
jjako52c24142002-12-16 13:33:51 +0000552 * This queue however is first really needed from gtp1.
553 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100554 * gtp_req:
jjako52c24142002-12-16 13:33:51 +0000555 * Send off a signalling message with appropiate sequence
556 * number. Store packet in queue.
557 * gtp_conf:
558 * Remove an incoming confirmation from the queue
559 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000560 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000561 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000562 * gtp_notification:
563 * Send off a notification message. This is neither a request nor
564 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000565 * gtp_retrans:
566 * Retransmit any outstanding packets which have exceeded
567 * a predefined timeout.
568 *************************************************************/
569
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100570static int gtp_req(struct gsn_t *gsn, uint8_t version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100571 union gtp_packet *packet, int len,
572 struct in_addr *inetaddr, void *cbp)
573{
Harald Weltefed598f2017-09-24 16:39:22 +0800574 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100575 struct sockaddr_in addr;
576 struct qmsg_t *qmsg;
577 int fd;
jjako08d331d2003-10-13 20:33:30 +0000578
Harald Weltebed35df2011-11-02 13:06:18 +0100579 memset(&addr, 0, sizeof(addr));
580 addr.sin_family = AF_INET;
581 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000582#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100583 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000584#endif
jjako52c24142002-12-16 13:33:51 +0000585
Harald Weltefed598f2017-09-24 16:39:22 +0800586 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100587 addr.sin_port = htons(GTP0_PORT);
588 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
589 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100590 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100591 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100592 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100593 }
Harald Weltebed35df2011-11-02 13:06:18 +0100594 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
595 || (packet->gtp0.h.type == GTP_ERROR)))
596 packet->gtp0.h.flow = hton16(pdp->flru);
597 else if (pdp)
598 packet->gtp0.h.flow = hton16(pdp->flrc);
599 fd = gsn->fd0;
Harald Weltefed598f2017-09-24 16:39:22 +0800600 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100601 addr.sin_port = htons(GTP1C_PORT);
602 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
603 packet->gtp1l.h.seq = hton16(gsn->seq_next);
604 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
605 (packet->gtp1l.h.type == GTP_ERROR)))
606 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
607 else if (pdp)
608 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
609 fd = gsn->fd1c;
610 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100611 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100612 return -1;
613 }
jjako52c24142002-12-16 13:33:51 +0000614
Harald Weltebed35df2011-11-02 13:06:18 +0100615 if (sendto(fd, packet, len, 0,
616 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
617 gsn->err_sendto++;
Max14b1b632017-08-21 20:14:59 +0200618 LOGP(DLGTP, LOGL_ERROR, "Sendto(fd=%d, msg=%lx, len=%d, dst=%s) failed: Error = %s\n", fd,
619 (unsigned long)&packet, len, inet_ntoa(addr.sin_addr), strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100620 return -1;
621 }
622
623 /* Use new queue structure */
624 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
625 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100626 LOGP(DLGTP, LOGL_ERROR,
627 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100628 } else {
629 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
630 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100631 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100632 qmsg->retrans = 0; /* No retransmissions so far */
633 qmsg->cbp = cbp;
634 qmsg->type = ntoh8(packet->gtp0.h.type);
635 qmsg->fd = fd;
Pau Espin Pedrol623c5b32019-08-16 13:20:09 +0200636 if (pdp) /* echo requests are not pdp-bound */
637 llist_add(&qmsg->entry, &pdp->qmsg_list_req);
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200638
639 /* Rearm timer: Retrans time for qmsg just queued may be required
640 before an existing one (for instance a gtp echo req) */
641 queue_timer_start(gsn);
Harald Weltebed35df2011-11-02 13:06:18 +0100642 }
643 gsn->seq_next++; /* Count up this time */
644 return 0;
jjako52c24142002-12-16 13:33:51 +0000645}
646
Alexander Couzense1412d92018-09-16 05:10:03 +0200647
648/**
649 * @brief clear the request and response queue. Useful for debugging to reset "some" state.
650 * @param gsn The GGSN instance
651 */
652void gtp_clear_queues(struct gsn_t *gsn)
653{
654 struct qmsg_t *qmsg;
655
656 while (!queue_getfirst(gsn->queue_req, &qmsg)) {
657 queue_freemsg(gsn->queue_req, qmsg);
658 }
659
660 while (!queue_getfirst(gsn->queue_resp, &qmsg)) {
661 queue_freemsg(gsn->queue_resp, qmsg);
662 }
663}
664
jjako52c24142002-12-16 13:33:51 +0000665/* gtp_conf
666 * Remove signalling packet from retransmission queue.
667 * return 0 on success, EOF if packet was not found */
668
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100669static int gtp_conf(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100670 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
671{
Harald Weltefed598f2017-09-24 16:39:22 +0800672 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100673 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000674
Harald Weltefed598f2017-09-24 16:39:22 +0800675 if (ver == 0)
Harald Weltebed35df2011-11-02 13:06:18 +0100676 seq = ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800677 else if (ver == 1 && (packet->gtp1l.h.flags & GTP1HDR_F_SEQ))
Harald Weltebed35df2011-11-02 13:06:18 +0100678 seq = ntoh16(packet->gtp1l.h.seq);
679 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100680 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
681 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100682 return EOF;
683 }
jjako08d331d2003-10-13 20:33:30 +0000684
Harald Weltebed35df2011-11-02 13:06:18 +0100685 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
686 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100687 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
688 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100689 return EOF;
690 }
jjako52c24142002-12-16 13:33:51 +0000691
Harald Weltebed35df2011-11-02 13:06:18 +0100692 return 0;
jjako52c24142002-12-16 13:33:51 +0000693}
694
Harald Weltebed35df2011-11-02 13:06:18 +0100695int gtp_retrans(struct gsn_t *gsn)
696{
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200697 /* dummy API, deprecated. */
Harald Weltebed35df2011-11-02 13:06:18 +0100698 return 0;
jjako52c24142002-12-16 13:33:51 +0000699}
700
Harald Weltebed35df2011-11-02 13:06:18 +0100701int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
702{
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200703 timeout->tv_sec = 24*60*60;
Pau Espin Pedrolceac0782019-05-27 17:39:45 +0200704 timeout->tv_usec = 0;
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200705 /* dummy API, deprecated. Return a huge timer to do nothing */
Harald Weltebed35df2011-11-02 13:06:18 +0100706 return 0;
jjako52c24142002-12-16 13:33:51 +0000707}
708
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100709static int gtp_resp(uint8_t version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000710 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100711 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
712{
Harald Weltefed598f2017-09-24 16:39:22 +0800713 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100714 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000715
Harald Weltefed598f2017-09-24 16:39:22 +0800716 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100717 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
718 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100719 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100720 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
721 (packet->gtp0.h.type == GTP_ERROR)))
722 packet->gtp0.h.flow = hton16(pdp->flru);
723 else if (pdp)
724 packet->gtp0.h.flow = hton16(pdp->flrc);
Harald Weltefed598f2017-09-24 16:39:22 +0800725 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100726 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
727 packet->gtp1l.h.seq = hton16(seq);
728 if (pdp && (fd == gsn->fd1u))
729 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
730 else if (pdp)
731 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
732 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100733 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100734 return -1;
735 }
jjako08d331d2003-10-13 20:33:30 +0000736
Harald Weltebed35df2011-11-02 13:06:18 +0100737 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100738 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100739 return -1;
740 }
jjako52c24142002-12-16 13:33:51 +0000741
Harald Weltebed35df2011-11-02 13:06:18 +0100742 if (sendto(fd, packet, len, 0,
743 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
744 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100745 LOGP(DLGTP, LOGL_ERROR,
746 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100747 (unsigned long)&packet, len, strerror(errno));
748 return -1;
749 }
750
751 /* Use new queue structure */
752 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
753 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100754 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100755 } else {
756 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
757 qmsg->l = len;
758 qmsg->timeout = time(NULL) + 60; /* When to timeout */
759 qmsg->retrans = 0; /* No retransmissions so far */
760 qmsg->cbp = NULL;
761 qmsg->type = 0;
762 qmsg->fd = fd;
Pau Espin Pedrol623c5b32019-08-16 13:20:09 +0200763 /* No need to add to pdp list here, because even on pdp ctx free
764 we want to leave messages in queue_resp until timeout to
765 detect duplicates */
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200766
767 /* Rearm timer: Retrans time for qmsg just queued may be required
768 before an existing one (for instance a gtp echo req) */
769 queue_timer_start(gsn);
Harald Weltebed35df2011-11-02 13:06:18 +0100770 }
771 return 0;
jjako52c24142002-12-16 13:33:51 +0000772}
773
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100774static int gtp_notification(struct gsn_t *gsn, uint8_t version,
jjako2c381332003-10-21 19:09:53 +0000775 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100776 struct sockaddr_in *peer, int fd, uint16_t seq)
777{
jjako2c381332003-10-21 19:09:53 +0000778
Harald Weltefed598f2017-09-24 16:39:22 +0800779 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100780 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000781
Harald Weltebed35df2011-11-02 13:06:18 +0100782 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000783
Harald Weltebed35df2011-11-02 13:06:18 +0100784 /* In GTP0 notifications are treated as replies. In GTP1 they
785 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000786
Harald Weltebed35df2011-11-02 13:06:18 +0100787 if (fd == gsn->fd1c)
788 addr.sin_port = htons(GTP1C_PORT);
789 else if (fd == gsn->fd1u)
790 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000791
Harald Weltefed598f2017-09-24 16:39:22 +0800792 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100793 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
794 packet->gtp0.h.seq = hton16(seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800795 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100796 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
797 packet->gtp1l.h.seq = hton16(seq);
798 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100799 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100800 return -1;
801 }
802
803 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100804 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100805 return -1;
806 }
807
808 if (sendto(fd, packet, len, 0,
809 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
810 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100811 LOGP(DLGTP, LOGL_ERROR,
812 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100813 (unsigned long)&packet, len, strerror(errno));
814 return -1;
815 }
816 return 0;
jjako2c381332003-10-21 19:09:53 +0000817}
818
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200819static int gtp_duplicate(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +0100820 struct sockaddr_in *peer, uint16_t seq)
821{
822 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000823
Harald Weltebed35df2011-11-02 13:06:18 +0100824 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
825 return EOF; /* Notfound */
826 }
jjakoa7cd2492003-04-11 09:40:12 +0000827
Harald Weltebed35df2011-11-02 13:06:18 +0100828 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100829 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100830 return -1;
831 }
832
833 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
834 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
835 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100836 LOGP(DLGTP, LOGL_ERROR,
837 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100838 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
839 strerror(errno));
840 }
841 return 0;
jjako52c24142002-12-16 13:33:51 +0000842}
843
jjako52c24142002-12-16 13:33:51 +0000844/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100845static void log_restart(struct gsn_t *gsn)
846{
jjako52c24142002-12-16 13:33:51 +0000847 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200848 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000849 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200850 char *filename;
jjako52c24142002-12-16 13:33:51 +0000851
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200852 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
853 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000854
855 /* We try to open file. On failure we will later try to create file */
856 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100857 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100858 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100859 filename);
860 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100861 rc = fscanf(f, "%d", &counter);
862 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100863 LOGP(DLGTP, LOGL_ERROR,
864 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100865 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100866 }
867 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100868 LOGP(DLGTP, LOGL_ERROR,
869 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100870 }
jjako52c24142002-12-16 13:33:51 +0000871 }
Harald Weltebed35df2011-11-02 13:06:18 +0100872
873 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000874 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100875
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200876 /* Keep the umask closely wrapped around our fopen() call in case the
877 * log outputs cause file creation. */
878 i = umask(022);
879 f = fopen(filename, "w");
880 umask(i);
881 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100882 LOGP(DLGTP, LOGL_ERROR,
883 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100884 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200885 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000886 }
887
jjako52c24142002-12-16 13:33:51 +0000888 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100889close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200890 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100891 LOGP(DLGTP, LOGL_ERROR,
892 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200893free_filename:
894 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000895}
896
jjako1db1c812003-07-06 20:53:57 +0000897int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100898 int mode)
jjako52c24142002-12-16 13:33:51 +0000899{
Harald Weltebed35df2011-11-02 13:06:18 +0100900 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000901
Max14b1b632017-08-21 20:14:59 +0200902 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
jjako52c24142002-12-16 13:33:51 +0000903
Harald Weltebed35df2011-11-02 13:06:18 +0100904 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000905
Harald Weltebed35df2011-11-02 13:06:18 +0100906 (*gsn)->statedir = statedir;
907 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000908
Harald Weltebed35df2011-11-02 13:06:18 +0100909 /* Initialise sequence number */
910 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000911
Harald Weltebed35df2011-11-02 13:06:18 +0100912 /* Initialise request retransmit queue */
913 queue_new(&(*gsn)->queue_req);
914 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000915
Harald Weltebed35df2011-11-02 13:06:18 +0100916 /* Initialise pdp table */
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +0200917 pdp_init(*gsn);
jjako08d331d2003-10-13 20:33:30 +0000918
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200919 /* Initialize internal queue timer */
920 osmo_timer_setup(&(*gsn)->queue_timer, queue_timer_cb, *gsn);
921
Harald Weltebed35df2011-11-02 13:06:18 +0100922 /* Initialise call back functions */
923 (*gsn)->cb_create_context_ind = 0;
924 (*gsn)->cb_delete_context = 0;
925 (*gsn)->cb_unsup_ind = 0;
926 (*gsn)->cb_conf = 0;
927 (*gsn)->cb_data_ind = 0;
928
929 /* Store function parameters */
930 (*gsn)->gsnc = *listen;
931 (*gsn)->gsnu = *listen;
932 (*gsn)->mode = mode;
933
934 /* Create GTP version 0 socket */
935 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
936 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100937 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200938 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100939 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200940 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100941 }
942
943 memset(&addr, 0, sizeof(addr));
944 addr.sin_family = AF_INET;
945 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
946 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000947#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100948 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000949#endif
jjako08d331d2003-10-13 20:33:30 +0000950
Harald Weltebed35df2011-11-02 13:06:18 +0100951 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
952 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200953 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
954 "bind(fd0=%d) failed: Error = %s\n",
955 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200956 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100957 }
jjako08d331d2003-10-13 20:33:30 +0000958
Harald Weltebed35df2011-11-02 13:06:18 +0100959 /* Create GTP version 1 control plane socket */
960 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
961 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100962 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200963 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100964 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200965 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100966 }
967
968 memset(&addr, 0, sizeof(addr));
969 addr.sin_family = AF_INET;
970 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
971 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000972#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100973 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000974#endif
jjako08d331d2003-10-13 20:33:30 +0000975
Harald Weltebed35df2011-11-02 13:06:18 +0100976 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
977 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200978 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
979 "bind(fd1c=%d) failed: Error = %s\n",
980 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200981 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100982 }
jjako08d331d2003-10-13 20:33:30 +0000983
Harald Weltebed35df2011-11-02 13:06:18 +0100984 /* Create GTP version 1 user plane socket */
985 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
986 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100987 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200988 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100989 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200990 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100991 }
992
993 memset(&addr, 0, sizeof(addr));
994 addr.sin_family = AF_INET;
995 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
996 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000997#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100998 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000999#endif
jjako52c24142002-12-16 13:33:51 +00001000
Harald Weltebed35df2011-11-02 13:06:18 +01001001 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1002 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +02001003 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +02001004 "bind(fd1u=%d) failed: Error = %s\n",
1005 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +02001006 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +01001007 }
1008
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +02001009 /* Start internal queue timer */
1010 queue_timer_start(*gsn);
1011
Harald Weltebed35df2011-11-02 13:06:18 +01001012 return 0;
jjako52c24142002-12-16 13:33:51 +00001013}
1014
Harald Weltebed35df2011-11-02 13:06:18 +01001015int gtp_free(struct gsn_t *gsn)
1016{
jjako52c24142002-12-16 13:33:51 +00001017
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +02001018 /* Cleanup internal queue timer */
1019 osmo_timer_del(&gsn->queue_timer);
1020
Harald Weltebed35df2011-11-02 13:06:18 +01001021 /* Clean up retransmit queues */
1022 queue_free(gsn->queue_req);
1023 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +00001024
Harald Weltebed35df2011-11-02 13:06:18 +01001025 close(gsn->fd0);
1026 close(gsn->fd1c);
1027 close(gsn->fd1u);
1028
1029 free(gsn);
1030 return 0;
jjako52c24142002-12-16 13:33:51 +00001031}
1032
1033/* ***********************************************************
1034 * Path management messages
1035 * Messages: echo and version not supported.
1036 * A path is connection between two UDP/IP endpoints
1037 *
1038 * A path is either using GTP0 or GTP1. A path can be
1039 * established by any kind of GTP message??
1040
1041 * Which source port to use?
1042 * GTP-C request destination port is 2123/3386
1043 * GTP-U request destination port is 2152/3386
1044 * T-PDU destination port is 2152/3386.
1045 * For the above messages the source port is locally allocated.
1046 * For response messages src=rx-dst and dst=rx-src.
1047 * For simplicity we should probably use 2123+2152/3386 as
1048 * src port even for the cases where src can be locally
1049 * allocated. This also means that we have to listen only to
1050 * the same ports.
1051 * For response messages we need to be able to respond to
1052 * the relevant src port even if it is locally allocated by
1053 * the peer.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001054 *
jjako52c24142002-12-16 13:33:51 +00001055 * The need for path management!
1056 * We might need to keep a list of active paths. This might
1057 * be in the form of remote IP address + UDP port numbers.
1058 * (We will consider a path astablished if we have a context
1059 * with the node in question)
1060 *************************************************************/
1061
1062/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +00001063int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
1064 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +00001065{
Harald Weltebed35df2011-11-02 13:06:18 +01001066 union gtp_packet packet;
1067 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
1068 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +00001069}
1070
jjako08d331d2003-10-13 20:33:30 +00001071/* Send off an echo reply */
1072int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001073 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001074{
Harald Weltebed35df2011-11-02 13:06:18 +01001075 union gtp_packet packet;
1076 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
1077 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1078 gsn->restart_counter);
1079 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
1080 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00001081}
1082
jjako52c24142002-12-16 13:33:51 +00001083/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +01001084int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1085 int fd, void *pack, unsigned len)
1086{
jjako52c24142002-12-16 13:33:51 +00001087
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02001088 /* Check if it was a duplicate request */
1089 if (!gtp_duplicate(gsn, 0, peer, get_seq(pack)))
Harald Weltebed35df2011-11-02 13:06:18 +01001090 return 0;
jjako52c24142002-12-16 13:33:51 +00001091
Harald Weltebed35df2011-11-02 13:06:18 +01001092 /* Send off reply to request */
1093 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +00001094}
1095
1096/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +00001097int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001098 void *pack, unsigned len)
1099{
1100 union gtpie_member *ie[GTPIE_SIZE];
1101 unsigned char recovery;
1102 void *cbp = NULL;
1103 uint8_t type = 0;
1104 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001105
Harald Weltebed35df2011-11-02 13:06:18 +01001106 /* Remove packet from queue */
1107 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1108 return EOF;
jjako52c24142002-12-16 13:33:51 +00001109
Harald Weltebed35df2011-11-02 13:06:18 +01001110 /* Extract information elements into a pointer array */
1111 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1112 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001113 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1114 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001115 if (gsn->cb_conf)
1116 gsn->cb_conf(type, EOF, NULL, cbp);
1117 return EOF;
1118 }
jjako52c24142002-12-16 13:33:51 +00001119
Harald Weltebed35df2011-11-02 13:06:18 +01001120 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1121 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001122 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1123 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001124 if (gsn->cb_conf)
1125 gsn->cb_conf(type, EOF, NULL, cbp);
1126 return EOF;
1127 }
jjako52c24142002-12-16 13:33:51 +00001128
Harald Weltebed35df2011-11-02 13:06:18 +01001129 /* Echo reply packages does not have a cause information element */
1130 /* Instead we return the recovery number in the callback function */
1131 if (gsn->cb_conf)
1132 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +01001133
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001134 emit_cb_recovery(gsn, peer, NULL, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001135
1136 return 0;
jjako52c24142002-12-16 13:33:51 +00001137}
1138
1139/* Send off a Version Not Supported message */
1140/* This message is somewhat special in that it actually is a
1141 * response to some other message with unsupported GTP version
1142 * For this reason it has parameters like a response, and does
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001143 * its own message transmission. No signalling queue is used
jjako52c24142002-12-16 13:33:51 +00001144 * The reply is sent to the peer IP and peer UDP. This means that
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001145 * the peer will be receiving a GTP0 message on a GTP1 port!
jjako52c24142002-12-16 13:33:51 +00001146 * In practice however this will never happen as a GTP0 GSN will
1147 * only listen to the GTP0 port, and therefore will never receive
1148 * anything else than GTP0 */
1149
jjako08d331d2003-10-13 20:33:30 +00001150int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1151 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001152{
Harald Weltebed35df2011-11-02 13:06:18 +01001153 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +00001154
Harald Weltebed35df2011-11-02 13:06:18 +01001155 /* GTP 1 is the highest supported protocol */
1156 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
1157 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +00001158}
1159
1160/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +01001161int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1162 void *pack, unsigned len)
1163{
jjako52c24142002-12-16 13:33:51 +00001164
Harald Weltebed35df2011-11-02 13:06:18 +01001165 if (gsn->cb_unsup_ind)
1166 gsn->cb_unsup_ind(peer);
1167
1168 return 0;
jjako52c24142002-12-16 13:33:51 +00001169}
1170
jjako2c381332003-10-21 19:09:53 +00001171/* Send off an Supported Extension Headers Notification */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001172static int gtp_extheader_req(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
jjako2c381332003-10-21 19:09:53 +00001173 int fd, void *pack, unsigned len)
1174{
Harald Weltebed35df2011-11-02 13:06:18 +01001175 union gtp_packet packet;
1176 unsigned int length =
1177 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +00001178
Harald Weltebed35df2011-11-02 13:06:18 +01001179 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +00001180
Harald Weltebed35df2011-11-02 13:06:18 +01001181 if (version < 1)
1182 return 0;
jjako2c381332003-10-21 19:09:53 +00001183
Harald Weltebed35df2011-11-02 13:06:18 +01001184 /* We report back that we support only PDCP PDU headers */
1185 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
1186 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +00001187
Harald Weltebed35df2011-11-02 13:06:18 +01001188 return gtp_notification(gsn, version, &packet, length,
1189 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +00001190}
1191
1192/* Handle a Supported Extension Headers Notification */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001193static int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001194 void *pack, unsigned len)
1195{
jjako2c381332003-10-21 19:09:53 +00001196
Harald Weltebed35df2011-11-02 13:06:18 +01001197 if (gsn->cb_extheader_ind)
1198 gsn->cb_extheader_ind(peer);
1199
1200 return 0;
jjako2c381332003-10-21 19:09:53 +00001201}
1202
jjako52c24142002-12-16 13:33:51 +00001203/* ***********************************************************
1204 * Session management messages
1205 * Messages: create, update and delete PDP context
1206 *
1207 * Information storage
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001208 * Information storage for each PDP context is defined in
jjako52c24142002-12-16 13:33:51 +00001209 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1210 * PDP-address (IP address), sequence numbers, charging ID.
1211 * For the SGSN it also includes radio related mobility
1212 * information.
1213 *************************************************************/
1214
Harald Welte7b3347b2010-05-15 12:18:46 +02001215/* API: Send Create PDP Context Request (7.3.1) */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001216int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001217 void *cbp)
1218{
1219 union gtp_packet packet;
1220 unsigned int length =
1221 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1222 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001223
Harald Weltebed35df2011-11-02 13:06:18 +01001224 /* TODO: Secondary PDP Context Activation Procedure */
1225 /* In secondary activation procedure the PDP context is identified
1226 by tei in the header. The following fields are omitted: Selection
1227 mode, IMSI, MSISDN, End User Address, Access Point Name and
1228 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001229
Harald Weltebed35df2011-11-02 13:06:18 +01001230 if (pdp->secondary) {
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001231 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001232 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001233 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001234 return EOF;
1235 }
1236 }
jjako2c381332003-10-21 19:09:53 +00001237
Harald Weltebed35df2011-11-02 13:06:18 +01001238 if (pdp->version == 0) {
1239 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1240 sizeof(pdp->qos_req0), pdp->qos_req0);
1241 }
jjako52c24142002-12-16 13:33:51 +00001242
Harald Weltebed35df2011-11-02 13:06:18 +01001243 /* Section 7.7.2 */
1244 if (pdp->version == 1) {
1245 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1246 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1247 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1248 }
jjako52c24142002-12-16 13:33:51 +00001249
Harald Weltebed35df2011-11-02 13:06:18 +01001250 /* Section 7.7.3 Routing Area Information */
1251 if (pdp->rai_given == 1)
1252 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1253 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001254
Harald Weltebed35df2011-11-02 13:06:18 +01001255 /* Section 7.7.11 */
1256 if (pdp->norecovery_given == 0)
1257 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1258 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001259
Harald Weltebed35df2011-11-02 13:06:18 +01001260 /* Section 7.7.12 */
1261 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1262 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1263 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001264
Harald Weltebed35df2011-11-02 13:06:18 +01001265 if (pdp->version == 0) {
1266 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1267 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1268 }
jjako08d331d2003-10-13 20:33:30 +00001269
Harald Weltebed35df2011-11-02 13:06:18 +01001270 /* Section 7.7.13 */
1271 if (pdp->version == 1) {
1272 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1273 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001274
Harald Weltebed35df2011-11-02 13:06:18 +01001275 /* Section 7.7.14 */
1276 if (!pdp->teic_confirmed)
1277 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1278 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001279
Harald Weltebed35df2011-11-02 13:06:18 +01001280 /* Section 7.7.17 */
1281 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001282
Harald Weltebed35df2011-11-02 13:06:18 +01001283 /* Section 7.7.17 */
1284 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1285 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1286 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001287
Harald Weltebed35df2011-11-02 13:06:18 +01001288 /* Section 7.7.23 */
1289 if (pdp->cch_pdp) /* Only include charging if flags are set */
1290 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1291 pdp->cch_pdp);
1292 }
jjako9b4971d2004-05-27 20:30:19 +00001293
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001294 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001295 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1296 pdp->traceref);
1297 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1298 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001299
Harald Weltebed35df2011-11-02 13:06:18 +01001300 /* Section 7.7.27 */
1301 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1302 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1303 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001304
Harald Weltebed35df2011-11-02 13:06:18 +01001305 /* Section 7.7.30 */
1306 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1307 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1308 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001309
Harald Weltebed35df2011-11-02 13:06:18 +01001310 /* Section 7.7.31 */
1311 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1312 if (pdp->pco_req.l)
1313 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1314 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001315
Harald Weltebed35df2011-11-02 13:06:18 +01001316 /* Section 7.7.32 */
1317 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1318 pdp->gsnlc.l, pdp->gsnlc.v);
1319 /* Section 7.7.32 */
1320 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1321 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001322
Harald Weltebed35df2011-11-02 13:06:18 +01001323 /* Section 7.7.33 */
1324 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1325 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1326 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001327
Harald Weltebed35df2011-11-02 13:06:18 +01001328 /* Section 7.7.34 */
1329 if (pdp->version == 1)
1330 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1331 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001332
Harald Weltebed35df2011-11-02 13:06:18 +01001333 /* Section 7.7.36 */
1334 if ((pdp->version == 1) && pdp->tft.l)
1335 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1336 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001337
Harald Weltebed35df2011-11-02 13:06:18 +01001338 /* Section 7.7.41 */
1339 if ((pdp->version == 1) && pdp->triggerid.l)
1340 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1341 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001342
Harald Weltebed35df2011-11-02 13:06:18 +01001343 /* Section 7.7.42 */
1344 if ((pdp->version == 1) && pdp->omcid.l)
1345 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1346 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001347
Harald Weltebed35df2011-11-02 13:06:18 +01001348 /* new R7 fields */
1349 if (pdp->rattype_given == 1)
1350 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1351 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001352
Harald Weltebed35df2011-11-02 13:06:18 +01001353 if (pdp->userloc_given == 1)
1354 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1355 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001356
Harald Weltebed35df2011-11-02 13:06:18 +01001357 if (pdp->mstz_given == 1)
1358 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1359 pdp->mstz.l, pdp->mstz.v);
1360
1361 if (pdp->imeisv_given == 1)
1362 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1363 pdp->imeisv.l, pdp->imeisv.v);
1364
1365 /* TODO hisaddr0 */
1366 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1367
1368 return 0;
jjako52c24142002-12-16 13:33:51 +00001369}
1370
jjako08d331d2003-10-13 20:33:30 +00001371/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001372int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1373{
jjako08d331d2003-10-13 20:33:30 +00001374
Harald Weltebed35df2011-11-02 13:06:18 +01001375 /* Now send off a reply to the peer */
1376 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1377
Pau Espin Pedrold9501342019-08-21 15:24:29 +02001378 if (cause != GTPCAUSE_ACC_REQ)
1379 gtp_freepdp(gsn, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001380
1381 return 0;
jjako08d331d2003-10-13 20:33:30 +00001382}
1383
1384/* API: Register create context indication callback */
1385int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001386 int (*cb_create_context_ind) (struct pdp_t *
1387 pdp))
jjako52c24142002-12-16 13:33:51 +00001388{
Harald Weltebed35df2011-11-02 13:06:18 +01001389 gsn->cb_create_context_ind = cb_create_context_ind;
1390 return 0;
jjako08d331d2003-10-13 20:33:30 +00001391}
1392
jjako08d331d2003-10-13 20:33:30 +00001393/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001394int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1395 uint8_t cause)
1396{
1397 union gtp_packet packet;
1398 unsigned int length =
1399 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001400
Harald Weltebed35df2011-11-02 13:06:18 +01001401 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001402
Harald Weltebed35df2011-11-02 13:06:18 +01001403 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001404
Harald Weltebed35df2011-11-02 13:06:18 +01001405 if (version == 0)
1406 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1407 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001408
Harald Weltebed35df2011-11-02 13:06:18 +01001409 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1410 pdp->reorder);
1411 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1412 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001413
Harald Weltebed35df2011-11-02 13:06:18 +01001414 if (version == 0) {
1415 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1416 pdp->fllu);
1417 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1418 pdp->fllc);
1419 }
jjako08d331d2003-10-13 20:33:30 +00001420
Harald Weltebed35df2011-11-02 13:06:18 +01001421 if (version == 1) {
1422 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1423 pdp->teid_own);
1424 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1425 pdp->teic_own);
1426 }
jjako08d331d2003-10-13 20:33:30 +00001427
Harald Weltebed35df2011-11-02 13:06:18 +01001428 /* TODO: We use teic_own as charging ID */
1429 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1430 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001431
Harald Weltebed35df2011-11-02 13:06:18 +01001432 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1433 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001434
Harald Weltebed35df2011-11-02 13:06:18 +01001435 if (pdp->pco_neg.l) { /* Optional PCO */
1436 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1437 pdp->pco_neg.l, pdp->pco_neg.v);
1438 }
jjako52c24142002-12-16 13:33:51 +00001439
Harald Weltebed35df2011-11-02 13:06:18 +01001440 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1441 pdp->gsnlc.l, pdp->gsnlc.v);
1442 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1443 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001444
Harald Weltebed35df2011-11-02 13:06:18 +01001445 if (version == 1)
1446 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1447 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001448
Harald Weltebed35df2011-11-02 13:06:18 +01001449 /* TODO: Charging gateway address */
1450 }
jjako52c24142002-12-16 13:33:51 +00001451
Harald Weltebed35df2011-11-02 13:06:18 +01001452 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1453 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001454}
1455
1456/* Handle Create PDP Context Request */
1457int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001458 struct sockaddr_in *peer, int fd,
1459 void *pack, unsigned len)
1460{
1461 struct pdp_t *pdp, *pdp_old;
1462 struct pdp_t pdp_buf;
1463 union gtpie_member *ie[GTPIE_SIZE];
1464 uint8_t recovery;
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001465 bool recovery_recvd = false;
1466 int rc;
jjako52c24142002-12-16 13:33:51 +00001467
Harald Weltebed35df2011-11-02 13:06:18 +01001468 uint16_t seq = get_seq(pack);
1469 int hlen = get_hlen(pack);
1470 uint8_t linked_nsapi = 0;
1471 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001472
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02001473 if (!gtp_duplicate(gsn, version, peer, seq))
Harald Weltebed35df2011-11-02 13:06:18 +01001474 return 0;
jjako08d331d2003-10-13 20:33:30 +00001475
Harald Weltebed35df2011-11-02 13:06:18 +01001476 pdp = &pdp_buf;
1477 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001478
Vadim Yanitskiy68c5a742019-08-30 21:04:19 +02001479 if (version == 0)
1480 pdp_set_imsi_nsapi(pdp, get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00001481
Harald Weltebed35df2011-11-02 13:06:18 +01001482 pdp->seq = seq;
1483 pdp->sa_peer = *peer;
1484 pdp->fd = fd;
1485 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001486
Harald Weltebed35df2011-11-02 13:06:18 +01001487 /* Decode information elements */
1488 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1489 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001490 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1491 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001492 if (0 == version)
1493 return EOF;
1494 else
1495 return gtp_create_pdp_resp(gsn, version, pdp,
1496 GTPCAUSE_INVALID_MESSAGE);
1497 }
jjako52c24142002-12-16 13:33:51 +00001498
Harald Weltebed35df2011-11-02 13:06:18 +01001499 if (version == 1) {
1500 /* Linked NSAPI (conditional) */
1501 /* If included this is the Secondary PDP Context Activation Procedure */
1502 /* In secondary activation IMSI is not included, so the context must be */
1503 /* identified by the tei */
1504 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001505
Harald Weltebed35df2011-11-02 13:06:18 +01001506 /* Find the primary PDP context */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001507 if (gtp_pdp_getgtp1(gsn, &linked_pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001508 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001509 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001510 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001511 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001512 return gtp_create_pdp_resp(gsn, version, pdp,
1513 GTPCAUSE_OPT_IE_INCORRECT);
1514 }
jjako2c381332003-10-21 19:09:53 +00001515
Harald Weltebed35df2011-11-02 13:06:18 +01001516 /* Check that the primary PDP context matches linked nsapi */
1517 if (linked_pdp->nsapi != linked_nsapi) {
1518 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001519 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001520 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001521 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001522 return gtp_create_pdp_resp(gsn, version, pdp,
1523 GTPCAUSE_OPT_IE_INCORRECT);
1524 }
jjako52c24142002-12-16 13:33:51 +00001525
Harald Weltebed35df2011-11-02 13:06:18 +01001526 /* Copy parameters from primary context */
1527 pdp->selmode = linked_pdp->selmode;
1528 pdp->imsi = linked_pdp->imsi;
1529 pdp->msisdn = linked_pdp->msisdn;
1530 pdp->eua = linked_pdp->eua;
1531 pdp->pco_req = linked_pdp->pco_req;
1532 pdp->apn_req = linked_pdp->apn_req;
1533 pdp->teic_gn = linked_pdp->teic_gn;
1534 pdp->secondary = 1;
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001535 } else {
1536 /* Not Secondary PDP Context Activation Procedure */
1537 /* IMSI (conditional): If the MS is emergency attached
1538 and the MS is UICCless, the IMSI cannot be included
1539 in the message and therefore IMSI shall not be
1540 included in the message. */
1541 if (gtpie_gettv0
1542 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1543 gsn->missing++;
1544 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1545 len, "Missing IMSI not supported\n");
1546 return gtp_create_pdp_resp(gsn, version, pdp,
1547 GTPCAUSE_MAN_IE_MISSING);
1548 }
1549 }
1550
1551 /* TEID (mandatory) */
1552 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1553 gsn->missing++;
1554 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1555 len, "Missing mandatory information field\n");
1556 return gtp_create_pdp_resp(gsn, version, pdp,
1557 GTPCAUSE_MAN_IE_MISSING);
1558 }
1559 /* TEIC (conditional) */
1560 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1561 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1562 gsn->missing++;
1563 GTP_LOGPKG(LOGL_ERROR, peer,
1564 pack, len,
1565 "Missing mandatory information field\n");
1566 return gtp_create_pdp_resp(gsn, version, pdp,
1567 GTPCAUSE_MAN_IE_MISSING);
1568 }
1569 }
1570 /* NSAPI (mandatory) */
1571 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1572 gsn->missing++;
1573 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1574 len, "Missing mandatory information field\n");
1575 return gtp_create_pdp_resp(gsn, version, pdp,
1576 GTPCAUSE_MAN_IE_MISSING);
1577 }
1578 /* QoS (mandatory) */
1579 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1580 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1581 gsn->missing++;
1582 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1583 len, "Missing mandatory information field\n");
1584 return gtp_create_pdp_resp(gsn, version, pdp,
1585 GTPCAUSE_MAN_IE_MISSING);
1586 }
1587 /* TFT (conditional) */
1588 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1589 &pdp->tft.v, sizeof(pdp->tft.v))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001590 }
1591 }
1592 /* if (version == 1) */
1593 if (version == 0) {
1594 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1595 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1596 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001597 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1598 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001599 return gtp_create_pdp_resp(gsn, version, pdp,
1600 GTPCAUSE_MAN_IE_MISSING);
1601 }
Harald Weltebed35df2011-11-02 13:06:18 +01001602 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1603 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001604 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1605 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001606 return gtp_create_pdp_resp(gsn, version, pdp,
1607 GTPCAUSE_MAN_IE_MISSING);
1608 }
Harald Weltebed35df2011-11-02 13:06:18 +01001609 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1610 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001611 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1612 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001613 return gtp_create_pdp_resp(gsn, version, pdp,
1614 GTPCAUSE_MAN_IE_MISSING);
1615 }
1616 }
jjako08d331d2003-10-13 20:33:30 +00001617
Harald Weltebed35df2011-11-02 13:06:18 +01001618 /* SGSN address for signalling (mandatory) */
1619 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1620 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1621 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001622 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1623 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001624 return gtp_create_pdp_resp(gsn, version, pdp,
1625 GTPCAUSE_MAN_IE_MISSING);
1626 }
jjako2e840a32003-01-28 16:05:18 +00001627
Harald Weltebed35df2011-11-02 13:06:18 +01001628 /* SGSN address for user traffic (mandatory) */
1629 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1630 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1631 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001632 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1633 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001634 return gtp_create_pdp_resp(gsn, version, pdp,
1635 GTPCAUSE_MAN_IE_MISSING);
1636 }
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001637 /* Recovery (optional) */
1638 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1639 /* we use recovery futher down after announcing new pdp ctx to user */
1640 recovery_recvd = true;
1641 }
jjako52c24142002-12-16 13:33:51 +00001642
Harald Weltebed35df2011-11-02 13:06:18 +01001643 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001644 /* Selection mode (conditional) */
1645 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1646 &pdp->selmode, sizeof(pdp->selmode))) {
1647 gsn->missing++;
1648 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1649 len, "Missing mandatory information field\n");
1650 return gtp_create_pdp_resp(gsn, version, pdp,
1651 GTPCAUSE_MAN_IE_MISSING);
1652 }
1653 /* End User Address (conditional) */
1654 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1655 &pdp->eua.v, sizeof(pdp->eua.v))) {
1656 gsn->missing++;
1657 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1658 len, "Missing mandatory information field\n");
1659 return gtp_create_pdp_resp(gsn, version, pdp,
1660 GTPCAUSE_MAN_IE_MISSING);
1661 }
1662 /* APN */
1663 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1664 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1665 gsn->missing++;
1666 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1667 len, "Missing mandatory information field\n");
1668 return gtp_create_pdp_resp(gsn, version, pdp,
1669 GTPCAUSE_MAN_IE_MISSING);
1670 }
1671 /* Extract protocol configuration options (optional) */
1672 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1673 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1674 }
Harald Weltebed35df2011-11-02 13:06:18 +01001675 /* MSISDN (conditional) */
1676 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1677 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1678 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001679 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1680 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001681 return gtp_create_pdp_resp(gsn, version, pdp,
1682 GTPCAUSE_MAN_IE_MISSING);
1683 }
1684 }
jjako52c24142002-12-16 13:33:51 +00001685
Harald Weltebed35df2011-11-02 13:06:18 +01001686 /* Initialize our own IP addresses */
1687 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1688 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1689
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001690 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before gtp_pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001691
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001692 if (!gtp_pdp_getimsi(gsn, &pdp_old, pdp->imsi, pdp->nsapi)) {
Harald Weltebed35df2011-11-02 13:06:18 +01001693 /* Found old pdp with same tid. Now the voodoo begins! */
1694 /* 09.60 / 29.060 allows create on existing context to "steal" */
1695 /* the context which was allready established */
1696 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001697 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001698 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1699 &&
1700 (!memcmp
1701 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1702 && (pdp->selmode == pdp_old->selmode)
1703 && (pdp->msisdn.l == pdp_old->msisdn.l)
1704 &&
1705 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1706 {
1707 /* OK! We are dealing with the same APN. We will copy new
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001708 * parameters to the old pdp and send off confirmation
Harald Weltebed35df2011-11-02 13:06:18 +01001709 * We ignore the following information elements:
1710 * QoS: MS will get originally negotiated QoS.
1711 * End user address (EUA). MS will get old EUA anyway.
1712 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001713 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001714
1715 /* Copy remote flow label */
1716 pdp_old->flru = pdp->flru;
1717 pdp_old->flrc = pdp->flrc;
1718
1719 /* Copy remote tei */
1720 pdp_old->teid_gn = pdp->teid_gn;
1721 pdp_old->teic_gn = pdp->teic_gn;
1722
1723 /* Copy peer GSN address */
1724 pdp_old->gsnrc.l = pdp->gsnrc.l;
1725 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1726 pdp_old->gsnru.l = pdp->gsnru.l;
1727 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1728
1729 /* Copy request parameters */
1730 pdp_old->seq = pdp->seq;
1731 pdp_old->sa_peer = pdp->sa_peer;
1732 pdp_old->fd = pdp->fd = fd;
1733 pdp_old->version = pdp->version = version;
1734
1735 /* Switch to using the old pdp context */
1736 pdp = pdp_old;
1737
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001738 if (recovery_recvd)
1739 emit_cb_recovery(gsn, peer, pdp, recovery);
1740
Harald Weltebed35df2011-11-02 13:06:18 +01001741 /* Confirm to peer that things were "successful" */
1742 return gtp_create_pdp_resp(gsn, version, pdp,
1743 GTPCAUSE_ACC_REQ);
1744 } else { /* This is not the same PDP context. Delete the old one. */
1745
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001746 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001747
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02001748 gtp_freepdp(gsn, pdp_old);
Harald Weltebed35df2011-11-02 13:06:18 +01001749
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001750 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001751 }
1752 }
1753
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +02001754 gtp_pdp_newpdp(gsn, &pdp, pdp->imsi, pdp->nsapi, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001755
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001756 /* Callback function to validate login */
Harald Weltebed35df2011-11-02 13:06:18 +01001757 if (gsn->cb_create_context_ind != 0)
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001758 rc = gsn->cb_create_context_ind(pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001759 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001760 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1761 "No create_context_ind callback defined\n");
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001762 rc = gtp_create_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001763 GTPCAUSE_NOT_SUPPORTED);
1764 }
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001765 if (recovery_recvd)
1766 emit_cb_recovery(gsn, peer, pdp, recovery);
1767 return rc;
jjako52c24142002-12-16 13:33:51 +00001768}
1769
jjako52c24142002-12-16 13:33:51 +00001770/* Handle Create PDP Context Response */
1771int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001772 struct sockaddr_in *peer, void *pack, unsigned len)
1773{
1774 struct pdp_t *pdp;
1775 union gtpie_member *ie[GTPIE_SIZE];
1776 uint8_t cause, recovery;
1777 void *cbp = NULL;
1778 uint8_t type = 0;
1779 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001780
Harald Weltebed35df2011-11-02 13:06:18 +01001781 /* Remove packet from queue */
1782 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1783 return EOF;
jjako52c24142002-12-16 13:33:51 +00001784
Harald Weltebed35df2011-11-02 13:06:18 +01001785 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001786 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001787 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001788 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001789 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001790 if (gsn->cb_conf)
1791 gsn->cb_conf(type, EOF, NULL, cbp);
1792 return EOF;
1793 }
jjako2c381332003-10-21 19:09:53 +00001794
Harald Weltebed35df2011-11-02 13:06:18 +01001795 /* Decode information elements */
1796 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1797 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001798 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1799 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001800 if (gsn->cb_conf)
1801 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001802 return EOF;
1803 }
jjako52c24142002-12-16 13:33:51 +00001804
Harald Weltebed35df2011-11-02 13:06:18 +01001805 /* Extract cause value (mandatory) */
1806 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1807 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001808 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1809 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001810 if (gsn->cb_conf)
1811 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001812 return EOF;
1813 }
jjako52c24142002-12-16 13:33:51 +00001814
Harald Weltebed35df2011-11-02 13:06:18 +01001815 /* Extract recovery (optional) */
1816 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001817 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001818 }
jjako52c24142002-12-16 13:33:51 +00001819
Harald Weltebed35df2011-11-02 13:06:18 +01001820 /* Extract protocol configuration options (optional) */
1821 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1822 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1823 }
jjako52c24142002-12-16 13:33:51 +00001824
Harald Weltebed35df2011-11-02 13:06:18 +01001825 /* Check all conditional information elements */
1826 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001827
Harald Weltebed35df2011-11-02 13:06:18 +01001828 if (version == 0) {
1829 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1830 &pdp->qos_neg0,
1831 sizeof(pdp->qos_neg0))) {
1832 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001833 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001834 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001835 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001836 if (gsn->cb_conf)
1837 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001838 return EOF;
1839 }
1840 }
jjako08d331d2003-10-13 20:33:30 +00001841
Harald Weltebed35df2011-11-02 13:06:18 +01001842 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1843 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001844 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001845 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001846 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001847 if (gsn->cb_conf)
1848 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001849 return EOF;
1850 }
jjako52c24142002-12-16 13:33:51 +00001851
Harald Weltebed35df2011-11-02 13:06:18 +01001852 if (version == 0) {
1853 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1854 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001855 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001856 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001857 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001858 if (gsn->cb_conf)
1859 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001860 return EOF;
1861 }
jjako52c24142002-12-16 13:33:51 +00001862
Harald Weltebed35df2011-11-02 13:06:18 +01001863 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1864 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001865 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001866 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001867 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001868 if (gsn->cb_conf)
1869 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001870 return EOF;
1871 }
1872 }
1873
1874 if (version == 1) {
1875 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1876 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001877 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001878 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001879 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001880 if (gsn->cb_conf)
1881 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001882 return EOF;
1883 }
1884
1885 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1886 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001887 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001888 pack, 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);
Harald Weltebed35df2011-11-02 13:06:18 +01001892 return EOF;
1893 }
Pau Espin Pedrol0b1d9db2021-04-21 19:45:23 +02001894 /* Register that we have received a valid teic from GGSN */
1895 pdp->teic_confirmed = 1;
Harald Weltebed35df2011-11-02 13:06:18 +01001896 }
1897
1898 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1899 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001900 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001901 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001902 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001903 if (gsn->cb_conf)
1904 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001905 }
1906
1907 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1908 &pdp->eua.v, sizeof(pdp->eua.v))) {
1909 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001910 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001911 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001912 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001913 if (gsn->cb_conf)
1914 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001915 return EOF;
1916 }
1917
1918 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1919 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1920 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001921 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001922 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001923 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001924 if (gsn->cb_conf)
1925 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001926 return EOF;
1927 }
1928
1929 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1930 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1931 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001932 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001933 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001934 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001935 if (gsn->cb_conf)
1936 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001937 return EOF;
1938 }
1939
1940 if (version == 1) {
1941 if (gtpie_gettlv
1942 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1943 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1944 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001945 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001946 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001947 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001948 if (gsn->cb_conf)
1949 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001950 return EOF;
1951 }
1952 }
1953
1954 }
1955
1956 if (gsn->cb_conf)
1957 gsn->cb_conf(type, cause, pdp, cbp);
1958
1959 return 0;
jjako52c24142002-12-16 13:33:51 +00001960}
1961
jjako08d331d2003-10-13 20:33:30 +00001962/* API: Send Update PDP Context Request */
1963int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001964 struct in_addr *inetaddr)
1965{
1966 union gtp_packet packet;
1967 unsigned int length =
1968 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001969
Harald Weltebed35df2011-11-02 13:06:18 +01001970 if (pdp->version == 0)
1971 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1972 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001973
Harald Weltebed35df2011-11-02 13:06:18 +01001974 /* Include IMSI if updating with unknown teic_gn */
1975 if ((pdp->version == 1) && (!pdp->teic_gn))
1976 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1977 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1978
1979 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1980 gsn->restart_counter);
1981
1982 if (pdp->version == 0) {
1983 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1984 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1985 }
1986
1987 if (pdp->version == 1) {
1988 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1989 pdp->teid_own);
1990
1991 if (!pdp->teic_confirmed)
1992 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1993 pdp->teic_own);
1994 }
1995
1996 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1997
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001998 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001999 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
2000 pdp->traceref);
2001 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
2002 pdp->tracetype); */
2003
2004 /* TODO if ggsn update message
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002005 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01002006 pdp->eua.l, pdp->eua.v);
2007 */
2008
2009 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2010 pdp->gsnlc.l, pdp->gsnlc.v);
2011 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2012 pdp->gsnlu.l, pdp->gsnlu.v);
2013
2014 if (pdp->version == 1)
2015 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2016 pdp->qos_req.l, pdp->qos_req.v);
2017
2018 if ((pdp->version == 1) && pdp->tft.l)
2019 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
2020 pdp->tft.l, pdp->tft.v);
2021
2022 if ((pdp->version == 1) && pdp->triggerid.l)
2023 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
2024 pdp->triggerid.l, pdp->triggerid.v);
2025
2026 if ((pdp->version == 1) && pdp->omcid.l)
2027 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
2028 pdp->omcid.l, pdp->omcid.v);
2029
Daniel Willmann134a7752016-02-03 18:53:29 +01002030 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002031
2032 return 0;
jjako52c24142002-12-16 13:33:51 +00002033}
2034
jjako08d331d2003-10-13 20:33:30 +00002035/* Send Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002036static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002037 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00002038 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01002039 struct pdp_t *pdp, uint8_t cause)
2040{
jjako08d331d2003-10-13 20:33:30 +00002041
Harald Weltebed35df2011-11-02 13:06:18 +01002042 union gtp_packet packet;
2043 unsigned int length =
2044 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00002045
Harald Weltebed35df2011-11-02 13:06:18 +01002046 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00002047
Harald Weltebed35df2011-11-02 13:06:18 +01002048 if (cause == GTPCAUSE_ACC_REQ) {
2049
2050 if (version == 0)
2051 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
2052 sizeof(pdp->qos_neg0), pdp->qos_neg0);
2053
2054 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
2055 gsn->restart_counter);
2056
2057 if (version == 0) {
2058 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
2059 pdp->fllu);
2060 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
2061 pdp->fllc);
2062 }
2063
2064 if (version == 1) {
2065 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2066 pdp->teid_own);
2067
2068 if (!pdp->teic_confirmed)
2069 gtpie_tv4(&packet, &length, GTP_MAX,
2070 GTPIE_TEI_C, pdp->teic_own);
2071 }
2072
2073 /* TODO we use teid_own as charging ID address */
2074 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
2075 pdp->teid_own);
2076
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002077 /* If ggsn
2078 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01002079 pdp->eua.l, pdp->eua.v); */
2080
2081 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2082 pdp->gsnlc.l, pdp->gsnlc.v);
2083 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2084 pdp->gsnlu.l, pdp->gsnlu.v);
2085
2086 if (version == 1)
2087 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2088 pdp->qos_neg.l, pdp->qos_neg.v);
2089
2090 /* TODO: Charging gateway address */
2091 }
2092
2093 return gtp_resp(version, gsn, pdp, &packet, length, peer,
2094 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00002095}
2096
jjako52c24142002-12-16 13:33:51 +00002097/* Handle Update PDP Context Request */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002098static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002099 struct sockaddr_in *peer, int fd,
2100 void *pack, unsigned len)
2101{
2102 struct pdp_t *pdp;
2103 struct pdp_t pdp_backup;
2104 union gtpie_member *ie[GTPIE_SIZE];
2105 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002106
Harald Weltebed35df2011-11-02 13:06:18 +01002107 uint16_t seq = get_seq(pack);
2108 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002109
Harald Weltebed35df2011-11-02 13:06:18 +01002110 uint64_t imsi;
2111 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002112
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002113 /* Is this a duplicate ? */
2114 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002115 return 0; /* We allready send of response once */
2116 }
jjako08d331d2003-10-13 20:33:30 +00002117
Harald Weltebed35df2011-11-02 13:06:18 +01002118 /* Decode information elements */
2119 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2120 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002121 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2122 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002123 if (0 == version)
2124 return EOF;
2125 else
2126 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2127 len, NULL,
2128 GTPCAUSE_INVALID_MESSAGE);
2129 }
jjako08d331d2003-10-13 20:33:30 +00002130
Harald Weltebed35df2011-11-02 13:06:18 +01002131 /* Finding PDP: */
2132 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2133 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2134 /* we have to use the tunnel endpoint identifier */
2135 if (version == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002136 /* Find the context in question */
Vadim Yanitskiy00a61712019-08-30 21:00:22 +02002137 if (gtp_pdp_tidget(gsn, &pdp, get_tid(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002138 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002139 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2140 "Unknown PDP context: TID=0x%" PRIx64 "\n",
2141 get_tid(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002142 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2143 len, NULL,
2144 GTPCAUSE_NON_EXIST);
2145 }
Vadim Yanitskiy00a61712019-08-30 21:00:22 +02002146
2147 /* Update IMSI and NSAPI */
2148 pdp_set_imsi_nsapi(pdp, get_tid(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002149 } else if (version == 1) {
2150 /* NSAPI (mandatory) */
2151 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2152 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002153 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2154 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002155 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2156 len, NULL,
2157 GTPCAUSE_MAN_IE_MISSING);
2158 }
jjako08d331d2003-10-13 20:33:30 +00002159
Harald Weltebed35df2011-11-02 13:06:18 +01002160 /* IMSI (conditional) */
2161 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2162 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002163 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002164 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002165 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2166 "Unknown PDP context: TEI=0x%" PRIx32 "\n",
2167 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002168 return gtp_update_pdp_resp(gsn, version, peer,
2169 fd, pack, len, NULL,
2170 GTPCAUSE_NON_EXIST);
2171 }
2172 } else {
2173 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002174 if (gtp_pdp_getimsi(gsn, &pdp, imsi, nsapi)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002175 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002176 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2177 "Unknown PDP context: IMSI=0x%" PRIx64
2178 " NSAPI=%" PRIu8 "\n", imsi, nsapi);
Harald Weltebed35df2011-11-02 13:06:18 +01002179 return gtp_update_pdp_resp(gsn, version, peer,
2180 fd, pack, len, NULL,
2181 GTPCAUSE_NON_EXIST);
2182 }
2183 }
2184 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002185 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002186 return EOF;
2187 }
jjako08d331d2003-10-13 20:33:30 +00002188
Harald Weltebed35df2011-11-02 13:06:18 +01002189 /* Make a backup copy in case anything is wrong */
2190 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002191
Harald Weltebed35df2011-11-02 13:06:18 +01002192 if (version == 0) {
2193 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2194 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2195 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002196 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2197 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002198 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2199 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2200 len, pdp,
2201 GTPCAUSE_MAN_IE_MISSING);
2202 }
2203 }
jjako52c24142002-12-16 13:33:51 +00002204
Harald Weltebed35df2011-11-02 13:06:18 +01002205 /* Recovery (optional) */
2206 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002207 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002208 }
jjako08d331d2003-10-13 20:33:30 +00002209
Harald Weltebed35df2011-11-02 13:06:18 +01002210 if (version == 0) {
2211 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2212 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002213 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2214 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002215 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2216 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2217 len, pdp,
2218 GTPCAUSE_MAN_IE_MISSING);
2219 }
jjako52c24142002-12-16 13:33:51 +00002220
Harald Weltebed35df2011-11-02 13:06:18 +01002221 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2222 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002223 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2224 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002225 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2226 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2227 len, pdp,
2228 GTPCAUSE_MAN_IE_MISSING);
2229 }
2230 }
jjako52c24142002-12-16 13:33:51 +00002231
Harald Weltebed35df2011-11-02 13:06:18 +01002232 if (version == 1) {
2233 /* TEID (mandatory) */
2234 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2235 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002236 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2237 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002238 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2239 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2240 len, pdp,
2241 GTPCAUSE_MAN_IE_MISSING);
2242 }
jjako52c24142002-12-16 13:33:51 +00002243
Harald Weltebed35df2011-11-02 13:06:18 +01002244 /* TEIC (conditional) */
2245 /* If TEIC is not included it means that we have allready received it */
2246 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2247 /* all updated contexts, or only for one of the linked contexts */
2248 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2249
2250 /* NSAPI (mandatory) */
2251 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2252 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002253 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2254 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002255 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2256 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2257 len, pdp,
2258 GTPCAUSE_MAN_IE_MISSING);
2259 }
2260 }
2261
2262 /* Trace reference (optional) */
2263 /* Trace type (optional) */
2264
2265 /* End User Address (conditional) TODO: GGSN Initiated
2266 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2267 &pdp->eua.v, sizeof(pdp->eua.v))) {
2268 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002269 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002270 "Missing mandatory information field");
2271 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002272 return gtp_update_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01002273 GTPCAUSE_MAN_IE_MISSING);
2274 } */
2275
2276 /* SGSN address for signalling (mandatory) */
2277 /* It is weird that this is mandatory when TEIC is conditional */
2278 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2279 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2280 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002281 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2282 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002283 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2284 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2285 pdp, GTPCAUSE_MAN_IE_MISSING);
2286 }
2287
2288 /* SGSN address for user traffic (mandatory) */
2289 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2290 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2291 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002292 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2293 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002294 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2295 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2296 pdp, GTPCAUSE_MAN_IE_MISSING);
2297 }
2298
2299 if (version == 1) {
2300 /* QoS (mandatory) */
2301 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2302 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2303 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002304 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2305 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002306 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2307 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2308 len, pdp,
2309 GTPCAUSE_MAN_IE_MISSING);
2310 }
2311
2312 /* TFT (conditional) */
2313 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2314 &pdp->tft.v, sizeof(pdp->tft.v))) {
2315 }
2316
2317 /* OMC identity */
2318 }
2319
2320 /* Confirm to peer that things were "successful" */
2321 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2322 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002323}
2324
jjako52c24142002-12-16 13:33:51 +00002325/* Handle Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002326static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002327 struct sockaddr_in *peer, void *pack, unsigned len)
2328{
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002329 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002330 union gtpie_member *ie[GTPIE_SIZE];
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002331 uint8_t cause = EOF;
2332 uint8_t recovery;
2333 int rc = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01002334 void *cbp = NULL;
2335 uint8_t type = 0;
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002336 bool trigger_recovery = false;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002337 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002338
Harald Weltebed35df2011-11-02 13:06:18 +01002339 /* Remove packet from queue */
2340 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2341 return EOF;
jjako52c24142002-12-16 13:33:51 +00002342
Harald Weltebed35df2011-11-02 13:06:18 +01002343 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002344 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002345 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002346 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2347 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002348 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002349 }
jjako52c24142002-12-16 13:33:51 +00002350
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002351 /* Extract recovery (optional) */
2352 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery))
2353 trigger_recovery = true;
2354
Harald Weltebed35df2011-11-02 13:06:18 +01002355 /* Extract cause value (mandatory) */
2356 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002357 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002358 }
jjako52c24142002-12-16 13:33:51 +00002359
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002360 /* 3GPP TS 29.060 sec 8.2: "Receiving node shall send back to the source
2361 * of the message, a response with the appropriate cause value (either
2362 * "Non-existent" or "Context not found"). The Tunnel Endpoint
2363 * Identifier used in the response message shall be set to all zeroes."
2364 * Hence, TEID=0 in this scenario, it makes no sense to infer PDP ctx
2365 * from it. User is responsible to infer it from cbp */
2366 if (cause != GTPCAUSE_NON_EXIST && cause != GTPCAUSE_CONTEXT_NOT_FOUND) {
2367 /* Find the context in question */
2368 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
2369 gsn->err_unknownpdp++;
2370 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002371 "Unknown PDP context: TEI=0x%" PRIx32 "\n", get_tei(pack));
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002372 goto err_out;
2373 }
Harald Weltebed35df2011-11-02 13:06:18 +01002374 }
2375
2376 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002377 /* TODO: This does not handle GGSN-initiated update responses */
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002378 if (cause == GTPCAUSE_ACC_REQ) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002379 if (version == 0) {
2380 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2381 &pdp->qos_neg0,
2382 sizeof(pdp->qos_neg0))) {
2383 goto err_missing;
2384 }
2385
2386 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2387 goto err_missing;
2388 }
2389
2390 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2391 goto err_missing;
2392 }
Harald Weltebed35df2011-11-02 13:06:18 +01002393 }
2394
Daniel Willmannd9975522016-02-04 15:38:12 +01002395 if (version == 1) {
2396 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2397 goto err_missing;
2398 }
Harald Weltebed35df2011-11-02 13:06:18 +01002399
Daniel Willmannd9975522016-02-04 15:38:12 +01002400 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2401 goto err_missing;
2402 }
Pau Espin Pedrol0b1d9db2021-04-21 19:45:23 +02002403 /* Register that we have received a valid teic from GGSN */
2404 pdp->teic_confirmed = 1;
Daniel Willmannd9975522016-02-04 15:38:12 +01002405 }
2406
2407 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2408 goto err_missing;
2409 }
2410
2411 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2412 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2413 goto err_missing;
2414 }
2415
2416 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2417 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2418 goto err_missing;
2419 }
2420
2421 if (version == 1) {
2422 if (gtpie_gettlv
2423 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2424 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2425 goto err_missing;
2426 }
2427 }
Harald Weltebed35df2011-11-02 13:06:18 +01002428 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002429
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002430generic_ret:
2431 if (trigger_recovery)
2432 emit_cb_recovery(gsn, peer, pdp, recovery);
Daniel Willmannd9975522016-02-04 15:38:12 +01002433 if (gsn->cb_conf)
2434 gsn->cb_conf(type, cause, pdp, cbp);
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002435 return rc; /* Succes */
Daniel Willmannd9975522016-02-04 15:38:12 +01002436
2437err_missing:
2438 gsn->missing++;
2439 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2440 "Missing information field\n");
2441err_out:
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002442 rc = EOF;
2443 goto generic_ret;
jjako52c24142002-12-16 13:33:51 +00002444}
2445
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002446/* API: Deprecated. Send Delete PDP Context Request And free pdp ctx. */
jjako2c381332003-10-21 19:09:53 +00002447int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002448 int teardown)
2449{
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002450 struct pdp_t *linked_pdp;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002451
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002452 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002453 LOGP(DLGTP, LOGL_ERROR,
2454 "Unknown linked PDP context: %u\n", pdp->teic_own);
2455 return EOF;
2456 }
2457
2458 if (gtp_delete_context_req2(gsn, pdp, cbp, teardown) == EOF)
2459 return EOF;
2460
2461 if (teardown) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002462 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002463 } else {
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002464 /* If we end up here (no teardown) it means we still
2465 have at least another pdp context active for this
2466 PDN connection (since last DeleteReq should come
2467 with teardown enabled). If the ctx to delete is a
2468 secondary ctx, simply free it. If it's the primary
2469 ctx, mark it as nodata but don't free it since we
2470 need it to hold data linked together and we'll
2471 require it later to tear down the entire tree. Still,
2472 we announce its deletion through cb_delete_context
2473 because we don't want user to release its related
2474 data and not use it anymore.
2475 */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002476 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002477 if (gsn->cb_delete_context)
2478 gsn->cb_delete_context(pdp);
2479 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2480 pdp->nodata = 1;
2481 } else {
2482 gtp_freepdp(gsn, pdp);
2483 }
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002484 }
2485
2486 return 0;
2487}
2488
Oliver Smith1cde2c12019-05-13 11:35:03 +02002489/* API: Send Delete PDP Context Request. PDP CTX shall be free'd by user at any
Pau Espin Pedrol4e605b32019-08-29 13:54:28 +02002490 point in time later than this function through a call to pdp_freepdp(pdp) (or
2491 through gtp_freepdp() if willing to receive cb_delete_context() callback),
2492 but it must be freed no later than during cb_conf(GTP_DELETE_PDP_REQ, pdp) */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002493int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2494 int teardown)
2495{
Harald Weltebed35df2011-11-02 13:06:18 +01002496 union gtp_packet packet;
2497 unsigned int length =
2498 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2499 struct in_addr addr;
2500 struct pdp_t *linked_pdp;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002501 int count;
jjako2c381332003-10-21 19:09:53 +00002502
Harald Weltebed35df2011-11-02 13:06:18 +01002503 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2504 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002505 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002506 return EOF;
jjako2c381332003-10-21 19:09:53 +00002507 }
jjako2c381332003-10-21 19:09:53 +00002508
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002509 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002510 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002511 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002512 return EOF;
2513 }
2514
2515 if (!teardown) {
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002516 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002517 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002518 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002519 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002520 return EOF;
2521 }
2522 }
2523
2524 if (pdp->version == 1) {
2525 if (teardown)
2526 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2527 0xff);
2528
2529 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2530 }
2531
2532 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2533
Harald Weltebed35df2011-11-02 13:06:18 +01002534 return 0;
jjako2c381332003-10-21 19:09:53 +00002535}
jjako08d331d2003-10-13 20:33:30 +00002536
jjako52c24142002-12-16 13:33:51 +00002537/* Send Delete PDP Context Response */
2538int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002539 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002540 void *pack, unsigned len,
2541 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002542 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002543{
Harald Weltebed35df2011-11-02 13:06:18 +01002544 union gtp_packet packet;
Harald Weltebed35df2011-11-02 13:06:18 +01002545 unsigned int length =
2546 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00002547
Harald Weltebed35df2011-11-02 13:06:18 +01002548 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002549
Harald Weltebed35df2011-11-02 13:06:18 +01002550 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2551 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002552
Harald Weltebed35df2011-11-02 13:06:18 +01002553 if (cause == GTPCAUSE_ACC_REQ) {
2554 if ((teardown) || (version == 0)) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002555 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002556 } else {
2557 /* If we end up here (no teardown) it means we still
2558 have at least another pdp context active for this
2559 PDN connection (since last DeleteReq should come
2560 with teardown enabled). If the ctx to delete is a
2561 secondary ctx, simply free it. If it's the primary
2562 ctx, mark it as nodata but don't free it since we
2563 need it to hold data linked together and we'll
2564 require it later to tear down the entire tree. Still,
2565 we announce its deletion through cb_delete_context
2566 because we don't want user to release its related
2567 data and not use it anymore.
2568 */
Harald Weltebed35df2011-11-02 13:06:18 +01002569 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002570 if (gsn->cb_delete_context)
2571 gsn->cb_delete_context(pdp);
2572 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2573 pdp->nodata = 1;
2574 } else {
2575 gtp_freepdp(gsn, pdp);
2576 }
Harald Weltebed35df2011-11-02 13:06:18 +01002577 }
jjako2c381332003-10-21 19:09:53 +00002578 }
Harald Weltebed35df2011-11-02 13:06:18 +01002579 /* if (cause == GTPCAUSE_ACC_REQ) */
2580 return 0;
jjako52c24142002-12-16 13:33:51 +00002581}
2582
2583/* Handle Delete PDP Context Request */
2584int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002585 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002586 void *pack, unsigned len)
2587{
2588 struct pdp_t *pdp = NULL;
2589 struct pdp_t *linked_pdp = NULL;
2590 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002591
Harald Weltebed35df2011-11-02 13:06:18 +01002592 uint16_t seq = get_seq(pack);
2593 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002594
Harald Weltebed35df2011-11-02 13:06:18 +01002595 uint8_t nsapi;
2596 uint8_t teardown = 0;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002597 int count;
jjako52c24142002-12-16 13:33:51 +00002598
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002599 /* Is this a duplicate ? */
2600 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002601 return 0; /* We allready send off response once */
2602 }
jjako2c381332003-10-21 19:09:53 +00002603
Harald Weltebed35df2011-11-02 13:06:18 +01002604 /* Find the linked context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002605 if (gtp_pdp_getgtp1(gsn, &linked_pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002606 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002607 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002608 "Unknown PDP context: TEI=0x%" PRIx32 "\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002609 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2610 NULL, NULL, GTPCAUSE_NON_EXIST,
2611 teardown);
2612 }
jjako2c381332003-10-21 19:09:53 +00002613
Harald Weltebed35df2011-11-02 13:06:18 +01002614 /* If version 0 this is also the secondary context */
2615 if (version == 0)
2616 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002617
Harald Weltebed35df2011-11-02 13:06:18 +01002618 /* Decode information elements */
2619 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2620 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002621 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2622 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002623 if (0 == version)
2624 return EOF;
2625 else
2626 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2627 len, NULL, NULL,
2628 GTPCAUSE_INVALID_MESSAGE,
2629 teardown);
2630 }
2631
2632 if (version == 1) {
2633 /* NSAPI (mandatory) */
2634 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2635 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002636 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002637 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002638 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2639 len, NULL, NULL,
2640 GTPCAUSE_MAN_IE_MISSING,
2641 teardown);
2642 }
2643
2644 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002645 if (gtp_pdp_getgtp1(gsn, &pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
Harald Weltebed35df2011-11-02 13:06:18 +01002646 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002647 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2648 "Unknown PDP context: Secondary TEI=0x%" PRIx32 "\n",
2649 linked_pdp->secondary_tei[nsapi & 0x0f]);
Harald Weltebed35df2011-11-02 13:06:18 +01002650 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2651 len, NULL, NULL,
2652 GTPCAUSE_NON_EXIST,
2653 teardown);
2654 }
2655
2656 /* Teardown (conditional) */
2657 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2658
2659 if (!teardown) {
Pau Espin Pedrol742a6b52019-05-30 13:36:10 +02002660 /* TS 29.060 section 7.3.5: If a GSN receives a Delete PDP context
2661 * without a Teardown Indicator or with a Teardown Indicator with
2662 * value set to "0" and only that PDP context is active for a PDN
2663 * connection, then the GSN shall ignore the message. (Note:
2664 * This is symptom of a race condition. The reliable delivery of
2665 * signalling messages will eventually lead to a consistent
2666 * situation, allowing the teardown of the PDP context.)
2667 */
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002668 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002669 if (count <= 1) {
Pau Espin Pedrold1bd6fc2018-07-13 19:11:45 +02002670 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2671 "Ignoring CTX DEL without teardown and count=%d\n",
2672 count);
Harald Weltebed35df2011-11-02 13:06:18 +01002673 return 0; /* 29.060 7.3.5 Ignore message */
2674 }
2675 }
2676 }
2677
2678 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2679 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002680}
2681
jjako52c24142002-12-16 13:33:51 +00002682/* Handle Delete PDP Context Response */
2683int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002684 struct sockaddr_in *peer, void *pack, unsigned len)
2685{
2686 union gtpie_member *ie[GTPIE_SIZE];
2687 uint8_t cause;
2688 void *cbp = NULL;
2689 uint8_t type = 0;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002690 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002691 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002692
Harald Weltebed35df2011-11-02 13:06:18 +01002693 /* Remove packet from queue */
2694 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2695 return EOF;
jjako52c24142002-12-16 13:33:51 +00002696
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002697 /* Find the context in question. It may not be available if gtp_delete_context_req
2698 * was used and as a result the PDP ctx was already freed */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002699 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002700 gsn->err_unknownpdp++;
2701 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002702 "Unknown PDP context: TEI=0x%" PRIx32 " (expected if "
2703 "gtp_delete_context_req is used or pdp ctx was freed "
2704 "manually before response)\n", get_tei(pack));
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002705 if (gsn->cb_conf)
2706 gsn->cb_conf(type, EOF, NULL, cbp);
2707 return EOF;
2708 }
2709
Harald Weltebed35df2011-11-02 13:06:18 +01002710 /* Decode information elements */
2711 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2712 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002713 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2714 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002715 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002716 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002717 return EOF;
2718 }
2719
2720 /* Extract cause value (mandatory) */
2721 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2722 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002723 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2724 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002725 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002726 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002727 return EOF;
2728 }
2729
2730 /* Check the cause value (again) */
2731 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2732 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002733 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2734 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002735 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002736 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002737 return EOF;
2738 }
2739
2740 /* Callback function to notify application */
2741 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002742 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002743
2744 return 0;
jjako52c24142002-12-16 13:33:51 +00002745}
2746
Harald Welte54d082e2017-08-12 22:43:21 +02002747/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002748static int gtp_error_ind_resp(struct gsn_t *gsn, uint8_t version,
jjako08d331d2003-10-13 20:33:30 +00002749 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002750 void *pack, unsigned len)
2751{
Harald Weltebed35df2011-11-02 13:06:18 +01002752 union gtp_packet packet;
2753 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2754
Harald Welte54d082e2017-08-12 22:43:21 +02002755 if (version == 1) {
2756 /* Mandatory 7.7.13 TEI Data I */
2757 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2758 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2759
2760 /* Mandatory 7.7.32 GSN Address */
2761 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2762 sizeof(gsn->gsnu), &gsn->gsnu);
2763 }
2764
Harald Weltebed35df2011-11-02 13:06:18 +01002765 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2766 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002767}
2768
2769/* Handle Error Indication */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002770static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002771 struct sockaddr_in *peer, void *pack, unsigned len)
2772{
Harald Welte37d5b152017-08-12 23:58:29 +02002773 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002774 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002775
Harald Weltebed35df2011-11-02 13:06:18 +01002776 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002777 if (version == 0) {
Vadim Yanitskiy68c5a742019-08-30 21:04:19 +02002778 if (gtp_pdp_tidget(gsn, &pdp, get_tid(pack))) {
Harald Welte37d5b152017-08-12 23:58:29 +02002779 gsn->err_unknownpdp++;
2780 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002781 "Unknown PDP context: TID=0x%" PRIx64 "\n",
2782 get_tid(pack));
Harald Welte37d5b152017-08-12 23:58:29 +02002783 return EOF;
2784 }
2785 } else if (version == 1) {
2786 /* we have to look-up based on the *peer* TEID */
2787 int hlen = get_hlen(pack);
2788 uint32_t teid_gn;
2789
2790 /* Decode information elements */
2791 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2792 gsn->invalid++;
2793 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2794 "Invalid message format\n");
2795 return EOF;
2796 }
2797
2798 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2799 gsn->missing++;
2800 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2801 "Missing mandatory information field\n");
2802 return EOF;
2803 }
2804
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002805 if (gtp_pdp_getgtp1_peer_d(gsn, &pdp, peer, teid_gn)) {
Harald Welte37d5b152017-08-12 23:58:29 +02002806 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002807 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2808 "Unknown PDP context: Peer TEID=0x%" PRIx32 "\n",
2809 teid_gn);
Harald Welte37d5b152017-08-12 23:58:29 +02002810 return EOF;
2811 }
Vadim Yanitskiybdf2cf92019-08-30 21:23:11 +02002812 } else {
2813 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
2814 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002815 }
jjako52c24142002-12-16 13:33:51 +00002816
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002817 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2818 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002819
Harald Weltebd228242017-11-06 03:16:49 +09002820 /* This is obvious from above code, given the semantics of the
2821 * functions above, but Coverity doesn't figure this out, so
2822 * let's make it clear. It's good style anyway in case above
2823 * code should ever change. */
2824 OSMO_ASSERT(pdp);
2825
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002826 gtp_freepdp(gsn, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002827 return 0;
jjako52c24142002-12-16 13:33:51 +00002828}
2829
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002830static int gtp_gpdu_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002831 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2832{
jjako08d331d2003-10-13 20:33:30 +00002833
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002834 int hlen;
jjako52c24142002-12-16 13:33:51 +00002835
Harald Weltebed35df2011-11-02 13:06:18 +01002836 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002837
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002838 switch (version) {
2839 case 0:
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002840 if (gtp_pdp_getgtp0(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002841 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002842 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2843 "Unknown PDP context: TEI=0x%" PRIx32 "\n",
2844 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002845 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2846 len);
2847 }
2848 hlen = GTP0_HEADER_SIZE;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002849 break;
2850 case 1:
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002851 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002852 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002853 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2854 "Unknown PDP context: TEI=0x%" PRIx32 "\n",
2855 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002856 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2857 len);
2858 }
jjako08d331d2003-10-13 20:33:30 +00002859
Harald Weltebed35df2011-11-02 13:06:18 +01002860 /* Is this a long or a short header ? */
2861 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2862 hlen = GTP1_HEADER_SIZE_LONG;
2863 else
2864 hlen = GTP1_HEADER_SIZE_SHORT;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002865 break;
2866 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002867 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002868 "Unknown version: %d\n", version);
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002869 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002870 }
jjako08d331d2003-10-13 20:33:30 +00002871
Harald Weltebed35df2011-11-02 13:06:18 +01002872 /* If the GPDU was not from the peer GSN tell him to delete context */
2873 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2874 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002875 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002876 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2877 }
jjako52c24142002-12-16 13:33:51 +00002878
Harald Weltebed35df2011-11-02 13:06:18 +01002879 /* Callback function */
2880 if (gsn->cb_data_ind != 0)
2881 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2882
2883 return 0;
jjako52c24142002-12-16 13:33:51 +00002884}
2885
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002886/* Receives GTP packet and sends off for further processing
jjako52c24142002-12-16 13:33:51 +00002887 * Function will check the validity of the header. If the header
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002888 * is not valid the packet is either dropped or a version not
2889 * supported is returned to the peer.
jjako52c24142002-12-16 13:33:51 +00002890 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002891int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002892{
Harald Weltebed35df2011-11-02 13:06:18 +01002893 unsigned char buffer[PACKET_MAX];
2894 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002895 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002896 int status;
2897 struct gtp0_header *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002898 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002899 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002900
Harald Weltebed35df2011-11-02 13:06:18 +01002901 /* TODO: Need strategy of userspace buffering and blocking */
2902 /* Currently read is non-blocking and send is blocking. */
2903 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002904
Harald Weltebed35df2011-11-02 13:06:18 +01002905 while (1) { /* Loop until no more to read */
2906 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002907 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002908 return -1;
2909 }
2910 peerlen = sizeof(peer);
2911 if ((status =
2912 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2913 (struct sockaddr *)&peer, &peerlen)) < 0) {
2914 if (errno == EAGAIN)
2915 return 0;
2916 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002917 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002918 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002919 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2920 status, status ? strerror(errno) : "No error");
2921 return -1;
2922 }
jjako1db1c812003-07-06 20:53:57 +00002923
Harald Weltebed35df2011-11-02 13:06:18 +01002924 /* Need at least 1 byte in order to check version */
2925 if (status < (1)) {
2926 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002927 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2928 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002929 continue;
2930 }
jjako08d331d2003-10-13 20:33:30 +00002931
Harald Weltebed35df2011-11-02 13:06:18 +01002932 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002933
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002934 version = GTPHDR_F_GET_VER(pheader->flags);
2935
Harald Weltebed35df2011-11-02 13:06:18 +01002936 /* Version should be gtp0 (or earlier) */
2937 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2938 /* GTP 0 messages. If other version message is received we reply that we */
2939 /* only support version 0, implying that this is the only version */
2940 /* supported on this port */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002941 if (version > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002942 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01002943 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2944 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002945 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2946 continue;
2947 }
2948
2949 /* Check length of gtp0 packet */
2950 if (status < GTP0_HEADER_SIZE) {
2951 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002952 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2953 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002954 continue; /* Silently discard 29.60: 11.1.2 */
2955 }
2956
2957 /* Check packet length field versus length of packet */
2958 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2959 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002960 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002961 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002962 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002963 continue; /* Silently discard */
2964 }
2965
2966 if ((gsn->mode == GTP_MODE_GGSN) &&
2967 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002968 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002969 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002970 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002971 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002972 "Unexpected GTPv0 Signalling Message '%s'\n",
2973 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002974 continue; /* Silently discard 29.60: 11.1.4 */
2975 }
2976
2977 if ((gsn->mode == GTP_MODE_SGSN) &&
2978 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002979 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002980 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002981 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002982 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002983 "Unexpected GTPv0 Signalling Message '%s'\n",
2984 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002985 continue; /* Silently discard 29.60: 11.1.4 */
2986 }
2987
2988 switch (pheader->type) {
2989 case GTP_ECHO_REQ:
2990 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2991 break;
2992 case GTP_ECHO_RSP:
2993 gtp_echo_conf(gsn, version, &peer, buffer, status);
2994 break;
2995 case GTP_NOT_SUPPORTED:
2996 gtp_unsup_ind(gsn, &peer, buffer, status);
2997 break;
2998 case GTP_CREATE_PDP_REQ:
2999 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3000 status);
3001 break;
3002 case GTP_CREATE_PDP_RSP:
3003 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3004 status);
3005 break;
3006 case GTP_UPDATE_PDP_REQ:
3007 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3008 status);
3009 break;
3010 case GTP_UPDATE_PDP_RSP:
3011 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3012 status);
3013 break;
3014 case GTP_DELETE_PDP_REQ:
3015 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3016 status);
3017 break;
3018 case GTP_DELETE_PDP_RSP:
3019 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3020 status);
3021 break;
3022 case GTP_ERROR:
3023 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3024 break;
3025 case GTP_GPDU:
3026 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3027 break;
3028 default:
3029 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003030 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3031 "Unknown GTP message type received: %d\n",
3032 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003033 break;
3034 }
3035 }
jjako08d331d2003-10-13 20:33:30 +00003036}
3037
jjako08d331d2003-10-13 20:33:30 +00003038int gtp_decaps1c(struct gsn_t *gsn)
3039{
Harald Weltebed35df2011-11-02 13:06:18 +01003040 unsigned char buffer[PACKET_MAX];
3041 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003042 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003043 int status;
3044 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003045 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003046 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00003047
Harald Weltebed35df2011-11-02 13:06:18 +01003048 /* TODO: Need strategy of userspace buffering and blocking */
3049 /* Currently read is non-blocking and send is blocking. */
3050 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003051
Harald Weltebed35df2011-11-02 13:06:18 +01003052 while (1) { /* Loop until no more to read */
3053 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003054 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003055 return -1;
3056 }
3057 peerlen = sizeof(peer);
3058 if ((status =
3059 recvfrom(fd, buffer, sizeof(buffer), 0,
3060 (struct sockaddr *)&peer, &peerlen)) < 0) {
3061 if (errno == EAGAIN)
3062 return 0;
3063 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003064 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003065 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003066 fd, (unsigned long)buffer, sizeof(buffer),
3067 status, status ? strerror(errno) : "No error");
3068 return -1;
3069 }
jjako08d331d2003-10-13 20:33:30 +00003070
Harald Weltebed35df2011-11-02 13:06:18 +01003071 /* Need at least 1 byte in order to check version */
3072 if (status < (1)) {
3073 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003074 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3075 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003076 continue;
3077 }
jjako08d331d2003-10-13 20:33:30 +00003078
Harald Weltebed35df2011-11-02 13:06:18 +01003079 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003080
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003081 version = GTPHDR_F_GET_VER(pheader->flags);
3082
Harald Weltebed35df2011-11-02 13:06:18 +01003083 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003084 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003085 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003086 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3087 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003088 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
3089 /*29.60: 11.1.1 */
3090 continue;
3091 }
jjako08d331d2003-10-13 20:33:30 +00003092
Harald Weltebed35df2011-11-02 13:06:18 +01003093 /* Version must be at least GTP 1 */
3094 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3095 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3096 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003097 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003098 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003099 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3100 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003101 continue;
3102 }
jjako08d331d2003-10-13 20:33:30 +00003103
Harald Weltebed35df2011-11-02 13:06:18 +01003104 /* Check packet flag field */
3105 if (((pheader->flags & 0xf7) != 0x32)) {
3106 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003107 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003108 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003109 continue;
3110 }
jjako2c381332003-10-21 19:09:53 +00003111
Harald Weltebed35df2011-11-02 13:06:18 +01003112 /* Check length of packet */
3113 if (status < GTP1_HEADER_SIZE_LONG) {
3114 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003115 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3116 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003117 continue; /* Silently discard 29.60: 11.1.2 */
3118 }
jjako2c381332003-10-21 19:09:53 +00003119
Harald Weltebed35df2011-11-02 13:06:18 +01003120 /* Check packet length field versus length of packet */
3121 if (status !=
3122 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3123 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003124 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003125 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003126 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003127 continue; /* Silently discard */
3128 }
jjako1db1c812003-07-06 20:53:57 +00003129
Harald Weltebed35df2011-11-02 13:06:18 +01003130 /* Check for extension headers */
3131 /* TODO: We really should cycle through the headers and determine */
3132 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003133 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003134 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003135 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3136 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003137 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3138 status);
jjako1db1c812003-07-06 20:53:57 +00003139
Harald Weltebed35df2011-11-02 13:06:18 +01003140 continue;
3141 }
3142
3143 if ((gsn->mode == GTP_MODE_GGSN) &&
3144 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003145 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003146 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003147 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003148 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003149 "Unexpected GTPv1 Signalling Message '%s'\n",
3150 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003151 continue; /* Silently discard 29.60: 11.1.4 */
3152 }
3153
3154 if ((gsn->mode == GTP_MODE_SGSN) &&
3155 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003156 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003157 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003158 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003159 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003160 "Unexpected GTPv1 Signalling Message '%s'\n",
3161 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003162 continue; /* Silently discard 29.60: 11.1.4 */
3163 }
3164
3165 switch (pheader->type) {
3166 case GTP_ECHO_REQ:
3167 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3168 break;
3169 case GTP_ECHO_RSP:
3170 gtp_echo_conf(gsn, version, &peer, buffer, status);
3171 break;
3172 case GTP_NOT_SUPPORTED:
3173 gtp_unsup_ind(gsn, &peer, buffer, status);
3174 break;
3175 case GTP_SUPP_EXT_HEADER:
3176 gtp_extheader_ind(gsn, &peer, buffer, status);
3177 break;
3178 case GTP_CREATE_PDP_REQ:
3179 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3180 status);
3181 break;
3182 case GTP_CREATE_PDP_RSP:
3183 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3184 status);
3185 break;
3186 case GTP_UPDATE_PDP_REQ:
3187 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3188 status);
3189 break;
3190 case GTP_UPDATE_PDP_RSP:
3191 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3192 status);
3193 break;
3194 case GTP_DELETE_PDP_REQ:
3195 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3196 status);
3197 break;
3198 case GTP_DELETE_PDP_RSP:
3199 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3200 status);
3201 break;
3202 case GTP_ERROR:
3203 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3204 break;
3205 default:
3206 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003207 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3208 "Unknown GTP message type received: %u\n",
3209 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003210 break;
3211 }
3212 }
jjako52c24142002-12-16 13:33:51 +00003213}
3214
jjako08d331d2003-10-13 20:33:30 +00003215int gtp_decaps1u(struct gsn_t *gsn)
3216{
Harald Weltebed35df2011-11-02 13:06:18 +01003217 unsigned char buffer[PACKET_MAX];
3218 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003219 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003220 int status;
3221 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003222 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003223 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003224
Harald Weltebed35df2011-11-02 13:06:18 +01003225 /* TODO: Need strategy of userspace buffering and blocking */
3226 /* Currently read is non-blocking and send is blocking. */
3227 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003228
Harald Weltebed35df2011-11-02 13:06:18 +01003229 while (1) { /* Loop until no more to read */
3230 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003231 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003232 return -1;
3233 }
3234 peerlen = sizeof(peer);
3235 if ((status =
3236 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3237 (struct sockaddr *)&peer, &peerlen)) < 0) {
3238 if (errno == EAGAIN)
3239 return 0;
3240 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003241 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003242 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003243 gsn->fd1u, (unsigned long)buffer,
3244 sizeof(buffer), status,
3245 status ? strerror(errno) : "No error");
3246 return -1;
3247 }
jjako08d331d2003-10-13 20:33:30 +00003248
Harald Weltebed35df2011-11-02 13:06:18 +01003249 /* Need at least 1 byte in order to check version */
3250 if (status < (1)) {
3251 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003252 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3253 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003254 continue;
3255 }
jjako08d331d2003-10-13 20:33:30 +00003256
Harald Weltebed35df2011-11-02 13:06:18 +01003257 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003258
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003259 version = GTPHDR_F_GET_VER(pheader->flags);
3260
Harald Weltebed35df2011-11-02 13:06:18 +01003261 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003262 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003263 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003264 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3265 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003266 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3267 continue;
3268 }
jjako08d331d2003-10-13 20:33:30 +00003269
Harald Weltebed35df2011-11-02 13:06:18 +01003270 /* Version must be at least GTP 1 */
3271 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3272 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3273 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003274 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003275 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003276 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3277 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003278 continue;
3279 }
jjako2c381332003-10-21 19:09:53 +00003280
Harald Weltebed35df2011-11-02 13:06:18 +01003281 /* Check packet flag field (allow both with and without sequence number) */
3282 if (((pheader->flags & 0xf5) != 0x30)) {
3283 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003284 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003285 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003286 continue;
3287 }
jjako2c381332003-10-21 19:09:53 +00003288
Harald Weltebed35df2011-11-02 13:06:18 +01003289 /* Check length of packet */
3290 if (status < GTP1_HEADER_SIZE_SHORT) {
3291 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003292 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3293 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003294 continue; /* Silently discard 29.60: 11.1.2 */
3295 }
3296
3297 /* Check packet length field versus length of packet */
3298 if (status !=
3299 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3300 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003301 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003302 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003303 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003304 continue; /* Silently discard */
3305 }
3306
3307 /* Check for extension headers */
3308 /* TODO: We really should cycle through the headers and determine */
3309 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003310 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003311 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003312 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3313 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003314 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3315 status);
3316
3317 continue;
3318 }
3319
3320 switch (pheader->type) {
3321 case GTP_ECHO_REQ:
3322 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3323 break;
3324 case GTP_ECHO_RSP:
3325 gtp_echo_conf(gsn, version, &peer, buffer, status);
3326 break;
3327 case GTP_SUPP_EXT_HEADER:
3328 gtp_extheader_ind(gsn, &peer, buffer, status);
3329 break;
3330 case GTP_ERROR:
3331 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3332 break;
3333 /* Supported header extensions */
3334 case GTP_GPDU:
3335 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3336 break;
3337 default:
3338 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003339 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3340 "Unknown GTP message type received: %u\n",
3341 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003342 break;
3343 }
3344 }
jjako08d331d2003-10-13 20:33:30 +00003345}
3346
Harald Weltebed35df2011-11-02 13:06:18 +01003347int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003348{
Harald Weltebed35df2011-11-02 13:06:18 +01003349 union gtp_packet packet;
3350 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003351 struct msghdr msgh;
3352 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003353 int fd;
jjako52c24142002-12-16 13:33:51 +00003354
Harald Welte471e3492017-09-24 16:12:39 +08003355 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003356 memset(&addr, 0, sizeof(addr));
3357 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003358#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003359 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003360#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003361 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003362
Harald Welte471e3492017-09-24 16:12:39 +08003363 /* prepare msghdr */
3364 memset(&msgh, 0, sizeof(msgh));
3365 msgh.msg_name = &addr;
3366 msgh.msg_namelen = sizeof(addr);
3367 msgh.msg_iov = iov;
3368 msgh.msg_iovlen = ARRAY_SIZE(iov);
3369
3370 /* prepare iovectors */
3371 iov[0].iov_base = &packet;
3372 /* iov[0].iov_len is not known here yet */
3373 iov[1].iov_base = pack;
3374 iov[1].iov_len = len;
3375
Harald Weltebed35df2011-11-02 13:06:18 +01003376 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003377
Harald Welte471e3492017-09-24 16:12:39 +08003378 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003379 addr.sin_port = htons(GTP0_PORT);
3380 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003381
Harald Weltebed35df2011-11-02 13:06:18 +01003382 get_default_gtp(0, GTP_GPDU, &packet);
3383 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003384 if (pdp->tx_gpdu_seq)
3385 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3386 else
3387 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003388 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003389 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003390 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003391
Harald Weltebed35df2011-11-02 13:06:18 +01003392 addr.sin_port = htons(GTP1U_PORT);
3393 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003394
Harald Weltebed35df2011-11-02 13:06:18 +01003395 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003396 if (pdp->tx_gpdu_seq) {
3397 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3398 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3399 GTP1_HEADER_SIZE_LONG);
3400 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3401 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3402 } else {
3403 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3404 packet.gtp1s.h.length = hton16(len);
3405 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3406 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3407 }
Harald Weltebed35df2011-11-02 13:06:18 +01003408 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003409 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003410 return EOF;
3411 }
3412
3413 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003414 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003415 return -1;
3416 }
3417
Harald Welte471e3492017-09-24 16:12:39 +08003418 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003419 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003420 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003421 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003422 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3423 strerror(errno));
3424 return EOF;
3425 }
3426 return 0;
jjako52c24142002-12-16 13:33:51 +00003427}
3428
jjako52c24142002-12-16 13:33:51 +00003429/* ***********************************************************
3430 * Conversion functions
3431 *************************************************************/
3432
jjako52c24142002-12-16 13:33:51 +00003433/* ***********************************************************
3434 * IP address conversion functions
3435 * There exist several types of address representations:
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01003436 * - eua: End User Address. (29.060, 7.7.27, message type 128)
jjako52c24142002-12-16 13:33:51 +00003437 * Used for signalling address to mobile station. Supports IPv4
3438 * IPv6 x.25 etc. etc.
3439 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3440 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3441 * - in_addr: IPv4 address struct.
3442 * - sockaddr_in: Socket API representation of IP address and
3443 * port number.
3444 *************************************************************/
3445
Harald Weltebed35df2011-11-02 13:06:18 +01003446int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3447{
Harald Weltecee75462017-09-24 17:45:05 +08003448 eua->v[0] = PDP_EUA_ORG_IETF;
3449 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003450 if (src) {
3451 eua->l = 6;
3452 memcpy(&eua->v[2], src, 4);
3453 } else {
3454 eua->l = 2;
3455 }
3456 return 0;
jjako52c24142002-12-16 13:33:51 +00003457}
3458
Harald Weltebed35df2011-11-02 13:06:18 +01003459int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3460{
Harald Weltecee75462017-09-24 17:45:05 +08003461 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 +01003462 return -1; /* Not IPv4 address */
3463 memcpy(dst, &eua->v[2], 4);
3464 return 0;
jjako52c24142002-12-16 13:33:51 +00003465}
3466
Harald Weltebed35df2011-11-02 13:06:18 +01003467int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3468{
3469 memset(dst, 0, sizeof(struct in_addr));
3470 if (gsna->l != 4)
3471 return EOF; /* Return if not IPv4 */
3472 memcpy(dst, gsna->v, gsna->l);
3473 return 0;
jjako52c24142002-12-16 13:33:51 +00003474}
3475
Harald Weltebed35df2011-11-02 13:06:18 +01003476int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3477{
3478 memset(gsna, 0, sizeof(struct ul16_t));
3479 gsna->l = 4;
3480 memcpy(gsna->v, src, gsna->l);
3481 return 0;
jjako52c24142002-12-16 13:33:51 +00003482}
Harald Welteb10ee082017-08-12 19:29:16 +02003483
3484/* TS 29.060 has yet again a different encoding for IMSIs than
3485 * what we have in other places, so we cannot use the gsm48
3486 * decoding functions. Also, libgtp uses an uint64_t in
3487 * _network byte order_ to contain BCD digits ?!? */
3488const char *imsi_gtp2str(const uint64_t *imsi)
3489{
Harald Weltea06120d2017-11-06 03:12:54 +09003490 static char buf[sizeof(*imsi)*2+1];
Harald Welteb10ee082017-08-12 19:29:16 +02003491 const uint8_t *imsi8 = (const uint8_t *) imsi;
3492 unsigned int i, j = 0;
3493
3494 for (i = 0; i < sizeof(*imsi); i++) {
3495 uint8_t nibble;
3496
3497 nibble = imsi8[i] & 0xf;
3498 if (nibble == 0xf)
3499 break;
3500 buf[j++] = osmo_bcd2char(nibble);
3501
3502 nibble = imsi8[i] >> 4;
3503 if (nibble == 0xf)
3504 break;
3505 buf[j++] = osmo_bcd2char(nibble);
3506 }
3507
3508 buf[j++] = '\0';
3509 return buf;
3510}
Keithcbc07bd2020-10-10 12:17:26 +02003511
Keithfb2a7292020-10-12 15:32:07 +02003512/* Generate the GTP IMSI IE according to 09.60 Section 7.9.2 */
3513uint64_t gtp_imsi_str2gtp(const char *str)
Keithcbc07bd2020-10-10 12:17:26 +02003514{
Keithfb2a7292020-10-12 15:32:07 +02003515 uint64_t imsi64 = 0;
3516 unsigned int n;
3517 unsigned int imsi_len = strlen(str);
Keithcbc07bd2020-10-10 12:17:26 +02003518
Keithfb2a7292020-10-12 15:32:07 +02003519 if (imsi_len > 16) {
3520 LOGP(DLGTP, LOGL_NOTICE, "IMSI length > 16 not supported!\n");
3521 return 0;
3522 }
3523
3524 for (n = 0; n < 16; n++) {
3525 uint64_t val;
3526 if (n < imsi_len)
3527 val = (str[n]-'0') & 0xf;
3528 else
3529 val = 0xf;
3530 imsi64 |= (val << (n*4));
3531 }
3532 return imsi64;
3533}