blob: 701aa362b0ab26198a70abdf6930f16aac22e510 [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{
2327 struct pdp_t *pdp;
2328 union gtpie_member *ie[GTPIE_SIZE];
2329 uint8_t cause, recovery;
2330 void *cbp = NULL;
2331 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002332 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002333
Harald Weltebed35df2011-11-02 13:06:18 +01002334 /* Remove packet from queue */
2335 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2336 return EOF;
jjako52c24142002-12-16 13:33:51 +00002337
Harald Weltebed35df2011-11-02 13:06:18 +01002338 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002339 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002340 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002341 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002342 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002343 pdp = NULL;
2344 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002345 }
jjako2c381332003-10-21 19:09:53 +00002346
Harald Weltebed35df2011-11-02 13:06:18 +01002347 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002348 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002349 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002350 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2351 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002352 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002353 }
jjako52c24142002-12-16 13:33:51 +00002354
Harald Weltebed35df2011-11-02 13:06:18 +01002355 /* Extract cause value (mandatory) */
2356 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002357 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002358 }
jjako52c24142002-12-16 13:33:51 +00002359
Harald Weltebed35df2011-11-02 13:06:18 +01002360 /* Extract recovery (optional) */
2361 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002362 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002363 }
2364
2365 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002366 /* TODO: This does not handle GGSN-initiated update responses */
2367 if (GTPCAUSE_ACC_REQ == cause) {
2368 if (version == 0) {
2369 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2370 &pdp->qos_neg0,
2371 sizeof(pdp->qos_neg0))) {
2372 goto err_missing;
2373 }
2374
2375 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2376 goto err_missing;
2377 }
2378
2379 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2380 goto err_missing;
2381 }
Harald Weltebed35df2011-11-02 13:06:18 +01002382 }
2383
Daniel Willmannd9975522016-02-04 15:38:12 +01002384 if (version == 1) {
2385 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2386 goto err_missing;
2387 }
Harald Weltebed35df2011-11-02 13:06:18 +01002388
Daniel Willmannd9975522016-02-04 15:38:12 +01002389 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2390 goto err_missing;
2391 }
Pau Espin Pedrol0b1d9db2021-04-21 19:45:23 +02002392 /* Register that we have received a valid teic from GGSN */
2393 pdp->teic_confirmed = 1;
Daniel Willmannd9975522016-02-04 15:38:12 +01002394 }
2395
2396 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2397 goto err_missing;
2398 }
2399
2400 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2401 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2402 goto err_missing;
2403 }
2404
2405 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2406 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2407 goto err_missing;
2408 }
2409
2410 if (version == 1) {
2411 if (gtpie_gettlv
2412 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2413 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2414 goto err_missing;
2415 }
2416 }
Harald Weltebed35df2011-11-02 13:06:18 +01002417 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002418
2419 if (gsn->cb_conf)
2420 gsn->cb_conf(type, cause, pdp, cbp);
2421 return 0; /* Succes */
2422
2423err_missing:
2424 gsn->missing++;
2425 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2426 "Missing information field\n");
2427err_out:
2428 if (gsn->cb_conf)
2429 gsn->cb_conf(type, EOF, pdp, cbp);
2430 return EOF;
jjako52c24142002-12-16 13:33:51 +00002431}
2432
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002433/* API: Deprecated. Send Delete PDP Context Request And free pdp ctx. */
jjako2c381332003-10-21 19:09:53 +00002434int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002435 int teardown)
2436{
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002437 struct pdp_t *linked_pdp;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002438
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002439 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002440 LOGP(DLGTP, LOGL_ERROR,
2441 "Unknown linked PDP context: %u\n", pdp->teic_own);
2442 return EOF;
2443 }
2444
2445 if (gtp_delete_context_req2(gsn, pdp, cbp, teardown) == EOF)
2446 return EOF;
2447
2448 if (teardown) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002449 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002450 } else {
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002451 /* If we end up here (no teardown) it means we still
2452 have at least another pdp context active for this
2453 PDN connection (since last DeleteReq should come
2454 with teardown enabled). If the ctx to delete is a
2455 secondary ctx, simply free it. If it's the primary
2456 ctx, mark it as nodata but don't free it since we
2457 need it to hold data linked together and we'll
2458 require it later to tear down the entire tree. Still,
2459 we announce its deletion through cb_delete_context
2460 because we don't want user to release its related
2461 data and not use it anymore.
2462 */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002463 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002464 if (gsn->cb_delete_context)
2465 gsn->cb_delete_context(pdp);
2466 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2467 pdp->nodata = 1;
2468 } else {
2469 gtp_freepdp(gsn, pdp);
2470 }
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002471 }
2472
2473 return 0;
2474}
2475
Oliver Smith1cde2c12019-05-13 11:35:03 +02002476/* API: Send Delete PDP Context Request. PDP CTX shall be free'd by user at any
Pau Espin Pedrol4e605b32019-08-29 13:54:28 +02002477 point in time later than this function through a call to pdp_freepdp(pdp) (or
2478 through gtp_freepdp() if willing to receive cb_delete_context() callback),
2479 but it must be freed no later than during cb_conf(GTP_DELETE_PDP_REQ, pdp) */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002480int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2481 int teardown)
2482{
Harald Weltebed35df2011-11-02 13:06:18 +01002483 union gtp_packet packet;
2484 unsigned int length =
2485 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2486 struct in_addr addr;
2487 struct pdp_t *linked_pdp;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002488 int count;
jjako2c381332003-10-21 19:09:53 +00002489
Harald Weltebed35df2011-11-02 13:06:18 +01002490 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2491 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002492 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002493 return EOF;
jjako2c381332003-10-21 19:09:53 +00002494 }
jjako2c381332003-10-21 19:09:53 +00002495
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002496 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002497 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002498 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002499 return EOF;
2500 }
2501
2502 if (!teardown) {
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002503 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002504 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002505 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002506 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002507 return EOF;
2508 }
2509 }
2510
2511 if (pdp->version == 1) {
2512 if (teardown)
2513 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2514 0xff);
2515
2516 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2517 }
2518
2519 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2520
Harald Weltebed35df2011-11-02 13:06:18 +01002521 return 0;
jjako2c381332003-10-21 19:09:53 +00002522}
jjako08d331d2003-10-13 20:33:30 +00002523
jjako52c24142002-12-16 13:33:51 +00002524/* Send Delete PDP Context Response */
2525int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002526 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002527 void *pack, unsigned len,
2528 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002529 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002530{
Harald Weltebed35df2011-11-02 13:06:18 +01002531 union gtp_packet packet;
Harald Weltebed35df2011-11-02 13:06:18 +01002532 unsigned int length =
2533 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00002534
Harald Weltebed35df2011-11-02 13:06:18 +01002535 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002536
Harald Weltebed35df2011-11-02 13:06:18 +01002537 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2538 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002539
Harald Weltebed35df2011-11-02 13:06:18 +01002540 if (cause == GTPCAUSE_ACC_REQ) {
2541 if ((teardown) || (version == 0)) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002542 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002543 } else {
2544 /* If we end up here (no teardown) it means we still
2545 have at least another pdp context active for this
2546 PDN connection (since last DeleteReq should come
2547 with teardown enabled). If the ctx to delete is a
2548 secondary ctx, simply free it. If it's the primary
2549 ctx, mark it as nodata but don't free it since we
2550 need it to hold data linked together and we'll
2551 require it later to tear down the entire tree. Still,
2552 we announce its deletion through cb_delete_context
2553 because we don't want user to release its related
2554 data and not use it anymore.
2555 */
Harald Weltebed35df2011-11-02 13:06:18 +01002556 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002557 if (gsn->cb_delete_context)
2558 gsn->cb_delete_context(pdp);
2559 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2560 pdp->nodata = 1;
2561 } else {
2562 gtp_freepdp(gsn, pdp);
2563 }
Harald Weltebed35df2011-11-02 13:06:18 +01002564 }
jjako2c381332003-10-21 19:09:53 +00002565 }
Harald Weltebed35df2011-11-02 13:06:18 +01002566 /* if (cause == GTPCAUSE_ACC_REQ) */
2567 return 0;
jjako52c24142002-12-16 13:33:51 +00002568}
2569
2570/* Handle Delete PDP Context Request */
2571int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002572 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002573 void *pack, unsigned len)
2574{
2575 struct pdp_t *pdp = NULL;
2576 struct pdp_t *linked_pdp = NULL;
2577 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002578
Harald Weltebed35df2011-11-02 13:06:18 +01002579 uint16_t seq = get_seq(pack);
2580 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002581
Harald Weltebed35df2011-11-02 13:06:18 +01002582 uint8_t nsapi;
2583 uint8_t teardown = 0;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002584 int count;
jjako52c24142002-12-16 13:33:51 +00002585
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002586 /* Is this a duplicate ? */
2587 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002588 return 0; /* We allready send off response once */
2589 }
jjako2c381332003-10-21 19:09:53 +00002590
Harald Weltebed35df2011-11-02 13:06:18 +01002591 /* Find the linked context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002592 if (gtp_pdp_getgtp1(gsn, &linked_pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002593 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002594 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002595 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002596 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2597 NULL, NULL, GTPCAUSE_NON_EXIST,
2598 teardown);
2599 }
jjako2c381332003-10-21 19:09:53 +00002600
Harald Weltebed35df2011-11-02 13:06:18 +01002601 /* If version 0 this is also the secondary context */
2602 if (version == 0)
2603 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002604
Harald Weltebed35df2011-11-02 13:06:18 +01002605 /* Decode information elements */
2606 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2607 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002608 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2609 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002610 if (0 == version)
2611 return EOF;
2612 else
2613 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2614 len, NULL, NULL,
2615 GTPCAUSE_INVALID_MESSAGE,
2616 teardown);
2617 }
2618
2619 if (version == 1) {
2620 /* NSAPI (mandatory) */
2621 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2622 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002623 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2624 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002625 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2626 len, NULL, NULL,
2627 GTPCAUSE_MAN_IE_MISSING,
2628 teardown);
2629 }
2630
2631 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002632 if (gtp_pdp_getgtp1(gsn, &pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
Harald Weltebed35df2011-11-02 13:06:18 +01002633 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002634 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2635 len, "Unknown PDP context\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_NON_EXIST,
2639 teardown);
2640 }
2641
2642 /* Teardown (conditional) */
2643 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2644
2645 if (!teardown) {
Pau Espin Pedrol742a6b52019-05-30 13:36:10 +02002646 /* TS 29.060 section 7.3.5: If a GSN receives a Delete PDP context
2647 * without a Teardown Indicator or with a Teardown Indicator with
2648 * value set to "0" and only that PDP context is active for a PDN
2649 * connection, then the GSN shall ignore the message. (Note:
2650 * This is symptom of a race condition. The reliable delivery of
2651 * signalling messages will eventually lead to a consistent
2652 * situation, allowing the teardown of the PDP context.)
2653 */
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002654 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002655 if (count <= 1) {
Pau Espin Pedrold1bd6fc2018-07-13 19:11:45 +02002656 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2657 "Ignoring CTX DEL without teardown and count=%d\n",
2658 count);
Harald Weltebed35df2011-11-02 13:06:18 +01002659 return 0; /* 29.060 7.3.5 Ignore message */
2660 }
2661 }
2662 }
2663
2664 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2665 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002666}
2667
jjako52c24142002-12-16 13:33:51 +00002668/* Handle Delete PDP Context Response */
2669int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002670 struct sockaddr_in *peer, void *pack, unsigned len)
2671{
2672 union gtpie_member *ie[GTPIE_SIZE];
2673 uint8_t cause;
2674 void *cbp = NULL;
2675 uint8_t type = 0;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002676 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002677 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002678
Harald Weltebed35df2011-11-02 13:06:18 +01002679 /* Remove packet from queue */
2680 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2681 return EOF;
jjako52c24142002-12-16 13:33:51 +00002682
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002683 /* Find the context in question. It may not be available if gtp_delete_context_req
2684 * was used and as a result the PDP ctx was already freed */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002685 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002686 gsn->err_unknownpdp++;
2687 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
Oliver Smith1cde2c12019-05-13 11:35:03 +02002688 "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 +02002689 get_tei(pack));
2690 if (gsn->cb_conf)
2691 gsn->cb_conf(type, EOF, NULL, cbp);
2692 return EOF;
2693 }
2694
Harald Weltebed35df2011-11-02 13:06:18 +01002695 /* Decode information elements */
2696 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2697 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002698 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2699 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002700 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002701 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002702 return EOF;
2703 }
2704
2705 /* Extract cause value (mandatory) */
2706 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2707 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002708 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2709 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002710 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002711 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002712 return EOF;
2713 }
2714
2715 /* Check the cause value (again) */
2716 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2717 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002718 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2719 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002720 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002721 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002722 return EOF;
2723 }
2724
2725 /* Callback function to notify application */
2726 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002727 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002728
2729 return 0;
jjako52c24142002-12-16 13:33:51 +00002730}
2731
Harald Welte54d082e2017-08-12 22:43:21 +02002732/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002733static int gtp_error_ind_resp(struct gsn_t *gsn, uint8_t version,
jjako08d331d2003-10-13 20:33:30 +00002734 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002735 void *pack, unsigned len)
2736{
Harald Weltebed35df2011-11-02 13:06:18 +01002737 union gtp_packet packet;
2738 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2739
Harald Welte54d082e2017-08-12 22:43:21 +02002740 if (version == 1) {
2741 /* Mandatory 7.7.13 TEI Data I */
2742 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2743 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2744
2745 /* Mandatory 7.7.32 GSN Address */
2746 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2747 sizeof(gsn->gsnu), &gsn->gsnu);
2748 }
2749
Harald Weltebed35df2011-11-02 13:06:18 +01002750 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2751 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002752}
2753
2754/* Handle Error Indication */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002755static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002756 struct sockaddr_in *peer, void *pack, unsigned len)
2757{
Harald Welte37d5b152017-08-12 23:58:29 +02002758 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002759 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002760
Harald Weltebed35df2011-11-02 13:06:18 +01002761 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002762 if (version == 0) {
Vadim Yanitskiy68c5a742019-08-30 21:04:19 +02002763 if (gtp_pdp_tidget(gsn, &pdp, get_tid(pack))) {
Harald Welte37d5b152017-08-12 23:58:29 +02002764 gsn->err_unknownpdp++;
2765 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2766 "Unknown PDP context\n");
2767 return EOF;
2768 }
2769 } else if (version == 1) {
2770 /* we have to look-up based on the *peer* TEID */
2771 int hlen = get_hlen(pack);
2772 uint32_t teid_gn;
2773
2774 /* Decode information elements */
2775 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2776 gsn->invalid++;
2777 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2778 "Invalid message format\n");
2779 return EOF;
2780 }
2781
2782 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2783 gsn->missing++;
2784 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2785 "Missing mandatory information field\n");
2786 return EOF;
2787 }
2788
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002789 if (gtp_pdp_getgtp1_peer_d(gsn, &pdp, peer, teid_gn)) {
Harald Welte37d5b152017-08-12 23:58:29 +02002790 gsn->err_unknownpdp++;
2791 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2792 return EOF;
2793 }
Vadim Yanitskiybdf2cf92019-08-30 21:23:11 +02002794 } else {
2795 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
2796 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002797 }
jjako52c24142002-12-16 13:33:51 +00002798
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002799 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2800 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002801
Harald Weltebd228242017-11-06 03:16:49 +09002802 /* This is obvious from above code, given the semantics of the
2803 * functions above, but Coverity doesn't figure this out, so
2804 * let's make it clear. It's good style anyway in case above
2805 * code should ever change. */
2806 OSMO_ASSERT(pdp);
2807
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002808 gtp_freepdp(gsn, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002809 return 0;
jjako52c24142002-12-16 13:33:51 +00002810}
2811
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002812static int gtp_gpdu_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002813 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2814{
jjako08d331d2003-10-13 20:33:30 +00002815
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002816 int hlen;
jjako52c24142002-12-16 13:33:51 +00002817
Harald Weltebed35df2011-11-02 13:06:18 +01002818 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002819
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002820 switch (version) {
2821 case 0:
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002822 if (gtp_pdp_getgtp0(gsn, &pdp,
2823 ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002824 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002825 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002826 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002827 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2828 len);
2829 }
2830 hlen = GTP0_HEADER_SIZE;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002831 break;
2832 case 1:
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002833 if (gtp_pdp_getgtp1(gsn, &pdp,
2834 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
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, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002838 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2839 len);
2840 }
jjako08d331d2003-10-13 20:33:30 +00002841
Harald Weltebed35df2011-11-02 13:06:18 +01002842 /* Is this a long or a short header ? */
2843 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2844 hlen = GTP1_HEADER_SIZE_LONG;
2845 else
2846 hlen = GTP1_HEADER_SIZE_SHORT;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002847 break;
2848 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002849 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002850 "Unknown version: %d\n", version);
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002851 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002852 }
jjako08d331d2003-10-13 20:33:30 +00002853
Harald Weltebed35df2011-11-02 13:06:18 +01002854 /* If the GPDU was not from the peer GSN tell him to delete context */
2855 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2856 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002857 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002858 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2859 }
jjako52c24142002-12-16 13:33:51 +00002860
Harald Weltebed35df2011-11-02 13:06:18 +01002861 /* Callback function */
2862 if (gsn->cb_data_ind != 0)
2863 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2864
2865 return 0;
jjako52c24142002-12-16 13:33:51 +00002866}
2867
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002868/* Receives GTP packet and sends off for further processing
jjako52c24142002-12-16 13:33:51 +00002869 * Function will check the validity of the header. If the header
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002870 * is not valid the packet is either dropped or a version not
2871 * supported is returned to the peer.
jjako52c24142002-12-16 13:33:51 +00002872 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002873int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002874{
Harald Weltebed35df2011-11-02 13:06:18 +01002875 unsigned char buffer[PACKET_MAX];
2876 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002877 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002878 int status;
2879 struct gtp0_header *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002880 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002881 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002882
Harald Weltebed35df2011-11-02 13:06:18 +01002883 /* TODO: Need strategy of userspace buffering and blocking */
2884 /* Currently read is non-blocking and send is blocking. */
2885 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002886
Harald Weltebed35df2011-11-02 13:06:18 +01002887 while (1) { /* Loop until no more to read */
2888 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002889 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002890 return -1;
2891 }
2892 peerlen = sizeof(peer);
2893 if ((status =
2894 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2895 (struct sockaddr *)&peer, &peerlen)) < 0) {
2896 if (errno == EAGAIN)
2897 return 0;
2898 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002899 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002900 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002901 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2902 status, status ? strerror(errno) : "No error");
2903 return -1;
2904 }
jjako1db1c812003-07-06 20:53:57 +00002905
Harald Weltebed35df2011-11-02 13:06:18 +01002906 /* Need at least 1 byte in order to check version */
2907 if (status < (1)) {
2908 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002909 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2910 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002911 continue;
2912 }
jjako08d331d2003-10-13 20:33:30 +00002913
Harald Weltebed35df2011-11-02 13:06:18 +01002914 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002915
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002916 version = GTPHDR_F_GET_VER(pheader->flags);
2917
Harald Weltebed35df2011-11-02 13:06:18 +01002918 /* Version should be gtp0 (or earlier) */
2919 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2920 /* GTP 0 messages. If other version message is received we reply that we */
2921 /* only support version 0, implying that this is the only version */
2922 /* supported on this port */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002923 if (version > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002924 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01002925 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2926 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002927 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2928 continue;
2929 }
2930
2931 /* Check length of gtp0 packet */
2932 if (status < GTP0_HEADER_SIZE) {
2933 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002934 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2935 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002936 continue; /* Silently discard 29.60: 11.1.2 */
2937 }
2938
2939 /* Check packet length field versus length of packet */
2940 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2941 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002942 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002943 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002944 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002945 continue; /* Silently discard */
2946 }
2947
2948 if ((gsn->mode == GTP_MODE_GGSN) &&
2949 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002950 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002951 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002952 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002953 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002954 "Unexpected GTPv0 Signalling Message '%s'\n",
2955 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002956 continue; /* Silently discard 29.60: 11.1.4 */
2957 }
2958
2959 if ((gsn->mode == GTP_MODE_SGSN) &&
2960 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002961 (pheader->type == GTP_UPDATE_PDP_REQ))) {
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 switch (pheader->type) {
2971 case GTP_ECHO_REQ:
2972 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2973 break;
2974 case GTP_ECHO_RSP:
2975 gtp_echo_conf(gsn, version, &peer, buffer, status);
2976 break;
2977 case GTP_NOT_SUPPORTED:
2978 gtp_unsup_ind(gsn, &peer, buffer, status);
2979 break;
2980 case GTP_CREATE_PDP_REQ:
2981 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2982 status);
2983 break;
2984 case GTP_CREATE_PDP_RSP:
2985 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2986 status);
2987 break;
2988 case GTP_UPDATE_PDP_REQ:
2989 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2990 status);
2991 break;
2992 case GTP_UPDATE_PDP_RSP:
2993 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2994 status);
2995 break;
2996 case GTP_DELETE_PDP_REQ:
2997 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2998 status);
2999 break;
3000 case GTP_DELETE_PDP_RSP:
3001 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3002 status);
3003 break;
3004 case GTP_ERROR:
3005 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3006 break;
3007 case GTP_GPDU:
3008 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3009 break;
3010 default:
3011 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003012 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3013 "Unknown GTP message type received: %d\n",
3014 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003015 break;
3016 }
3017 }
jjako08d331d2003-10-13 20:33:30 +00003018}
3019
jjako08d331d2003-10-13 20:33:30 +00003020int gtp_decaps1c(struct gsn_t *gsn)
3021{
Harald Weltebed35df2011-11-02 13:06:18 +01003022 unsigned char buffer[PACKET_MAX];
3023 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003024 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003025 int status;
3026 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003027 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003028 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00003029
Harald Weltebed35df2011-11-02 13:06:18 +01003030 /* TODO: Need strategy of userspace buffering and blocking */
3031 /* Currently read is non-blocking and send is blocking. */
3032 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003033
Harald Weltebed35df2011-11-02 13:06:18 +01003034 while (1) { /* Loop until no more to read */
3035 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003036 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003037 return -1;
3038 }
3039 peerlen = sizeof(peer);
3040 if ((status =
3041 recvfrom(fd, buffer, sizeof(buffer), 0,
3042 (struct sockaddr *)&peer, &peerlen)) < 0) {
3043 if (errno == EAGAIN)
3044 return 0;
3045 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003046 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003047 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003048 fd, (unsigned long)buffer, sizeof(buffer),
3049 status, status ? strerror(errno) : "No error");
3050 return -1;
3051 }
jjako08d331d2003-10-13 20:33:30 +00003052
Harald Weltebed35df2011-11-02 13:06:18 +01003053 /* Need at least 1 byte in order to check version */
3054 if (status < (1)) {
3055 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003056 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3057 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003058 continue;
3059 }
jjako08d331d2003-10-13 20:33:30 +00003060
Harald Weltebed35df2011-11-02 13:06:18 +01003061 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003062
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003063 version = GTPHDR_F_GET_VER(pheader->flags);
3064
Harald Weltebed35df2011-11-02 13:06:18 +01003065 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003066 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003067 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003068 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3069 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003070 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
3071 /*29.60: 11.1.1 */
3072 continue;
3073 }
jjako08d331d2003-10-13 20:33:30 +00003074
Harald Weltebed35df2011-11-02 13:06:18 +01003075 /* Version must be at least GTP 1 */
3076 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3077 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3078 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003079 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003080 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003081 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3082 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003083 continue;
3084 }
jjako08d331d2003-10-13 20:33:30 +00003085
Harald Weltebed35df2011-11-02 13:06:18 +01003086 /* Check packet flag field */
3087 if (((pheader->flags & 0xf7) != 0x32)) {
3088 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003089 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003090 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003091 continue;
3092 }
jjako2c381332003-10-21 19:09:53 +00003093
Harald Weltebed35df2011-11-02 13:06:18 +01003094 /* Check length of packet */
3095 if (status < GTP1_HEADER_SIZE_LONG) {
3096 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003097 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3098 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003099 continue; /* Silently discard 29.60: 11.1.2 */
3100 }
jjako2c381332003-10-21 19:09:53 +00003101
Harald Weltebed35df2011-11-02 13:06:18 +01003102 /* Check packet length field versus length of packet */
3103 if (status !=
3104 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3105 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003106 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003107 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003108 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003109 continue; /* Silently discard */
3110 }
jjako1db1c812003-07-06 20:53:57 +00003111
Harald Weltebed35df2011-11-02 13:06:18 +01003112 /* Check for extension headers */
3113 /* TODO: We really should cycle through the headers and determine */
3114 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003115 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003116 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003117 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3118 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003119 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3120 status);
jjako1db1c812003-07-06 20:53:57 +00003121
Harald Weltebed35df2011-11-02 13:06:18 +01003122 continue;
3123 }
3124
3125 if ((gsn->mode == GTP_MODE_GGSN) &&
3126 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003127 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003128 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003129 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003130 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003131 "Unexpected GTPv1 Signalling Message '%s'\n",
3132 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003133 continue; /* Silently discard 29.60: 11.1.4 */
3134 }
3135
3136 if ((gsn->mode == GTP_MODE_SGSN) &&
3137 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003138 (pheader->type == GTP_UPDATE_PDP_REQ))) {
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 switch (pheader->type) {
3148 case GTP_ECHO_REQ:
3149 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3150 break;
3151 case GTP_ECHO_RSP:
3152 gtp_echo_conf(gsn, version, &peer, buffer, status);
3153 break;
3154 case GTP_NOT_SUPPORTED:
3155 gtp_unsup_ind(gsn, &peer, buffer, status);
3156 break;
3157 case GTP_SUPP_EXT_HEADER:
3158 gtp_extheader_ind(gsn, &peer, buffer, status);
3159 break;
3160 case GTP_CREATE_PDP_REQ:
3161 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3162 status);
3163 break;
3164 case GTP_CREATE_PDP_RSP:
3165 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3166 status);
3167 break;
3168 case GTP_UPDATE_PDP_REQ:
3169 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3170 status);
3171 break;
3172 case GTP_UPDATE_PDP_RSP:
3173 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3174 status);
3175 break;
3176 case GTP_DELETE_PDP_REQ:
3177 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3178 status);
3179 break;
3180 case GTP_DELETE_PDP_RSP:
3181 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3182 status);
3183 break;
3184 case GTP_ERROR:
3185 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3186 break;
3187 default:
3188 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003189 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3190 "Unknown GTP message type received: %u\n",
3191 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003192 break;
3193 }
3194 }
jjako52c24142002-12-16 13:33:51 +00003195}
3196
jjako08d331d2003-10-13 20:33:30 +00003197int gtp_decaps1u(struct gsn_t *gsn)
3198{
Harald Weltebed35df2011-11-02 13:06:18 +01003199 unsigned char buffer[PACKET_MAX];
3200 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003201 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003202 int status;
3203 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003204 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003205 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003206
Harald Weltebed35df2011-11-02 13:06:18 +01003207 /* TODO: Need strategy of userspace buffering and blocking */
3208 /* Currently read is non-blocking and send is blocking. */
3209 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003210
Harald Weltebed35df2011-11-02 13:06:18 +01003211 while (1) { /* Loop until no more to read */
3212 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003213 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003214 return -1;
3215 }
3216 peerlen = sizeof(peer);
3217 if ((status =
3218 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3219 (struct sockaddr *)&peer, &peerlen)) < 0) {
3220 if (errno == EAGAIN)
3221 return 0;
3222 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003223 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003224 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003225 gsn->fd1u, (unsigned long)buffer,
3226 sizeof(buffer), status,
3227 status ? strerror(errno) : "No error");
3228 return -1;
3229 }
jjako08d331d2003-10-13 20:33:30 +00003230
Harald Weltebed35df2011-11-02 13:06:18 +01003231 /* Need at least 1 byte in order to check version */
3232 if (status < (1)) {
3233 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003234 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3235 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003236 continue;
3237 }
jjako08d331d2003-10-13 20:33:30 +00003238
Harald Weltebed35df2011-11-02 13:06:18 +01003239 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003240
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003241 version = GTPHDR_F_GET_VER(pheader->flags);
3242
Harald Weltebed35df2011-11-02 13:06:18 +01003243 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003244 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003245 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003246 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3247 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003248 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3249 continue;
3250 }
jjako08d331d2003-10-13 20:33:30 +00003251
Harald Weltebed35df2011-11-02 13:06:18 +01003252 /* Version must be at least GTP 1 */
3253 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3254 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3255 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003256 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003257 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003258 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3259 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003260 continue;
3261 }
jjako2c381332003-10-21 19:09:53 +00003262
Harald Weltebed35df2011-11-02 13:06:18 +01003263 /* Check packet flag field (allow both with and without sequence number) */
3264 if (((pheader->flags & 0xf5) != 0x30)) {
3265 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003266 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003267 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003268 continue;
3269 }
jjako2c381332003-10-21 19:09:53 +00003270
Harald Weltebed35df2011-11-02 13:06:18 +01003271 /* Check length of packet */
3272 if (status < GTP1_HEADER_SIZE_SHORT) {
3273 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003274 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3275 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003276 continue; /* Silently discard 29.60: 11.1.2 */
3277 }
3278
3279 /* Check packet length field versus length of packet */
3280 if (status !=
3281 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3282 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003283 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003284 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003285 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003286 continue; /* Silently discard */
3287 }
3288
3289 /* Check for extension headers */
3290 /* TODO: We really should cycle through the headers and determine */
3291 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003292 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003293 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003294 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3295 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003296 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3297 status);
3298
3299 continue;
3300 }
3301
3302 switch (pheader->type) {
3303 case GTP_ECHO_REQ:
3304 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3305 break;
3306 case GTP_ECHO_RSP:
3307 gtp_echo_conf(gsn, version, &peer, buffer, status);
3308 break;
3309 case GTP_SUPP_EXT_HEADER:
3310 gtp_extheader_ind(gsn, &peer, buffer, status);
3311 break;
3312 case GTP_ERROR:
3313 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3314 break;
3315 /* Supported header extensions */
3316 case GTP_GPDU:
3317 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3318 break;
3319 default:
3320 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003321 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3322 "Unknown GTP message type received: %u\n",
3323 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003324 break;
3325 }
3326 }
jjako08d331d2003-10-13 20:33:30 +00003327}
3328
Harald Weltebed35df2011-11-02 13:06:18 +01003329int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003330{
Harald Weltebed35df2011-11-02 13:06:18 +01003331 union gtp_packet packet;
3332 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003333 struct msghdr msgh;
3334 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003335 int fd;
jjako52c24142002-12-16 13:33:51 +00003336
Harald Welte471e3492017-09-24 16:12:39 +08003337 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003338 memset(&addr, 0, sizeof(addr));
3339 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003340#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003341 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003342#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003343 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003344
Harald Welte471e3492017-09-24 16:12:39 +08003345 /* prepare msghdr */
3346 memset(&msgh, 0, sizeof(msgh));
3347 msgh.msg_name = &addr;
3348 msgh.msg_namelen = sizeof(addr);
3349 msgh.msg_iov = iov;
3350 msgh.msg_iovlen = ARRAY_SIZE(iov);
3351
3352 /* prepare iovectors */
3353 iov[0].iov_base = &packet;
3354 /* iov[0].iov_len is not known here yet */
3355 iov[1].iov_base = pack;
3356 iov[1].iov_len = len;
3357
Harald Weltebed35df2011-11-02 13:06:18 +01003358 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003359
Harald Welte471e3492017-09-24 16:12:39 +08003360 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003361 addr.sin_port = htons(GTP0_PORT);
3362 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003363
Harald Weltebed35df2011-11-02 13:06:18 +01003364 get_default_gtp(0, GTP_GPDU, &packet);
3365 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003366 if (pdp->tx_gpdu_seq)
3367 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3368 else
3369 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003370 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003371 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003372 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003373
Harald Weltebed35df2011-11-02 13:06:18 +01003374 addr.sin_port = htons(GTP1U_PORT);
3375 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003376
Harald Weltebed35df2011-11-02 13:06:18 +01003377 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003378 if (pdp->tx_gpdu_seq) {
3379 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3380 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3381 GTP1_HEADER_SIZE_LONG);
3382 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3383 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3384 } else {
3385 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3386 packet.gtp1s.h.length = hton16(len);
3387 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3388 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3389 }
Harald Weltebed35df2011-11-02 13:06:18 +01003390 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003391 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003392 return EOF;
3393 }
3394
3395 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003396 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003397 return -1;
3398 }
3399
Harald Welte471e3492017-09-24 16:12:39 +08003400 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003401 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003402 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003403 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003404 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3405 strerror(errno));
3406 return EOF;
3407 }
3408 return 0;
jjako52c24142002-12-16 13:33:51 +00003409}
3410
jjako52c24142002-12-16 13:33:51 +00003411/* ***********************************************************
3412 * Conversion functions
3413 *************************************************************/
3414
jjako52c24142002-12-16 13:33:51 +00003415/* ***********************************************************
3416 * IP address conversion functions
3417 * There exist several types of address representations:
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01003418 * - eua: End User Address. (29.060, 7.7.27, message type 128)
jjako52c24142002-12-16 13:33:51 +00003419 * Used for signalling address to mobile station. Supports IPv4
3420 * IPv6 x.25 etc. etc.
3421 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3422 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3423 * - in_addr: IPv4 address struct.
3424 * - sockaddr_in: Socket API representation of IP address and
3425 * port number.
3426 *************************************************************/
3427
Harald Weltebed35df2011-11-02 13:06:18 +01003428int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3429{
Harald Weltecee75462017-09-24 17:45:05 +08003430 eua->v[0] = PDP_EUA_ORG_IETF;
3431 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003432 if (src) {
3433 eua->l = 6;
3434 memcpy(&eua->v[2], src, 4);
3435 } else {
3436 eua->l = 2;
3437 }
3438 return 0;
jjako52c24142002-12-16 13:33:51 +00003439}
3440
Harald Weltebed35df2011-11-02 13:06:18 +01003441int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3442{
Harald Weltecee75462017-09-24 17:45:05 +08003443 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 +01003444 return -1; /* Not IPv4 address */
3445 memcpy(dst, &eua->v[2], 4);
3446 return 0;
jjako52c24142002-12-16 13:33:51 +00003447}
3448
Harald Weltebed35df2011-11-02 13:06:18 +01003449int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3450{
3451 memset(dst, 0, sizeof(struct in_addr));
3452 if (gsna->l != 4)
3453 return EOF; /* Return if not IPv4 */
3454 memcpy(dst, gsna->v, gsna->l);
3455 return 0;
jjako52c24142002-12-16 13:33:51 +00003456}
3457
Harald Weltebed35df2011-11-02 13:06:18 +01003458int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3459{
3460 memset(gsna, 0, sizeof(struct ul16_t));
3461 gsna->l = 4;
3462 memcpy(gsna->v, src, gsna->l);
3463 return 0;
jjako52c24142002-12-16 13:33:51 +00003464}
Harald Welteb10ee082017-08-12 19:29:16 +02003465
3466/* TS 29.060 has yet again a different encoding for IMSIs than
3467 * what we have in other places, so we cannot use the gsm48
3468 * decoding functions. Also, libgtp uses an uint64_t in
3469 * _network byte order_ to contain BCD digits ?!? */
3470const char *imsi_gtp2str(const uint64_t *imsi)
3471{
Harald Weltea06120d2017-11-06 03:12:54 +09003472 static char buf[sizeof(*imsi)*2+1];
Harald Welteb10ee082017-08-12 19:29:16 +02003473 const uint8_t *imsi8 = (const uint8_t *) imsi;
3474 unsigned int i, j = 0;
3475
3476 for (i = 0; i < sizeof(*imsi); i++) {
3477 uint8_t nibble;
3478
3479 nibble = imsi8[i] & 0xf;
3480 if (nibble == 0xf)
3481 break;
3482 buf[j++] = osmo_bcd2char(nibble);
3483
3484 nibble = imsi8[i] >> 4;
3485 if (nibble == 0xf)
3486 break;
3487 buf[j++] = osmo_bcd2char(nibble);
3488 }
3489
3490 buf[j++] = '\0';
3491 return buf;
3492}
Keithcbc07bd2020-10-10 12:17:26 +02003493
Keithfb2a7292020-10-12 15:32:07 +02003494/* Generate the GTP IMSI IE according to 09.60 Section 7.9.2 */
3495uint64_t gtp_imsi_str2gtp(const char *str)
Keithcbc07bd2020-10-10 12:17:26 +02003496{
Keithfb2a7292020-10-12 15:32:07 +02003497 uint64_t imsi64 = 0;
3498 unsigned int n;
3499 unsigned int imsi_len = strlen(str);
Keithcbc07bd2020-10-10 12:17:26 +02003500
Keithfb2a7292020-10-12 15:32:07 +02003501 if (imsi_len > 16) {
3502 LOGP(DLGTP, LOGL_NOTICE, "IMSI length > 16 not supported!\n");
3503 return 0;
3504 }
3505
3506 for (n = 0; n < 16; n++) {
3507 uint64_t val;
3508 if (n < imsi_len)
3509 val = (str[n]-'0') & 0xf;
3510 else
3511 val = 0xf;
3512 imsi64 |= (val << (n*4));
3513 }
3514 return imsi64;
3515}