blob: 59fd35541930a7139904af3666e734a894a80610 [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
Pau Espin Pedrolf32c6a92021-05-03 17:58:55 +0200199int gtp_set_cb_ran_info_relay_ind(struct gsn_t *gsn,
200 int (*cb) (struct sockaddr_in * peer, union gtpie_member **ie))
201{
202 gsn->cb_ran_info_relay_ind = cb;
203 return 0;
204}
205
jjako08d331d2003-10-13 20:33:30 +0000206/* API: Initialise delete context callback */
207/* Called whenever a pdp context is deleted for any reason */
Harald Weltebed35df2011-11-02 13:06:18 +0100208int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
jjako52c24142002-12-16 13:33:51 +0000209{
Harald Weltebed35df2011-11-02 13:06:18 +0100210 gsn->cb_delete_context = cb;
211 return 0;
jjako52c24142002-12-16 13:33:51 +0000212}
213
jjako52c24142002-12-16 13:33:51 +0000214int gtp_set_cb_conf(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100215 int (*cb) (int type, int cause,
216 struct pdp_t * pdp, void *cbp))
217{
218 gsn->cb_conf = cb;
219 return 0;
jjako52c24142002-12-16 13:33:51 +0000220}
221
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200222static void emit_cb_recovery(struct gsn_t *gsn, struct sockaddr_in * peer,
223 struct pdp_t * pdp, uint8_t recovery)
224{
225 if (gsn->cb_recovery)
226 gsn->cb_recovery(peer, recovery);
227 if (gsn->cb_recovery2)
228 gsn->cb_recovery2(peer, pdp, recovery);
Pau Espin Pedrol5d8b2262019-08-22 15:00:00 +0200229 if (gsn->cb_recovery3)
230 gsn->cb_recovery3(gsn, peer, pdp, recovery);
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200231}
232
Harald Welte629e9862010-12-24 20:58:09 +0100233int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100234 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
235{
236 gsn->cb_recovery = cb;
237 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100238}
239
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200240/* cb_recovery()
241 * pdp may be NULL if Recovery IE was received from a message independent
242 * of any PDP ctx (such as Echo Response), or because pdp ctx is unknown to the
243 * local setup. In case pdp is known, caller may want to keep that pdp alive to
244 * handle subsequent msg cb as this specific pdp ctx is still valid according to
245 * specs.
246 */
247int gtp_set_cb_recovery2(struct gsn_t *gsn,
248 int (*cb_recovery2) (struct sockaddr_in * peer, struct pdp_t * pdp, uint8_t recovery))
249{
250 gsn->cb_recovery2 = cb_recovery2;
251 return 0;
252}
253
Pau Espin Pedrol5d8b2262019-08-22 15:00:00 +0200254/* cb_recovery()
255 * pdp may be NULL if Recovery IE was received from a message independent
256 * of any PDP ctx (such as Echo Response), or because pdp ctx is unknown to the
257 * local setup. In case pdp is known, caller may want to keep that pdp alive to
258 * handle subsequent msg cb as this specific pdp ctx is still valid according to
259 * specs.
260 */
261int gtp_set_cb_recovery3(struct gsn_t *gsn,
262 int (*cb_recovery3) (struct gsn_t *gsn, struct sockaddr_in *peer,
263 struct pdp_t *pdp, uint8_t recovery))
264{
265 gsn->cb_recovery3 = cb_recovery3;
266 return 0;
267}
268
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +0100269int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100270 int (*cb_data_ind) (struct pdp_t * pdp,
271 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000272{
Harald Weltebed35df2011-11-02 13:06:18 +0100273 gsn->cb_data_ind = cb_data_ind;
274 return 0;
jjako52c24142002-12-16 13:33:51 +0000275}
276
jjako08d331d2003-10-13 20:33:30 +0000277/**
278 * get_default_gtp()
279 * Generate a GPRS Tunneling Protocol signalling packet header, depending
280 * on GTP version and message type. pdp is used for teid/flow label.
281 * *packet must be allocated by the calling function, and be large enough
282 * to hold the packet header.
283 * returns the length of the header. 0 on error.
284 **/
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100285static unsigned int get_default_gtp(uint8_t version, uint8_t type, void *packet)
Harald Weltebed35df2011-11-02 13:06:18 +0100286{
287 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
288 struct gtp1_header_long *gtp1_default =
289 (struct gtp1_header_long *)packet;
290 switch (version) {
291 case 0:
292 /* Initialise "standard" GTP0 header */
293 memset(gtp0_default, 0, sizeof(struct gtp0_header));
294 gtp0_default->flags = 0x1e;
295 gtp0_default->type = hton8(type);
296 gtp0_default->spare1 = 0xff;
297 gtp0_default->spare2 = 0xff;
298 gtp0_default->spare3 = 0xff;
299 gtp0_default->number = 0xff;
300 return GTP0_HEADER_SIZE;
301 case 1:
302 /* Initialise "standard" GTP1 header */
303 /* 29.060: 8.2: S=1 and PN=0 */
304 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
305 /* and Supported Extension Headers Notification, the S field shall be */
306 /* set to 1 */
307 /* Currently extension headers are not supported */
308 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
Harald Weltefed598f2017-09-24 16:39:22 +0800309 /* No extension, enable sequence, no N-PDU */
310 gtp1_default->flags = GTPHDR_F_VER(1) | GTP1HDR_F_GTP1 | GTP1HDR_F_SEQ;
Harald Weltebed35df2011-11-02 13:06:18 +0100311 gtp1_default->type = hton8(type);
312 return GTP1_HEADER_SIZE_LONG;
313 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100314 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100315 "Unknown GTP packet version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +0100316 return 0;
317 }
jjako52c24142002-12-16 13:33:51 +0000318}
319
jjako08d331d2003-10-13 20:33:30 +0000320/**
321 * get_seq()
322 * Get sequence number of a packet.
323 * Returns 0 on error
324 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100325static uint16_t get_seq(void *pack)
326{
327 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800328 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000329
Harald Weltefed598f2017-09-24 16:39:22 +0800330 if (ver == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +0100331 return ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800332 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100333 return ntoh16(packet->gtp1l.h.seq);
334 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100335 return 0;
336 }
jjako08d331d2003-10-13 20:33:30 +0000337}
338
339/**
340 * get_tid()
341 * Get tunnel identifier of a packet.
342 * Returns 0 on error
343 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100344static uint64_t get_tid(void *pack)
345{
346 union gtp_packet *packet = (union gtp_packet *)pack;
347
Harald Weltefed598f2017-09-24 16:39:22 +0800348 if (GTPHDR_F_GET_VER(packet->flags) == 0) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100349 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100350 }
351 return 0;
jjako08d331d2003-10-13 20:33:30 +0000352}
353
354/**
355 * get_hlen()
356 * Get the header length of a packet.
357 * Returns 0 on error
358 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100359static uint16_t get_hlen(void *pack)
360{
361 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800362 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000363
Harald Weltefed598f2017-09-24 16:39:22 +0800364 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100365 return GTP0_HEADER_SIZE;
Harald Weltefed598f2017-09-24 16:39:22 +0800366 } else if (ver == 1 && (packet->flags & 0x07) == 0) { /* Short version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100367 return GTP1_HEADER_SIZE_SHORT;
Harald Weltefed598f2017-09-24 16:39:22 +0800368 } else if (ver == 1) { /* Version 1 with seq/n-pdu/ext */
369 return GTP1_HEADER_SIZE_LONG;
Harald Weltebed35df2011-11-02 13:06:18 +0100370 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100371 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100372 return 0;
373 }
jjako08d331d2003-10-13 20:33:30 +0000374}
375
376/**
377 * get_tei()
378 * Get the tunnel endpoint identifier (flow label) of a packet.
379 * Returns 0xffffffff on error.
380 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100381static uint32_t get_tei(void *pack)
382{
383 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800384 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000385
Harald Weltefed598f2017-09-24 16:39:22 +0800386 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100387 return ntoh16(packet->gtp0.h.flow);
Harald Weltefed598f2017-09-24 16:39:22 +0800388 } else if (ver == 1) { /* Version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100389 return ntoh32(packet->gtp1l.h.tei);
390 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100391 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100392 return 0xffffffff;
393 }
jjako08d331d2003-10-13 20:33:30 +0000394}
jjakoa7cd2492003-04-11 09:40:12 +0000395
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200396static int queue_timer_retrans(struct gsn_t *gsn)
397{
398 /* Retransmit any outstanding packets */
399 /* Remove from queue if maxretrans exceeded */
400 time_t now;
401 struct qmsg_t *qmsg;
402 now = time(NULL);
403 /*printf("Retrans: New beginning %d\n", (int) now); */
404
405 /* get first element in queue, as long as the timeout of that
406 * element has expired */
407 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
408 (qmsg->timeout <= now)) {
409 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
410 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
411 LOGP(DLGTP, LOGL_NOTICE, "Timeout of seq %" PRIu16 "\n",
412 qmsg->seq);
413 if (gsn->cb_conf)
414 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
415 queue_freemsg(gsn->queue_req, qmsg);
416 } else {
417 LOGP(DLGTP, LOGL_INFO, "Retransmit (%d) of seq %" PRIu16 "\n",
418 qmsg->retrans, qmsg->seq);
419 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
420 (struct sockaddr *)&qmsg->peer,
421 sizeof(struct sockaddr_in)) < 0) {
422 gsn->err_sendto++;
423 LOGP(DLGTP, LOGL_ERROR,
424 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
425 gsn->fd0, (unsigned long)&qmsg->p,
426 qmsg->l, strerror(errno));
427 }
428 queue_back(gsn->queue_req, qmsg);
429 qmsg->timeout = now + T3_REQUEST;
430 qmsg->retrans++;
431 }
432 }
433
434 /* Also clean up reply timeouts */
435 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
436 (qmsg->timeout < now)) {
437 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
438 queue_freemsg(gsn->queue_resp, qmsg);
439 }
440
441 return 0;
442}
443
444static int queue_timer_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
445{
446 time_t now, later, diff;
447 struct qmsg_t *qmsg;
448 timeout->tv_usec = 0;
449
450 if (queue_getfirst(gsn->queue_req, &qmsg)) {
451 timeout->tv_sec = 10;
452 } else {
453 now = time(NULL);
454 later = qmsg->timeout;
455 timeout->tv_sec = later - now;
456 if (timeout->tv_sec < 0)
457 timeout->tv_sec = 0; /* No negative allowed */
458 if (timeout->tv_sec > 10)
459 timeout->tv_sec = 10; /* Max sleep for 10 sec */
460 }
461
462 if (queue_getfirst(gsn->queue_resp, &qmsg)) {
463 /* already set by queue_req, do nothing */
464 } else { /* trigger faster if earlier timeout exists in queue_resp */
465 now = time(NULL);
466 later = qmsg->timeout;
467 diff = later - now;
468 if (diff < 0)
469 diff = 0;
470 if (diff < timeout->tv_sec)
471 timeout->tv_sec = diff;
472 }
473
474 return 0;
475}
476
477static void queue_timer_start(struct gsn_t *gsn)
478{
479 struct timeval next;
480
481 /* Retrieve next retransmission as timeval */
482 queue_timer_retranstimeout(gsn, &next);
483
484 /* re-schedule the timer */
485 osmo_timer_schedule(&gsn->queue_timer, next.tv_sec, next.tv_usec/1000);
486}
487
488/* timer callback for libgtp retransmission and ping */
489static void queue_timer_cb(void *data)
490{
491 struct gsn_t *gsn = data;
492
493 /* do all the retransmissions as needed */
494 queue_timer_retrans(gsn);
495
496 queue_timer_start(gsn);
497}
498
jjako52c24142002-12-16 13:33:51 +0000499/* ***********************************************************
500 * Reliable delivery of signalling messages
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100501 *
jjako52c24142002-12-16 13:33:51 +0000502 * Sequence numbers are used for both signalling messages and
503 * data messages.
504 *
505 * For data messages each tunnel maintains a sequence counter,
506 * which is incremented by one each time a new data message
507 * is sent. The sequence number starts at (0) zero at tunnel
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100508 * establishment, and wraps around at 65535 (29.060 9.3.1.1
jjako52c24142002-12-16 13:33:51 +0000509 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
510 * or can be used to check the validity of the message in the
511 * receiver, or for reordering af packets.
512 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100513 * For signalling messages the sequence number is used by
jjako52c24142002-12-16 13:33:51 +0000514 * signalling messages for which a response is defined. A response
515 * message should copy the sequence from the corresponding request
516 * message. The sequence number "unambiguously" identifies a request
517 * message within a given path, with a path being defined as a set of
518 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
519 * messages shall be responded to, and all response messages associated
520 * with a certain request shall always include the same information"
521 *
522 * We take this to mean that the GSN transmitting a request is free to
523 * choose the sequence number, as long as it is unique within a given path.
524 * It means that we are allowed to count backwards, or roll over at 17
525 * if we prefer that. It also means that we can use the same counter for
526 * all paths. This has the advantage that the transmitted request sequence
527 * numbers are unique within each GSN, and also we dont have to mess around
528 * with path setup and teardown.
529 *
530 * If a response message is lost, the request will be retransmitted, and
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100531 * the receiving GSN will receive a "duplicated" request. The standard
jjako52c24142002-12-16 13:33:51 +0000532 * requires the receiving GSN to send a response, with the same information
533 * as in the original response. For most messages this happens automatically:
534 *
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200535 * Echo: Automatically duplicates the original response
jjako52c24142002-12-16 13:33:51 +0000536 * Create pdp context: The SGSN may send create context request even if
537 * a context allready exist (imsi+nsapi?). This means that the reply will
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200538 automatically duplicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000539 * side effects in the application which is asked twice to validate
540 * the login.
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200541 * Update pdp context: Automatically duplicates the original response???
jjako52c24142002-12-16 13:33:51 +0000542 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
543 * a nonexist reply message.
544 *
545 * The correct solution will be to make a queue containing response messages.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100546 * This queue should be checked whenever a request is received. If the
jjako52c24142002-12-16 13:33:51 +0000547 * response is allready in the queue that response should be transmitted.
548 * It should be possible to find messages in this queue on the basis of
549 * the sequence number and peer GSN IP address (The sequense number is unique
550 * within each path). This need to be implemented by a hash table. Furthermore
551 * it should be possibly to delete messages based on a timeout. This can be
552 * achieved by means of a linked list. The timeout value need to be larger
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100553 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
jjako52c24142002-12-16 13:33:51 +0000554 * set in the peer GSN, so there is no way to know these parameters. On the
555 * other hand the timeout value need to be so small that we do not receive
556 * wraparound sequence numbere before the message is deleted. 60 seconds is
557 * probably not a bad choise.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100558 *
jjako52c24142002-12-16 13:33:51 +0000559 * This queue however is first really needed from gtp1.
560 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100561 * gtp_req:
jjako52c24142002-12-16 13:33:51 +0000562 * Send off a signalling message with appropiate sequence
563 * number. Store packet in queue.
564 * gtp_conf:
565 * Remove an incoming confirmation from the queue
566 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000567 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000568 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000569 * gtp_notification:
570 * Send off a notification message. This is neither a request nor
571 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000572 * gtp_retrans:
573 * Retransmit any outstanding packets which have exceeded
574 * a predefined timeout.
575 *************************************************************/
576
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100577static int gtp_req(struct gsn_t *gsn, uint8_t version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100578 union gtp_packet *packet, int len,
579 struct in_addr *inetaddr, void *cbp)
580{
Harald Weltefed598f2017-09-24 16:39:22 +0800581 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100582 struct sockaddr_in addr;
583 struct qmsg_t *qmsg;
584 int fd;
jjako08d331d2003-10-13 20:33:30 +0000585
Harald Weltebed35df2011-11-02 13:06:18 +0100586 memset(&addr, 0, sizeof(addr));
587 addr.sin_family = AF_INET;
588 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000589#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100590 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000591#endif
jjako52c24142002-12-16 13:33:51 +0000592
Harald Weltefed598f2017-09-24 16:39:22 +0800593 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100594 addr.sin_port = htons(GTP0_PORT);
595 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
596 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100597 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100598 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100599 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100600 }
Harald Weltebed35df2011-11-02 13:06:18 +0100601 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
602 || (packet->gtp0.h.type == GTP_ERROR)))
603 packet->gtp0.h.flow = hton16(pdp->flru);
604 else if (pdp)
605 packet->gtp0.h.flow = hton16(pdp->flrc);
606 fd = gsn->fd0;
Harald Weltefed598f2017-09-24 16:39:22 +0800607 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100608 addr.sin_port = htons(GTP1C_PORT);
609 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
610 packet->gtp1l.h.seq = hton16(gsn->seq_next);
611 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
612 (packet->gtp1l.h.type == GTP_ERROR)))
613 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
614 else if (pdp)
615 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
616 fd = gsn->fd1c;
617 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100618 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100619 return -1;
620 }
jjako52c24142002-12-16 13:33:51 +0000621
Harald Weltebed35df2011-11-02 13:06:18 +0100622 if (sendto(fd, packet, len, 0,
623 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
624 gsn->err_sendto++;
Max14b1b632017-08-21 20:14:59 +0200625 LOGP(DLGTP, LOGL_ERROR, "Sendto(fd=%d, msg=%lx, len=%d, dst=%s) failed: Error = %s\n", fd,
626 (unsigned long)&packet, len, inet_ntoa(addr.sin_addr), strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100627 return -1;
628 }
629
630 /* Use new queue structure */
631 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
632 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100633 LOGP(DLGTP, LOGL_ERROR,
634 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100635 } else {
636 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
637 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100638 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100639 qmsg->retrans = 0; /* No retransmissions so far */
640 qmsg->cbp = cbp;
641 qmsg->type = ntoh8(packet->gtp0.h.type);
642 qmsg->fd = fd;
Pau Espin Pedrol623c5b32019-08-16 13:20:09 +0200643 if (pdp) /* echo requests are not pdp-bound */
644 llist_add(&qmsg->entry, &pdp->qmsg_list_req);
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200645
646 /* Rearm timer: Retrans time for qmsg just queued may be required
647 before an existing one (for instance a gtp echo req) */
648 queue_timer_start(gsn);
Harald Weltebed35df2011-11-02 13:06:18 +0100649 }
650 gsn->seq_next++; /* Count up this time */
651 return 0;
jjako52c24142002-12-16 13:33:51 +0000652}
653
Alexander Couzense1412d92018-09-16 05:10:03 +0200654
655/**
656 * @brief clear the request and response queue. Useful for debugging to reset "some" state.
657 * @param gsn The GGSN instance
658 */
659void gtp_clear_queues(struct gsn_t *gsn)
660{
661 struct qmsg_t *qmsg;
662
663 while (!queue_getfirst(gsn->queue_req, &qmsg)) {
664 queue_freemsg(gsn->queue_req, qmsg);
665 }
666
667 while (!queue_getfirst(gsn->queue_resp, &qmsg)) {
668 queue_freemsg(gsn->queue_resp, qmsg);
669 }
670}
671
jjako52c24142002-12-16 13:33:51 +0000672/* gtp_conf
673 * Remove signalling packet from retransmission queue.
674 * return 0 on success, EOF if packet was not found */
675
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100676static int gtp_conf(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100677 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
678{
Harald Weltefed598f2017-09-24 16:39:22 +0800679 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100680 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000681
Harald Weltefed598f2017-09-24 16:39:22 +0800682 if (ver == 0)
Harald Weltebed35df2011-11-02 13:06:18 +0100683 seq = ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800684 else if (ver == 1 && (packet->gtp1l.h.flags & GTP1HDR_F_SEQ))
Harald Weltebed35df2011-11-02 13:06:18 +0100685 seq = ntoh16(packet->gtp1l.h.seq);
686 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100687 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
688 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100689 return EOF;
690 }
jjako08d331d2003-10-13 20:33:30 +0000691
Harald Weltebed35df2011-11-02 13:06:18 +0100692 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
693 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100694 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
695 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100696 return EOF;
697 }
jjako52c24142002-12-16 13:33:51 +0000698
Harald Weltebed35df2011-11-02 13:06:18 +0100699 return 0;
jjako52c24142002-12-16 13:33:51 +0000700}
701
Harald Weltebed35df2011-11-02 13:06:18 +0100702int gtp_retrans(struct gsn_t *gsn)
703{
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200704 /* dummy API, deprecated. */
Harald Weltebed35df2011-11-02 13:06:18 +0100705 return 0;
jjako52c24142002-12-16 13:33:51 +0000706}
707
Harald Weltebed35df2011-11-02 13:06:18 +0100708int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
709{
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200710 timeout->tv_sec = 24*60*60;
Pau Espin Pedrolceac0782019-05-27 17:39:45 +0200711 timeout->tv_usec = 0;
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200712 /* dummy API, deprecated. Return a huge timer to do nothing */
Harald Weltebed35df2011-11-02 13:06:18 +0100713 return 0;
jjako52c24142002-12-16 13:33:51 +0000714}
715
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100716static int gtp_resp(uint8_t version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000717 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100718 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
719{
Harald Weltefed598f2017-09-24 16:39:22 +0800720 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100721 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000722
Harald Weltefed598f2017-09-24 16:39:22 +0800723 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100724 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
725 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100726 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100727 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
728 (packet->gtp0.h.type == GTP_ERROR)))
729 packet->gtp0.h.flow = hton16(pdp->flru);
730 else if (pdp)
731 packet->gtp0.h.flow = hton16(pdp->flrc);
Harald Weltefed598f2017-09-24 16:39:22 +0800732 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100733 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
734 packet->gtp1l.h.seq = hton16(seq);
735 if (pdp && (fd == gsn->fd1u))
736 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
737 else if (pdp)
738 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
739 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100740 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100741 return -1;
742 }
jjako08d331d2003-10-13 20:33:30 +0000743
Harald Weltebed35df2011-11-02 13:06:18 +0100744 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100745 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100746 return -1;
747 }
jjako52c24142002-12-16 13:33:51 +0000748
Harald Weltebed35df2011-11-02 13:06:18 +0100749 if (sendto(fd, packet, len, 0,
750 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
751 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100752 LOGP(DLGTP, LOGL_ERROR,
753 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100754 (unsigned long)&packet, len, strerror(errno));
755 return -1;
756 }
757
758 /* Use new queue structure */
759 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
760 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100761 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100762 } else {
763 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
764 qmsg->l = len;
765 qmsg->timeout = time(NULL) + 60; /* When to timeout */
766 qmsg->retrans = 0; /* No retransmissions so far */
767 qmsg->cbp = NULL;
768 qmsg->type = 0;
769 qmsg->fd = fd;
Pau Espin Pedrol623c5b32019-08-16 13:20:09 +0200770 /* No need to add to pdp list here, because even on pdp ctx free
771 we want to leave messages in queue_resp until timeout to
772 detect duplicates */
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200773
774 /* Rearm timer: Retrans time for qmsg just queued may be required
775 before an existing one (for instance a gtp echo req) */
776 queue_timer_start(gsn);
Harald Weltebed35df2011-11-02 13:06:18 +0100777 }
778 return 0;
jjako52c24142002-12-16 13:33:51 +0000779}
780
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100781static int gtp_notification(struct gsn_t *gsn, uint8_t version,
jjako2c381332003-10-21 19:09:53 +0000782 union gtp_packet *packet, int len,
Pau Espin Pedrol2eed6ec2021-05-05 17:51:19 +0200783 const struct sockaddr_in *peer, int fd, uint16_t seq)
Harald Weltebed35df2011-11-02 13:06:18 +0100784{
jjako2c381332003-10-21 19:09:53 +0000785
Harald Weltefed598f2017-09-24 16:39:22 +0800786 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100787 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000788
Harald Weltebed35df2011-11-02 13:06:18 +0100789 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000790
Harald Weltebed35df2011-11-02 13:06:18 +0100791 /* In GTP0 notifications are treated as replies. In GTP1 they
792 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000793
Harald Weltebed35df2011-11-02 13:06:18 +0100794 if (fd == gsn->fd1c)
795 addr.sin_port = htons(GTP1C_PORT);
796 else if (fd == gsn->fd1u)
797 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000798
Harald Weltefed598f2017-09-24 16:39:22 +0800799 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100800 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
801 packet->gtp0.h.seq = hton16(seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800802 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100803 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
804 packet->gtp1l.h.seq = hton16(seq);
805 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100806 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100807 return -1;
808 }
809
810 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100811 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100812 return -1;
813 }
814
815 if (sendto(fd, packet, len, 0,
816 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
817 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100818 LOGP(DLGTP, LOGL_ERROR,
819 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100820 (unsigned long)&packet, len, strerror(errno));
821 return -1;
822 }
823 return 0;
jjako2c381332003-10-21 19:09:53 +0000824}
825
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200826static int gtp_duplicate(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +0100827 struct sockaddr_in *peer, uint16_t seq)
828{
829 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000830
Harald Weltebed35df2011-11-02 13:06:18 +0100831 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
832 return EOF; /* Notfound */
833 }
jjakoa7cd2492003-04-11 09:40:12 +0000834
Harald Weltebed35df2011-11-02 13:06:18 +0100835 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100836 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100837 return -1;
838 }
839
840 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
841 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
842 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100843 LOGP(DLGTP, LOGL_ERROR,
844 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100845 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
846 strerror(errno));
847 }
848 return 0;
jjako52c24142002-12-16 13:33:51 +0000849}
850
jjako52c24142002-12-16 13:33:51 +0000851/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100852static void log_restart(struct gsn_t *gsn)
853{
jjako52c24142002-12-16 13:33:51 +0000854 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200855 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000856 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200857 char *filename;
jjako52c24142002-12-16 13:33:51 +0000858
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200859 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
860 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000861
862 /* We try to open file. On failure we will later try to create file */
863 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100864 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100865 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100866 filename);
867 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100868 rc = fscanf(f, "%d", &counter);
869 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100870 LOGP(DLGTP, LOGL_ERROR,
871 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100872 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100873 }
874 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100875 LOGP(DLGTP, LOGL_ERROR,
876 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100877 }
jjako52c24142002-12-16 13:33:51 +0000878 }
Harald Weltebed35df2011-11-02 13:06:18 +0100879
880 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000881 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100882
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200883 /* Keep the umask closely wrapped around our fopen() call in case the
884 * log outputs cause file creation. */
885 i = umask(022);
886 f = fopen(filename, "w");
887 umask(i);
888 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100889 LOGP(DLGTP, LOGL_ERROR,
890 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100891 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200892 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000893 }
894
jjako52c24142002-12-16 13:33:51 +0000895 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100896close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200897 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100898 LOGP(DLGTP, LOGL_ERROR,
899 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200900free_filename:
901 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000902}
903
jjako1db1c812003-07-06 20:53:57 +0000904int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100905 int mode)
jjako52c24142002-12-16 13:33:51 +0000906{
Harald Weltebed35df2011-11-02 13:06:18 +0100907 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000908
Max14b1b632017-08-21 20:14:59 +0200909 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
jjako52c24142002-12-16 13:33:51 +0000910
Harald Weltebed35df2011-11-02 13:06:18 +0100911 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000912
Harald Weltebed35df2011-11-02 13:06:18 +0100913 (*gsn)->statedir = statedir;
914 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000915
Harald Weltebed35df2011-11-02 13:06:18 +0100916 /* Initialise sequence number */
917 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000918
Harald Weltebed35df2011-11-02 13:06:18 +0100919 /* Initialise request retransmit queue */
920 queue_new(&(*gsn)->queue_req);
921 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000922
Harald Weltebed35df2011-11-02 13:06:18 +0100923 /* Initialise pdp table */
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +0200924 pdp_init(*gsn);
jjako08d331d2003-10-13 20:33:30 +0000925
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200926 /* Initialize internal queue timer */
927 osmo_timer_setup(&(*gsn)->queue_timer, queue_timer_cb, *gsn);
928
Harald Weltebed35df2011-11-02 13:06:18 +0100929 /* Initialise call back functions */
930 (*gsn)->cb_create_context_ind = 0;
931 (*gsn)->cb_delete_context = 0;
932 (*gsn)->cb_unsup_ind = 0;
933 (*gsn)->cb_conf = 0;
934 (*gsn)->cb_data_ind = 0;
935
936 /* Store function parameters */
937 (*gsn)->gsnc = *listen;
938 (*gsn)->gsnu = *listen;
939 (*gsn)->mode = mode;
940
941 /* Create GTP version 0 socket */
942 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
943 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100944 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200945 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100946 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200947 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100948 }
949
950 memset(&addr, 0, sizeof(addr));
951 addr.sin_family = AF_INET;
952 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
953 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000954#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100955 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000956#endif
jjako08d331d2003-10-13 20:33:30 +0000957
Harald Weltebed35df2011-11-02 13:06:18 +0100958 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
959 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200960 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
961 "bind(fd0=%d) failed: Error = %s\n",
962 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200963 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100964 }
jjako08d331d2003-10-13 20:33:30 +0000965
Harald Weltebed35df2011-11-02 13:06:18 +0100966 /* Create GTP version 1 control plane socket */
967 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
968 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100969 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200970 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100971 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200972 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100973 }
974
975 memset(&addr, 0, sizeof(addr));
976 addr.sin_family = AF_INET;
977 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
978 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000979#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100980 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000981#endif
jjako08d331d2003-10-13 20:33:30 +0000982
Harald Weltebed35df2011-11-02 13:06:18 +0100983 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
984 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200985 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
986 "bind(fd1c=%d) failed: Error = %s\n",
987 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200988 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100989 }
jjako08d331d2003-10-13 20:33:30 +0000990
Harald Weltebed35df2011-11-02 13:06:18 +0100991 /* Create GTP version 1 user plane socket */
992 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
993 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100994 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200995 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100996 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200997 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100998 }
999
1000 memset(&addr, 0, sizeof(addr));
1001 addr.sin_family = AF_INET;
1002 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
1003 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +00001004#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01001005 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00001006#endif
jjako52c24142002-12-16 13:33:51 +00001007
Harald Weltebed35df2011-11-02 13:06:18 +01001008 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1009 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +02001010 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +02001011 "bind(fd1u=%d) failed: Error = %s\n",
1012 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +02001013 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +01001014 }
1015
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +02001016 /* Start internal queue timer */
1017 queue_timer_start(*gsn);
1018
Harald Weltebed35df2011-11-02 13:06:18 +01001019 return 0;
jjako52c24142002-12-16 13:33:51 +00001020}
1021
Harald Weltebed35df2011-11-02 13:06:18 +01001022int gtp_free(struct gsn_t *gsn)
1023{
jjako52c24142002-12-16 13:33:51 +00001024
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +02001025 /* Cleanup internal queue timer */
1026 osmo_timer_del(&gsn->queue_timer);
1027
Harald Weltebed35df2011-11-02 13:06:18 +01001028 /* Clean up retransmit queues */
1029 queue_free(gsn->queue_req);
1030 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +00001031
Harald Weltebed35df2011-11-02 13:06:18 +01001032 close(gsn->fd0);
1033 close(gsn->fd1c);
1034 close(gsn->fd1u);
1035
1036 free(gsn);
1037 return 0;
jjako52c24142002-12-16 13:33:51 +00001038}
1039
1040/* ***********************************************************
1041 * Path management messages
1042 * Messages: echo and version not supported.
1043 * A path is connection between two UDP/IP endpoints
1044 *
1045 * A path is either using GTP0 or GTP1. A path can be
1046 * established by any kind of GTP message??
1047
1048 * Which source port to use?
1049 * GTP-C request destination port is 2123/3386
1050 * GTP-U request destination port is 2152/3386
1051 * T-PDU destination port is 2152/3386.
1052 * For the above messages the source port is locally allocated.
1053 * For response messages src=rx-dst and dst=rx-src.
1054 * For simplicity we should probably use 2123+2152/3386 as
1055 * src port even for the cases where src can be locally
1056 * allocated. This also means that we have to listen only to
1057 * the same ports.
1058 * For response messages we need to be able to respond to
1059 * the relevant src port even if it is locally allocated by
1060 * the peer.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001061 *
jjako52c24142002-12-16 13:33:51 +00001062 * The need for path management!
1063 * We might need to keep a list of active paths. This might
1064 * be in the form of remote IP address + UDP port numbers.
1065 * (We will consider a path astablished if we have a context
1066 * with the node in question)
1067 *************************************************************/
1068
1069/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +00001070int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
1071 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +00001072{
Harald Weltebed35df2011-11-02 13:06:18 +01001073 union gtp_packet packet;
1074 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
1075 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +00001076}
1077
jjako08d331d2003-10-13 20:33:30 +00001078/* Send off an echo reply */
1079int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001080 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001081{
Harald Weltebed35df2011-11-02 13:06:18 +01001082 union gtp_packet packet;
1083 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
1084 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1085 gsn->restart_counter);
1086 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
1087 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00001088}
1089
jjako52c24142002-12-16 13:33:51 +00001090/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +01001091int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1092 int fd, void *pack, unsigned len)
1093{
jjako52c24142002-12-16 13:33:51 +00001094
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02001095 /* Check if it was a duplicate request */
1096 if (!gtp_duplicate(gsn, 0, peer, get_seq(pack)))
Harald Weltebed35df2011-11-02 13:06:18 +01001097 return 0;
jjako52c24142002-12-16 13:33:51 +00001098
Harald Weltebed35df2011-11-02 13:06:18 +01001099 /* Send off reply to request */
1100 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +00001101}
1102
1103/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +00001104int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001105 void *pack, unsigned len)
1106{
1107 union gtpie_member *ie[GTPIE_SIZE];
1108 unsigned char recovery;
1109 void *cbp = NULL;
1110 uint8_t type = 0;
1111 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001112
Harald Weltebed35df2011-11-02 13:06:18 +01001113 /* Remove packet from queue */
1114 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1115 return EOF;
jjako52c24142002-12-16 13:33:51 +00001116
Harald Weltebed35df2011-11-02 13:06:18 +01001117 /* Extract information elements into a pointer array */
1118 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1119 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001120 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1121 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001122 if (gsn->cb_conf)
1123 gsn->cb_conf(type, EOF, NULL, cbp);
1124 return EOF;
1125 }
jjako52c24142002-12-16 13:33:51 +00001126
Harald Weltebed35df2011-11-02 13:06:18 +01001127 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1128 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001129 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1130 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001131 if (gsn->cb_conf)
1132 gsn->cb_conf(type, EOF, NULL, cbp);
1133 return EOF;
1134 }
jjako52c24142002-12-16 13:33:51 +00001135
Harald Weltebed35df2011-11-02 13:06:18 +01001136 /* Echo reply packages does not have a cause information element */
1137 /* Instead we return the recovery number in the callback function */
1138 if (gsn->cb_conf)
1139 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +01001140
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001141 emit_cb_recovery(gsn, peer, NULL, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001142
1143 return 0;
jjako52c24142002-12-16 13:33:51 +00001144}
1145
1146/* Send off a Version Not Supported message */
1147/* This message is somewhat special in that it actually is a
1148 * response to some other message with unsupported GTP version
1149 * For this reason it has parameters like a response, and does
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001150 * its own message transmission. No signalling queue is used
jjako52c24142002-12-16 13:33:51 +00001151 * The reply is sent to the peer IP and peer UDP. This means that
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001152 * the peer will be receiving a GTP0 message on a GTP1 port!
jjako52c24142002-12-16 13:33:51 +00001153 * In practice however this will never happen as a GTP0 GSN will
1154 * only listen to the GTP0 port, and therefore will never receive
1155 * anything else than GTP0 */
1156
jjako08d331d2003-10-13 20:33:30 +00001157int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1158 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001159{
Harald Weltebed35df2011-11-02 13:06:18 +01001160 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +00001161
Harald Weltebed35df2011-11-02 13:06:18 +01001162 /* GTP 1 is the highest supported protocol */
1163 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
1164 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +00001165}
1166
1167/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +01001168int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1169 void *pack, unsigned len)
1170{
jjako52c24142002-12-16 13:33:51 +00001171
Harald Weltebed35df2011-11-02 13:06:18 +01001172 if (gsn->cb_unsup_ind)
1173 gsn->cb_unsup_ind(peer);
1174
1175 return 0;
jjako52c24142002-12-16 13:33:51 +00001176}
1177
jjako2c381332003-10-21 19:09:53 +00001178/* Send off an Supported Extension Headers Notification */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001179static int gtp_extheader_req(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
jjako2c381332003-10-21 19:09:53 +00001180 int fd, void *pack, unsigned len)
1181{
Harald Weltebed35df2011-11-02 13:06:18 +01001182 union gtp_packet packet;
1183 unsigned int length =
1184 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +00001185
Harald Weltebed35df2011-11-02 13:06:18 +01001186 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +00001187
Harald Weltebed35df2011-11-02 13:06:18 +01001188 if (version < 1)
1189 return 0;
jjako2c381332003-10-21 19:09:53 +00001190
Harald Weltebed35df2011-11-02 13:06:18 +01001191 /* We report back that we support only PDCP PDU headers */
1192 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
1193 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +00001194
Harald Weltebed35df2011-11-02 13:06:18 +01001195 return gtp_notification(gsn, version, &packet, length,
1196 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +00001197}
1198
1199/* Handle a Supported Extension Headers Notification */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001200static int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001201 void *pack, unsigned len)
1202{
jjako2c381332003-10-21 19:09:53 +00001203
Harald Weltebed35df2011-11-02 13:06:18 +01001204 if (gsn->cb_extheader_ind)
1205 gsn->cb_extheader_ind(peer);
1206
1207 return 0;
jjako2c381332003-10-21 19:09:53 +00001208}
1209
Pau Espin Pedrolf32c6a92021-05-03 17:58:55 +02001210/* Handle a RAN Information Relay message */
1211static int gtp_ran_info_relay_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1212 void *pack, unsigned len)
1213{
1214 union gtpie_member *ie[GTPIE_SIZE];
1215
1216 if (version != 1) {
1217 LOGP(DLGTP, LOGL_NOTICE,
1218 "RAN Information Relay expected only on GTPCv1: %u\n", version);
1219 return -EINVAL;
1220 }
1221
1222 int hlen = get_hlen(pack);
1223
1224 /* Decode information elements */
1225 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1226 gsn->invalid++;
1227 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1228 "Invalid message format (AN Information Relay)\n");
1229 return -EINVAL;
1230 }
1231
1232 if (gsn->cb_ran_info_relay_ind)
1233 gsn->cb_ran_info_relay_ind(peer, ie);
1234
1235 return 0;
1236}
1237
1238/* Send off a RAN Information Relay message */
1239int gtp_ran_info_relay_req(struct gsn_t *gsn, const struct sockaddr_in *peer,
1240 const uint8_t *ran_container, size_t ran_container_len,
1241 const uint8_t *rim_route_addr, size_t rim_route_addr_len,
1242 uint8_t rim_route_addr_discr)
1243{
1244 union gtp_packet packet;
1245
1246 /* GTP 1 is the highest supported protocol */
1247 unsigned int length = get_default_gtp(1, GTP_RAN_INFO_RELAY, &packet);
1248
1249 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAN_T_CONTAIN, ran_container_len,
1250 ran_container);
1251 if (rim_route_addr) {
1252 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RIM_ROUT_ADDR,
1253 rim_route_addr_len, rim_route_addr);
1254 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RIM_RA_DISCR, 1,
1255 &rim_route_addr_discr);
1256 }
1257
1258 return gtp_notification(gsn, 1, &packet, length, peer, gsn->fd1c, 0);
1259}
1260
jjako52c24142002-12-16 13:33:51 +00001261/* ***********************************************************
1262 * Session management messages
1263 * Messages: create, update and delete PDP context
1264 *
1265 * Information storage
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001266 * Information storage for each PDP context is defined in
jjako52c24142002-12-16 13:33:51 +00001267 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1268 * PDP-address (IP address), sequence numbers, charging ID.
1269 * For the SGSN it also includes radio related mobility
1270 * information.
1271 *************************************************************/
1272
Harald Welte7b3347b2010-05-15 12:18:46 +02001273/* API: Send Create PDP Context Request (7.3.1) */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001274int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001275 void *cbp)
1276{
1277 union gtp_packet packet;
1278 unsigned int length =
1279 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1280 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001281
Harald Weltebed35df2011-11-02 13:06:18 +01001282 /* TODO: Secondary PDP Context Activation Procedure */
1283 /* In secondary activation procedure the PDP context is identified
1284 by tei in the header. The following fields are omitted: Selection
1285 mode, IMSI, MSISDN, End User Address, Access Point Name and
1286 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001287
Harald Weltebed35df2011-11-02 13:06:18 +01001288 if (pdp->secondary) {
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001289 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001290 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001291 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001292 return EOF;
1293 }
1294 }
jjako2c381332003-10-21 19:09:53 +00001295
Harald Weltebed35df2011-11-02 13:06:18 +01001296 if (pdp->version == 0) {
1297 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1298 sizeof(pdp->qos_req0), pdp->qos_req0);
1299 }
jjako52c24142002-12-16 13:33:51 +00001300
Harald Weltebed35df2011-11-02 13:06:18 +01001301 /* Section 7.7.2 */
1302 if (pdp->version == 1) {
1303 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1304 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1305 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1306 }
jjako52c24142002-12-16 13:33:51 +00001307
Harald Weltebed35df2011-11-02 13:06:18 +01001308 /* Section 7.7.3 Routing Area Information */
1309 if (pdp->rai_given == 1)
1310 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1311 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001312
Harald Weltebed35df2011-11-02 13:06:18 +01001313 /* Section 7.7.11 */
1314 if (pdp->norecovery_given == 0)
1315 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1316 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001317
Harald Weltebed35df2011-11-02 13:06:18 +01001318 /* Section 7.7.12 */
1319 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1320 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1321 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001322
Harald Weltebed35df2011-11-02 13:06:18 +01001323 if (pdp->version == 0) {
1324 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1325 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1326 }
jjako08d331d2003-10-13 20:33:30 +00001327
Harald Weltebed35df2011-11-02 13:06:18 +01001328 /* Section 7.7.13 */
1329 if (pdp->version == 1) {
1330 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1331 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001332
Harald Weltebed35df2011-11-02 13:06:18 +01001333 /* Section 7.7.14 */
1334 if (!pdp->teic_confirmed)
1335 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1336 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001337
Harald Weltebed35df2011-11-02 13:06:18 +01001338 /* Section 7.7.17 */
1339 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001340
Harald Weltebed35df2011-11-02 13:06:18 +01001341 /* Section 7.7.17 */
1342 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1343 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1344 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001345
Harald Weltebed35df2011-11-02 13:06:18 +01001346 /* Section 7.7.23 */
1347 if (pdp->cch_pdp) /* Only include charging if flags are set */
1348 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1349 pdp->cch_pdp);
1350 }
jjako9b4971d2004-05-27 20:30:19 +00001351
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001352 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001353 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1354 pdp->traceref);
1355 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1356 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001357
Harald Weltebed35df2011-11-02 13:06:18 +01001358 /* Section 7.7.27 */
1359 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1360 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1361 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001362
Harald Weltebed35df2011-11-02 13:06:18 +01001363 /* Section 7.7.30 */
1364 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1365 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1366 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001367
Harald Weltebed35df2011-11-02 13:06:18 +01001368 /* Section 7.7.31 */
1369 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1370 if (pdp->pco_req.l)
1371 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1372 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001373
Harald Weltebed35df2011-11-02 13:06:18 +01001374 /* Section 7.7.32 */
1375 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1376 pdp->gsnlc.l, pdp->gsnlc.v);
1377 /* Section 7.7.32 */
1378 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1379 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001380
Harald Weltebed35df2011-11-02 13:06:18 +01001381 /* Section 7.7.33 */
1382 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1383 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1384 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001385
Harald Weltebed35df2011-11-02 13:06:18 +01001386 /* Section 7.7.34 */
1387 if (pdp->version == 1)
1388 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1389 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001390
Harald Weltebed35df2011-11-02 13:06:18 +01001391 /* Section 7.7.36 */
1392 if ((pdp->version == 1) && pdp->tft.l)
1393 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1394 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001395
Harald Weltebed35df2011-11-02 13:06:18 +01001396 /* Section 7.7.41 */
1397 if ((pdp->version == 1) && pdp->triggerid.l)
1398 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1399 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001400
Harald Weltebed35df2011-11-02 13:06:18 +01001401 /* Section 7.7.42 */
1402 if ((pdp->version == 1) && pdp->omcid.l)
1403 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1404 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001405
Harald Weltebed35df2011-11-02 13:06:18 +01001406 /* new R7 fields */
1407 if (pdp->rattype_given == 1)
1408 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1409 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001410
Harald Weltebed35df2011-11-02 13:06:18 +01001411 if (pdp->userloc_given == 1)
1412 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1413 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001414
Harald Weltebed35df2011-11-02 13:06:18 +01001415 if (pdp->mstz_given == 1)
1416 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1417 pdp->mstz.l, pdp->mstz.v);
1418
1419 if (pdp->imeisv_given == 1)
1420 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1421 pdp->imeisv.l, pdp->imeisv.v);
1422
1423 /* TODO hisaddr0 */
1424 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1425
1426 return 0;
jjako52c24142002-12-16 13:33:51 +00001427}
1428
jjako08d331d2003-10-13 20:33:30 +00001429/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001430int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1431{
jjako08d331d2003-10-13 20:33:30 +00001432
Harald Weltebed35df2011-11-02 13:06:18 +01001433 /* Now send off a reply to the peer */
1434 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1435
Pau Espin Pedrold9501342019-08-21 15:24:29 +02001436 if (cause != GTPCAUSE_ACC_REQ)
1437 gtp_freepdp(gsn, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001438
1439 return 0;
jjako08d331d2003-10-13 20:33:30 +00001440}
1441
1442/* API: Register create context indication callback */
1443int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001444 int (*cb_create_context_ind) (struct pdp_t *
1445 pdp))
jjako52c24142002-12-16 13:33:51 +00001446{
Harald Weltebed35df2011-11-02 13:06:18 +01001447 gsn->cb_create_context_ind = cb_create_context_ind;
1448 return 0;
jjako08d331d2003-10-13 20:33:30 +00001449}
1450
jjako08d331d2003-10-13 20:33:30 +00001451/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001452int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1453 uint8_t cause)
1454{
1455 union gtp_packet packet;
1456 unsigned int length =
1457 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001458
Harald Weltebed35df2011-11-02 13:06:18 +01001459 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001460
Harald Weltebed35df2011-11-02 13:06:18 +01001461 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001462
Harald Weltebed35df2011-11-02 13:06:18 +01001463 if (version == 0)
1464 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1465 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001466
Harald Weltebed35df2011-11-02 13:06:18 +01001467 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1468 pdp->reorder);
1469 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1470 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001471
Harald Weltebed35df2011-11-02 13:06:18 +01001472 if (version == 0) {
1473 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1474 pdp->fllu);
1475 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1476 pdp->fllc);
1477 }
jjako08d331d2003-10-13 20:33:30 +00001478
Harald Weltebed35df2011-11-02 13:06:18 +01001479 if (version == 1) {
1480 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1481 pdp->teid_own);
1482 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1483 pdp->teic_own);
1484 }
jjako08d331d2003-10-13 20:33:30 +00001485
Harald Weltebed35df2011-11-02 13:06:18 +01001486 /* TODO: We use teic_own as charging ID */
1487 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1488 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001489
Harald Weltebed35df2011-11-02 13:06:18 +01001490 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1491 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001492
Harald Weltebed35df2011-11-02 13:06:18 +01001493 if (pdp->pco_neg.l) { /* Optional PCO */
1494 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1495 pdp->pco_neg.l, pdp->pco_neg.v);
1496 }
jjako52c24142002-12-16 13:33:51 +00001497
Harald Weltebed35df2011-11-02 13:06:18 +01001498 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1499 pdp->gsnlc.l, pdp->gsnlc.v);
1500 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1501 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001502
Harald Weltebed35df2011-11-02 13:06:18 +01001503 if (version == 1)
1504 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1505 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001506
Harald Weltebed35df2011-11-02 13:06:18 +01001507 /* TODO: Charging gateway address */
1508 }
jjako52c24142002-12-16 13:33:51 +00001509
Harald Weltebed35df2011-11-02 13:06:18 +01001510 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1511 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001512}
1513
1514/* Handle Create PDP Context Request */
1515int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001516 struct sockaddr_in *peer, int fd,
1517 void *pack, unsigned len)
1518{
1519 struct pdp_t *pdp, *pdp_old;
1520 struct pdp_t pdp_buf;
1521 union gtpie_member *ie[GTPIE_SIZE];
1522 uint8_t recovery;
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001523 bool recovery_recvd = false;
1524 int rc;
jjako52c24142002-12-16 13:33:51 +00001525
Harald Weltebed35df2011-11-02 13:06:18 +01001526 uint16_t seq = get_seq(pack);
1527 int hlen = get_hlen(pack);
1528 uint8_t linked_nsapi = 0;
1529 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001530
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02001531 if (!gtp_duplicate(gsn, version, peer, seq))
Harald Weltebed35df2011-11-02 13:06:18 +01001532 return 0;
jjako08d331d2003-10-13 20:33:30 +00001533
Harald Weltebed35df2011-11-02 13:06:18 +01001534 pdp = &pdp_buf;
1535 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001536
Vadim Yanitskiy68c5a742019-08-30 21:04:19 +02001537 if (version == 0)
1538 pdp_set_imsi_nsapi(pdp, get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00001539
Harald Weltebed35df2011-11-02 13:06:18 +01001540 pdp->seq = seq;
1541 pdp->sa_peer = *peer;
1542 pdp->fd = fd;
1543 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001544
Harald Weltebed35df2011-11-02 13:06:18 +01001545 /* Decode information elements */
1546 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1547 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001548 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1549 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001550 if (0 == version)
1551 return EOF;
1552 else
1553 return gtp_create_pdp_resp(gsn, version, pdp,
1554 GTPCAUSE_INVALID_MESSAGE);
1555 }
jjako52c24142002-12-16 13:33:51 +00001556
Harald Weltebed35df2011-11-02 13:06:18 +01001557 if (version == 1) {
1558 /* Linked NSAPI (conditional) */
1559 /* If included this is the Secondary PDP Context Activation Procedure */
1560 /* In secondary activation IMSI is not included, so the context must be */
1561 /* identified by the tei */
1562 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001563
Harald Weltebed35df2011-11-02 13:06:18 +01001564 /* Find the primary PDP context */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001565 if (gtp_pdp_getgtp1(gsn, &linked_pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001566 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001567 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001568 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001569 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001570 return gtp_create_pdp_resp(gsn, version, pdp,
1571 GTPCAUSE_OPT_IE_INCORRECT);
1572 }
jjako2c381332003-10-21 19:09:53 +00001573
Harald Weltebed35df2011-11-02 13:06:18 +01001574 /* Check that the primary PDP context matches linked nsapi */
1575 if (linked_pdp->nsapi != linked_nsapi) {
1576 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001577 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001578 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001579 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001580 return gtp_create_pdp_resp(gsn, version, pdp,
1581 GTPCAUSE_OPT_IE_INCORRECT);
1582 }
jjako52c24142002-12-16 13:33:51 +00001583
Harald Weltebed35df2011-11-02 13:06:18 +01001584 /* Copy parameters from primary context */
1585 pdp->selmode = linked_pdp->selmode;
1586 pdp->imsi = linked_pdp->imsi;
1587 pdp->msisdn = linked_pdp->msisdn;
1588 pdp->eua = linked_pdp->eua;
1589 pdp->pco_req = linked_pdp->pco_req;
1590 pdp->apn_req = linked_pdp->apn_req;
1591 pdp->teic_gn = linked_pdp->teic_gn;
1592 pdp->secondary = 1;
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001593 } else {
1594 /* Not Secondary PDP Context Activation Procedure */
1595 /* IMSI (conditional): If the MS is emergency attached
1596 and the MS is UICCless, the IMSI cannot be included
1597 in the message and therefore IMSI shall not be
1598 included in the message. */
1599 if (gtpie_gettv0
1600 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1601 gsn->missing++;
1602 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1603 len, "Missing IMSI not supported\n");
1604 return gtp_create_pdp_resp(gsn, version, pdp,
1605 GTPCAUSE_MAN_IE_MISSING);
1606 }
1607 }
1608
1609 /* TEID (mandatory) */
1610 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1611 gsn->missing++;
1612 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1613 len, "Missing mandatory information field\n");
1614 return gtp_create_pdp_resp(gsn, version, pdp,
1615 GTPCAUSE_MAN_IE_MISSING);
1616 }
1617 /* TEIC (conditional) */
1618 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1619 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1620 gsn->missing++;
1621 GTP_LOGPKG(LOGL_ERROR, peer,
1622 pack, len,
1623 "Missing mandatory information field\n");
1624 return gtp_create_pdp_resp(gsn, version, pdp,
1625 GTPCAUSE_MAN_IE_MISSING);
1626 }
1627 }
1628 /* NSAPI (mandatory) */
1629 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1630 gsn->missing++;
1631 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1632 len, "Missing mandatory information field\n");
1633 return gtp_create_pdp_resp(gsn, version, pdp,
1634 GTPCAUSE_MAN_IE_MISSING);
1635 }
1636 /* QoS (mandatory) */
1637 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1638 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1639 gsn->missing++;
1640 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1641 len, "Missing mandatory information field\n");
1642 return gtp_create_pdp_resp(gsn, version, pdp,
1643 GTPCAUSE_MAN_IE_MISSING);
1644 }
1645 /* TFT (conditional) */
1646 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1647 &pdp->tft.v, sizeof(pdp->tft.v))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001648 }
1649 }
1650 /* if (version == 1) */
1651 if (version == 0) {
1652 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1653 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1654 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001655 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1656 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001657 return gtp_create_pdp_resp(gsn, version, pdp,
1658 GTPCAUSE_MAN_IE_MISSING);
1659 }
Harald Weltebed35df2011-11-02 13:06:18 +01001660 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1661 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001662 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1663 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001664 return gtp_create_pdp_resp(gsn, version, pdp,
1665 GTPCAUSE_MAN_IE_MISSING);
1666 }
Harald Weltebed35df2011-11-02 13:06:18 +01001667 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1668 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001669 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1670 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001671 return gtp_create_pdp_resp(gsn, version, pdp,
1672 GTPCAUSE_MAN_IE_MISSING);
1673 }
1674 }
jjako08d331d2003-10-13 20:33:30 +00001675
Harald Weltebed35df2011-11-02 13:06:18 +01001676 /* SGSN address for signalling (mandatory) */
1677 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1678 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1679 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001680 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1681 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001682 return gtp_create_pdp_resp(gsn, version, pdp,
1683 GTPCAUSE_MAN_IE_MISSING);
1684 }
jjako2e840a32003-01-28 16:05:18 +00001685
Harald Weltebed35df2011-11-02 13:06:18 +01001686 /* SGSN address for user traffic (mandatory) */
1687 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1688 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1689 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001690 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1691 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001692 return gtp_create_pdp_resp(gsn, version, pdp,
1693 GTPCAUSE_MAN_IE_MISSING);
1694 }
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001695 /* Recovery (optional) */
1696 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1697 /* we use recovery futher down after announcing new pdp ctx to user */
1698 recovery_recvd = true;
1699 }
jjako52c24142002-12-16 13:33:51 +00001700
Harald Weltebed35df2011-11-02 13:06:18 +01001701 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001702 /* Selection mode (conditional) */
1703 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1704 &pdp->selmode, sizeof(pdp->selmode))) {
1705 gsn->missing++;
1706 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1707 len, "Missing mandatory information field\n");
1708 return gtp_create_pdp_resp(gsn, version, pdp,
1709 GTPCAUSE_MAN_IE_MISSING);
1710 }
1711 /* End User Address (conditional) */
1712 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1713 &pdp->eua.v, sizeof(pdp->eua.v))) {
1714 gsn->missing++;
1715 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1716 len, "Missing mandatory information field\n");
1717 return gtp_create_pdp_resp(gsn, version, pdp,
1718 GTPCAUSE_MAN_IE_MISSING);
1719 }
1720 /* APN */
1721 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1722 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1723 gsn->missing++;
1724 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1725 len, "Missing mandatory information field\n");
1726 return gtp_create_pdp_resp(gsn, version, pdp,
1727 GTPCAUSE_MAN_IE_MISSING);
1728 }
1729 /* Extract protocol configuration options (optional) */
1730 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1731 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1732 }
Harald Weltebed35df2011-11-02 13:06:18 +01001733 /* MSISDN (conditional) */
1734 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1735 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1736 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001737 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1738 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001739 return gtp_create_pdp_resp(gsn, version, pdp,
1740 GTPCAUSE_MAN_IE_MISSING);
1741 }
1742 }
jjako52c24142002-12-16 13:33:51 +00001743
Harald Weltebed35df2011-11-02 13:06:18 +01001744 /* Initialize our own IP addresses */
1745 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1746 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1747
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001748 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before gtp_pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001749
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001750 if (!gtp_pdp_getimsi(gsn, &pdp_old, pdp->imsi, pdp->nsapi)) {
Harald Weltebed35df2011-11-02 13:06:18 +01001751 /* Found old pdp with same tid. Now the voodoo begins! */
1752 /* 09.60 / 29.060 allows create on existing context to "steal" */
1753 /* the context which was allready established */
1754 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001755 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001756 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1757 &&
1758 (!memcmp
1759 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1760 && (pdp->selmode == pdp_old->selmode)
1761 && (pdp->msisdn.l == pdp_old->msisdn.l)
1762 &&
1763 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1764 {
1765 /* OK! We are dealing with the same APN. We will copy new
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001766 * parameters to the old pdp and send off confirmation
Harald Weltebed35df2011-11-02 13:06:18 +01001767 * We ignore the following information elements:
1768 * QoS: MS will get originally negotiated QoS.
1769 * End user address (EUA). MS will get old EUA anyway.
1770 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001771 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001772
1773 /* Copy remote flow label */
1774 pdp_old->flru = pdp->flru;
1775 pdp_old->flrc = pdp->flrc;
1776
1777 /* Copy remote tei */
1778 pdp_old->teid_gn = pdp->teid_gn;
1779 pdp_old->teic_gn = pdp->teic_gn;
1780
1781 /* Copy peer GSN address */
1782 pdp_old->gsnrc.l = pdp->gsnrc.l;
1783 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1784 pdp_old->gsnru.l = pdp->gsnru.l;
1785 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1786
1787 /* Copy request parameters */
1788 pdp_old->seq = pdp->seq;
1789 pdp_old->sa_peer = pdp->sa_peer;
1790 pdp_old->fd = pdp->fd = fd;
1791 pdp_old->version = pdp->version = version;
1792
1793 /* Switch to using the old pdp context */
1794 pdp = pdp_old;
1795
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001796 if (recovery_recvd)
1797 emit_cb_recovery(gsn, peer, pdp, recovery);
1798
Harald Weltebed35df2011-11-02 13:06:18 +01001799 /* Confirm to peer that things were "successful" */
1800 return gtp_create_pdp_resp(gsn, version, pdp,
1801 GTPCAUSE_ACC_REQ);
1802 } else { /* This is not the same PDP context. Delete the old one. */
1803
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001804 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001805
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02001806 gtp_freepdp(gsn, pdp_old);
Harald Weltebed35df2011-11-02 13:06:18 +01001807
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001808 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001809 }
1810 }
1811
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +02001812 gtp_pdp_newpdp(gsn, &pdp, pdp->imsi, pdp->nsapi, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001813
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001814 /* Callback function to validate login */
Harald Weltebed35df2011-11-02 13:06:18 +01001815 if (gsn->cb_create_context_ind != 0)
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001816 rc = gsn->cb_create_context_ind(pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001817 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001818 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1819 "No create_context_ind callback defined\n");
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001820 rc = gtp_create_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001821 GTPCAUSE_NOT_SUPPORTED);
1822 }
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001823 if (recovery_recvd)
1824 emit_cb_recovery(gsn, peer, pdp, recovery);
1825 return rc;
jjako52c24142002-12-16 13:33:51 +00001826}
1827
jjako52c24142002-12-16 13:33:51 +00001828/* Handle Create PDP Context Response */
1829int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001830 struct sockaddr_in *peer, void *pack, unsigned len)
1831{
1832 struct pdp_t *pdp;
1833 union gtpie_member *ie[GTPIE_SIZE];
1834 uint8_t cause, recovery;
1835 void *cbp = NULL;
1836 uint8_t type = 0;
1837 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001838
Harald Weltebed35df2011-11-02 13:06:18 +01001839 /* Remove packet from queue */
1840 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1841 return EOF;
jjako52c24142002-12-16 13:33:51 +00001842
Harald Weltebed35df2011-11-02 13:06:18 +01001843 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001844 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001845 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001846 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001847 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001848 if (gsn->cb_conf)
1849 gsn->cb_conf(type, EOF, NULL, cbp);
1850 return EOF;
1851 }
jjako2c381332003-10-21 19:09:53 +00001852
Harald Weltebed35df2011-11-02 13:06:18 +01001853 /* Decode information elements */
1854 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1855 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001856 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1857 "Invalid message format\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 /* Extract cause value (mandatory) */
1864 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1865 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001866 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1867 "Missing mandatory 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 }
jjako52c24142002-12-16 13:33:51 +00001872
Harald Weltebed35df2011-11-02 13:06:18 +01001873 /* Extract recovery (optional) */
1874 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001875 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001876 }
jjako52c24142002-12-16 13:33:51 +00001877
Harald Weltebed35df2011-11-02 13:06:18 +01001878 /* Extract protocol configuration options (optional) */
1879 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1880 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1881 }
jjako52c24142002-12-16 13:33:51 +00001882
Harald Weltebed35df2011-11-02 13:06:18 +01001883 /* Check all conditional information elements */
1884 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001885
Harald Weltebed35df2011-11-02 13:06:18 +01001886 if (version == 0) {
1887 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1888 &pdp->qos_neg0,
1889 sizeof(pdp->qos_neg0))) {
1890 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001891 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001892 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001893 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001894 if (gsn->cb_conf)
1895 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001896 return EOF;
1897 }
1898 }
jjako08d331d2003-10-13 20:33:30 +00001899
Harald Weltebed35df2011-11-02 13:06:18 +01001900 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1901 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001902 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001903 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001904 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001905 if (gsn->cb_conf)
1906 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001907 return EOF;
1908 }
jjako52c24142002-12-16 13:33:51 +00001909
Harald Weltebed35df2011-11-02 13:06:18 +01001910 if (version == 0) {
1911 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1912 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001913 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001914 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001915 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001916 if (gsn->cb_conf)
1917 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001918 return EOF;
1919 }
jjako52c24142002-12-16 13:33:51 +00001920
Harald Weltebed35df2011-11-02 13:06:18 +01001921 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1922 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001923 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001924 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001925 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001926 if (gsn->cb_conf)
1927 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001928 return EOF;
1929 }
1930 }
1931
1932 if (version == 1) {
1933 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1934 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001935 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001936 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001937 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001938 if (gsn->cb_conf)
1939 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001940 return EOF;
1941 }
1942
1943 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
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 }
Pau Espin Pedrol0b1d9db2021-04-21 19:45:23 +02001952 /* Register that we have received a valid teic from GGSN */
1953 pdp->teic_confirmed = 1;
Harald Weltebed35df2011-11-02 13:06:18 +01001954 }
1955
1956 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1957 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001958 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001959 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001960 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001961 if (gsn->cb_conf)
1962 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001963 }
1964
1965 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1966 &pdp->eua.v, sizeof(pdp->eua.v))) {
1967 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001968 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001969 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001970 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001971 if (gsn->cb_conf)
1972 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001973 return EOF;
1974 }
1975
1976 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1977 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1978 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001979 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001980 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001981 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001982 if (gsn->cb_conf)
1983 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001984 return EOF;
1985 }
1986
1987 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1988 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1989 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001990 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001991 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001992 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001993 if (gsn->cb_conf)
1994 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001995 return EOF;
1996 }
1997
1998 if (version == 1) {
1999 if (gtpie_gettlv
2000 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2001 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2002 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002003 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01002004 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002005 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002006 if (gsn->cb_conf)
2007 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002008 return EOF;
2009 }
2010 }
2011
2012 }
2013
2014 if (gsn->cb_conf)
2015 gsn->cb_conf(type, cause, pdp, cbp);
2016
2017 return 0;
jjako52c24142002-12-16 13:33:51 +00002018}
2019
jjako08d331d2003-10-13 20:33:30 +00002020/* API: Send Update PDP Context Request */
2021int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002022 struct in_addr *inetaddr)
2023{
2024 union gtp_packet packet;
2025 unsigned int length =
2026 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00002027
Harald Weltebed35df2011-11-02 13:06:18 +01002028 if (pdp->version == 0)
2029 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
2030 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00002031
Harald Weltebed35df2011-11-02 13:06:18 +01002032 /* Include IMSI if updating with unknown teic_gn */
2033 if ((pdp->version == 1) && (!pdp->teic_gn))
2034 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
2035 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
2036
2037 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
2038 gsn->restart_counter);
2039
2040 if (pdp->version == 0) {
2041 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
2042 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
2043 }
2044
2045 if (pdp->version == 1) {
2046 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2047 pdp->teid_own);
2048
2049 if (!pdp->teic_confirmed)
2050 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
2051 pdp->teic_own);
2052 }
2053
2054 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2055
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002056 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01002057 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
2058 pdp->traceref);
2059 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
2060 pdp->tracetype); */
2061
2062 /* TODO if ggsn update message
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002063 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01002064 pdp->eua.l, pdp->eua.v);
2065 */
2066
2067 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2068 pdp->gsnlc.l, pdp->gsnlc.v);
2069 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2070 pdp->gsnlu.l, pdp->gsnlu.v);
2071
2072 if (pdp->version == 1)
2073 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2074 pdp->qos_req.l, pdp->qos_req.v);
2075
2076 if ((pdp->version == 1) && pdp->tft.l)
2077 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
2078 pdp->tft.l, pdp->tft.v);
2079
2080 if ((pdp->version == 1) && pdp->triggerid.l)
2081 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
2082 pdp->triggerid.l, pdp->triggerid.v);
2083
2084 if ((pdp->version == 1) && pdp->omcid.l)
2085 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
2086 pdp->omcid.l, pdp->omcid.v);
2087
Daniel Willmann134a7752016-02-03 18:53:29 +01002088 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002089
2090 return 0;
jjako52c24142002-12-16 13:33:51 +00002091}
2092
jjako08d331d2003-10-13 20:33:30 +00002093/* Send Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002094static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002095 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00002096 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01002097 struct pdp_t *pdp, uint8_t cause)
2098{
jjako08d331d2003-10-13 20:33:30 +00002099
Harald Weltebed35df2011-11-02 13:06:18 +01002100 union gtp_packet packet;
2101 unsigned int length =
2102 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00002103
Harald Weltebed35df2011-11-02 13:06:18 +01002104 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00002105
Harald Weltebed35df2011-11-02 13:06:18 +01002106 if (cause == GTPCAUSE_ACC_REQ) {
2107
2108 if (version == 0)
2109 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
2110 sizeof(pdp->qos_neg0), pdp->qos_neg0);
2111
2112 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
2113 gsn->restart_counter);
2114
2115 if (version == 0) {
2116 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
2117 pdp->fllu);
2118 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
2119 pdp->fllc);
2120 }
2121
2122 if (version == 1) {
2123 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2124 pdp->teid_own);
2125
2126 if (!pdp->teic_confirmed)
2127 gtpie_tv4(&packet, &length, GTP_MAX,
2128 GTPIE_TEI_C, pdp->teic_own);
2129 }
2130
2131 /* TODO we use teid_own as charging ID address */
2132 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
2133 pdp->teid_own);
2134
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002135 /* If ggsn
2136 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01002137 pdp->eua.l, pdp->eua.v); */
2138
2139 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2140 pdp->gsnlc.l, pdp->gsnlc.v);
2141 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2142 pdp->gsnlu.l, pdp->gsnlu.v);
2143
2144 if (version == 1)
2145 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2146 pdp->qos_neg.l, pdp->qos_neg.v);
2147
2148 /* TODO: Charging gateway address */
2149 }
2150
2151 return gtp_resp(version, gsn, pdp, &packet, length, peer,
2152 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00002153}
2154
jjako52c24142002-12-16 13:33:51 +00002155/* Handle Update PDP Context Request */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002156static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002157 struct sockaddr_in *peer, int fd,
2158 void *pack, unsigned len)
2159{
2160 struct pdp_t *pdp;
2161 struct pdp_t pdp_backup;
2162 union gtpie_member *ie[GTPIE_SIZE];
2163 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002164
Harald Weltebed35df2011-11-02 13:06:18 +01002165 uint16_t seq = get_seq(pack);
2166 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002167
Harald Weltebed35df2011-11-02 13:06:18 +01002168 uint64_t imsi;
2169 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002170
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002171 /* Is this a duplicate ? */
2172 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002173 return 0; /* We allready send of response once */
2174 }
jjako08d331d2003-10-13 20:33:30 +00002175
Harald Weltebed35df2011-11-02 13:06:18 +01002176 /* Decode information elements */
2177 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2178 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002179 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2180 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002181 if (0 == version)
2182 return EOF;
2183 else
2184 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2185 len, NULL,
2186 GTPCAUSE_INVALID_MESSAGE);
2187 }
jjako08d331d2003-10-13 20:33:30 +00002188
Harald Weltebed35df2011-11-02 13:06:18 +01002189 /* Finding PDP: */
2190 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2191 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2192 /* we have to use the tunnel endpoint identifier */
2193 if (version == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002194 /* Find the context in question */
Vadim Yanitskiy00a61712019-08-30 21:00:22 +02002195 if (gtp_pdp_tidget(gsn, &pdp, get_tid(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002196 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002197 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2198 "Unknown PDP context: TID=0x%" PRIx64 "\n",
2199 get_tid(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002200 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2201 len, NULL,
2202 GTPCAUSE_NON_EXIST);
2203 }
Vadim Yanitskiy00a61712019-08-30 21:00:22 +02002204
2205 /* Update IMSI and NSAPI */
2206 pdp_set_imsi_nsapi(pdp, get_tid(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002207 } else if (version == 1) {
2208 /* NSAPI (mandatory) */
2209 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2210 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002211 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2212 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002213 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2214 len, NULL,
2215 GTPCAUSE_MAN_IE_MISSING);
2216 }
jjako08d331d2003-10-13 20:33:30 +00002217
Harald Weltebed35df2011-11-02 13:06:18 +01002218 /* IMSI (conditional) */
2219 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2220 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002221 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002222 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002223 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2224 "Unknown PDP context: TEI=0x%" PRIx32 "\n",
2225 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002226 return gtp_update_pdp_resp(gsn, version, peer,
2227 fd, pack, len, NULL,
2228 GTPCAUSE_NON_EXIST);
2229 }
2230 } else {
2231 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002232 if (gtp_pdp_getimsi(gsn, &pdp, imsi, nsapi)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002233 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002234 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2235 "Unknown PDP context: IMSI=0x%" PRIx64
2236 " NSAPI=%" PRIu8 "\n", imsi, nsapi);
Harald Weltebed35df2011-11-02 13:06:18 +01002237 return gtp_update_pdp_resp(gsn, version, peer,
2238 fd, pack, len, NULL,
2239 GTPCAUSE_NON_EXIST);
2240 }
2241 }
2242 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002243 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002244 return EOF;
2245 }
jjako08d331d2003-10-13 20:33:30 +00002246
Harald Weltebed35df2011-11-02 13:06:18 +01002247 /* Make a backup copy in case anything is wrong */
2248 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002249
Harald Weltebed35df2011-11-02 13:06:18 +01002250 if (version == 0) {
2251 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2252 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2253 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002254 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2255 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002256 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2257 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2258 len, pdp,
2259 GTPCAUSE_MAN_IE_MISSING);
2260 }
2261 }
jjako52c24142002-12-16 13:33:51 +00002262
Harald Weltebed35df2011-11-02 13:06:18 +01002263 /* Recovery (optional) */
2264 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002265 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002266 }
jjako08d331d2003-10-13 20:33:30 +00002267
Harald Weltebed35df2011-11-02 13:06:18 +01002268 if (version == 0) {
2269 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2270 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002271 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2272 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002273 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2274 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2275 len, pdp,
2276 GTPCAUSE_MAN_IE_MISSING);
2277 }
jjako52c24142002-12-16 13:33:51 +00002278
Harald Weltebed35df2011-11-02 13:06:18 +01002279 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2280 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002281 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2282 len, "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,
2285 len, pdp,
2286 GTPCAUSE_MAN_IE_MISSING);
2287 }
2288 }
jjako52c24142002-12-16 13:33:51 +00002289
Harald Weltebed35df2011-11-02 13:06:18 +01002290 if (version == 1) {
2291 /* TEID (mandatory) */
2292 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2293 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002294 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2295 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002296 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2297 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2298 len, pdp,
2299 GTPCAUSE_MAN_IE_MISSING);
2300 }
jjako52c24142002-12-16 13:33:51 +00002301
Harald Weltebed35df2011-11-02 13:06:18 +01002302 /* TEIC (conditional) */
2303 /* If TEIC is not included it means that we have allready received it */
2304 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2305 /* all updated contexts, or only for one of the linked contexts */
2306 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2307
2308 /* NSAPI (mandatory) */
2309 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2310 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002311 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2312 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002313 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2314 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2315 len, pdp,
2316 GTPCAUSE_MAN_IE_MISSING);
2317 }
2318 }
2319
2320 /* Trace reference (optional) */
2321 /* Trace type (optional) */
2322
2323 /* End User Address (conditional) TODO: GGSN Initiated
2324 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2325 &pdp->eua.v, sizeof(pdp->eua.v))) {
2326 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002327 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002328 "Missing mandatory information field");
2329 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002330 return gtp_update_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01002331 GTPCAUSE_MAN_IE_MISSING);
2332 } */
2333
2334 /* SGSN address for signalling (mandatory) */
2335 /* It is weird that this is mandatory when TEIC is conditional */
2336 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2337 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2338 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002339 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2340 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002341 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2342 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2343 pdp, GTPCAUSE_MAN_IE_MISSING);
2344 }
2345
2346 /* SGSN address for user traffic (mandatory) */
2347 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2348 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2349 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002350 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2351 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002352 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2353 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2354 pdp, GTPCAUSE_MAN_IE_MISSING);
2355 }
2356
2357 if (version == 1) {
2358 /* QoS (mandatory) */
2359 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2360 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2361 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002362 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2363 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002364 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2365 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2366 len, pdp,
2367 GTPCAUSE_MAN_IE_MISSING);
2368 }
2369
2370 /* TFT (conditional) */
2371 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2372 &pdp->tft.v, sizeof(pdp->tft.v))) {
2373 }
2374
2375 /* OMC identity */
2376 }
2377
2378 /* Confirm to peer that things were "successful" */
2379 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2380 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002381}
2382
jjako52c24142002-12-16 13:33:51 +00002383/* Handle Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002384static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002385 struct sockaddr_in *peer, void *pack, unsigned len)
2386{
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002387 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002388 union gtpie_member *ie[GTPIE_SIZE];
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002389 uint8_t cause = EOF;
2390 uint8_t recovery;
2391 int rc = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01002392 void *cbp = NULL;
2393 uint8_t type = 0;
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002394 bool trigger_recovery = false;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002395 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002396
Harald Weltebed35df2011-11-02 13:06:18 +01002397 /* Remove packet from queue */
2398 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2399 return EOF;
jjako52c24142002-12-16 13:33:51 +00002400
Harald Weltebed35df2011-11-02 13:06:18 +01002401 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002402 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002403 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002404 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2405 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002406 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002407 }
jjako52c24142002-12-16 13:33:51 +00002408
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002409 /* Extract recovery (optional) */
2410 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery))
2411 trigger_recovery = true;
2412
Harald Weltebed35df2011-11-02 13:06:18 +01002413 /* Extract cause value (mandatory) */
2414 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002415 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002416 }
jjako52c24142002-12-16 13:33:51 +00002417
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002418 /* 3GPP TS 29.060 sec 8.2: "Receiving node shall send back to the source
2419 * of the message, a response with the appropriate cause value (either
2420 * "Non-existent" or "Context not found"). The Tunnel Endpoint
2421 * Identifier used in the response message shall be set to all zeroes."
2422 * Hence, TEID=0 in this scenario, it makes no sense to infer PDP ctx
2423 * from it. User is responsible to infer it from cbp */
2424 if (cause != GTPCAUSE_NON_EXIST && cause != GTPCAUSE_CONTEXT_NOT_FOUND) {
2425 /* Find the context in question */
2426 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
2427 gsn->err_unknownpdp++;
2428 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002429 "Unknown PDP context: TEI=0x%" PRIx32 "\n", get_tei(pack));
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002430 goto err_out;
2431 }
Harald Weltebed35df2011-11-02 13:06:18 +01002432 }
2433
2434 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002435 /* TODO: This does not handle GGSN-initiated update responses */
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002436 if (cause == GTPCAUSE_ACC_REQ) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002437 if (version == 0) {
2438 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2439 &pdp->qos_neg0,
2440 sizeof(pdp->qos_neg0))) {
2441 goto err_missing;
2442 }
2443
2444 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2445 goto err_missing;
2446 }
2447
2448 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2449 goto err_missing;
2450 }
Harald Weltebed35df2011-11-02 13:06:18 +01002451 }
2452
Daniel Willmannd9975522016-02-04 15:38:12 +01002453 if (version == 1) {
2454 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2455 goto err_missing;
2456 }
Harald Weltebed35df2011-11-02 13:06:18 +01002457
Daniel Willmannd9975522016-02-04 15:38:12 +01002458 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2459 goto err_missing;
2460 }
Pau Espin Pedrol0b1d9db2021-04-21 19:45:23 +02002461 /* Register that we have received a valid teic from GGSN */
2462 pdp->teic_confirmed = 1;
Daniel Willmannd9975522016-02-04 15:38:12 +01002463 }
2464
2465 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2466 goto err_missing;
2467 }
2468
2469 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2470 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2471 goto err_missing;
2472 }
2473
2474 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2475 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2476 goto err_missing;
2477 }
2478
2479 if (version == 1) {
2480 if (gtpie_gettlv
2481 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2482 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2483 goto err_missing;
2484 }
2485 }
Harald Weltebed35df2011-11-02 13:06:18 +01002486 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002487
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002488generic_ret:
2489 if (trigger_recovery)
2490 emit_cb_recovery(gsn, peer, pdp, recovery);
Daniel Willmannd9975522016-02-04 15:38:12 +01002491 if (gsn->cb_conf)
2492 gsn->cb_conf(type, cause, pdp, cbp);
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002493 return rc; /* Succes */
Daniel Willmannd9975522016-02-04 15:38:12 +01002494
2495err_missing:
2496 gsn->missing++;
2497 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2498 "Missing information field\n");
2499err_out:
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002500 rc = EOF;
2501 goto generic_ret;
jjako52c24142002-12-16 13:33:51 +00002502}
2503
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002504/* API: Deprecated. Send Delete PDP Context Request And free pdp ctx. */
jjako2c381332003-10-21 19:09:53 +00002505int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002506 int teardown)
2507{
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002508 struct pdp_t *linked_pdp;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002509
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002510 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002511 LOGP(DLGTP, LOGL_ERROR,
2512 "Unknown linked PDP context: %u\n", pdp->teic_own);
2513 return EOF;
2514 }
2515
2516 if (gtp_delete_context_req2(gsn, pdp, cbp, teardown) == EOF)
2517 return EOF;
2518
2519 if (teardown) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002520 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002521 } else {
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002522 /* If we end up here (no teardown) it means we still
2523 have at least another pdp context active for this
2524 PDN connection (since last DeleteReq should come
2525 with teardown enabled). If the ctx to delete is a
2526 secondary ctx, simply free it. If it's the primary
2527 ctx, mark it as nodata but don't free it since we
2528 need it to hold data linked together and we'll
2529 require it later to tear down the entire tree. Still,
2530 we announce its deletion through cb_delete_context
2531 because we don't want user to release its related
2532 data and not use it anymore.
2533 */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002534 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002535 if (gsn->cb_delete_context)
2536 gsn->cb_delete_context(pdp);
2537 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2538 pdp->nodata = 1;
2539 } else {
2540 gtp_freepdp(gsn, pdp);
2541 }
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002542 }
2543
2544 return 0;
2545}
2546
Oliver Smith1cde2c12019-05-13 11:35:03 +02002547/* API: Send Delete PDP Context Request. PDP CTX shall be free'd by user at any
Pau Espin Pedrol4e605b32019-08-29 13:54:28 +02002548 point in time later than this function through a call to pdp_freepdp(pdp) (or
2549 through gtp_freepdp() if willing to receive cb_delete_context() callback),
2550 but it must be freed no later than during cb_conf(GTP_DELETE_PDP_REQ, pdp) */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002551int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2552 int teardown)
2553{
Harald Weltebed35df2011-11-02 13:06:18 +01002554 union gtp_packet packet;
2555 unsigned int length =
2556 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2557 struct in_addr addr;
2558 struct pdp_t *linked_pdp;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002559 int count;
jjako2c381332003-10-21 19:09:53 +00002560
Harald Weltebed35df2011-11-02 13:06:18 +01002561 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2562 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002563 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002564 return EOF;
jjako2c381332003-10-21 19:09:53 +00002565 }
jjako2c381332003-10-21 19:09:53 +00002566
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002567 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002568 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002569 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002570 return EOF;
2571 }
2572
2573 if (!teardown) {
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002574 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002575 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002576 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002577 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002578 return EOF;
2579 }
2580 }
2581
2582 if (pdp->version == 1) {
2583 if (teardown)
2584 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2585 0xff);
2586
2587 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2588 }
2589
2590 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2591
Harald Weltebed35df2011-11-02 13:06:18 +01002592 return 0;
jjako2c381332003-10-21 19:09:53 +00002593}
jjako08d331d2003-10-13 20:33:30 +00002594
jjako52c24142002-12-16 13:33:51 +00002595/* Send Delete PDP Context Response */
2596int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002597 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002598 void *pack, unsigned len,
2599 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002600 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002601{
Harald Weltebed35df2011-11-02 13:06:18 +01002602 union gtp_packet packet;
Harald Weltebed35df2011-11-02 13:06:18 +01002603 unsigned int length =
2604 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00002605
Harald Weltebed35df2011-11-02 13:06:18 +01002606 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002607
Harald Weltebed35df2011-11-02 13:06:18 +01002608 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2609 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002610
Harald Weltebed35df2011-11-02 13:06:18 +01002611 if (cause == GTPCAUSE_ACC_REQ) {
2612 if ((teardown) || (version == 0)) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002613 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002614 } else {
2615 /* If we end up here (no teardown) it means we still
2616 have at least another pdp context active for this
2617 PDN connection (since last DeleteReq should come
2618 with teardown enabled). If the ctx to delete is a
2619 secondary ctx, simply free it. If it's the primary
2620 ctx, mark it as nodata but don't free it since we
2621 need it to hold data linked together and we'll
2622 require it later to tear down the entire tree. Still,
2623 we announce its deletion through cb_delete_context
2624 because we don't want user to release its related
2625 data and not use it anymore.
2626 */
Harald Weltebed35df2011-11-02 13:06:18 +01002627 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002628 if (gsn->cb_delete_context)
2629 gsn->cb_delete_context(pdp);
2630 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2631 pdp->nodata = 1;
2632 } else {
2633 gtp_freepdp(gsn, pdp);
2634 }
Harald Weltebed35df2011-11-02 13:06:18 +01002635 }
jjako2c381332003-10-21 19:09:53 +00002636 }
Harald Weltebed35df2011-11-02 13:06:18 +01002637 /* if (cause == GTPCAUSE_ACC_REQ) */
2638 return 0;
jjako52c24142002-12-16 13:33:51 +00002639}
2640
2641/* Handle Delete PDP Context Request */
2642int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002643 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002644 void *pack, unsigned len)
2645{
2646 struct pdp_t *pdp = NULL;
2647 struct pdp_t *linked_pdp = NULL;
2648 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002649
Harald Weltebed35df2011-11-02 13:06:18 +01002650 uint16_t seq = get_seq(pack);
2651 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002652
Harald Weltebed35df2011-11-02 13:06:18 +01002653 uint8_t nsapi;
2654 uint8_t teardown = 0;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002655 int count;
jjako52c24142002-12-16 13:33:51 +00002656
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002657 /* Is this a duplicate ? */
2658 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002659 return 0; /* We allready send off response once */
2660 }
jjako2c381332003-10-21 19:09:53 +00002661
Harald Weltebed35df2011-11-02 13:06:18 +01002662 /* Find the linked context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002663 if (gtp_pdp_getgtp1(gsn, &linked_pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002664 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002665 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002666 "Unknown PDP context: TEI=0x%" PRIx32 "\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002667 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2668 NULL, NULL, GTPCAUSE_NON_EXIST,
2669 teardown);
2670 }
jjako2c381332003-10-21 19:09:53 +00002671
Harald Weltebed35df2011-11-02 13:06:18 +01002672 /* If version 0 this is also the secondary context */
2673 if (version == 0)
2674 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002675
Harald Weltebed35df2011-11-02 13:06:18 +01002676 /* Decode information elements */
2677 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2678 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002679 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2680 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002681 if (0 == version)
2682 return EOF;
2683 else
2684 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2685 len, NULL, NULL,
2686 GTPCAUSE_INVALID_MESSAGE,
2687 teardown);
2688 }
2689
2690 if (version == 1) {
2691 /* NSAPI (mandatory) */
2692 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2693 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002694 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002695 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002696 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2697 len, NULL, NULL,
2698 GTPCAUSE_MAN_IE_MISSING,
2699 teardown);
2700 }
2701
2702 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002703 if (gtp_pdp_getgtp1(gsn, &pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
Harald Weltebed35df2011-11-02 13:06:18 +01002704 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002705 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2706 "Unknown PDP context: Secondary TEI=0x%" PRIx32 "\n",
2707 linked_pdp->secondary_tei[nsapi & 0x0f]);
Harald Weltebed35df2011-11-02 13:06:18 +01002708 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2709 len, NULL, NULL,
2710 GTPCAUSE_NON_EXIST,
2711 teardown);
2712 }
2713
2714 /* Teardown (conditional) */
2715 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2716
2717 if (!teardown) {
Pau Espin Pedrol742a6b52019-05-30 13:36:10 +02002718 /* TS 29.060 section 7.3.5: If a GSN receives a Delete PDP context
2719 * without a Teardown Indicator or with a Teardown Indicator with
2720 * value set to "0" and only that PDP context is active for a PDN
2721 * connection, then the GSN shall ignore the message. (Note:
2722 * This is symptom of a race condition. The reliable delivery of
2723 * signalling messages will eventually lead to a consistent
2724 * situation, allowing the teardown of the PDP context.)
2725 */
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002726 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002727 if (count <= 1) {
Pau Espin Pedrold1bd6fc2018-07-13 19:11:45 +02002728 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2729 "Ignoring CTX DEL without teardown and count=%d\n",
2730 count);
Harald Weltebed35df2011-11-02 13:06:18 +01002731 return 0; /* 29.060 7.3.5 Ignore message */
2732 }
2733 }
2734 }
2735
2736 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2737 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002738}
2739
jjako52c24142002-12-16 13:33:51 +00002740/* Handle Delete PDP Context Response */
2741int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002742 struct sockaddr_in *peer, void *pack, unsigned len)
2743{
2744 union gtpie_member *ie[GTPIE_SIZE];
2745 uint8_t cause;
2746 void *cbp = NULL;
2747 uint8_t type = 0;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002748 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002749 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002750
Harald Weltebed35df2011-11-02 13:06:18 +01002751 /* Remove packet from queue */
2752 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2753 return EOF;
jjako52c24142002-12-16 13:33:51 +00002754
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002755 /* Find the context in question. It may not be available if gtp_delete_context_req
2756 * was used and as a result the PDP ctx was already freed */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002757 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002758 gsn->err_unknownpdp++;
2759 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002760 "Unknown PDP context: TEI=0x%" PRIx32 " (expected if "
2761 "gtp_delete_context_req is used or pdp ctx was freed "
2762 "manually before response)\n", get_tei(pack));
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002763 if (gsn->cb_conf)
2764 gsn->cb_conf(type, EOF, NULL, cbp);
2765 return EOF;
2766 }
2767
Harald Weltebed35df2011-11-02 13:06:18 +01002768 /* Decode information elements */
2769 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2770 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002771 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2772 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002773 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002774 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002775 return EOF;
2776 }
2777
2778 /* Extract cause value (mandatory) */
2779 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2780 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002781 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2782 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002783 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002784 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002785 return EOF;
2786 }
2787
2788 /* Check the cause value (again) */
2789 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2790 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002791 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2792 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002793 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002794 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002795 return EOF;
2796 }
2797
2798 /* Callback function to notify application */
2799 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002800 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002801
2802 return 0;
jjako52c24142002-12-16 13:33:51 +00002803}
2804
Harald Welte54d082e2017-08-12 22:43:21 +02002805/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002806static int gtp_error_ind_resp(struct gsn_t *gsn, uint8_t version,
jjako08d331d2003-10-13 20:33:30 +00002807 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002808 void *pack, unsigned len)
2809{
Harald Weltebed35df2011-11-02 13:06:18 +01002810 union gtp_packet packet;
2811 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2812
Harald Welte54d082e2017-08-12 22:43:21 +02002813 if (version == 1) {
2814 /* Mandatory 7.7.13 TEI Data I */
2815 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2816 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2817
2818 /* Mandatory 7.7.32 GSN Address */
2819 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2820 sizeof(gsn->gsnu), &gsn->gsnu);
2821 }
2822
Harald Weltebed35df2011-11-02 13:06:18 +01002823 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2824 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002825}
2826
2827/* Handle Error Indication */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002828static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002829 struct sockaddr_in *peer, void *pack, unsigned len)
2830{
Harald Welte37d5b152017-08-12 23:58:29 +02002831 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002832 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002833
Harald Weltebed35df2011-11-02 13:06:18 +01002834 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002835 if (version == 0) {
Vadim Yanitskiy68c5a742019-08-30 21:04:19 +02002836 if (gtp_pdp_tidget(gsn, &pdp, get_tid(pack))) {
Harald Welte37d5b152017-08-12 23:58:29 +02002837 gsn->err_unknownpdp++;
2838 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002839 "Unknown PDP context: TID=0x%" PRIx64 "\n",
2840 get_tid(pack));
Harald Welte37d5b152017-08-12 23:58:29 +02002841 return EOF;
2842 }
2843 } else if (version == 1) {
2844 /* we have to look-up based on the *peer* TEID */
2845 int hlen = get_hlen(pack);
2846 uint32_t teid_gn;
2847
2848 /* Decode information elements */
2849 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2850 gsn->invalid++;
2851 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2852 "Invalid message format\n");
2853 return EOF;
2854 }
2855
2856 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2857 gsn->missing++;
2858 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2859 "Missing mandatory information field\n");
2860 return EOF;
2861 }
2862
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002863 if (gtp_pdp_getgtp1_peer_d(gsn, &pdp, peer, teid_gn)) {
Harald Welte37d5b152017-08-12 23:58:29 +02002864 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002865 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2866 "Unknown PDP context: Peer TEID=0x%" PRIx32 "\n",
2867 teid_gn);
Harald Welte37d5b152017-08-12 23:58:29 +02002868 return EOF;
2869 }
Vadim Yanitskiybdf2cf92019-08-30 21:23:11 +02002870 } else {
2871 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
2872 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002873 }
jjako52c24142002-12-16 13:33:51 +00002874
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002875 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2876 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002877
Harald Weltebd228242017-11-06 03:16:49 +09002878 /* This is obvious from above code, given the semantics of the
2879 * functions above, but Coverity doesn't figure this out, so
2880 * let's make it clear. It's good style anyway in case above
2881 * code should ever change. */
2882 OSMO_ASSERT(pdp);
2883
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002884 gtp_freepdp(gsn, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002885 return 0;
jjako52c24142002-12-16 13:33:51 +00002886}
2887
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002888static int gtp_gpdu_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002889 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2890{
jjako08d331d2003-10-13 20:33:30 +00002891
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002892 int hlen;
jjako52c24142002-12-16 13:33:51 +00002893
Harald Weltebed35df2011-11-02 13:06:18 +01002894 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002895
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002896 switch (version) {
2897 case 0:
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002898 if (gtp_pdp_getgtp0(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002899 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002900 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2901 "Unknown PDP context: TEI=0x%" PRIx32 "\n",
2902 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002903 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2904 len);
2905 }
2906 hlen = GTP0_HEADER_SIZE;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002907 break;
2908 case 1:
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002909 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002910 gsn->err_unknownpdp++;
Pau Espin Pedrolbfd31192021-04-22 15:01:23 +02002911 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2912 "Unknown PDP context: TEI=0x%" PRIx32 "\n",
2913 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002914 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2915 len);
2916 }
jjako08d331d2003-10-13 20:33:30 +00002917
Harald Weltebed35df2011-11-02 13:06:18 +01002918 /* Is this a long or a short header ? */
2919 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2920 hlen = GTP1_HEADER_SIZE_LONG;
2921 else
2922 hlen = GTP1_HEADER_SIZE_SHORT;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002923 break;
2924 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002925 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002926 "Unknown version: %d\n", version);
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002927 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002928 }
jjako08d331d2003-10-13 20:33:30 +00002929
Harald Weltebed35df2011-11-02 13:06:18 +01002930 /* If the GPDU was not from the peer GSN tell him to delete context */
2931 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2932 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002933 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002934 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2935 }
jjako52c24142002-12-16 13:33:51 +00002936
Harald Weltebed35df2011-11-02 13:06:18 +01002937 /* Callback function */
2938 if (gsn->cb_data_ind != 0)
2939 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2940
2941 return 0;
jjako52c24142002-12-16 13:33:51 +00002942}
2943
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002944/* Receives GTP packet and sends off for further processing
jjako52c24142002-12-16 13:33:51 +00002945 * Function will check the validity of the header. If the header
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002946 * is not valid the packet is either dropped or a version not
2947 * supported is returned to the peer.
jjako52c24142002-12-16 13:33:51 +00002948 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002949int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002950{
Harald Weltebed35df2011-11-02 13:06:18 +01002951 unsigned char buffer[PACKET_MAX];
2952 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002953 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002954 int status;
2955 struct gtp0_header *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002956 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002957 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002958
Harald Weltebed35df2011-11-02 13:06:18 +01002959 /* TODO: Need strategy of userspace buffering and blocking */
2960 /* Currently read is non-blocking and send is blocking. */
2961 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002962
Harald Weltebed35df2011-11-02 13:06:18 +01002963 while (1) { /* Loop until no more to read */
2964 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002965 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002966 return -1;
2967 }
2968 peerlen = sizeof(peer);
2969 if ((status =
2970 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2971 (struct sockaddr *)&peer, &peerlen)) < 0) {
2972 if (errno == EAGAIN)
2973 return 0;
2974 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002975 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002976 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002977 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2978 status, status ? strerror(errno) : "No error");
2979 return -1;
2980 }
jjako1db1c812003-07-06 20:53:57 +00002981
Harald Weltebed35df2011-11-02 13:06:18 +01002982 /* Need at least 1 byte in order to check version */
2983 if (status < (1)) {
2984 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002985 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2986 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002987 continue;
2988 }
jjako08d331d2003-10-13 20:33:30 +00002989
Harald Weltebed35df2011-11-02 13:06:18 +01002990 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002991
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002992 version = GTPHDR_F_GET_VER(pheader->flags);
2993
Harald Weltebed35df2011-11-02 13:06:18 +01002994 /* Version should be gtp0 (or earlier) */
2995 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2996 /* GTP 0 messages. If other version message is received we reply that we */
2997 /* only support version 0, implying that this is the only version */
2998 /* supported on this port */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002999 if (version > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003000 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003001 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3002 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003003 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
3004 continue;
3005 }
3006
3007 /* Check length of gtp0 packet */
3008 if (status < GTP0_HEADER_SIZE) {
3009 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003010 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3011 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003012 continue; /* Silently discard 29.60: 11.1.2 */
3013 }
3014
3015 /* Check packet length field versus length of packet */
3016 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
3017 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003018 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003019 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003020 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003021 continue; /* Silently discard */
3022 }
3023
3024 if ((gsn->mode == GTP_MODE_GGSN) &&
3025 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003026 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003027 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003028 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003029 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003030 "Unexpected GTPv0 Signalling Message '%s'\n",
3031 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003032 continue; /* Silently discard 29.60: 11.1.4 */
3033 }
3034
3035 if ((gsn->mode == GTP_MODE_SGSN) &&
3036 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003037 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003038 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003039 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003040 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003041 "Unexpected GTPv0 Signalling Message '%s'\n",
3042 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003043 continue; /* Silently discard 29.60: 11.1.4 */
3044 }
3045
3046 switch (pheader->type) {
3047 case GTP_ECHO_REQ:
3048 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3049 break;
3050 case GTP_ECHO_RSP:
3051 gtp_echo_conf(gsn, version, &peer, buffer, status);
3052 break;
3053 case GTP_NOT_SUPPORTED:
3054 gtp_unsup_ind(gsn, &peer, buffer, status);
3055 break;
3056 case GTP_CREATE_PDP_REQ:
3057 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3058 status);
3059 break;
3060 case GTP_CREATE_PDP_RSP:
3061 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3062 status);
3063 break;
3064 case GTP_UPDATE_PDP_REQ:
3065 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3066 status);
3067 break;
3068 case GTP_UPDATE_PDP_RSP:
3069 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3070 status);
3071 break;
3072 case GTP_DELETE_PDP_REQ:
3073 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3074 status);
3075 break;
3076 case GTP_DELETE_PDP_RSP:
3077 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3078 status);
3079 break;
3080 case GTP_ERROR:
3081 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3082 break;
3083 case GTP_GPDU:
3084 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3085 break;
3086 default:
3087 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003088 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3089 "Unknown GTP message type received: %d\n",
3090 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003091 break;
3092 }
3093 }
jjako08d331d2003-10-13 20:33:30 +00003094}
3095
jjako08d331d2003-10-13 20:33:30 +00003096int gtp_decaps1c(struct gsn_t *gsn)
3097{
Harald Weltebed35df2011-11-02 13:06:18 +01003098 unsigned char buffer[PACKET_MAX];
3099 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003100 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003101 int status;
3102 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003103 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003104 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00003105
Harald Weltebed35df2011-11-02 13:06:18 +01003106 /* TODO: Need strategy of userspace buffering and blocking */
3107 /* Currently read is non-blocking and send is blocking. */
3108 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003109
Harald Weltebed35df2011-11-02 13:06:18 +01003110 while (1) { /* Loop until no more to read */
3111 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003112 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003113 return -1;
3114 }
3115 peerlen = sizeof(peer);
3116 if ((status =
3117 recvfrom(fd, buffer, sizeof(buffer), 0,
3118 (struct sockaddr *)&peer, &peerlen)) < 0) {
3119 if (errno == EAGAIN)
3120 return 0;
3121 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003122 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003123 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003124 fd, (unsigned long)buffer, sizeof(buffer),
3125 status, status ? strerror(errno) : "No error");
3126 return -1;
3127 }
jjako08d331d2003-10-13 20:33:30 +00003128
Harald Weltebed35df2011-11-02 13:06:18 +01003129 /* Need at least 1 byte in order to check version */
3130 if (status < (1)) {
3131 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003132 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3133 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003134 continue;
3135 }
jjako08d331d2003-10-13 20:33:30 +00003136
Harald Weltebed35df2011-11-02 13:06:18 +01003137 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003138
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003139 version = GTPHDR_F_GET_VER(pheader->flags);
3140
Harald Weltebed35df2011-11-02 13:06:18 +01003141 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003142 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003143 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003144 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3145 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003146 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
3147 /*29.60: 11.1.1 */
3148 continue;
3149 }
jjako08d331d2003-10-13 20:33:30 +00003150
Harald Weltebed35df2011-11-02 13:06:18 +01003151 /* Version must be at least GTP 1 */
3152 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3153 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3154 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003155 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003156 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003157 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3158 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003159 continue;
3160 }
jjako08d331d2003-10-13 20:33:30 +00003161
Harald Weltebed35df2011-11-02 13:06:18 +01003162 /* Check packet flag field */
3163 if (((pheader->flags & 0xf7) != 0x32)) {
3164 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003165 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003166 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003167 continue;
3168 }
jjako2c381332003-10-21 19:09:53 +00003169
Harald Weltebed35df2011-11-02 13:06:18 +01003170 /* Check length of packet */
3171 if (status < GTP1_HEADER_SIZE_LONG) {
3172 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003173 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3174 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003175 continue; /* Silently discard 29.60: 11.1.2 */
3176 }
jjako2c381332003-10-21 19:09:53 +00003177
Harald Weltebed35df2011-11-02 13:06:18 +01003178 /* Check packet length field versus length of packet */
3179 if (status !=
3180 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3181 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003182 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003183 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003184 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003185 continue; /* Silently discard */
3186 }
jjako1db1c812003-07-06 20:53:57 +00003187
Harald Weltebed35df2011-11-02 13:06:18 +01003188 /* Check for extension headers */
3189 /* TODO: We really should cycle through the headers and determine */
3190 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003191 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003192 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003193 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3194 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003195 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3196 status);
jjako1db1c812003-07-06 20:53:57 +00003197
Harald Weltebed35df2011-11-02 13:06:18 +01003198 continue;
3199 }
3200
3201 if ((gsn->mode == GTP_MODE_GGSN) &&
3202 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003203 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003204 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003205 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003206 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003207 "Unexpected GTPv1 Signalling Message '%s'\n",
3208 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003209 continue; /* Silently discard 29.60: 11.1.4 */
3210 }
3211
3212 if ((gsn->mode == GTP_MODE_SGSN) &&
3213 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003214 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003215 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003216 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003217 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003218 "Unexpected GTPv1 Signalling Message '%s'\n",
3219 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003220 continue; /* Silently discard 29.60: 11.1.4 */
3221 }
3222
3223 switch (pheader->type) {
3224 case GTP_ECHO_REQ:
3225 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3226 break;
3227 case GTP_ECHO_RSP:
3228 gtp_echo_conf(gsn, version, &peer, buffer, status);
3229 break;
3230 case GTP_NOT_SUPPORTED:
3231 gtp_unsup_ind(gsn, &peer, buffer, status);
3232 break;
3233 case GTP_SUPP_EXT_HEADER:
3234 gtp_extheader_ind(gsn, &peer, buffer, status);
3235 break;
3236 case GTP_CREATE_PDP_REQ:
3237 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3238 status);
3239 break;
3240 case GTP_CREATE_PDP_RSP:
3241 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3242 status);
3243 break;
3244 case GTP_UPDATE_PDP_REQ:
3245 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3246 status);
3247 break;
3248 case GTP_UPDATE_PDP_RSP:
3249 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3250 status);
3251 break;
3252 case GTP_DELETE_PDP_REQ:
3253 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3254 status);
3255 break;
3256 case GTP_DELETE_PDP_RSP:
3257 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3258 status);
3259 break;
3260 case GTP_ERROR:
3261 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3262 break;
Pau Espin Pedrolf32c6a92021-05-03 17:58:55 +02003263 case GTP_RAN_INFO_RELAY:
3264 gtp_ran_info_relay_ind(gsn, version, &peer, buffer, status);
3265 break;
Harald Weltebed35df2011-11-02 13:06:18 +01003266 default:
3267 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003268 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3269 "Unknown GTP message type received: %u\n",
3270 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003271 break;
3272 }
3273 }
jjako52c24142002-12-16 13:33:51 +00003274}
3275
jjako08d331d2003-10-13 20:33:30 +00003276int gtp_decaps1u(struct gsn_t *gsn)
3277{
Harald Weltebed35df2011-11-02 13:06:18 +01003278 unsigned char buffer[PACKET_MAX];
3279 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003280 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003281 int status;
3282 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003283 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003284 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003285
Harald Weltebed35df2011-11-02 13:06:18 +01003286 /* TODO: Need strategy of userspace buffering and blocking */
3287 /* Currently read is non-blocking and send is blocking. */
3288 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003289
Harald Weltebed35df2011-11-02 13:06:18 +01003290 while (1) { /* Loop until no more to read */
3291 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003292 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003293 return -1;
3294 }
3295 peerlen = sizeof(peer);
3296 if ((status =
3297 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3298 (struct sockaddr *)&peer, &peerlen)) < 0) {
3299 if (errno == EAGAIN)
3300 return 0;
3301 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003302 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003303 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003304 gsn->fd1u, (unsigned long)buffer,
3305 sizeof(buffer), status,
3306 status ? strerror(errno) : "No error");
3307 return -1;
3308 }
jjako08d331d2003-10-13 20:33:30 +00003309
Harald Weltebed35df2011-11-02 13:06:18 +01003310 /* Need at least 1 byte in order to check version */
3311 if (status < (1)) {
3312 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003313 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3314 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003315 continue;
3316 }
jjako08d331d2003-10-13 20:33:30 +00003317
Harald Weltebed35df2011-11-02 13:06:18 +01003318 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003319
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003320 version = GTPHDR_F_GET_VER(pheader->flags);
3321
Harald Weltebed35df2011-11-02 13:06:18 +01003322 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003323 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003324 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003325 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3326 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003327 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3328 continue;
3329 }
jjako08d331d2003-10-13 20:33:30 +00003330
Harald Weltebed35df2011-11-02 13:06:18 +01003331 /* Version must be at least GTP 1 */
3332 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3333 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3334 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003335 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003336 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003337 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3338 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003339 continue;
3340 }
jjako2c381332003-10-21 19:09:53 +00003341
Harald Weltebed35df2011-11-02 13:06:18 +01003342 /* Check packet flag field (allow both with and without sequence number) */
3343 if (((pheader->flags & 0xf5) != 0x30)) {
3344 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003345 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003346 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003347 continue;
3348 }
jjako2c381332003-10-21 19:09:53 +00003349
Harald Weltebed35df2011-11-02 13:06:18 +01003350 /* Check length of packet */
3351 if (status < GTP1_HEADER_SIZE_SHORT) {
3352 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003353 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3354 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003355 continue; /* Silently discard 29.60: 11.1.2 */
3356 }
3357
3358 /* Check packet length field versus length of packet */
3359 if (status !=
3360 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3361 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003362 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003363 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003364 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003365 continue; /* Silently discard */
3366 }
3367
3368 /* Check for extension headers */
3369 /* TODO: We really should cycle through the headers and determine */
3370 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003371 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003372 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003373 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3374 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003375 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3376 status);
3377
3378 continue;
3379 }
3380
3381 switch (pheader->type) {
3382 case GTP_ECHO_REQ:
3383 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3384 break;
3385 case GTP_ECHO_RSP:
3386 gtp_echo_conf(gsn, version, &peer, buffer, status);
3387 break;
3388 case GTP_SUPP_EXT_HEADER:
3389 gtp_extheader_ind(gsn, &peer, buffer, status);
3390 break;
3391 case GTP_ERROR:
3392 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3393 break;
3394 /* Supported header extensions */
3395 case GTP_GPDU:
3396 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3397 break;
3398 default:
3399 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003400 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3401 "Unknown GTP message type received: %u\n",
3402 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003403 break;
3404 }
3405 }
jjako08d331d2003-10-13 20:33:30 +00003406}
3407
Harald Weltebed35df2011-11-02 13:06:18 +01003408int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003409{
Harald Weltebed35df2011-11-02 13:06:18 +01003410 union gtp_packet packet;
3411 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003412 struct msghdr msgh;
3413 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003414 int fd;
jjako52c24142002-12-16 13:33:51 +00003415
Harald Welte471e3492017-09-24 16:12:39 +08003416 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003417 memset(&addr, 0, sizeof(addr));
3418 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003419#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003420 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003421#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003422 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003423
Harald Welte471e3492017-09-24 16:12:39 +08003424 /* prepare msghdr */
3425 memset(&msgh, 0, sizeof(msgh));
3426 msgh.msg_name = &addr;
3427 msgh.msg_namelen = sizeof(addr);
3428 msgh.msg_iov = iov;
3429 msgh.msg_iovlen = ARRAY_SIZE(iov);
3430
3431 /* prepare iovectors */
3432 iov[0].iov_base = &packet;
3433 /* iov[0].iov_len is not known here yet */
3434 iov[1].iov_base = pack;
3435 iov[1].iov_len = len;
3436
Harald Weltebed35df2011-11-02 13:06:18 +01003437 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003438
Harald Welte471e3492017-09-24 16:12:39 +08003439 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003440 addr.sin_port = htons(GTP0_PORT);
3441 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003442
Harald Weltebed35df2011-11-02 13:06:18 +01003443 get_default_gtp(0, GTP_GPDU, &packet);
3444 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003445 if (pdp->tx_gpdu_seq)
3446 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3447 else
3448 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003449 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003450 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003451 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003452
Harald Weltebed35df2011-11-02 13:06:18 +01003453 addr.sin_port = htons(GTP1U_PORT);
3454 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003455
Harald Weltebed35df2011-11-02 13:06:18 +01003456 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003457 if (pdp->tx_gpdu_seq) {
3458 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3459 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3460 GTP1_HEADER_SIZE_LONG);
3461 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3462 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3463 } else {
3464 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3465 packet.gtp1s.h.length = hton16(len);
3466 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3467 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3468 }
Harald Weltebed35df2011-11-02 13:06:18 +01003469 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003470 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003471 return EOF;
3472 }
3473
3474 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003475 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003476 return -1;
3477 }
3478
Harald Welte471e3492017-09-24 16:12:39 +08003479 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003480 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003481 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003482 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003483 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3484 strerror(errno));
3485 return EOF;
3486 }
3487 return 0;
jjako52c24142002-12-16 13:33:51 +00003488}
3489
jjako52c24142002-12-16 13:33:51 +00003490/* ***********************************************************
3491 * Conversion functions
3492 *************************************************************/
3493
jjako52c24142002-12-16 13:33:51 +00003494/* ***********************************************************
3495 * IP address conversion functions
3496 * There exist several types of address representations:
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01003497 * - eua: End User Address. (29.060, 7.7.27, message type 128)
jjako52c24142002-12-16 13:33:51 +00003498 * Used for signalling address to mobile station. Supports IPv4
3499 * IPv6 x.25 etc. etc.
3500 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3501 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3502 * - in_addr: IPv4 address struct.
3503 * - sockaddr_in: Socket API representation of IP address and
3504 * port number.
3505 *************************************************************/
3506
Harald Weltebed35df2011-11-02 13:06:18 +01003507int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3508{
Harald Weltecee75462017-09-24 17:45:05 +08003509 eua->v[0] = PDP_EUA_ORG_IETF;
3510 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003511 if (src) {
3512 eua->l = 6;
3513 memcpy(&eua->v[2], src, 4);
3514 } else {
3515 eua->l = 2;
3516 }
3517 return 0;
jjako52c24142002-12-16 13:33:51 +00003518}
3519
Harald Weltebed35df2011-11-02 13:06:18 +01003520int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3521{
Harald Weltecee75462017-09-24 17:45:05 +08003522 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 +01003523 return -1; /* Not IPv4 address */
3524 memcpy(dst, &eua->v[2], 4);
3525 return 0;
jjako52c24142002-12-16 13:33:51 +00003526}
3527
Harald Weltebed35df2011-11-02 13:06:18 +01003528int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3529{
3530 memset(dst, 0, sizeof(struct in_addr));
3531 if (gsna->l != 4)
3532 return EOF; /* Return if not IPv4 */
3533 memcpy(dst, gsna->v, gsna->l);
3534 return 0;
jjako52c24142002-12-16 13:33:51 +00003535}
3536
Harald Weltebed35df2011-11-02 13:06:18 +01003537int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3538{
3539 memset(gsna, 0, sizeof(struct ul16_t));
3540 gsna->l = 4;
3541 memcpy(gsna->v, src, gsna->l);
3542 return 0;
jjako52c24142002-12-16 13:33:51 +00003543}
Harald Welteb10ee082017-08-12 19:29:16 +02003544
3545/* TS 29.060 has yet again a different encoding for IMSIs than
3546 * what we have in other places, so we cannot use the gsm48
3547 * decoding functions. Also, libgtp uses an uint64_t in
3548 * _network byte order_ to contain BCD digits ?!? */
3549const char *imsi_gtp2str(const uint64_t *imsi)
3550{
Harald Weltea06120d2017-11-06 03:12:54 +09003551 static char buf[sizeof(*imsi)*2+1];
Harald Welteb10ee082017-08-12 19:29:16 +02003552 const uint8_t *imsi8 = (const uint8_t *) imsi;
3553 unsigned int i, j = 0;
3554
3555 for (i = 0; i < sizeof(*imsi); i++) {
3556 uint8_t nibble;
3557
3558 nibble = imsi8[i] & 0xf;
3559 if (nibble == 0xf)
3560 break;
3561 buf[j++] = osmo_bcd2char(nibble);
3562
3563 nibble = imsi8[i] >> 4;
3564 if (nibble == 0xf)
3565 break;
3566 buf[j++] = osmo_bcd2char(nibble);
3567 }
3568
3569 buf[j++] = '\0';
3570 return buf;
3571}
Keithcbc07bd2020-10-10 12:17:26 +02003572
Keithfb2a7292020-10-12 15:32:07 +02003573/* Generate the GTP IMSI IE according to 09.60 Section 7.9.2 */
3574uint64_t gtp_imsi_str2gtp(const char *str)
Keithcbc07bd2020-10-10 12:17:26 +02003575{
Keithfb2a7292020-10-12 15:32:07 +02003576 uint64_t imsi64 = 0;
3577 unsigned int n;
3578 unsigned int imsi_len = strlen(str);
Keithcbc07bd2020-10-10 12:17:26 +02003579
Keithfb2a7292020-10-12 15:32:07 +02003580 if (imsi_len > 16) {
3581 LOGP(DLGTP, LOGL_NOTICE, "IMSI length > 16 not supported!\n");
3582 return 0;
3583 }
3584
3585 for (n = 0; n < 16; n++) {
3586 uint64_t val;
3587 if (n < imsi_len)
3588 val = (str[n]-'0') & 0xf;
3589 else
3590 val = 0xf;
3591 imsi64 |= (val << (n*4));
3592 }
3593 return imsi64;
3594}