blob: d0135b9d8eb64c9cb45589e00a2c6ca7919cee6c [file] [log] [blame]
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001/*
Harald Welte632e8432017-09-05 18:12:14 +02002 * OsmoGGSN - Gateway GPRS Support Node
jjako0fe0df02004-09-17 11:30:40 +00003 * Copyright (C) 2002, 2003, 2004 Mondru AB.
Harald Welte632e8432017-09-05 18:12:14 +02004 * Copyright (C) 2010-2011, 2016-2017 Harald Welte <laforge@gnumonks.org>
5 * Copyright (C) 2015-2017 sysmocom - s.f.m.c. GmbH
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01006 *
jjako52c24142002-12-16 13:33:51 +00007 * The contents of this file may be used under the terms of the GNU
8 * General Public License Version 2, provided that the above copyright
9 * notice and this permission notice is included in all copies or
10 * substantial portions of the software.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +010011 *
jjako52c24142002-12-16 13:33:51 +000012 */
13
14/*
15 * gtp.c: Contains all GTP functionality. Should be able to handle multiple
Pau Espin Pedrol732131d2018-01-25 17:23:09 +010016 * tunnels in the same program.
jjako52c24142002-12-16 13:33:51 +000017 *
18 * TODO:
19 * - Do we need to handle fragmentation?
20 */
21
jjako52c24142002-12-16 13:33:51 +000022#ifdef __linux__
23#define _GNU_SOURCE 1
24#endif
25
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +010026#include <osmocom/core/logging.h>
27#include <osmocom/core/utils.h>
28
Holger Hans Peter Freyther5816bcf2014-04-04 11:43:09 +020029#if defined(__FreeBSD__)
30#include <sys/endian.h>
31#endif
32
jjako0fe0df02004-09-17 11:30:40 +000033#include "../config.h"
34#ifdef HAVE_STDINT_H
35#include <stdint.h>
36#endif
jjako52c24142002-12-16 13:33:51 +000037
jjako52c24142002-12-16 13:33:51 +000038#include <stdio.h>
39#include <stdarg.h>
40#include <stdlib.h>
41#include <sys/time.h>
42#include <sys/types.h>
43#include <sys/socket.h>
44#include <netinet/in.h>
45#include <arpa/inet.h>
46#include <sys/stat.h>
47#include <time.h>
48#include <unistd.h>
49#include <string.h>
50#include <errno.h>
51#include <fcntl.h>
Alexander Huemerdb852a12015-11-06 20:59:01 +010052#include <inttypes.h>
jjako52c24142002-12-16 13:33:51 +000053
54#include <arpa/inet.h>
55
jjakobae2cd42004-01-09 12:04:39 +000056/* #include <stdint.h> ISO C99 types */
jjako52c24142002-12-16 13:33:51 +000057
58#include "pdp.h"
59#include "gtp.h"
60#include "gtpie.h"
61#include "queue.h"
62
Harald Welte95848ba2011-11-02 18:17:50 +010063/* According to section 14.2 of 3GPP TS 29.006 version 6.9.0 */
64#define N3_REQUESTS 5
65
66#define T3_REQUEST 3
67
jjako1db1c812003-07-06 20:53:57 +000068/* Error reporting functions */
69
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +010070#define GTP_LOGPKG(pri, peer, pack, len, fmt, args...) \
71 logp2(DLGTP, pri, __FILE__, __LINE__, 0, \
72 "Packet from %s:%u, length: %d content: %s: " fmt, \
73 inet_ntoa((peer)->sin_addr), htons((peer)->sin_port), \
74 len, osmo_hexdump((const uint8_t *) pack, len), \
75 ##args);
jjako1db1c812003-07-06 20:53:57 +000076
Neels Hofmeyr9b097382015-10-12 14:00:19 +020077#define LOGP_WITH_ADDR(ss, level, addr, fmt, args...) \
78 LOGP(ss, level, "addr(%s:%d) " fmt, \
79 inet_ntoa((addr).sin_addr), htons((addr).sin_port), \
80 ##args);
81
jjako52c24142002-12-16 13:33:51 +000082/* API Functions */
83
Harald Weltebed35df2011-11-02 13:06:18 +010084const char *gtp_version()
jjako52c24142002-12-16 13:33:51 +000085{
Harald Weltebed35df2011-11-02 13:06:18 +010086 return VERSION;
jjako52c24142002-12-16 13:33:51 +000087}
88
Maxe6612772018-01-11 18:25:37 +010089const struct value_string gtp_type_names[] = {
90 { GTP_ECHO_REQ, "Echo Request" },
91 { GTP_ECHO_RSP, "Echo Response" },
92 { GTP_NOT_SUPPORTED, "Version Not Supported" },
93 { GTP_ALIVE_REQ, "Node Alive Request" },
94 { GTP_ALIVE_RSP, "Node Alive Response" },
95 { GTP_REDIR_REQ, "Redirection Request" },
96 { GTP_REDIR_RSP, "Redirection Response" },
97 { GTP_CREATE_PDP_REQ, "Create PDP Context Request" },
98 { GTP_CREATE_PDP_RSP, "Create PDP Context Response" },
99 { GTP_UPDATE_PDP_REQ, "Update PDP Context Request" },
100 { GTP_UPDATE_PDP_RSP, "Update PDP Context Response" },
101 { GTP_DELETE_PDP_REQ, "Delete PDP Context Request" },
102 { GTP_DELETE_PDP_RSP, "Delete PDP Context Response" },
103 { GTP_ERROR, "Error Indication" },
104 { GTP_PDU_NOT_REQ, "PDU Notification Request" },
105 { GTP_PDU_NOT_RSP, "PDU Notification Response" },
106 { GTP_PDU_NOT_REJ_REQ, "PDU Notification Reject Request" },
107 { GTP_PDU_NOT_REJ_RSP, "PDU Notification Reject Response" },
108 { GTP_SUPP_EXT_HEADER, "Supported Extension Headers Notification" },
109 { GTP_SND_ROUTE_REQ, "Send Routeing Information for GPRS Request" },
110 { GTP_SND_ROUTE_RSP, "Send Routeing Information for GPRS Response" },
111 { GTP_FAILURE_REQ, "Failure Report Request" },
112 { GTP_FAILURE_RSP, "Failure Report Response" },
113 { GTP_MS_PRESENT_REQ, "Note MS GPRS Present Request" },
114 { GTP_MS_PRESENT_RSP, "Note MS GPRS Present Response" },
115 { GTP_IDEN_REQ, "Identification Request" },
116 { GTP_IDEN_RSP, "Identification Response" },
117 { GTP_SGSN_CONTEXT_REQ,"SGSN Context Request" },
118 { GTP_SGSN_CONTEXT_RSP,"SGSN Context Response" },
119 { GTP_SGSN_CONTEXT_ACK,"SGSN Context Acknowledge" },
120 { GTP_FWD_RELOC_REQ, "Forward Relocation Request" },
121 { GTP_FWD_RELOC_RSP, "Forward Relocation Response" },
122 { GTP_FWD_RELOC_COMPL, "Forward Relocation Complete" },
123 { GTP_RELOC_CANCEL_REQ,"Relocation Cancel Request" },
124 { GTP_RELOC_CANCEL_RSP,"Relocation Cancel Response" },
125 { GTP_FWD_SRNS, "Forward SRNS Context" },
126 { GTP_FWD_RELOC_ACK, "Forward Relocation Complete Acknowledge" },
127 { GTP_FWD_SRNS_ACK, "Forward SRNS Context Acknowledge" },
128 { GTP_DATA_TRAN_REQ, "Data Record Transfer Request" },
129 { GTP_DATA_TRAN_RSP, "Data Record Transfer Response" },
130 { GTP_GPDU, "G-PDU" },
131 { 0, NULL }
132};
133
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +0200134/* Deprecated, use gtp_pdp_newpdp() instead */
Harald Weltebed35df2011-11-02 13:06:18 +0100135int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
136 uint64_t imsi, uint8_t nsapi)
137{
Harald Weltee257be12017-08-12 14:55:09 +0200138 int rc;
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +0200139 rc = gtp_pdp_newpdp(gsn, pdp, imsi, nsapi, NULL);
Harald Weltee257be12017-08-12 14:55:09 +0200140 return rc;
jjako52c24142002-12-16 13:33:51 +0000141}
142
Harald Weltebed35df2011-11-02 13:06:18 +0100143int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp)
144{
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +0200145 if (gsn->cb_delete_context)
146 gsn->cb_delete_context(pdp);
Harald Weltebed35df2011-11-02 13:06:18 +0100147 return pdp_freepdp(pdp);
jjako52c24142002-12-16 13:33:51 +0000148}
149
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +0200150/* Free pdp and all its secondary PDP contexts. Must be called on the primary PDP context. */
151int gtp_freepdp_teardown(struct gsn_t *gsn, struct pdp_t *pdp)
152{
153 int n;
154 struct pdp_t *secondary_pdp;
155 OSMO_ASSERT(!pdp->secondary);
156
157 for (n = 0; n < PDP_MAXNSAPI; n++) {
158 if (pdp->secondary_tei[n]) {
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +0200159 if (gtp_pdp_getgtp1(gsn, &secondary_pdp,
160 pdp->secondary_tei[n])) {
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +0200161 LOGP(DLGTP, LOGL_ERROR,
162 "Unknown secondary PDP context\n");
163 continue;
164 }
165 if (pdp != secondary_pdp) {
166 gtp_freepdp(gsn, secondary_pdp);
167 }
168 }
169 }
170
171 return gtp_freepdp(gsn, pdp);
172}
173
jjako52c24142002-12-16 13:33:51 +0000174/* gtp_gpdu */
175
Harald Weltebed35df2011-11-02 13:06:18 +0100176extern int gtp_fd(struct gsn_t *gsn)
177{
178 return gsn->fd0;
jjako52c24142002-12-16 13:33:51 +0000179}
180
181/* gtp_decaps */
182/* gtp_retrans */
183/* gtp_retranstimeout */
184
jjako08d331d2003-10-13 20:33:30 +0000185int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100186 int (*cb) (struct sockaddr_in * peer))
187{
188 gsn->cb_unsup_ind = cb;
189 return 0;
jjako08d331d2003-10-13 20:33:30 +0000190}
191
jjako2c381332003-10-21 19:09:53 +0000192int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100193 int (*cb) (struct sockaddr_in * peer))
194{
195 gsn->cb_extheader_ind = cb;
196 return 0;
jjako2c381332003-10-21 19:09:53 +0000197}
198
jjako08d331d2003-10-13 20:33:30 +0000199/* API: Initialise delete context callback */
200/* Called whenever a pdp context is deleted for any reason */
Harald Weltebed35df2011-11-02 13:06:18 +0100201int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
jjako52c24142002-12-16 13:33:51 +0000202{
Harald Weltebed35df2011-11-02 13:06:18 +0100203 gsn->cb_delete_context = cb;
204 return 0;
jjako52c24142002-12-16 13:33:51 +0000205}
206
jjako52c24142002-12-16 13:33:51 +0000207int gtp_set_cb_conf(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100208 int (*cb) (int type, int cause,
209 struct pdp_t * pdp, void *cbp))
210{
211 gsn->cb_conf = cb;
212 return 0;
jjako52c24142002-12-16 13:33:51 +0000213}
214
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200215static void emit_cb_recovery(struct gsn_t *gsn, struct sockaddr_in * peer,
216 struct pdp_t * pdp, uint8_t recovery)
217{
218 if (gsn->cb_recovery)
219 gsn->cb_recovery(peer, recovery);
220 if (gsn->cb_recovery2)
221 gsn->cb_recovery2(peer, pdp, recovery);
Pau Espin Pedrol5d8b2262019-08-22 15:00:00 +0200222 if (gsn->cb_recovery3)
223 gsn->cb_recovery3(gsn, peer, pdp, recovery);
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200224}
225
Harald Welte629e9862010-12-24 20:58:09 +0100226int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100227 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
228{
229 gsn->cb_recovery = cb;
230 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100231}
232
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200233/* cb_recovery()
234 * pdp may be NULL if Recovery IE was received from a message independent
235 * of any PDP ctx (such as Echo Response), or because pdp ctx is unknown to the
236 * local setup. In case pdp is known, caller may want to keep that pdp alive to
237 * handle subsequent msg cb as this specific pdp ctx is still valid according to
238 * specs.
239 */
240int gtp_set_cb_recovery2(struct gsn_t *gsn,
241 int (*cb_recovery2) (struct sockaddr_in * peer, struct pdp_t * pdp, uint8_t recovery))
242{
243 gsn->cb_recovery2 = cb_recovery2;
244 return 0;
245}
246
Pau Espin Pedrol5d8b2262019-08-22 15:00:00 +0200247/* cb_recovery()
248 * pdp may be NULL if Recovery IE was received from a message independent
249 * of any PDP ctx (such as Echo Response), or because pdp ctx is unknown to the
250 * local setup. In case pdp is known, caller may want to keep that pdp alive to
251 * handle subsequent msg cb as this specific pdp ctx is still valid according to
252 * specs.
253 */
254int gtp_set_cb_recovery3(struct gsn_t *gsn,
255 int (*cb_recovery3) (struct gsn_t *gsn, struct sockaddr_in *peer,
256 struct pdp_t *pdp, uint8_t recovery))
257{
258 gsn->cb_recovery3 = cb_recovery3;
259 return 0;
260}
261
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +0100262int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100263 int (*cb_data_ind) (struct pdp_t * pdp,
264 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000265{
Harald Weltebed35df2011-11-02 13:06:18 +0100266 gsn->cb_data_ind = cb_data_ind;
267 return 0;
jjako52c24142002-12-16 13:33:51 +0000268}
269
jjako08d331d2003-10-13 20:33:30 +0000270/**
271 * get_default_gtp()
272 * Generate a GPRS Tunneling Protocol signalling packet header, depending
273 * on GTP version and message type. pdp is used for teid/flow label.
274 * *packet must be allocated by the calling function, and be large enough
275 * to hold the packet header.
276 * returns the length of the header. 0 on error.
277 **/
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100278static unsigned int get_default_gtp(uint8_t version, uint8_t type, void *packet)
Harald Weltebed35df2011-11-02 13:06:18 +0100279{
280 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
281 struct gtp1_header_long *gtp1_default =
282 (struct gtp1_header_long *)packet;
283 switch (version) {
284 case 0:
285 /* Initialise "standard" GTP0 header */
286 memset(gtp0_default, 0, sizeof(struct gtp0_header));
287 gtp0_default->flags = 0x1e;
288 gtp0_default->type = hton8(type);
289 gtp0_default->spare1 = 0xff;
290 gtp0_default->spare2 = 0xff;
291 gtp0_default->spare3 = 0xff;
292 gtp0_default->number = 0xff;
293 return GTP0_HEADER_SIZE;
294 case 1:
295 /* Initialise "standard" GTP1 header */
296 /* 29.060: 8.2: S=1 and PN=0 */
297 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
298 /* and Supported Extension Headers Notification, the S field shall be */
299 /* set to 1 */
300 /* Currently extension headers are not supported */
301 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
Harald Weltefed598f2017-09-24 16:39:22 +0800302 /* No extension, enable sequence, no N-PDU */
303 gtp1_default->flags = GTPHDR_F_VER(1) | GTP1HDR_F_GTP1 | GTP1HDR_F_SEQ;
Harald Weltebed35df2011-11-02 13:06:18 +0100304 gtp1_default->type = hton8(type);
305 return GTP1_HEADER_SIZE_LONG;
306 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100307 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100308 "Unknown GTP packet version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +0100309 return 0;
310 }
jjako52c24142002-12-16 13:33:51 +0000311}
312
jjako08d331d2003-10-13 20:33:30 +0000313/**
314 * get_seq()
315 * Get sequence number of a packet.
316 * Returns 0 on error
317 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100318static uint16_t get_seq(void *pack)
319{
320 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800321 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000322
Harald Weltefed598f2017-09-24 16:39:22 +0800323 if (ver == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +0100324 return ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800325 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100326 return ntoh16(packet->gtp1l.h.seq);
327 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100328 return 0;
329 }
jjako08d331d2003-10-13 20:33:30 +0000330}
331
332/**
333 * get_tid()
334 * Get tunnel identifier of a packet.
335 * Returns 0 on error
336 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100337static uint64_t get_tid(void *pack)
338{
339 union gtp_packet *packet = (union gtp_packet *)pack;
340
Harald Weltefed598f2017-09-24 16:39:22 +0800341 if (GTPHDR_F_GET_VER(packet->flags) == 0) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100342 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100343 }
344 return 0;
jjako08d331d2003-10-13 20:33:30 +0000345}
346
347/**
348 * get_hlen()
349 * Get the header length of a packet.
350 * Returns 0 on error
351 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100352static uint16_t get_hlen(void *pack)
353{
354 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800355 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000356
Harald Weltefed598f2017-09-24 16:39:22 +0800357 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100358 return GTP0_HEADER_SIZE;
Harald Weltefed598f2017-09-24 16:39:22 +0800359 } else if (ver == 1 && (packet->flags & 0x07) == 0) { /* Short version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100360 return GTP1_HEADER_SIZE_SHORT;
Harald Weltefed598f2017-09-24 16:39:22 +0800361 } else if (ver == 1) { /* Version 1 with seq/n-pdu/ext */
362 return GTP1_HEADER_SIZE_LONG;
Harald Weltebed35df2011-11-02 13:06:18 +0100363 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100364 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100365 return 0;
366 }
jjako08d331d2003-10-13 20:33:30 +0000367}
368
369/**
370 * get_tei()
371 * Get the tunnel endpoint identifier (flow label) of a packet.
372 * Returns 0xffffffff on error.
373 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100374static uint32_t get_tei(void *pack)
375{
376 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800377 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000378
Harald Weltefed598f2017-09-24 16:39:22 +0800379 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100380 return ntoh16(packet->gtp0.h.flow);
Harald Weltefed598f2017-09-24 16:39:22 +0800381 } else if (ver == 1) { /* Version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100382 return ntoh32(packet->gtp1l.h.tei);
383 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100384 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100385 return 0xffffffff;
386 }
jjako08d331d2003-10-13 20:33:30 +0000387}
jjakoa7cd2492003-04-11 09:40:12 +0000388
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200389static int queue_timer_retrans(struct gsn_t *gsn)
390{
391 /* Retransmit any outstanding packets */
392 /* Remove from queue if maxretrans exceeded */
393 time_t now;
394 struct qmsg_t *qmsg;
395 now = time(NULL);
396 /*printf("Retrans: New beginning %d\n", (int) now); */
397
398 /* get first element in queue, as long as the timeout of that
399 * element has expired */
400 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
401 (qmsg->timeout <= now)) {
402 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
403 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
404 LOGP(DLGTP, LOGL_NOTICE, "Timeout of seq %" PRIu16 "\n",
405 qmsg->seq);
406 if (gsn->cb_conf)
407 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
408 queue_freemsg(gsn->queue_req, qmsg);
409 } else {
410 LOGP(DLGTP, LOGL_INFO, "Retransmit (%d) of seq %" PRIu16 "\n",
411 qmsg->retrans, qmsg->seq);
412 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
413 (struct sockaddr *)&qmsg->peer,
414 sizeof(struct sockaddr_in)) < 0) {
415 gsn->err_sendto++;
416 LOGP(DLGTP, LOGL_ERROR,
417 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
418 gsn->fd0, (unsigned long)&qmsg->p,
419 qmsg->l, strerror(errno));
420 }
421 queue_back(gsn->queue_req, qmsg);
422 qmsg->timeout = now + T3_REQUEST;
423 qmsg->retrans++;
424 }
425 }
426
427 /* Also clean up reply timeouts */
428 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
429 (qmsg->timeout < now)) {
430 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
431 queue_freemsg(gsn->queue_resp, qmsg);
432 }
433
434 return 0;
435}
436
437static int queue_timer_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
438{
439 time_t now, later, diff;
440 struct qmsg_t *qmsg;
441 timeout->tv_usec = 0;
442
443 if (queue_getfirst(gsn->queue_req, &qmsg)) {
444 timeout->tv_sec = 10;
445 } else {
446 now = time(NULL);
447 later = qmsg->timeout;
448 timeout->tv_sec = later - now;
449 if (timeout->tv_sec < 0)
450 timeout->tv_sec = 0; /* No negative allowed */
451 if (timeout->tv_sec > 10)
452 timeout->tv_sec = 10; /* Max sleep for 10 sec */
453 }
454
455 if (queue_getfirst(gsn->queue_resp, &qmsg)) {
456 /* already set by queue_req, do nothing */
457 } else { /* trigger faster if earlier timeout exists in queue_resp */
458 now = time(NULL);
459 later = qmsg->timeout;
460 diff = later - now;
461 if (diff < 0)
462 diff = 0;
463 if (diff < timeout->tv_sec)
464 timeout->tv_sec = diff;
465 }
466
467 return 0;
468}
469
470static void queue_timer_start(struct gsn_t *gsn)
471{
472 struct timeval next;
473
474 /* Retrieve next retransmission as timeval */
475 queue_timer_retranstimeout(gsn, &next);
476
477 /* re-schedule the timer */
478 osmo_timer_schedule(&gsn->queue_timer, next.tv_sec, next.tv_usec/1000);
479}
480
481/* timer callback for libgtp retransmission and ping */
482static void queue_timer_cb(void *data)
483{
484 struct gsn_t *gsn = data;
485
486 /* do all the retransmissions as needed */
487 queue_timer_retrans(gsn);
488
489 queue_timer_start(gsn);
490}
491
jjako52c24142002-12-16 13:33:51 +0000492/* ***********************************************************
493 * Reliable delivery of signalling messages
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100494 *
jjako52c24142002-12-16 13:33:51 +0000495 * Sequence numbers are used for both signalling messages and
496 * data messages.
497 *
498 * For data messages each tunnel maintains a sequence counter,
499 * which is incremented by one each time a new data message
500 * is sent. The sequence number starts at (0) zero at tunnel
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100501 * establishment, and wraps around at 65535 (29.060 9.3.1.1
jjako52c24142002-12-16 13:33:51 +0000502 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
503 * or can be used to check the validity of the message in the
504 * receiver, or for reordering af packets.
505 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100506 * For signalling messages the sequence number is used by
jjako52c24142002-12-16 13:33:51 +0000507 * signalling messages for which a response is defined. A response
508 * message should copy the sequence from the corresponding request
509 * message. The sequence number "unambiguously" identifies a request
510 * message within a given path, with a path being defined as a set of
511 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
512 * messages shall be responded to, and all response messages associated
513 * with a certain request shall always include the same information"
514 *
515 * We take this to mean that the GSN transmitting a request is free to
516 * choose the sequence number, as long as it is unique within a given path.
517 * It means that we are allowed to count backwards, or roll over at 17
518 * if we prefer that. It also means that we can use the same counter for
519 * all paths. This has the advantage that the transmitted request sequence
520 * numbers are unique within each GSN, and also we dont have to mess around
521 * with path setup and teardown.
522 *
523 * If a response message is lost, the request will be retransmitted, and
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100524 * the receiving GSN will receive a "duplicated" request. The standard
jjako52c24142002-12-16 13:33:51 +0000525 * requires the receiving GSN to send a response, with the same information
526 * as in the original response. For most messages this happens automatically:
527 *
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200528 * Echo: Automatically duplicates the original response
jjako52c24142002-12-16 13:33:51 +0000529 * Create pdp context: The SGSN may send create context request even if
530 * a context allready exist (imsi+nsapi?). This means that the reply will
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200531 automatically duplicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000532 * side effects in the application which is asked twice to validate
533 * the login.
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200534 * Update pdp context: Automatically duplicates the original response???
jjako52c24142002-12-16 13:33:51 +0000535 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
536 * a nonexist reply message.
537 *
538 * The correct solution will be to make a queue containing response messages.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100539 * This queue should be checked whenever a request is received. If the
jjako52c24142002-12-16 13:33:51 +0000540 * response is allready in the queue that response should be transmitted.
541 * It should be possible to find messages in this queue on the basis of
542 * the sequence number and peer GSN IP address (The sequense number is unique
543 * within each path). This need to be implemented by a hash table. Furthermore
544 * it should be possibly to delete messages based on a timeout. This can be
545 * achieved by means of a linked list. The timeout value need to be larger
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100546 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
jjako52c24142002-12-16 13:33:51 +0000547 * set in the peer GSN, so there is no way to know these parameters. On the
548 * other hand the timeout value need to be so small that we do not receive
549 * wraparound sequence numbere before the message is deleted. 60 seconds is
550 * probably not a bad choise.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100551 *
jjako52c24142002-12-16 13:33:51 +0000552 * This queue however is first really needed from gtp1.
553 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100554 * gtp_req:
jjako52c24142002-12-16 13:33:51 +0000555 * Send off a signalling message with appropiate sequence
556 * number. Store packet in queue.
557 * gtp_conf:
558 * Remove an incoming confirmation from the queue
559 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000560 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000561 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000562 * gtp_notification:
563 * Send off a notification message. This is neither a request nor
564 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000565 * gtp_retrans:
566 * Retransmit any outstanding packets which have exceeded
567 * a predefined timeout.
568 *************************************************************/
569
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100570static int gtp_req(struct gsn_t *gsn, uint8_t version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100571 union gtp_packet *packet, int len,
572 struct in_addr *inetaddr, void *cbp)
573{
Harald Weltefed598f2017-09-24 16:39:22 +0800574 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100575 struct sockaddr_in addr;
576 struct qmsg_t *qmsg;
577 int fd;
jjako08d331d2003-10-13 20:33:30 +0000578
Harald Weltebed35df2011-11-02 13:06:18 +0100579 memset(&addr, 0, sizeof(addr));
580 addr.sin_family = AF_INET;
581 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000582#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100583 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000584#endif
jjako52c24142002-12-16 13:33:51 +0000585
Harald Weltefed598f2017-09-24 16:39:22 +0800586 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100587 addr.sin_port = htons(GTP0_PORT);
588 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
589 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100590 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100591 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100592 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100593 }
Harald Weltebed35df2011-11-02 13:06:18 +0100594 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
595 || (packet->gtp0.h.type == GTP_ERROR)))
596 packet->gtp0.h.flow = hton16(pdp->flru);
597 else if (pdp)
598 packet->gtp0.h.flow = hton16(pdp->flrc);
599 fd = gsn->fd0;
Harald Weltefed598f2017-09-24 16:39:22 +0800600 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100601 addr.sin_port = htons(GTP1C_PORT);
602 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
603 packet->gtp1l.h.seq = hton16(gsn->seq_next);
604 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
605 (packet->gtp1l.h.type == GTP_ERROR)))
606 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
607 else if (pdp)
608 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
609 fd = gsn->fd1c;
610 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100611 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100612 return -1;
613 }
jjako52c24142002-12-16 13:33:51 +0000614
Harald Weltebed35df2011-11-02 13:06:18 +0100615 if (sendto(fd, packet, len, 0,
616 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
617 gsn->err_sendto++;
Max14b1b632017-08-21 20:14:59 +0200618 LOGP(DLGTP, LOGL_ERROR, "Sendto(fd=%d, msg=%lx, len=%d, dst=%s) failed: Error = %s\n", fd,
619 (unsigned long)&packet, len, inet_ntoa(addr.sin_addr), strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100620 return -1;
621 }
622
623 /* Use new queue structure */
624 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
625 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100626 LOGP(DLGTP, LOGL_ERROR,
627 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100628 } else {
629 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
630 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100631 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100632 qmsg->retrans = 0; /* No retransmissions so far */
633 qmsg->cbp = cbp;
634 qmsg->type = ntoh8(packet->gtp0.h.type);
635 qmsg->fd = fd;
Pau Espin Pedrol623c5b32019-08-16 13:20:09 +0200636 if (pdp) /* echo requests are not pdp-bound */
637 llist_add(&qmsg->entry, &pdp->qmsg_list_req);
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200638
639 /* Rearm timer: Retrans time for qmsg just queued may be required
640 before an existing one (for instance a gtp echo req) */
641 queue_timer_start(gsn);
Harald Weltebed35df2011-11-02 13:06:18 +0100642 }
643 gsn->seq_next++; /* Count up this time */
644 return 0;
jjako52c24142002-12-16 13:33:51 +0000645}
646
Alexander Couzense1412d92018-09-16 05:10:03 +0200647
648/**
649 * @brief clear the request and response queue. Useful for debugging to reset "some" state.
650 * @param gsn The GGSN instance
651 */
652void gtp_clear_queues(struct gsn_t *gsn)
653{
654 struct qmsg_t *qmsg;
655
656 while (!queue_getfirst(gsn->queue_req, &qmsg)) {
657 queue_freemsg(gsn->queue_req, qmsg);
658 }
659
660 while (!queue_getfirst(gsn->queue_resp, &qmsg)) {
661 queue_freemsg(gsn->queue_resp, qmsg);
662 }
663}
664
jjako52c24142002-12-16 13:33:51 +0000665/* gtp_conf
666 * Remove signalling packet from retransmission queue.
667 * return 0 on success, EOF if packet was not found */
668
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100669static int gtp_conf(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100670 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
671{
Harald Weltefed598f2017-09-24 16:39:22 +0800672 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100673 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000674
Harald Weltefed598f2017-09-24 16:39:22 +0800675 if (ver == 0)
Harald Weltebed35df2011-11-02 13:06:18 +0100676 seq = ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800677 else if (ver == 1 && (packet->gtp1l.h.flags & GTP1HDR_F_SEQ))
Harald Weltebed35df2011-11-02 13:06:18 +0100678 seq = ntoh16(packet->gtp1l.h.seq);
679 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100680 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
681 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100682 return EOF;
683 }
jjako08d331d2003-10-13 20:33:30 +0000684
Harald Weltebed35df2011-11-02 13:06:18 +0100685 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
686 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100687 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
688 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100689 return EOF;
690 }
jjako52c24142002-12-16 13:33:51 +0000691
Harald Weltebed35df2011-11-02 13:06:18 +0100692 return 0;
jjako52c24142002-12-16 13:33:51 +0000693}
694
Harald Weltebed35df2011-11-02 13:06:18 +0100695int gtp_retrans(struct gsn_t *gsn)
696{
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200697 /* dummy API, deprecated. */
Harald Weltebed35df2011-11-02 13:06:18 +0100698 return 0;
jjako52c24142002-12-16 13:33:51 +0000699}
700
Harald Weltebed35df2011-11-02 13:06:18 +0100701int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
702{
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200703 timeout->tv_sec = 24*60*60;
Pau Espin Pedrolceac0782019-05-27 17:39:45 +0200704 timeout->tv_usec = 0;
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200705 /* dummy API, deprecated. Return a huge timer to do nothing */
Harald Weltebed35df2011-11-02 13:06:18 +0100706 return 0;
jjako52c24142002-12-16 13:33:51 +0000707}
708
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100709static int gtp_resp(uint8_t version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000710 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100711 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
712{
Harald Weltefed598f2017-09-24 16:39:22 +0800713 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100714 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000715
Harald Weltefed598f2017-09-24 16:39:22 +0800716 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100717 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
718 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100719 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100720 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
721 (packet->gtp0.h.type == GTP_ERROR)))
722 packet->gtp0.h.flow = hton16(pdp->flru);
723 else if (pdp)
724 packet->gtp0.h.flow = hton16(pdp->flrc);
Harald Weltefed598f2017-09-24 16:39:22 +0800725 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100726 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
727 packet->gtp1l.h.seq = hton16(seq);
728 if (pdp && (fd == gsn->fd1u))
729 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
730 else if (pdp)
731 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
732 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100733 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100734 return -1;
735 }
jjako08d331d2003-10-13 20:33:30 +0000736
Harald Weltebed35df2011-11-02 13:06:18 +0100737 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100738 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100739 return -1;
740 }
jjako52c24142002-12-16 13:33:51 +0000741
Harald Weltebed35df2011-11-02 13:06:18 +0100742 if (sendto(fd, packet, len, 0,
743 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
744 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100745 LOGP(DLGTP, LOGL_ERROR,
746 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100747 (unsigned long)&packet, len, strerror(errno));
748 return -1;
749 }
750
751 /* Use new queue structure */
752 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
753 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100754 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100755 } else {
756 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
757 qmsg->l = len;
758 qmsg->timeout = time(NULL) + 60; /* When to timeout */
759 qmsg->retrans = 0; /* No retransmissions so far */
760 qmsg->cbp = NULL;
761 qmsg->type = 0;
762 qmsg->fd = fd;
Pau Espin Pedrol623c5b32019-08-16 13:20:09 +0200763 /* No need to add to pdp list here, because even on pdp ctx free
764 we want to leave messages in queue_resp until timeout to
765 detect duplicates */
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200766
767 /* Rearm timer: Retrans time for qmsg just queued may be required
768 before an existing one (for instance a gtp echo req) */
769 queue_timer_start(gsn);
Harald Weltebed35df2011-11-02 13:06:18 +0100770 }
771 return 0;
jjako52c24142002-12-16 13:33:51 +0000772}
773
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100774static int gtp_notification(struct gsn_t *gsn, uint8_t version,
jjako2c381332003-10-21 19:09:53 +0000775 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100776 struct sockaddr_in *peer, int fd, uint16_t seq)
777{
jjako2c381332003-10-21 19:09:53 +0000778
Harald Weltefed598f2017-09-24 16:39:22 +0800779 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100780 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000781
Harald Weltebed35df2011-11-02 13:06:18 +0100782 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000783
Harald Weltebed35df2011-11-02 13:06:18 +0100784 /* In GTP0 notifications are treated as replies. In GTP1 they
785 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000786
Harald Weltebed35df2011-11-02 13:06:18 +0100787 if (fd == gsn->fd1c)
788 addr.sin_port = htons(GTP1C_PORT);
789 else if (fd == gsn->fd1u)
790 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000791
Harald Weltefed598f2017-09-24 16:39:22 +0800792 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100793 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
794 packet->gtp0.h.seq = hton16(seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800795 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100796 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
797 packet->gtp1l.h.seq = hton16(seq);
798 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100799 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100800 return -1;
801 }
802
803 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100804 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100805 return -1;
806 }
807
808 if (sendto(fd, packet, len, 0,
809 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
810 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100811 LOGP(DLGTP, LOGL_ERROR,
812 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100813 (unsigned long)&packet, len, strerror(errno));
814 return -1;
815 }
816 return 0;
jjako2c381332003-10-21 19:09:53 +0000817}
818
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200819static int gtp_duplicate(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +0100820 struct sockaddr_in *peer, uint16_t seq)
821{
822 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000823
Harald Weltebed35df2011-11-02 13:06:18 +0100824 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
825 return EOF; /* Notfound */
826 }
jjakoa7cd2492003-04-11 09:40:12 +0000827
Harald Weltebed35df2011-11-02 13:06:18 +0100828 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100829 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100830 return -1;
831 }
832
833 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
834 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
835 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100836 LOGP(DLGTP, LOGL_ERROR,
837 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100838 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
839 strerror(errno));
840 }
841 return 0;
jjako52c24142002-12-16 13:33:51 +0000842}
843
jjako52c24142002-12-16 13:33:51 +0000844/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100845static void log_restart(struct gsn_t *gsn)
846{
jjako52c24142002-12-16 13:33:51 +0000847 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200848 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000849 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200850 char *filename;
jjako52c24142002-12-16 13:33:51 +0000851
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200852 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
853 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000854
855 /* We try to open file. On failure we will later try to create file */
856 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100857 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100858 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100859 filename);
860 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100861 rc = fscanf(f, "%d", &counter);
862 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100863 LOGP(DLGTP, LOGL_ERROR,
864 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100865 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100866 }
867 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100868 LOGP(DLGTP, LOGL_ERROR,
869 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100870 }
jjako52c24142002-12-16 13:33:51 +0000871 }
Harald Weltebed35df2011-11-02 13:06:18 +0100872
873 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000874 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100875
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200876 /* Keep the umask closely wrapped around our fopen() call in case the
877 * log outputs cause file creation. */
878 i = umask(022);
879 f = fopen(filename, "w");
880 umask(i);
881 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100882 LOGP(DLGTP, LOGL_ERROR,
883 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100884 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200885 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000886 }
887
jjako52c24142002-12-16 13:33:51 +0000888 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100889close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200890 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100891 LOGP(DLGTP, LOGL_ERROR,
892 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200893free_filename:
894 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000895}
896
jjako1db1c812003-07-06 20:53:57 +0000897int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100898 int mode)
jjako52c24142002-12-16 13:33:51 +0000899{
Harald Weltebed35df2011-11-02 13:06:18 +0100900 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000901
Max14b1b632017-08-21 20:14:59 +0200902 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
jjako52c24142002-12-16 13:33:51 +0000903
Harald Weltebed35df2011-11-02 13:06:18 +0100904 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000905
Harald Weltebed35df2011-11-02 13:06:18 +0100906 (*gsn)->statedir = statedir;
907 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000908
Harald Weltebed35df2011-11-02 13:06:18 +0100909 /* Initialise sequence number */
910 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000911
Harald Weltebed35df2011-11-02 13:06:18 +0100912 /* Initialise request retransmit queue */
913 queue_new(&(*gsn)->queue_req);
914 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000915
Harald Weltebed35df2011-11-02 13:06:18 +0100916 /* Initialise pdp table */
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +0200917 pdp_init(*gsn);
jjako08d331d2003-10-13 20:33:30 +0000918
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +0200919 /* Initialize internal queue timer */
920 osmo_timer_setup(&(*gsn)->queue_timer, queue_timer_cb, *gsn);
921
Harald Weltebed35df2011-11-02 13:06:18 +0100922 /* Initialise call back functions */
923 (*gsn)->cb_create_context_ind = 0;
924 (*gsn)->cb_delete_context = 0;
925 (*gsn)->cb_unsup_ind = 0;
926 (*gsn)->cb_conf = 0;
927 (*gsn)->cb_data_ind = 0;
928
929 /* Store function parameters */
930 (*gsn)->gsnc = *listen;
931 (*gsn)->gsnu = *listen;
932 (*gsn)->mode = mode;
933
934 /* Create GTP version 0 socket */
935 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
936 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100937 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200938 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100939 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200940 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100941 }
942
943 memset(&addr, 0, sizeof(addr));
944 addr.sin_family = AF_INET;
945 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
946 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000947#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100948 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000949#endif
jjako08d331d2003-10-13 20:33:30 +0000950
Harald Weltebed35df2011-11-02 13:06:18 +0100951 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
952 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200953 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
954 "bind(fd0=%d) failed: Error = %s\n",
955 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200956 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100957 }
jjako08d331d2003-10-13 20:33:30 +0000958
Harald Weltebed35df2011-11-02 13:06:18 +0100959 /* Create GTP version 1 control plane socket */
960 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
961 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100962 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200963 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100964 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200965 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100966 }
967
968 memset(&addr, 0, sizeof(addr));
969 addr.sin_family = AF_INET;
970 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
971 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000972#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100973 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000974#endif
jjako08d331d2003-10-13 20:33:30 +0000975
Harald Weltebed35df2011-11-02 13:06:18 +0100976 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
977 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200978 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
979 "bind(fd1c=%d) failed: Error = %s\n",
980 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200981 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100982 }
jjako08d331d2003-10-13 20:33:30 +0000983
Harald Weltebed35df2011-11-02 13:06:18 +0100984 /* Create GTP version 1 user plane socket */
985 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
986 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100987 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200988 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100989 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200990 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100991 }
992
993 memset(&addr, 0, sizeof(addr));
994 addr.sin_family = AF_INET;
995 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
996 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000997#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100998 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000999#endif
jjako52c24142002-12-16 13:33:51 +00001000
Harald Weltebed35df2011-11-02 13:06:18 +01001001 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1002 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +02001003 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +02001004 "bind(fd1u=%d) failed: Error = %s\n",
1005 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +02001006 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +01001007 }
1008
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +02001009 /* Start internal queue timer */
1010 queue_timer_start(*gsn);
1011
Harald Weltebed35df2011-11-02 13:06:18 +01001012 return 0;
jjako52c24142002-12-16 13:33:51 +00001013}
1014
Harald Weltebed35df2011-11-02 13:06:18 +01001015int gtp_free(struct gsn_t *gsn)
1016{
jjako52c24142002-12-16 13:33:51 +00001017
Pau Espin Pedrolc94837c2019-08-28 19:44:20 +02001018 /* Cleanup internal queue timer */
1019 osmo_timer_del(&gsn->queue_timer);
1020
Harald Weltebed35df2011-11-02 13:06:18 +01001021 /* Clean up retransmit queues */
1022 queue_free(gsn->queue_req);
1023 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +00001024
Harald Weltebed35df2011-11-02 13:06:18 +01001025 close(gsn->fd0);
1026 close(gsn->fd1c);
1027 close(gsn->fd1u);
1028
1029 free(gsn);
1030 return 0;
jjako52c24142002-12-16 13:33:51 +00001031}
1032
1033/* ***********************************************************
1034 * Path management messages
1035 * Messages: echo and version not supported.
1036 * A path is connection between two UDP/IP endpoints
1037 *
1038 * A path is either using GTP0 or GTP1. A path can be
1039 * established by any kind of GTP message??
1040
1041 * Which source port to use?
1042 * GTP-C request destination port is 2123/3386
1043 * GTP-U request destination port is 2152/3386
1044 * T-PDU destination port is 2152/3386.
1045 * For the above messages the source port is locally allocated.
1046 * For response messages src=rx-dst and dst=rx-src.
1047 * For simplicity we should probably use 2123+2152/3386 as
1048 * src port even for the cases where src can be locally
1049 * allocated. This also means that we have to listen only to
1050 * the same ports.
1051 * For response messages we need to be able to respond to
1052 * the relevant src port even if it is locally allocated by
1053 * the peer.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001054 *
jjako52c24142002-12-16 13:33:51 +00001055 * The need for path management!
1056 * We might need to keep a list of active paths. This might
1057 * be in the form of remote IP address + UDP port numbers.
1058 * (We will consider a path astablished if we have a context
1059 * with the node in question)
1060 *************************************************************/
1061
1062/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +00001063int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
1064 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +00001065{
Harald Weltebed35df2011-11-02 13:06:18 +01001066 union gtp_packet packet;
1067 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
1068 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +00001069}
1070
jjako08d331d2003-10-13 20:33:30 +00001071/* Send off an echo reply */
1072int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001073 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001074{
Harald Weltebed35df2011-11-02 13:06:18 +01001075 union gtp_packet packet;
1076 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
1077 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1078 gsn->restart_counter);
1079 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
1080 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00001081}
1082
jjako52c24142002-12-16 13:33:51 +00001083/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +01001084int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1085 int fd, void *pack, unsigned len)
1086{
jjako52c24142002-12-16 13:33:51 +00001087
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02001088 /* Check if it was a duplicate request */
1089 if (!gtp_duplicate(gsn, 0, peer, get_seq(pack)))
Harald Weltebed35df2011-11-02 13:06:18 +01001090 return 0;
jjako52c24142002-12-16 13:33:51 +00001091
Harald Weltebed35df2011-11-02 13:06:18 +01001092 /* Send off reply to request */
1093 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +00001094}
1095
1096/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +00001097int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001098 void *pack, unsigned len)
1099{
1100 union gtpie_member *ie[GTPIE_SIZE];
1101 unsigned char recovery;
1102 void *cbp = NULL;
1103 uint8_t type = 0;
1104 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001105
Harald Weltebed35df2011-11-02 13:06:18 +01001106 /* Remove packet from queue */
1107 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1108 return EOF;
jjako52c24142002-12-16 13:33:51 +00001109
Harald Weltebed35df2011-11-02 13:06:18 +01001110 /* Extract information elements into a pointer array */
1111 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1112 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001113 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1114 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001115 if (gsn->cb_conf)
1116 gsn->cb_conf(type, EOF, NULL, cbp);
1117 return EOF;
1118 }
jjako52c24142002-12-16 13:33:51 +00001119
Harald Weltebed35df2011-11-02 13:06:18 +01001120 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1121 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001122 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1123 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001124 if (gsn->cb_conf)
1125 gsn->cb_conf(type, EOF, NULL, cbp);
1126 return EOF;
1127 }
jjako52c24142002-12-16 13:33:51 +00001128
Harald Weltebed35df2011-11-02 13:06:18 +01001129 /* Echo reply packages does not have a cause information element */
1130 /* Instead we return the recovery number in the callback function */
1131 if (gsn->cb_conf)
1132 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +01001133
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001134 emit_cb_recovery(gsn, peer, NULL, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001135
1136 return 0;
jjako52c24142002-12-16 13:33:51 +00001137}
1138
1139/* Send off a Version Not Supported message */
1140/* This message is somewhat special in that it actually is a
1141 * response to some other message with unsupported GTP version
1142 * For this reason it has parameters like a response, and does
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001143 * its own message transmission. No signalling queue is used
jjako52c24142002-12-16 13:33:51 +00001144 * The reply is sent to the peer IP and peer UDP. This means that
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001145 * the peer will be receiving a GTP0 message on a GTP1 port!
jjako52c24142002-12-16 13:33:51 +00001146 * In practice however this will never happen as a GTP0 GSN will
1147 * only listen to the GTP0 port, and therefore will never receive
1148 * anything else than GTP0 */
1149
jjako08d331d2003-10-13 20:33:30 +00001150int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1151 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001152{
Harald Weltebed35df2011-11-02 13:06:18 +01001153 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +00001154
Harald Weltebed35df2011-11-02 13:06:18 +01001155 /* GTP 1 is the highest supported protocol */
1156 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
1157 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +00001158}
1159
1160/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +01001161int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1162 void *pack, unsigned len)
1163{
jjako52c24142002-12-16 13:33:51 +00001164
Harald Weltebed35df2011-11-02 13:06:18 +01001165 if (gsn->cb_unsup_ind)
1166 gsn->cb_unsup_ind(peer);
1167
1168 return 0;
jjako52c24142002-12-16 13:33:51 +00001169}
1170
jjako2c381332003-10-21 19:09:53 +00001171/* Send off an Supported Extension Headers Notification */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001172static int gtp_extheader_req(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
jjako2c381332003-10-21 19:09:53 +00001173 int fd, void *pack, unsigned len)
1174{
Harald Weltebed35df2011-11-02 13:06:18 +01001175 union gtp_packet packet;
1176 unsigned int length =
1177 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +00001178
Harald Weltebed35df2011-11-02 13:06:18 +01001179 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +00001180
Harald Weltebed35df2011-11-02 13:06:18 +01001181 if (version < 1)
1182 return 0;
jjako2c381332003-10-21 19:09:53 +00001183
Harald Weltebed35df2011-11-02 13:06:18 +01001184 /* We report back that we support only PDCP PDU headers */
1185 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
1186 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +00001187
Harald Weltebed35df2011-11-02 13:06:18 +01001188 return gtp_notification(gsn, version, &packet, length,
1189 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +00001190}
1191
1192/* Handle a Supported Extension Headers Notification */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001193static int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001194 void *pack, unsigned len)
1195{
jjako2c381332003-10-21 19:09:53 +00001196
Harald Weltebed35df2011-11-02 13:06:18 +01001197 if (gsn->cb_extheader_ind)
1198 gsn->cb_extheader_ind(peer);
1199
1200 return 0;
jjako2c381332003-10-21 19:09:53 +00001201}
1202
jjako52c24142002-12-16 13:33:51 +00001203/* ***********************************************************
1204 * Session management messages
1205 * Messages: create, update and delete PDP context
1206 *
1207 * Information storage
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001208 * Information storage for each PDP context is defined in
jjako52c24142002-12-16 13:33:51 +00001209 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1210 * PDP-address (IP address), sequence numbers, charging ID.
1211 * For the SGSN it also includes radio related mobility
1212 * information.
1213 *************************************************************/
1214
Harald Welte7b3347b2010-05-15 12:18:46 +02001215/* API: Send Create PDP Context Request (7.3.1) */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001216int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001217 void *cbp)
1218{
1219 union gtp_packet packet;
1220 unsigned int length =
1221 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1222 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001223
Harald Weltebed35df2011-11-02 13:06:18 +01001224 /* TODO: Secondary PDP Context Activation Procedure */
1225 /* In secondary activation procedure the PDP context is identified
1226 by tei in the header. The following fields are omitted: Selection
1227 mode, IMSI, MSISDN, End User Address, Access Point Name and
1228 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001229
Harald Weltebed35df2011-11-02 13:06:18 +01001230 if (pdp->secondary) {
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001231 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001232 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001233 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001234 return EOF;
1235 }
1236 }
jjako2c381332003-10-21 19:09:53 +00001237
Harald Weltebed35df2011-11-02 13:06:18 +01001238 if (pdp->version == 0) {
1239 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1240 sizeof(pdp->qos_req0), pdp->qos_req0);
1241 }
jjako52c24142002-12-16 13:33:51 +00001242
Harald Weltebed35df2011-11-02 13:06:18 +01001243 /* Section 7.7.2 */
1244 if (pdp->version == 1) {
1245 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1246 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1247 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1248 }
jjako52c24142002-12-16 13:33:51 +00001249
Harald Weltebed35df2011-11-02 13:06:18 +01001250 /* Section 7.7.3 Routing Area Information */
1251 if (pdp->rai_given == 1)
1252 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1253 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001254
Harald Weltebed35df2011-11-02 13:06:18 +01001255 /* Section 7.7.11 */
1256 if (pdp->norecovery_given == 0)
1257 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1258 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001259
Harald Weltebed35df2011-11-02 13:06:18 +01001260 /* Section 7.7.12 */
1261 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1262 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1263 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001264
Harald Weltebed35df2011-11-02 13:06:18 +01001265 if (pdp->version == 0) {
1266 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1267 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1268 }
jjako08d331d2003-10-13 20:33:30 +00001269
Harald Weltebed35df2011-11-02 13:06:18 +01001270 /* Section 7.7.13 */
1271 if (pdp->version == 1) {
1272 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1273 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001274
Harald Weltebed35df2011-11-02 13:06:18 +01001275 /* Section 7.7.14 */
1276 if (!pdp->teic_confirmed)
1277 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1278 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001279
Harald Weltebed35df2011-11-02 13:06:18 +01001280 /* Section 7.7.17 */
1281 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001282
Harald Weltebed35df2011-11-02 13:06:18 +01001283 /* Section 7.7.17 */
1284 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1285 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1286 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001287
Harald Weltebed35df2011-11-02 13:06:18 +01001288 /* Section 7.7.23 */
1289 if (pdp->cch_pdp) /* Only include charging if flags are set */
1290 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1291 pdp->cch_pdp);
1292 }
jjako9b4971d2004-05-27 20:30:19 +00001293
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001294 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001295 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1296 pdp->traceref);
1297 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1298 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001299
Harald Weltebed35df2011-11-02 13:06:18 +01001300 /* Section 7.7.27 */
1301 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1302 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1303 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001304
Harald Weltebed35df2011-11-02 13:06:18 +01001305 /* Section 7.7.30 */
1306 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1307 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1308 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001309
Harald Weltebed35df2011-11-02 13:06:18 +01001310 /* Section 7.7.31 */
1311 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1312 if (pdp->pco_req.l)
1313 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1314 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001315
Harald Weltebed35df2011-11-02 13:06:18 +01001316 /* Section 7.7.32 */
1317 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1318 pdp->gsnlc.l, pdp->gsnlc.v);
1319 /* Section 7.7.32 */
1320 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1321 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001322
Harald Weltebed35df2011-11-02 13:06:18 +01001323 /* Section 7.7.33 */
1324 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1325 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1326 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001327
Harald Weltebed35df2011-11-02 13:06:18 +01001328 /* Section 7.7.34 */
1329 if (pdp->version == 1)
1330 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1331 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001332
Harald Weltebed35df2011-11-02 13:06:18 +01001333 /* Section 7.7.36 */
1334 if ((pdp->version == 1) && pdp->tft.l)
1335 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1336 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001337
Harald Weltebed35df2011-11-02 13:06:18 +01001338 /* Section 7.7.41 */
1339 if ((pdp->version == 1) && pdp->triggerid.l)
1340 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1341 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001342
Harald Weltebed35df2011-11-02 13:06:18 +01001343 /* Section 7.7.42 */
1344 if ((pdp->version == 1) && pdp->omcid.l)
1345 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1346 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001347
Harald Weltebed35df2011-11-02 13:06:18 +01001348 /* new R7 fields */
1349 if (pdp->rattype_given == 1)
1350 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1351 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001352
Harald Weltebed35df2011-11-02 13:06:18 +01001353 if (pdp->userloc_given == 1)
1354 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1355 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001356
Harald Weltebed35df2011-11-02 13:06:18 +01001357 if (pdp->mstz_given == 1)
1358 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1359 pdp->mstz.l, pdp->mstz.v);
1360
1361 if (pdp->imeisv_given == 1)
1362 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1363 pdp->imeisv.l, pdp->imeisv.v);
1364
1365 /* TODO hisaddr0 */
1366 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1367
1368 return 0;
jjako52c24142002-12-16 13:33:51 +00001369}
1370
jjako08d331d2003-10-13 20:33:30 +00001371/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001372int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1373{
jjako08d331d2003-10-13 20:33:30 +00001374
Harald Weltebed35df2011-11-02 13:06:18 +01001375 /* Now send off a reply to the peer */
1376 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1377
Pau Espin Pedrold9501342019-08-21 15:24:29 +02001378 if (cause != GTPCAUSE_ACC_REQ)
1379 gtp_freepdp(gsn, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001380
1381 return 0;
jjako08d331d2003-10-13 20:33:30 +00001382}
1383
1384/* API: Register create context indication callback */
1385int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001386 int (*cb_create_context_ind) (struct pdp_t *
1387 pdp))
jjako52c24142002-12-16 13:33:51 +00001388{
Harald Weltebed35df2011-11-02 13:06:18 +01001389 gsn->cb_create_context_ind = cb_create_context_ind;
1390 return 0;
jjako08d331d2003-10-13 20:33:30 +00001391}
1392
jjako08d331d2003-10-13 20:33:30 +00001393/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001394int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1395 uint8_t cause)
1396{
1397 union gtp_packet packet;
1398 unsigned int length =
1399 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001400
Harald Weltebed35df2011-11-02 13:06:18 +01001401 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001402
Harald Weltebed35df2011-11-02 13:06:18 +01001403 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001404
Harald Weltebed35df2011-11-02 13:06:18 +01001405 if (version == 0)
1406 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1407 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001408
Harald Weltebed35df2011-11-02 13:06:18 +01001409 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1410 pdp->reorder);
1411 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1412 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001413
Harald Weltebed35df2011-11-02 13:06:18 +01001414 if (version == 0) {
1415 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1416 pdp->fllu);
1417 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1418 pdp->fllc);
1419 }
jjako08d331d2003-10-13 20:33:30 +00001420
Harald Weltebed35df2011-11-02 13:06:18 +01001421 if (version == 1) {
1422 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1423 pdp->teid_own);
1424 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1425 pdp->teic_own);
1426 }
jjako08d331d2003-10-13 20:33:30 +00001427
Harald Weltebed35df2011-11-02 13:06:18 +01001428 /* TODO: We use teic_own as charging ID */
1429 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1430 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001431
Harald Weltebed35df2011-11-02 13:06:18 +01001432 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1433 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001434
Harald Weltebed35df2011-11-02 13:06:18 +01001435 if (pdp->pco_neg.l) { /* Optional PCO */
1436 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1437 pdp->pco_neg.l, pdp->pco_neg.v);
1438 }
jjako52c24142002-12-16 13:33:51 +00001439
Harald Weltebed35df2011-11-02 13:06:18 +01001440 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1441 pdp->gsnlc.l, pdp->gsnlc.v);
1442 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1443 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001444
Harald Weltebed35df2011-11-02 13:06:18 +01001445 if (version == 1)
1446 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1447 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001448
Harald Weltebed35df2011-11-02 13:06:18 +01001449 /* TODO: Charging gateway address */
1450 }
jjako52c24142002-12-16 13:33:51 +00001451
Harald Weltebed35df2011-11-02 13:06:18 +01001452 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1453 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001454}
1455
1456/* Handle Create PDP Context Request */
1457int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001458 struct sockaddr_in *peer, int fd,
1459 void *pack, unsigned len)
1460{
1461 struct pdp_t *pdp, *pdp_old;
1462 struct pdp_t pdp_buf;
1463 union gtpie_member *ie[GTPIE_SIZE];
1464 uint8_t recovery;
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001465 bool recovery_recvd = false;
1466 int rc;
jjako52c24142002-12-16 13:33:51 +00001467
Harald Weltebed35df2011-11-02 13:06:18 +01001468 uint16_t seq = get_seq(pack);
1469 int hlen = get_hlen(pack);
1470 uint8_t linked_nsapi = 0;
1471 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001472
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02001473 if (!gtp_duplicate(gsn, version, peer, seq))
Harald Weltebed35df2011-11-02 13:06:18 +01001474 return 0;
jjako08d331d2003-10-13 20:33:30 +00001475
Harald Weltebed35df2011-11-02 13:06:18 +01001476 pdp = &pdp_buf;
1477 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001478
Vadim Yanitskiy68c5a742019-08-30 21:04:19 +02001479 if (version == 0)
1480 pdp_set_imsi_nsapi(pdp, get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00001481
Harald Weltebed35df2011-11-02 13:06:18 +01001482 pdp->seq = seq;
1483 pdp->sa_peer = *peer;
1484 pdp->fd = fd;
1485 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001486
Harald Weltebed35df2011-11-02 13:06:18 +01001487 /* Decode information elements */
1488 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1489 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001490 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1491 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001492 if (0 == version)
1493 return EOF;
1494 else
1495 return gtp_create_pdp_resp(gsn, version, pdp,
1496 GTPCAUSE_INVALID_MESSAGE);
1497 }
jjako52c24142002-12-16 13:33:51 +00001498
Harald Weltebed35df2011-11-02 13:06:18 +01001499 if (version == 1) {
1500 /* Linked NSAPI (conditional) */
1501 /* If included this is the Secondary PDP Context Activation Procedure */
1502 /* In secondary activation IMSI is not included, so the context must be */
1503 /* identified by the tei */
1504 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001505
Harald Weltebed35df2011-11-02 13:06:18 +01001506 /* Find the primary PDP context */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001507 if (gtp_pdp_getgtp1(gsn, &linked_pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001508 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001509 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001510 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001511 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001512 return gtp_create_pdp_resp(gsn, version, pdp,
1513 GTPCAUSE_OPT_IE_INCORRECT);
1514 }
jjako2c381332003-10-21 19:09:53 +00001515
Harald Weltebed35df2011-11-02 13:06:18 +01001516 /* Check that the primary PDP context matches linked nsapi */
1517 if (linked_pdp->nsapi != linked_nsapi) {
1518 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001519 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001520 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001521 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001522 return gtp_create_pdp_resp(gsn, version, pdp,
1523 GTPCAUSE_OPT_IE_INCORRECT);
1524 }
jjako52c24142002-12-16 13:33:51 +00001525
Harald Weltebed35df2011-11-02 13:06:18 +01001526 /* Copy parameters from primary context */
1527 pdp->selmode = linked_pdp->selmode;
1528 pdp->imsi = linked_pdp->imsi;
1529 pdp->msisdn = linked_pdp->msisdn;
1530 pdp->eua = linked_pdp->eua;
1531 pdp->pco_req = linked_pdp->pco_req;
1532 pdp->apn_req = linked_pdp->apn_req;
1533 pdp->teic_gn = linked_pdp->teic_gn;
1534 pdp->secondary = 1;
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001535 } else {
1536 /* Not Secondary PDP Context Activation Procedure */
1537 /* IMSI (conditional): If the MS is emergency attached
1538 and the MS is UICCless, the IMSI cannot be included
1539 in the message and therefore IMSI shall not be
1540 included in the message. */
1541 if (gtpie_gettv0
1542 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1543 gsn->missing++;
1544 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1545 len, "Missing IMSI not supported\n");
1546 return gtp_create_pdp_resp(gsn, version, pdp,
1547 GTPCAUSE_MAN_IE_MISSING);
1548 }
1549 }
1550
1551 /* TEID (mandatory) */
1552 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1553 gsn->missing++;
1554 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1555 len, "Missing mandatory information field\n");
1556 return gtp_create_pdp_resp(gsn, version, pdp,
1557 GTPCAUSE_MAN_IE_MISSING);
1558 }
1559 /* TEIC (conditional) */
1560 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1561 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1562 gsn->missing++;
1563 GTP_LOGPKG(LOGL_ERROR, peer,
1564 pack, len,
1565 "Missing mandatory information field\n");
1566 return gtp_create_pdp_resp(gsn, version, pdp,
1567 GTPCAUSE_MAN_IE_MISSING);
1568 }
1569 }
1570 /* NSAPI (mandatory) */
1571 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1572 gsn->missing++;
1573 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1574 len, "Missing mandatory information field\n");
1575 return gtp_create_pdp_resp(gsn, version, pdp,
1576 GTPCAUSE_MAN_IE_MISSING);
1577 }
1578 /* QoS (mandatory) */
1579 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1580 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1581 gsn->missing++;
1582 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1583 len, "Missing mandatory information field\n");
1584 return gtp_create_pdp_resp(gsn, version, pdp,
1585 GTPCAUSE_MAN_IE_MISSING);
1586 }
1587 /* TFT (conditional) */
1588 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1589 &pdp->tft.v, sizeof(pdp->tft.v))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001590 }
1591 }
1592 /* if (version == 1) */
1593 if (version == 0) {
1594 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1595 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1596 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001597 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1598 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001599 return gtp_create_pdp_resp(gsn, version, pdp,
1600 GTPCAUSE_MAN_IE_MISSING);
1601 }
Harald Weltebed35df2011-11-02 13:06:18 +01001602 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1603 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001604 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1605 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001606 return gtp_create_pdp_resp(gsn, version, pdp,
1607 GTPCAUSE_MAN_IE_MISSING);
1608 }
Harald Weltebed35df2011-11-02 13:06:18 +01001609 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1610 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001611 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1612 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001613 return gtp_create_pdp_resp(gsn, version, pdp,
1614 GTPCAUSE_MAN_IE_MISSING);
1615 }
1616 }
jjako08d331d2003-10-13 20:33:30 +00001617
Harald Weltebed35df2011-11-02 13:06:18 +01001618 /* SGSN address for signalling (mandatory) */
1619 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1620 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1621 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001622 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1623 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001624 return gtp_create_pdp_resp(gsn, version, pdp,
1625 GTPCAUSE_MAN_IE_MISSING);
1626 }
jjako2e840a32003-01-28 16:05:18 +00001627
Harald Weltebed35df2011-11-02 13:06:18 +01001628 /* SGSN address for user traffic (mandatory) */
1629 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1630 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1631 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001632 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1633 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001634 return gtp_create_pdp_resp(gsn, version, pdp,
1635 GTPCAUSE_MAN_IE_MISSING);
1636 }
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001637 /* Recovery (optional) */
1638 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1639 /* we use recovery futher down after announcing new pdp ctx to user */
1640 recovery_recvd = true;
1641 }
jjako52c24142002-12-16 13:33:51 +00001642
Harald Weltebed35df2011-11-02 13:06:18 +01001643 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001644 /* Selection mode (conditional) */
1645 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1646 &pdp->selmode, sizeof(pdp->selmode))) {
1647 gsn->missing++;
1648 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1649 len, "Missing mandatory information field\n");
1650 return gtp_create_pdp_resp(gsn, version, pdp,
1651 GTPCAUSE_MAN_IE_MISSING);
1652 }
1653 /* End User Address (conditional) */
1654 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1655 &pdp->eua.v, sizeof(pdp->eua.v))) {
1656 gsn->missing++;
1657 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1658 len, "Missing mandatory information field\n");
1659 return gtp_create_pdp_resp(gsn, version, pdp,
1660 GTPCAUSE_MAN_IE_MISSING);
1661 }
1662 /* APN */
1663 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1664 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1665 gsn->missing++;
1666 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1667 len, "Missing mandatory information field\n");
1668 return gtp_create_pdp_resp(gsn, version, pdp,
1669 GTPCAUSE_MAN_IE_MISSING);
1670 }
1671 /* Extract protocol configuration options (optional) */
1672 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1673 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1674 }
Harald Weltebed35df2011-11-02 13:06:18 +01001675 /* MSISDN (conditional) */
1676 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1677 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1678 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001679 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1680 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001681 return gtp_create_pdp_resp(gsn, version, pdp,
1682 GTPCAUSE_MAN_IE_MISSING);
1683 }
1684 }
jjako52c24142002-12-16 13:33:51 +00001685
Harald Weltebed35df2011-11-02 13:06:18 +01001686 /* Initialize our own IP addresses */
1687 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1688 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1689
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001690 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before gtp_pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001691
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001692 if (!gtp_pdp_getimsi(gsn, &pdp_old, pdp->imsi, pdp->nsapi)) {
Harald Weltebed35df2011-11-02 13:06:18 +01001693 /* Found old pdp with same tid. Now the voodoo begins! */
1694 /* 09.60 / 29.060 allows create on existing context to "steal" */
1695 /* the context which was allready established */
1696 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001697 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001698 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1699 &&
1700 (!memcmp
1701 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1702 && (pdp->selmode == pdp_old->selmode)
1703 && (pdp->msisdn.l == pdp_old->msisdn.l)
1704 &&
1705 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1706 {
1707 /* OK! We are dealing with the same APN. We will copy new
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001708 * parameters to the old pdp and send off confirmation
Harald Weltebed35df2011-11-02 13:06:18 +01001709 * We ignore the following information elements:
1710 * QoS: MS will get originally negotiated QoS.
1711 * End user address (EUA). MS will get old EUA anyway.
1712 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001713 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001714
1715 /* Copy remote flow label */
1716 pdp_old->flru = pdp->flru;
1717 pdp_old->flrc = pdp->flrc;
1718
1719 /* Copy remote tei */
1720 pdp_old->teid_gn = pdp->teid_gn;
1721 pdp_old->teic_gn = pdp->teic_gn;
1722
1723 /* Copy peer GSN address */
1724 pdp_old->gsnrc.l = pdp->gsnrc.l;
1725 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1726 pdp_old->gsnru.l = pdp->gsnru.l;
1727 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1728
1729 /* Copy request parameters */
1730 pdp_old->seq = pdp->seq;
1731 pdp_old->sa_peer = pdp->sa_peer;
1732 pdp_old->fd = pdp->fd = fd;
1733 pdp_old->version = pdp->version = version;
1734
1735 /* Switch to using the old pdp context */
1736 pdp = pdp_old;
1737
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001738 if (recovery_recvd)
1739 emit_cb_recovery(gsn, peer, pdp, recovery);
1740
Harald Weltebed35df2011-11-02 13:06:18 +01001741 /* Confirm to peer that things were "successful" */
1742 return gtp_create_pdp_resp(gsn, version, pdp,
1743 GTPCAUSE_ACC_REQ);
1744 } else { /* This is not the same PDP context. Delete the old one. */
1745
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001746 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001747
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02001748 gtp_freepdp(gsn, pdp_old);
Harald Weltebed35df2011-11-02 13:06:18 +01001749
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001750 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001751 }
1752 }
1753
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +02001754 gtp_pdp_newpdp(gsn, &pdp, pdp->imsi, pdp->nsapi, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001755
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001756 /* Callback function to validate login */
Harald Weltebed35df2011-11-02 13:06:18 +01001757 if (gsn->cb_create_context_ind != 0)
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001758 rc = gsn->cb_create_context_ind(pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001759 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001760 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1761 "No create_context_ind callback defined\n");
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001762 rc = gtp_create_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001763 GTPCAUSE_NOT_SUPPORTED);
1764 }
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001765 if (recovery_recvd)
1766 emit_cb_recovery(gsn, peer, pdp, recovery);
1767 return rc;
jjako52c24142002-12-16 13:33:51 +00001768}
1769
jjako52c24142002-12-16 13:33:51 +00001770/* Handle Create PDP Context Response */
1771int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001772 struct sockaddr_in *peer, void *pack, unsigned len)
1773{
1774 struct pdp_t *pdp;
1775 union gtpie_member *ie[GTPIE_SIZE];
1776 uint8_t cause, recovery;
1777 void *cbp = NULL;
1778 uint8_t type = 0;
1779 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001780
Harald Weltebed35df2011-11-02 13:06:18 +01001781 /* Remove packet from queue */
1782 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1783 return EOF;
jjako52c24142002-12-16 13:33:51 +00001784
Harald Weltebed35df2011-11-02 13:06:18 +01001785 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001786 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001787 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001788 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001789 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001790 if (gsn->cb_conf)
1791 gsn->cb_conf(type, EOF, NULL, cbp);
1792 return EOF;
1793 }
jjako2c381332003-10-21 19:09:53 +00001794
Harald Weltebed35df2011-11-02 13:06:18 +01001795 /* Decode information elements */
1796 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1797 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001798 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1799 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001800 if (gsn->cb_conf)
1801 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001802 return EOF;
1803 }
jjako52c24142002-12-16 13:33:51 +00001804
Harald Weltebed35df2011-11-02 13:06:18 +01001805 /* Extract cause value (mandatory) */
1806 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1807 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001808 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1809 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001810 if (gsn->cb_conf)
1811 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001812 return EOF;
1813 }
jjako52c24142002-12-16 13:33:51 +00001814
Harald Weltebed35df2011-11-02 13:06:18 +01001815 /* Extract recovery (optional) */
1816 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001817 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001818 }
jjako52c24142002-12-16 13:33:51 +00001819
Harald Weltebed35df2011-11-02 13:06:18 +01001820 /* Extract protocol configuration options (optional) */
1821 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1822 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1823 }
jjako52c24142002-12-16 13:33:51 +00001824
Harald Weltebed35df2011-11-02 13:06:18 +01001825 /* Check all conditional information elements */
1826 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001827
Harald Weltebed35df2011-11-02 13:06:18 +01001828 if (version == 0) {
1829 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1830 &pdp->qos_neg0,
1831 sizeof(pdp->qos_neg0))) {
1832 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001833 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001834 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001835 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001836 if (gsn->cb_conf)
1837 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001838 return EOF;
1839 }
1840 }
jjako08d331d2003-10-13 20:33:30 +00001841
Harald Weltebed35df2011-11-02 13:06:18 +01001842 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1843 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001844 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001845 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001846 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001847 if (gsn->cb_conf)
1848 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001849 return EOF;
1850 }
jjako52c24142002-12-16 13:33:51 +00001851
Harald Weltebed35df2011-11-02 13:06:18 +01001852 if (version == 0) {
1853 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1854 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001855 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001856 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001857 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001858 if (gsn->cb_conf)
1859 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001860 return EOF;
1861 }
jjako52c24142002-12-16 13:33:51 +00001862
Harald Weltebed35df2011-11-02 13:06:18 +01001863 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1864 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001865 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001866 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001867 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001868 if (gsn->cb_conf)
1869 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001870 return EOF;
1871 }
1872 }
1873
1874 if (version == 1) {
1875 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1876 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001877 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001878 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001879 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001880 if (gsn->cb_conf)
1881 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001882 return EOF;
1883 }
1884
1885 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1886 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001887 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001888 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001889 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001890 if (gsn->cb_conf)
1891 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001892 return EOF;
1893 }
Pau Espin Pedrol0b1d9db2021-04-21 19:45:23 +02001894 /* Register that we have received a valid teic from GGSN */
1895 pdp->teic_confirmed = 1;
Harald Weltebed35df2011-11-02 13:06:18 +01001896 }
1897
1898 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1899 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001900 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001901 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001902 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001903 if (gsn->cb_conf)
1904 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001905 }
1906
1907 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1908 &pdp->eua.v, sizeof(pdp->eua.v))) {
1909 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001910 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001911 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001912 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001913 if (gsn->cb_conf)
1914 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001915 return EOF;
1916 }
1917
1918 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1919 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1920 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001921 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001922 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001923 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001924 if (gsn->cb_conf)
1925 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001926 return EOF;
1927 }
1928
1929 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1930 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1931 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001932 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001933 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001934 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001935 if (gsn->cb_conf)
1936 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001937 return EOF;
1938 }
1939
1940 if (version == 1) {
1941 if (gtpie_gettlv
1942 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1943 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1944 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001945 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001946 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001947 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001948 if (gsn->cb_conf)
1949 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001950 return EOF;
1951 }
1952 }
1953
1954 }
1955
1956 if (gsn->cb_conf)
1957 gsn->cb_conf(type, cause, pdp, cbp);
1958
1959 return 0;
jjako52c24142002-12-16 13:33:51 +00001960}
1961
jjako08d331d2003-10-13 20:33:30 +00001962/* API: Send Update PDP Context Request */
1963int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001964 struct in_addr *inetaddr)
1965{
1966 union gtp_packet packet;
1967 unsigned int length =
1968 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001969
Harald Weltebed35df2011-11-02 13:06:18 +01001970 if (pdp->version == 0)
1971 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1972 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001973
Harald Weltebed35df2011-11-02 13:06:18 +01001974 /* Include IMSI if updating with unknown teic_gn */
1975 if ((pdp->version == 1) && (!pdp->teic_gn))
1976 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1977 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1978
1979 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1980 gsn->restart_counter);
1981
1982 if (pdp->version == 0) {
1983 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1984 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1985 }
1986
1987 if (pdp->version == 1) {
1988 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1989 pdp->teid_own);
1990
1991 if (!pdp->teic_confirmed)
1992 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1993 pdp->teic_own);
1994 }
1995
1996 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1997
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001998 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001999 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
2000 pdp->traceref);
2001 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
2002 pdp->tracetype); */
2003
2004 /* TODO if ggsn update message
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002005 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01002006 pdp->eua.l, pdp->eua.v);
2007 */
2008
2009 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2010 pdp->gsnlc.l, pdp->gsnlc.v);
2011 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2012 pdp->gsnlu.l, pdp->gsnlu.v);
2013
2014 if (pdp->version == 1)
2015 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2016 pdp->qos_req.l, pdp->qos_req.v);
2017
2018 if ((pdp->version == 1) && pdp->tft.l)
2019 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
2020 pdp->tft.l, pdp->tft.v);
2021
2022 if ((pdp->version == 1) && pdp->triggerid.l)
2023 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
2024 pdp->triggerid.l, pdp->triggerid.v);
2025
2026 if ((pdp->version == 1) && pdp->omcid.l)
2027 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
2028 pdp->omcid.l, pdp->omcid.v);
2029
Daniel Willmann134a7752016-02-03 18:53:29 +01002030 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002031
2032 return 0;
jjako52c24142002-12-16 13:33:51 +00002033}
2034
jjako08d331d2003-10-13 20:33:30 +00002035/* Send Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002036static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002037 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00002038 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01002039 struct pdp_t *pdp, uint8_t cause)
2040{
jjako08d331d2003-10-13 20:33:30 +00002041
Harald Weltebed35df2011-11-02 13:06:18 +01002042 union gtp_packet packet;
2043 unsigned int length =
2044 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00002045
Harald Weltebed35df2011-11-02 13:06:18 +01002046 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00002047
Harald Weltebed35df2011-11-02 13:06:18 +01002048 if (cause == GTPCAUSE_ACC_REQ) {
2049
2050 if (version == 0)
2051 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
2052 sizeof(pdp->qos_neg0), pdp->qos_neg0);
2053
2054 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
2055 gsn->restart_counter);
2056
2057 if (version == 0) {
2058 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
2059 pdp->fllu);
2060 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
2061 pdp->fllc);
2062 }
2063
2064 if (version == 1) {
2065 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2066 pdp->teid_own);
2067
2068 if (!pdp->teic_confirmed)
2069 gtpie_tv4(&packet, &length, GTP_MAX,
2070 GTPIE_TEI_C, pdp->teic_own);
2071 }
2072
2073 /* TODO we use teid_own as charging ID address */
2074 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
2075 pdp->teid_own);
2076
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002077 /* If ggsn
2078 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01002079 pdp->eua.l, pdp->eua.v); */
2080
2081 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2082 pdp->gsnlc.l, pdp->gsnlc.v);
2083 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2084 pdp->gsnlu.l, pdp->gsnlu.v);
2085
2086 if (version == 1)
2087 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2088 pdp->qos_neg.l, pdp->qos_neg.v);
2089
2090 /* TODO: Charging gateway address */
2091 }
2092
2093 return gtp_resp(version, gsn, pdp, &packet, length, peer,
2094 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00002095}
2096
jjako52c24142002-12-16 13:33:51 +00002097/* Handle Update PDP Context Request */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002098static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002099 struct sockaddr_in *peer, int fd,
2100 void *pack, unsigned len)
2101{
2102 struct pdp_t *pdp;
2103 struct pdp_t pdp_backup;
2104 union gtpie_member *ie[GTPIE_SIZE];
2105 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002106
Harald Weltebed35df2011-11-02 13:06:18 +01002107 uint16_t seq = get_seq(pack);
2108 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002109
Harald Weltebed35df2011-11-02 13:06:18 +01002110 uint64_t imsi;
2111 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002112
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002113 /* Is this a duplicate ? */
2114 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002115 return 0; /* We allready send of response once */
2116 }
jjako08d331d2003-10-13 20:33:30 +00002117
Harald Weltebed35df2011-11-02 13:06:18 +01002118 /* Decode information elements */
2119 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2120 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002121 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2122 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002123 if (0 == version)
2124 return EOF;
2125 else
2126 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2127 len, NULL,
2128 GTPCAUSE_INVALID_MESSAGE);
2129 }
jjako08d331d2003-10-13 20:33:30 +00002130
Harald Weltebed35df2011-11-02 13:06:18 +01002131 /* Finding PDP: */
2132 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2133 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2134 /* we have to use the tunnel endpoint identifier */
2135 if (version == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002136 /* Find the context in question */
Vadim Yanitskiy00a61712019-08-30 21:00:22 +02002137 if (gtp_pdp_tidget(gsn, &pdp, get_tid(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002138 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002139 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2140 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002141 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2142 len, NULL,
2143 GTPCAUSE_NON_EXIST);
2144 }
Vadim Yanitskiy00a61712019-08-30 21:00:22 +02002145
2146 /* Update IMSI and NSAPI */
2147 pdp_set_imsi_nsapi(pdp, get_tid(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002148 } else if (version == 1) {
2149 /* NSAPI (mandatory) */
2150 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2151 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002152 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2153 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002154 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2155 len, NULL,
2156 GTPCAUSE_MAN_IE_MISSING);
2157 }
jjako08d331d2003-10-13 20:33:30 +00002158
Harald Weltebed35df2011-11-02 13:06:18 +01002159 /* IMSI (conditional) */
2160 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2161 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002162 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002163 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002164 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002165 pack, len, "Unknown PDP context: %u\n",
2166 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002167 return gtp_update_pdp_resp(gsn, version, peer,
2168 fd, pack, len, NULL,
2169 GTPCAUSE_NON_EXIST);
2170 }
2171 } else {
2172 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002173 if (gtp_pdp_getimsi(gsn, &pdp, imsi, nsapi)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002174 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002175 GTP_LOGPKG(LOGL_ERROR, peer,
2176 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002177 return gtp_update_pdp_resp(gsn, version, peer,
2178 fd, pack, len, NULL,
2179 GTPCAUSE_NON_EXIST);
2180 }
2181 }
2182 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002183 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002184 return EOF;
2185 }
jjako08d331d2003-10-13 20:33:30 +00002186
Harald Weltebed35df2011-11-02 13:06:18 +01002187 /* Make a backup copy in case anything is wrong */
2188 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002189
Harald Weltebed35df2011-11-02 13:06:18 +01002190 if (version == 0) {
2191 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2192 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2193 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002194 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2195 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002196 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2197 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2198 len, pdp,
2199 GTPCAUSE_MAN_IE_MISSING);
2200 }
2201 }
jjako52c24142002-12-16 13:33:51 +00002202
Harald Weltebed35df2011-11-02 13:06:18 +01002203 /* Recovery (optional) */
2204 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002205 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002206 }
jjako08d331d2003-10-13 20:33:30 +00002207
Harald Weltebed35df2011-11-02 13:06:18 +01002208 if (version == 0) {
2209 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2210 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002211 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2212 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002213 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2214 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2215 len, pdp,
2216 GTPCAUSE_MAN_IE_MISSING);
2217 }
jjako52c24142002-12-16 13:33:51 +00002218
Harald Weltebed35df2011-11-02 13:06:18 +01002219 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2220 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002221 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2222 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002223 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2224 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2225 len, pdp,
2226 GTPCAUSE_MAN_IE_MISSING);
2227 }
2228 }
jjako52c24142002-12-16 13:33:51 +00002229
Harald Weltebed35df2011-11-02 13:06:18 +01002230 if (version == 1) {
2231 /* TEID (mandatory) */
2232 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2233 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002234 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2235 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002236 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2237 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2238 len, pdp,
2239 GTPCAUSE_MAN_IE_MISSING);
2240 }
jjako52c24142002-12-16 13:33:51 +00002241
Harald Weltebed35df2011-11-02 13:06:18 +01002242 /* TEIC (conditional) */
2243 /* If TEIC is not included it means that we have allready received it */
2244 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2245 /* all updated contexts, or only for one of the linked contexts */
2246 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2247
2248 /* NSAPI (mandatory) */
2249 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2250 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002251 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2252 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002253 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2254 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2255 len, pdp,
2256 GTPCAUSE_MAN_IE_MISSING);
2257 }
2258 }
2259
2260 /* Trace reference (optional) */
2261 /* Trace type (optional) */
2262
2263 /* End User Address (conditional) TODO: GGSN Initiated
2264 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2265 &pdp->eua.v, sizeof(pdp->eua.v))) {
2266 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002267 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002268 "Missing mandatory information field");
2269 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002270 return gtp_update_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01002271 GTPCAUSE_MAN_IE_MISSING);
2272 } */
2273
2274 /* SGSN address for signalling (mandatory) */
2275 /* It is weird that this is mandatory when TEIC is conditional */
2276 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2277 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2278 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002279 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2280 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002281 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2282 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2283 pdp, GTPCAUSE_MAN_IE_MISSING);
2284 }
2285
2286 /* SGSN address for user traffic (mandatory) */
2287 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2288 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2289 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002290 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2291 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002292 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2293 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2294 pdp, GTPCAUSE_MAN_IE_MISSING);
2295 }
2296
2297 if (version == 1) {
2298 /* QoS (mandatory) */
2299 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2300 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2301 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002302 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2303 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002304 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2305 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2306 len, pdp,
2307 GTPCAUSE_MAN_IE_MISSING);
2308 }
2309
2310 /* TFT (conditional) */
2311 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2312 &pdp->tft.v, sizeof(pdp->tft.v))) {
2313 }
2314
2315 /* OMC identity */
2316 }
2317
2318 /* Confirm to peer that things were "successful" */
2319 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2320 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002321}
2322
jjako52c24142002-12-16 13:33:51 +00002323/* Handle Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002324static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002325 struct sockaddr_in *peer, void *pack, unsigned len)
2326{
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002327 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002328 union gtpie_member *ie[GTPIE_SIZE];
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002329 uint8_t cause = EOF;
2330 uint8_t recovery;
2331 int rc = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01002332 void *cbp = NULL;
2333 uint8_t type = 0;
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002334 bool trigger_recovery = false;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002335 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002336
Harald Weltebed35df2011-11-02 13:06:18 +01002337 /* Remove packet from queue */
2338 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2339 return EOF;
jjako52c24142002-12-16 13:33:51 +00002340
Harald Weltebed35df2011-11-02 13:06:18 +01002341 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002342 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002343 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002344 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2345 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002346 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002347 }
jjako52c24142002-12-16 13:33:51 +00002348
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002349 /* Extract recovery (optional) */
2350 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery))
2351 trigger_recovery = true;
2352
Harald Weltebed35df2011-11-02 13:06:18 +01002353 /* Extract cause value (mandatory) */
2354 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002355 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002356 }
jjako52c24142002-12-16 13:33:51 +00002357
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002358 /* 3GPP TS 29.060 sec 8.2: "Receiving node shall send back to the source
2359 * of the message, a response with the appropriate cause value (either
2360 * "Non-existent" or "Context not found"). The Tunnel Endpoint
2361 * Identifier used in the response message shall be set to all zeroes."
2362 * Hence, TEID=0 in this scenario, it makes no sense to infer PDP ctx
2363 * from it. User is responsible to infer it from cbp */
2364 if (cause != GTPCAUSE_NON_EXIST && cause != GTPCAUSE_CONTEXT_NOT_FOUND) {
2365 /* Find the context in question */
2366 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
2367 gsn->err_unknownpdp++;
2368 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2369 "Unknown PDP context: %u\n", get_tei(pack));
2370 goto err_out;
2371 }
Harald Weltebed35df2011-11-02 13:06:18 +01002372 }
2373
2374 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002375 /* TODO: This does not handle GGSN-initiated update responses */
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002376 if (cause == GTPCAUSE_ACC_REQ) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002377 if (version == 0) {
2378 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2379 &pdp->qos_neg0,
2380 sizeof(pdp->qos_neg0))) {
2381 goto err_missing;
2382 }
2383
2384 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2385 goto err_missing;
2386 }
2387
2388 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2389 goto err_missing;
2390 }
Harald Weltebed35df2011-11-02 13:06:18 +01002391 }
2392
Daniel Willmannd9975522016-02-04 15:38:12 +01002393 if (version == 1) {
2394 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2395 goto err_missing;
2396 }
Harald Weltebed35df2011-11-02 13:06:18 +01002397
Daniel Willmannd9975522016-02-04 15:38:12 +01002398 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2399 goto err_missing;
2400 }
Pau Espin Pedrol0b1d9db2021-04-21 19:45:23 +02002401 /* Register that we have received a valid teic from GGSN */
2402 pdp->teic_confirmed = 1;
Daniel Willmannd9975522016-02-04 15:38:12 +01002403 }
2404
2405 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2406 goto err_missing;
2407 }
2408
2409 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2410 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2411 goto err_missing;
2412 }
2413
2414 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2415 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2416 goto err_missing;
2417 }
2418
2419 if (version == 1) {
2420 if (gtpie_gettlv
2421 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2422 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2423 goto err_missing;
2424 }
2425 }
Harald Weltebed35df2011-11-02 13:06:18 +01002426 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002427
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002428generic_ret:
2429 if (trigger_recovery)
2430 emit_cb_recovery(gsn, peer, pdp, recovery);
Daniel Willmannd9975522016-02-04 15:38:12 +01002431 if (gsn->cb_conf)
2432 gsn->cb_conf(type, cause, pdp, cbp);
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002433 return rc; /* Succes */
Daniel Willmannd9975522016-02-04 15:38:12 +01002434
2435err_missing:
2436 gsn->missing++;
2437 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2438 "Missing information field\n");
2439err_out:
Pau Espin Pedrol00e05592021-04-22 13:47:57 +02002440 rc = EOF;
2441 goto generic_ret;
jjako52c24142002-12-16 13:33:51 +00002442}
2443
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002444/* API: Deprecated. Send Delete PDP Context Request And free pdp ctx. */
jjako2c381332003-10-21 19:09:53 +00002445int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002446 int teardown)
2447{
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002448 struct pdp_t *linked_pdp;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002449
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002450 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002451 LOGP(DLGTP, LOGL_ERROR,
2452 "Unknown linked PDP context: %u\n", pdp->teic_own);
2453 return EOF;
2454 }
2455
2456 if (gtp_delete_context_req2(gsn, pdp, cbp, teardown) == EOF)
2457 return EOF;
2458
2459 if (teardown) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002460 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002461 } else {
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002462 /* If we end up here (no teardown) it means we still
2463 have at least another pdp context active for this
2464 PDN connection (since last DeleteReq should come
2465 with teardown enabled). If the ctx to delete is a
2466 secondary ctx, simply free it. If it's the primary
2467 ctx, mark it as nodata but don't free it since we
2468 need it to hold data linked together and we'll
2469 require it later to tear down the entire tree. Still,
2470 we announce its deletion through cb_delete_context
2471 because we don't want user to release its related
2472 data and not use it anymore.
2473 */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002474 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002475 if (gsn->cb_delete_context)
2476 gsn->cb_delete_context(pdp);
2477 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2478 pdp->nodata = 1;
2479 } else {
2480 gtp_freepdp(gsn, pdp);
2481 }
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002482 }
2483
2484 return 0;
2485}
2486
Oliver Smith1cde2c12019-05-13 11:35:03 +02002487/* API: Send Delete PDP Context Request. PDP CTX shall be free'd by user at any
Pau Espin Pedrol4e605b32019-08-29 13:54:28 +02002488 point in time later than this function through a call to pdp_freepdp(pdp) (or
2489 through gtp_freepdp() if willing to receive cb_delete_context() callback),
2490 but it must be freed no later than during cb_conf(GTP_DELETE_PDP_REQ, pdp) */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002491int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2492 int teardown)
2493{
Harald Weltebed35df2011-11-02 13:06:18 +01002494 union gtp_packet packet;
2495 unsigned int length =
2496 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2497 struct in_addr addr;
2498 struct pdp_t *linked_pdp;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002499 int count;
jjako2c381332003-10-21 19:09:53 +00002500
Harald Weltebed35df2011-11-02 13:06:18 +01002501 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2502 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002503 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002504 return EOF;
jjako2c381332003-10-21 19:09:53 +00002505 }
jjako2c381332003-10-21 19:09:53 +00002506
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002507 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002508 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002509 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002510 return EOF;
2511 }
2512
2513 if (!teardown) {
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002514 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002515 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002516 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002517 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002518 return EOF;
2519 }
2520 }
2521
2522 if (pdp->version == 1) {
2523 if (teardown)
2524 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2525 0xff);
2526
2527 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2528 }
2529
2530 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2531
Harald Weltebed35df2011-11-02 13:06:18 +01002532 return 0;
jjako2c381332003-10-21 19:09:53 +00002533}
jjako08d331d2003-10-13 20:33:30 +00002534
jjako52c24142002-12-16 13:33:51 +00002535/* Send Delete PDP Context Response */
2536int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002537 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002538 void *pack, unsigned len,
2539 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002540 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002541{
Harald Weltebed35df2011-11-02 13:06:18 +01002542 union gtp_packet packet;
Harald Weltebed35df2011-11-02 13:06:18 +01002543 unsigned int length =
2544 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00002545
Harald Weltebed35df2011-11-02 13:06:18 +01002546 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002547
Harald Weltebed35df2011-11-02 13:06:18 +01002548 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2549 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002550
Harald Weltebed35df2011-11-02 13:06:18 +01002551 if (cause == GTPCAUSE_ACC_REQ) {
2552 if ((teardown) || (version == 0)) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002553 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002554 } else {
2555 /* If we end up here (no teardown) it means we still
2556 have at least another pdp context active for this
2557 PDN connection (since last DeleteReq should come
2558 with teardown enabled). If the ctx to delete is a
2559 secondary ctx, simply free it. If it's the primary
2560 ctx, mark it as nodata but don't free it since we
2561 need it to hold data linked together and we'll
2562 require it later to tear down the entire tree. Still,
2563 we announce its deletion through cb_delete_context
2564 because we don't want user to release its related
2565 data and not use it anymore.
2566 */
Harald Weltebed35df2011-11-02 13:06:18 +01002567 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002568 if (gsn->cb_delete_context)
2569 gsn->cb_delete_context(pdp);
2570 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2571 pdp->nodata = 1;
2572 } else {
2573 gtp_freepdp(gsn, pdp);
2574 }
Harald Weltebed35df2011-11-02 13:06:18 +01002575 }
jjako2c381332003-10-21 19:09:53 +00002576 }
Harald Weltebed35df2011-11-02 13:06:18 +01002577 /* if (cause == GTPCAUSE_ACC_REQ) */
2578 return 0;
jjako52c24142002-12-16 13:33:51 +00002579}
2580
2581/* Handle Delete PDP Context Request */
2582int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002583 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002584 void *pack, unsigned len)
2585{
2586 struct pdp_t *pdp = NULL;
2587 struct pdp_t *linked_pdp = NULL;
2588 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002589
Harald Weltebed35df2011-11-02 13:06:18 +01002590 uint16_t seq = get_seq(pack);
2591 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002592
Harald Weltebed35df2011-11-02 13:06:18 +01002593 uint8_t nsapi;
2594 uint8_t teardown = 0;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002595 int count;
jjako52c24142002-12-16 13:33:51 +00002596
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002597 /* Is this a duplicate ? */
2598 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002599 return 0; /* We allready send off response once */
2600 }
jjako2c381332003-10-21 19:09:53 +00002601
Harald Weltebed35df2011-11-02 13:06:18 +01002602 /* Find the linked context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002603 if (gtp_pdp_getgtp1(gsn, &linked_pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002604 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002605 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002606 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002607 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2608 NULL, NULL, GTPCAUSE_NON_EXIST,
2609 teardown);
2610 }
jjako2c381332003-10-21 19:09:53 +00002611
Harald Weltebed35df2011-11-02 13:06:18 +01002612 /* If version 0 this is also the secondary context */
2613 if (version == 0)
2614 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002615
Harald Weltebed35df2011-11-02 13:06:18 +01002616 /* Decode information elements */
2617 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2618 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002619 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2620 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002621 if (0 == version)
2622 return EOF;
2623 else
2624 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2625 len, NULL, NULL,
2626 GTPCAUSE_INVALID_MESSAGE,
2627 teardown);
2628 }
2629
2630 if (version == 1) {
2631 /* NSAPI (mandatory) */
2632 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2633 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002634 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2635 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002636 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2637 len, NULL, NULL,
2638 GTPCAUSE_MAN_IE_MISSING,
2639 teardown);
2640 }
2641
2642 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002643 if (gtp_pdp_getgtp1(gsn, &pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
Harald Weltebed35df2011-11-02 13:06:18 +01002644 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002645 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2646 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002647 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2648 len, NULL, NULL,
2649 GTPCAUSE_NON_EXIST,
2650 teardown);
2651 }
2652
2653 /* Teardown (conditional) */
2654 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2655
2656 if (!teardown) {
Pau Espin Pedrol742a6b52019-05-30 13:36:10 +02002657 /* TS 29.060 section 7.3.5: If a GSN receives a Delete PDP context
2658 * without a Teardown Indicator or with a Teardown Indicator with
2659 * value set to "0" and only that PDP context is active for a PDN
2660 * connection, then the GSN shall ignore the message. (Note:
2661 * This is symptom of a race condition. The reliable delivery of
2662 * signalling messages will eventually lead to a consistent
2663 * situation, allowing the teardown of the PDP context.)
2664 */
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002665 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002666 if (count <= 1) {
Pau Espin Pedrold1bd6fc2018-07-13 19:11:45 +02002667 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2668 "Ignoring CTX DEL without teardown and count=%d\n",
2669 count);
Harald Weltebed35df2011-11-02 13:06:18 +01002670 return 0; /* 29.060 7.3.5 Ignore message */
2671 }
2672 }
2673 }
2674
2675 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2676 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002677}
2678
jjako52c24142002-12-16 13:33:51 +00002679/* Handle Delete PDP Context Response */
2680int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002681 struct sockaddr_in *peer, void *pack, unsigned len)
2682{
2683 union gtpie_member *ie[GTPIE_SIZE];
2684 uint8_t cause;
2685 void *cbp = NULL;
2686 uint8_t type = 0;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002687 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002688 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002689
Harald Weltebed35df2011-11-02 13:06:18 +01002690 /* Remove packet from queue */
2691 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2692 return EOF;
jjako52c24142002-12-16 13:33:51 +00002693
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002694 /* Find the context in question. It may not be available if gtp_delete_context_req
2695 * was used and as a result the PDP ctx was already freed */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002696 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002697 gsn->err_unknownpdp++;
2698 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
Oliver Smith1cde2c12019-05-13 11:35:03 +02002699 "Unknown PDP context: %u (expected if gtp_delete_context_req is used or pdp ctx was freed manually before response)\n",
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002700 get_tei(pack));
2701 if (gsn->cb_conf)
2702 gsn->cb_conf(type, EOF, NULL, cbp);
2703 return EOF;
2704 }
2705
Harald Weltebed35df2011-11-02 13:06:18 +01002706 /* Decode information elements */
2707 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2708 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002709 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2710 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002711 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002712 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002713 return EOF;
2714 }
2715
2716 /* Extract cause value (mandatory) */
2717 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2718 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002719 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2720 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002721 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002722 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002723 return EOF;
2724 }
2725
2726 /* Check the cause value (again) */
2727 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2728 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002729 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2730 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002731 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002732 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002733 return EOF;
2734 }
2735
2736 /* Callback function to notify application */
2737 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002738 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002739
2740 return 0;
jjako52c24142002-12-16 13:33:51 +00002741}
2742
Harald Welte54d082e2017-08-12 22:43:21 +02002743/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002744static int gtp_error_ind_resp(struct gsn_t *gsn, uint8_t version,
jjako08d331d2003-10-13 20:33:30 +00002745 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002746 void *pack, unsigned len)
2747{
Harald Weltebed35df2011-11-02 13:06:18 +01002748 union gtp_packet packet;
2749 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2750
Harald Welte54d082e2017-08-12 22:43:21 +02002751 if (version == 1) {
2752 /* Mandatory 7.7.13 TEI Data I */
2753 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2754 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2755
2756 /* Mandatory 7.7.32 GSN Address */
2757 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2758 sizeof(gsn->gsnu), &gsn->gsnu);
2759 }
2760
Harald Weltebed35df2011-11-02 13:06:18 +01002761 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2762 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002763}
2764
2765/* Handle Error Indication */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002766static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002767 struct sockaddr_in *peer, void *pack, unsigned len)
2768{
Harald Welte37d5b152017-08-12 23:58:29 +02002769 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002770 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002771
Harald Weltebed35df2011-11-02 13:06:18 +01002772 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002773 if (version == 0) {
Vadim Yanitskiy68c5a742019-08-30 21:04:19 +02002774 if (gtp_pdp_tidget(gsn, &pdp, get_tid(pack))) {
Harald Welte37d5b152017-08-12 23:58:29 +02002775 gsn->err_unknownpdp++;
2776 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2777 "Unknown PDP context\n");
2778 return EOF;
2779 }
2780 } else if (version == 1) {
2781 /* we have to look-up based on the *peer* TEID */
2782 int hlen = get_hlen(pack);
2783 uint32_t teid_gn;
2784
2785 /* Decode information elements */
2786 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2787 gsn->invalid++;
2788 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2789 "Invalid message format\n");
2790 return EOF;
2791 }
2792
2793 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2794 gsn->missing++;
2795 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2796 "Missing mandatory information field\n");
2797 return EOF;
2798 }
2799
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002800 if (gtp_pdp_getgtp1_peer_d(gsn, &pdp, peer, teid_gn)) {
Harald Welte37d5b152017-08-12 23:58:29 +02002801 gsn->err_unknownpdp++;
2802 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2803 return EOF;
2804 }
Vadim Yanitskiybdf2cf92019-08-30 21:23:11 +02002805 } else {
2806 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
2807 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002808 }
jjako52c24142002-12-16 13:33:51 +00002809
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002810 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2811 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002812
Harald Weltebd228242017-11-06 03:16:49 +09002813 /* This is obvious from above code, given the semantics of the
2814 * functions above, but Coverity doesn't figure this out, so
2815 * let's make it clear. It's good style anyway in case above
2816 * code should ever change. */
2817 OSMO_ASSERT(pdp);
2818
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002819 gtp_freepdp(gsn, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002820 return 0;
jjako52c24142002-12-16 13:33:51 +00002821}
2822
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002823static int gtp_gpdu_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002824 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2825{
jjako08d331d2003-10-13 20:33:30 +00002826
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002827 int hlen;
jjako52c24142002-12-16 13:33:51 +00002828
Harald Weltebed35df2011-11-02 13:06:18 +01002829 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002830
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002831 switch (version) {
2832 case 0:
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002833 if (gtp_pdp_getgtp0(gsn, &pdp,
2834 ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002835 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002836 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002837 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002838 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2839 len);
2840 }
2841 hlen = GTP0_HEADER_SIZE;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002842 break;
2843 case 1:
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002844 if (gtp_pdp_getgtp1(gsn, &pdp,
2845 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002846 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002847 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002848 len, "Unknown PDP context, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002849 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2850 len);
2851 }
jjako08d331d2003-10-13 20:33:30 +00002852
Harald Weltebed35df2011-11-02 13:06:18 +01002853 /* Is this a long or a short header ? */
2854 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2855 hlen = GTP1_HEADER_SIZE_LONG;
2856 else
2857 hlen = GTP1_HEADER_SIZE_SHORT;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002858 break;
2859 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002860 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002861 "Unknown version: %d\n", version);
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002862 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002863 }
jjako08d331d2003-10-13 20:33:30 +00002864
Harald Weltebed35df2011-11-02 13:06:18 +01002865 /* If the GPDU was not from the peer GSN tell him to delete context */
2866 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2867 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002868 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002869 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2870 }
jjako52c24142002-12-16 13:33:51 +00002871
Harald Weltebed35df2011-11-02 13:06:18 +01002872 /* Callback function */
2873 if (gsn->cb_data_ind != 0)
2874 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2875
2876 return 0;
jjako52c24142002-12-16 13:33:51 +00002877}
2878
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002879/* Receives GTP packet and sends off for further processing
jjako52c24142002-12-16 13:33:51 +00002880 * Function will check the validity of the header. If the header
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002881 * is not valid the packet is either dropped or a version not
2882 * supported is returned to the peer.
jjako52c24142002-12-16 13:33:51 +00002883 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002884int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002885{
Harald Weltebed35df2011-11-02 13:06:18 +01002886 unsigned char buffer[PACKET_MAX];
2887 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002888 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002889 int status;
2890 struct gtp0_header *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002891 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002892 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002893
Harald Weltebed35df2011-11-02 13:06:18 +01002894 /* TODO: Need strategy of userspace buffering and blocking */
2895 /* Currently read is non-blocking and send is blocking. */
2896 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002897
Harald Weltebed35df2011-11-02 13:06:18 +01002898 while (1) { /* Loop until no more to read */
2899 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002900 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002901 return -1;
2902 }
2903 peerlen = sizeof(peer);
2904 if ((status =
2905 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2906 (struct sockaddr *)&peer, &peerlen)) < 0) {
2907 if (errno == EAGAIN)
2908 return 0;
2909 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002910 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002911 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002912 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2913 status, status ? strerror(errno) : "No error");
2914 return -1;
2915 }
jjako1db1c812003-07-06 20:53:57 +00002916
Harald Weltebed35df2011-11-02 13:06:18 +01002917 /* Need at least 1 byte in order to check version */
2918 if (status < (1)) {
2919 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002920 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2921 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002922 continue;
2923 }
jjako08d331d2003-10-13 20:33:30 +00002924
Harald Weltebed35df2011-11-02 13:06:18 +01002925 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002926
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002927 version = GTPHDR_F_GET_VER(pheader->flags);
2928
Harald Weltebed35df2011-11-02 13:06:18 +01002929 /* Version should be gtp0 (or earlier) */
2930 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2931 /* GTP 0 messages. If other version message is received we reply that we */
2932 /* only support version 0, implying that this is the only version */
2933 /* supported on this port */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002934 if (version > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002935 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01002936 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2937 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002938 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2939 continue;
2940 }
2941
2942 /* Check length of gtp0 packet */
2943 if (status < GTP0_HEADER_SIZE) {
2944 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002945 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2946 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002947 continue; /* Silently discard 29.60: 11.1.2 */
2948 }
2949
2950 /* Check packet length field versus length of packet */
2951 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2952 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002953 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002954 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002955 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002956 continue; /* Silently discard */
2957 }
2958
2959 if ((gsn->mode == GTP_MODE_GGSN) &&
2960 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002961 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002962 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002963 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002964 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002965 "Unexpected GTPv0 Signalling Message '%s'\n",
2966 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002967 continue; /* Silently discard 29.60: 11.1.4 */
2968 }
2969
2970 if ((gsn->mode == GTP_MODE_SGSN) &&
2971 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002972 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002973 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002974 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002975 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002976 "Unexpected GTPv0 Signalling Message '%s'\n",
2977 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002978 continue; /* Silently discard 29.60: 11.1.4 */
2979 }
2980
2981 switch (pheader->type) {
2982 case GTP_ECHO_REQ:
2983 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2984 break;
2985 case GTP_ECHO_RSP:
2986 gtp_echo_conf(gsn, version, &peer, buffer, status);
2987 break;
2988 case GTP_NOT_SUPPORTED:
2989 gtp_unsup_ind(gsn, &peer, buffer, status);
2990 break;
2991 case GTP_CREATE_PDP_REQ:
2992 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2993 status);
2994 break;
2995 case GTP_CREATE_PDP_RSP:
2996 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2997 status);
2998 break;
2999 case GTP_UPDATE_PDP_REQ:
3000 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3001 status);
3002 break;
3003 case GTP_UPDATE_PDP_RSP:
3004 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3005 status);
3006 break;
3007 case GTP_DELETE_PDP_REQ:
3008 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3009 status);
3010 break;
3011 case GTP_DELETE_PDP_RSP:
3012 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3013 status);
3014 break;
3015 case GTP_ERROR:
3016 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3017 break;
3018 case GTP_GPDU:
3019 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3020 break;
3021 default:
3022 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003023 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3024 "Unknown GTP message type received: %d\n",
3025 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003026 break;
3027 }
3028 }
jjako08d331d2003-10-13 20:33:30 +00003029}
3030
jjako08d331d2003-10-13 20:33:30 +00003031int gtp_decaps1c(struct gsn_t *gsn)
3032{
Harald Weltebed35df2011-11-02 13:06:18 +01003033 unsigned char buffer[PACKET_MAX];
3034 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003035 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003036 int status;
3037 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003038 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003039 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00003040
Harald Weltebed35df2011-11-02 13:06:18 +01003041 /* TODO: Need strategy of userspace buffering and blocking */
3042 /* Currently read is non-blocking and send is blocking. */
3043 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003044
Harald Weltebed35df2011-11-02 13:06:18 +01003045 while (1) { /* Loop until no more to read */
3046 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003047 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003048 return -1;
3049 }
3050 peerlen = sizeof(peer);
3051 if ((status =
3052 recvfrom(fd, buffer, sizeof(buffer), 0,
3053 (struct sockaddr *)&peer, &peerlen)) < 0) {
3054 if (errno == EAGAIN)
3055 return 0;
3056 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003057 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003058 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003059 fd, (unsigned long)buffer, sizeof(buffer),
3060 status, status ? strerror(errno) : "No error");
3061 return -1;
3062 }
jjako08d331d2003-10-13 20:33:30 +00003063
Harald Weltebed35df2011-11-02 13:06:18 +01003064 /* Need at least 1 byte in order to check version */
3065 if (status < (1)) {
3066 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003067 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3068 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003069 continue;
3070 }
jjako08d331d2003-10-13 20:33:30 +00003071
Harald Weltebed35df2011-11-02 13:06:18 +01003072 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003073
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003074 version = GTPHDR_F_GET_VER(pheader->flags);
3075
Harald Weltebed35df2011-11-02 13:06:18 +01003076 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003077 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003078 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003079 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3080 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003081 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
3082 /*29.60: 11.1.1 */
3083 continue;
3084 }
jjako08d331d2003-10-13 20:33:30 +00003085
Harald Weltebed35df2011-11-02 13:06:18 +01003086 /* Version must be at least GTP 1 */
3087 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3088 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3089 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003090 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003091 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003092 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3093 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003094 continue;
3095 }
jjako08d331d2003-10-13 20:33:30 +00003096
Harald Weltebed35df2011-11-02 13:06:18 +01003097 /* Check packet flag field */
3098 if (((pheader->flags & 0xf7) != 0x32)) {
3099 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003100 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003101 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003102 continue;
3103 }
jjako2c381332003-10-21 19:09:53 +00003104
Harald Weltebed35df2011-11-02 13:06:18 +01003105 /* Check length of packet */
3106 if (status < GTP1_HEADER_SIZE_LONG) {
3107 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003108 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3109 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003110 continue; /* Silently discard 29.60: 11.1.2 */
3111 }
jjako2c381332003-10-21 19:09:53 +00003112
Harald Weltebed35df2011-11-02 13:06:18 +01003113 /* Check packet length field versus length of packet */
3114 if (status !=
3115 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3116 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003117 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003118 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003119 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003120 continue; /* Silently discard */
3121 }
jjako1db1c812003-07-06 20:53:57 +00003122
Harald Weltebed35df2011-11-02 13:06:18 +01003123 /* Check for extension headers */
3124 /* TODO: We really should cycle through the headers and determine */
3125 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003126 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003127 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003128 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3129 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003130 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3131 status);
jjako1db1c812003-07-06 20:53:57 +00003132
Harald Weltebed35df2011-11-02 13:06:18 +01003133 continue;
3134 }
3135
3136 if ((gsn->mode == GTP_MODE_GGSN) &&
3137 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003138 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003139 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003140 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003141 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003142 "Unexpected GTPv1 Signalling Message '%s'\n",
3143 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003144 continue; /* Silently discard 29.60: 11.1.4 */
3145 }
3146
3147 if ((gsn->mode == GTP_MODE_SGSN) &&
3148 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003149 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003150 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003151 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003152 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003153 "Unexpected GTPv1 Signalling Message '%s'\n",
3154 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003155 continue; /* Silently discard 29.60: 11.1.4 */
3156 }
3157
3158 switch (pheader->type) {
3159 case GTP_ECHO_REQ:
3160 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3161 break;
3162 case GTP_ECHO_RSP:
3163 gtp_echo_conf(gsn, version, &peer, buffer, status);
3164 break;
3165 case GTP_NOT_SUPPORTED:
3166 gtp_unsup_ind(gsn, &peer, buffer, status);
3167 break;
3168 case GTP_SUPP_EXT_HEADER:
3169 gtp_extheader_ind(gsn, &peer, buffer, status);
3170 break;
3171 case GTP_CREATE_PDP_REQ:
3172 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3173 status);
3174 break;
3175 case GTP_CREATE_PDP_RSP:
3176 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3177 status);
3178 break;
3179 case GTP_UPDATE_PDP_REQ:
3180 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3181 status);
3182 break;
3183 case GTP_UPDATE_PDP_RSP:
3184 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3185 status);
3186 break;
3187 case GTP_DELETE_PDP_REQ:
3188 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3189 status);
3190 break;
3191 case GTP_DELETE_PDP_RSP:
3192 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3193 status);
3194 break;
3195 case GTP_ERROR:
3196 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3197 break;
3198 default:
3199 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003200 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3201 "Unknown GTP message type received: %u\n",
3202 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003203 break;
3204 }
3205 }
jjako52c24142002-12-16 13:33:51 +00003206}
3207
jjako08d331d2003-10-13 20:33:30 +00003208int gtp_decaps1u(struct gsn_t *gsn)
3209{
Harald Weltebed35df2011-11-02 13:06:18 +01003210 unsigned char buffer[PACKET_MAX];
3211 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003212 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003213 int status;
3214 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003215 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003216 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003217
Harald Weltebed35df2011-11-02 13:06:18 +01003218 /* TODO: Need strategy of userspace buffering and blocking */
3219 /* Currently read is non-blocking and send is blocking. */
3220 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003221
Harald Weltebed35df2011-11-02 13:06:18 +01003222 while (1) { /* Loop until no more to read */
3223 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003224 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003225 return -1;
3226 }
3227 peerlen = sizeof(peer);
3228 if ((status =
3229 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3230 (struct sockaddr *)&peer, &peerlen)) < 0) {
3231 if (errno == EAGAIN)
3232 return 0;
3233 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003234 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003235 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003236 gsn->fd1u, (unsigned long)buffer,
3237 sizeof(buffer), status,
3238 status ? strerror(errno) : "No error");
3239 return -1;
3240 }
jjako08d331d2003-10-13 20:33:30 +00003241
Harald Weltebed35df2011-11-02 13:06:18 +01003242 /* Need at least 1 byte in order to check version */
3243 if (status < (1)) {
3244 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003245 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3246 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003247 continue;
3248 }
jjako08d331d2003-10-13 20:33:30 +00003249
Harald Weltebed35df2011-11-02 13:06:18 +01003250 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003251
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003252 version = GTPHDR_F_GET_VER(pheader->flags);
3253
Harald Weltebed35df2011-11-02 13:06:18 +01003254 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003255 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003256 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003257 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3258 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003259 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3260 continue;
3261 }
jjako08d331d2003-10-13 20:33:30 +00003262
Harald Weltebed35df2011-11-02 13:06:18 +01003263 /* Version must be at least GTP 1 */
3264 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3265 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3266 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003267 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003268 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003269 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3270 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003271 continue;
3272 }
jjako2c381332003-10-21 19:09:53 +00003273
Harald Weltebed35df2011-11-02 13:06:18 +01003274 /* Check packet flag field (allow both with and without sequence number) */
3275 if (((pheader->flags & 0xf5) != 0x30)) {
3276 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003277 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003278 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003279 continue;
3280 }
jjako2c381332003-10-21 19:09:53 +00003281
Harald Weltebed35df2011-11-02 13:06:18 +01003282 /* Check length of packet */
3283 if (status < GTP1_HEADER_SIZE_SHORT) {
3284 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003285 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3286 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003287 continue; /* Silently discard 29.60: 11.1.2 */
3288 }
3289
3290 /* Check packet length field versus length of packet */
3291 if (status !=
3292 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3293 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003294 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003295 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003296 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003297 continue; /* Silently discard */
3298 }
3299
3300 /* Check for extension headers */
3301 /* TODO: We really should cycle through the headers and determine */
3302 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003303 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003304 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003305 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3306 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003307 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3308 status);
3309
3310 continue;
3311 }
3312
3313 switch (pheader->type) {
3314 case GTP_ECHO_REQ:
3315 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3316 break;
3317 case GTP_ECHO_RSP:
3318 gtp_echo_conf(gsn, version, &peer, buffer, status);
3319 break;
3320 case GTP_SUPP_EXT_HEADER:
3321 gtp_extheader_ind(gsn, &peer, buffer, status);
3322 break;
3323 case GTP_ERROR:
3324 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3325 break;
3326 /* Supported header extensions */
3327 case GTP_GPDU:
3328 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3329 break;
3330 default:
3331 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003332 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3333 "Unknown GTP message type received: %u\n",
3334 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003335 break;
3336 }
3337 }
jjako08d331d2003-10-13 20:33:30 +00003338}
3339
Harald Weltebed35df2011-11-02 13:06:18 +01003340int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003341{
Harald Weltebed35df2011-11-02 13:06:18 +01003342 union gtp_packet packet;
3343 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003344 struct msghdr msgh;
3345 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003346 int fd;
jjako52c24142002-12-16 13:33:51 +00003347
Harald Welte471e3492017-09-24 16:12:39 +08003348 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003349 memset(&addr, 0, sizeof(addr));
3350 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003351#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003352 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003353#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003354 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003355
Harald Welte471e3492017-09-24 16:12:39 +08003356 /* prepare msghdr */
3357 memset(&msgh, 0, sizeof(msgh));
3358 msgh.msg_name = &addr;
3359 msgh.msg_namelen = sizeof(addr);
3360 msgh.msg_iov = iov;
3361 msgh.msg_iovlen = ARRAY_SIZE(iov);
3362
3363 /* prepare iovectors */
3364 iov[0].iov_base = &packet;
3365 /* iov[0].iov_len is not known here yet */
3366 iov[1].iov_base = pack;
3367 iov[1].iov_len = len;
3368
Harald Weltebed35df2011-11-02 13:06:18 +01003369 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003370
Harald Welte471e3492017-09-24 16:12:39 +08003371 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003372 addr.sin_port = htons(GTP0_PORT);
3373 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003374
Harald Weltebed35df2011-11-02 13:06:18 +01003375 get_default_gtp(0, GTP_GPDU, &packet);
3376 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003377 if (pdp->tx_gpdu_seq)
3378 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3379 else
3380 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003381 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003382 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003383 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003384
Harald Weltebed35df2011-11-02 13:06:18 +01003385 addr.sin_port = htons(GTP1U_PORT);
3386 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003387
Harald Weltebed35df2011-11-02 13:06:18 +01003388 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003389 if (pdp->tx_gpdu_seq) {
3390 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3391 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3392 GTP1_HEADER_SIZE_LONG);
3393 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3394 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3395 } else {
3396 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3397 packet.gtp1s.h.length = hton16(len);
3398 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3399 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3400 }
Harald Weltebed35df2011-11-02 13:06:18 +01003401 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003402 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003403 return EOF;
3404 }
3405
3406 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003407 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003408 return -1;
3409 }
3410
Harald Welte471e3492017-09-24 16:12:39 +08003411 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003412 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003413 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003414 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003415 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3416 strerror(errno));
3417 return EOF;
3418 }
3419 return 0;
jjako52c24142002-12-16 13:33:51 +00003420}
3421
jjako52c24142002-12-16 13:33:51 +00003422/* ***********************************************************
3423 * Conversion functions
3424 *************************************************************/
3425
jjako52c24142002-12-16 13:33:51 +00003426/* ***********************************************************
3427 * IP address conversion functions
3428 * There exist several types of address representations:
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01003429 * - eua: End User Address. (29.060, 7.7.27, message type 128)
jjako52c24142002-12-16 13:33:51 +00003430 * Used for signalling address to mobile station. Supports IPv4
3431 * IPv6 x.25 etc. etc.
3432 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3433 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3434 * - in_addr: IPv4 address struct.
3435 * - sockaddr_in: Socket API representation of IP address and
3436 * port number.
3437 *************************************************************/
3438
Harald Weltebed35df2011-11-02 13:06:18 +01003439int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3440{
Harald Weltecee75462017-09-24 17:45:05 +08003441 eua->v[0] = PDP_EUA_ORG_IETF;
3442 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003443 if (src) {
3444 eua->l = 6;
3445 memcpy(&eua->v[2], src, 4);
3446 } else {
3447 eua->l = 2;
3448 }
3449 return 0;
jjako52c24142002-12-16 13:33:51 +00003450}
3451
Harald Weltebed35df2011-11-02 13:06:18 +01003452int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3453{
Harald Weltecee75462017-09-24 17:45:05 +08003454 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 +01003455 return -1; /* Not IPv4 address */
3456 memcpy(dst, &eua->v[2], 4);
3457 return 0;
jjako52c24142002-12-16 13:33:51 +00003458}
3459
Harald Weltebed35df2011-11-02 13:06:18 +01003460int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3461{
3462 memset(dst, 0, sizeof(struct in_addr));
3463 if (gsna->l != 4)
3464 return EOF; /* Return if not IPv4 */
3465 memcpy(dst, gsna->v, gsna->l);
3466 return 0;
jjako52c24142002-12-16 13:33:51 +00003467}
3468
Harald Weltebed35df2011-11-02 13:06:18 +01003469int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3470{
3471 memset(gsna, 0, sizeof(struct ul16_t));
3472 gsna->l = 4;
3473 memcpy(gsna->v, src, gsna->l);
3474 return 0;
jjako52c24142002-12-16 13:33:51 +00003475}
Harald Welteb10ee082017-08-12 19:29:16 +02003476
3477/* TS 29.060 has yet again a different encoding for IMSIs than
3478 * what we have in other places, so we cannot use the gsm48
3479 * decoding functions. Also, libgtp uses an uint64_t in
3480 * _network byte order_ to contain BCD digits ?!? */
3481const char *imsi_gtp2str(const uint64_t *imsi)
3482{
Harald Weltea06120d2017-11-06 03:12:54 +09003483 static char buf[sizeof(*imsi)*2+1];
Harald Welteb10ee082017-08-12 19:29:16 +02003484 const uint8_t *imsi8 = (const uint8_t *) imsi;
3485 unsigned int i, j = 0;
3486
3487 for (i = 0; i < sizeof(*imsi); i++) {
3488 uint8_t nibble;
3489
3490 nibble = imsi8[i] & 0xf;
3491 if (nibble == 0xf)
3492 break;
3493 buf[j++] = osmo_bcd2char(nibble);
3494
3495 nibble = imsi8[i] >> 4;
3496 if (nibble == 0xf)
3497 break;
3498 buf[j++] = osmo_bcd2char(nibble);
3499 }
3500
3501 buf[j++] = '\0';
3502 return buf;
3503}
Keithcbc07bd2020-10-10 12:17:26 +02003504
Keithfb2a7292020-10-12 15:32:07 +02003505/* Generate the GTP IMSI IE according to 09.60 Section 7.9.2 */
3506uint64_t gtp_imsi_str2gtp(const char *str)
Keithcbc07bd2020-10-10 12:17:26 +02003507{
Keithfb2a7292020-10-12 15:32:07 +02003508 uint64_t imsi64 = 0;
3509 unsigned int n;
3510 unsigned int imsi_len = strlen(str);
Keithcbc07bd2020-10-10 12:17:26 +02003511
Keithfb2a7292020-10-12 15:32:07 +02003512 if (imsi_len > 16) {
3513 LOGP(DLGTP, LOGL_NOTICE, "IMSI length > 16 not supported!\n");
3514 return 0;
3515 }
3516
3517 for (n = 0; n < 16; n++) {
3518 uint64_t val;
3519 if (n < imsi_len)
3520 val = (str[n]-'0') & 0xf;
3521 else
3522 val = 0xf;
3523 imsi64 |= (val << (n*4));
3524 }
3525 return imsi64;
3526}