blob: d4c83d98f649560ee2462c4a8519c01bbd8e2e67 [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 /* Register that we have received a valid teic from GGSN */
1796 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001797
Harald Weltebed35df2011-11-02 13:06:18 +01001798 /* Decode information elements */
1799 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1800 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001801 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1802 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001803 if (gsn->cb_conf)
1804 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001805 return EOF;
1806 }
jjako52c24142002-12-16 13:33:51 +00001807
Harald Weltebed35df2011-11-02 13:06:18 +01001808 /* Extract cause value (mandatory) */
1809 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1810 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001811 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1812 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001813 if (gsn->cb_conf)
1814 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001815 return EOF;
1816 }
jjako52c24142002-12-16 13:33:51 +00001817
Harald Weltebed35df2011-11-02 13:06:18 +01001818 /* Extract recovery (optional) */
1819 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001820 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001821 }
jjako52c24142002-12-16 13:33:51 +00001822
Harald Weltebed35df2011-11-02 13:06:18 +01001823 /* Extract protocol configuration options (optional) */
1824 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1825 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1826 }
jjako52c24142002-12-16 13:33:51 +00001827
Harald Weltebed35df2011-11-02 13:06:18 +01001828 /* Check all conditional information elements */
1829 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001830
Harald Weltebed35df2011-11-02 13:06:18 +01001831 if (version == 0) {
1832 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1833 &pdp->qos_neg0,
1834 sizeof(pdp->qos_neg0))) {
1835 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001836 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001837 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001838 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001839 if (gsn->cb_conf)
1840 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001841 return EOF;
1842 }
1843 }
jjako08d331d2003-10-13 20:33:30 +00001844
Harald Weltebed35df2011-11-02 13:06:18 +01001845 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1846 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001847 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001848 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001849 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001850 if (gsn->cb_conf)
1851 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001852 return EOF;
1853 }
jjako52c24142002-12-16 13:33:51 +00001854
Harald Weltebed35df2011-11-02 13:06:18 +01001855 if (version == 0) {
1856 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1857 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001858 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001859 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001860 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001861 if (gsn->cb_conf)
1862 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001863 return EOF;
1864 }
jjako52c24142002-12-16 13:33:51 +00001865
Harald Weltebed35df2011-11-02 13:06:18 +01001866 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1867 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001868 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001869 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001870 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001871 if (gsn->cb_conf)
1872 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001873 return EOF;
1874 }
1875 }
1876
1877 if (version == 1) {
1878 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1879 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001880 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001881 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001882 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001883 if (gsn->cb_conf)
1884 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001885 return EOF;
1886 }
1887
1888 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1889 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001890 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001891 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001892 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001893 if (gsn->cb_conf)
1894 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001895 return EOF;
1896 }
1897 }
1898
1899 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1900 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001901 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001902 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001903 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001904 if (gsn->cb_conf)
1905 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001906 }
1907
1908 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1909 &pdp->eua.v, sizeof(pdp->eua.v))) {
1910 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001911 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001912 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001913 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001914 if (gsn->cb_conf)
1915 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001916 return EOF;
1917 }
1918
1919 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1920 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1921 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001922 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001923 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001924 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001925 if (gsn->cb_conf)
1926 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001927 return EOF;
1928 }
1929
1930 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1931 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1932 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001933 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001934 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001935 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001936 if (gsn->cb_conf)
1937 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001938 return EOF;
1939 }
1940
1941 if (version == 1) {
1942 if (gtpie_gettlv
1943 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1944 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1945 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001946 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001947 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001948 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001949 if (gsn->cb_conf)
1950 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001951 return EOF;
1952 }
1953 }
1954
1955 }
1956
1957 if (gsn->cb_conf)
1958 gsn->cb_conf(type, cause, pdp, cbp);
1959
1960 return 0;
jjako52c24142002-12-16 13:33:51 +00001961}
1962
jjako08d331d2003-10-13 20:33:30 +00001963/* API: Send Update PDP Context Request */
1964int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001965 struct in_addr *inetaddr)
1966{
1967 union gtp_packet packet;
1968 unsigned int length =
1969 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001970
Harald Weltebed35df2011-11-02 13:06:18 +01001971 if (pdp->version == 0)
1972 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1973 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001974
Harald Weltebed35df2011-11-02 13:06:18 +01001975 /* Include IMSI if updating with unknown teic_gn */
1976 if ((pdp->version == 1) && (!pdp->teic_gn))
1977 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1978 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1979
1980 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1981 gsn->restart_counter);
1982
1983 if (pdp->version == 0) {
1984 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1985 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1986 }
1987
1988 if (pdp->version == 1) {
1989 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1990 pdp->teid_own);
1991
1992 if (!pdp->teic_confirmed)
1993 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1994 pdp->teic_own);
1995 }
1996
1997 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1998
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001999 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01002000 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
2001 pdp->traceref);
2002 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
2003 pdp->tracetype); */
2004
2005 /* TODO if ggsn update message
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002006 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01002007 pdp->eua.l, pdp->eua.v);
2008 */
2009
2010 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2011 pdp->gsnlc.l, pdp->gsnlc.v);
2012 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2013 pdp->gsnlu.l, pdp->gsnlu.v);
2014
2015 if (pdp->version == 1)
2016 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2017 pdp->qos_req.l, pdp->qos_req.v);
2018
2019 if ((pdp->version == 1) && pdp->tft.l)
2020 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
2021 pdp->tft.l, pdp->tft.v);
2022
2023 if ((pdp->version == 1) && pdp->triggerid.l)
2024 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
2025 pdp->triggerid.l, pdp->triggerid.v);
2026
2027 if ((pdp->version == 1) && pdp->omcid.l)
2028 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
2029 pdp->omcid.l, pdp->omcid.v);
2030
Daniel Willmann134a7752016-02-03 18:53:29 +01002031 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002032
2033 return 0;
jjako52c24142002-12-16 13:33:51 +00002034}
2035
jjako08d331d2003-10-13 20:33:30 +00002036/* Send Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002037static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002038 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00002039 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01002040 struct pdp_t *pdp, uint8_t cause)
2041{
jjako08d331d2003-10-13 20:33:30 +00002042
Harald Weltebed35df2011-11-02 13:06:18 +01002043 union gtp_packet packet;
2044 unsigned int length =
2045 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00002046
Harald Weltebed35df2011-11-02 13:06:18 +01002047 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00002048
Harald Weltebed35df2011-11-02 13:06:18 +01002049 if (cause == GTPCAUSE_ACC_REQ) {
2050
2051 if (version == 0)
2052 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
2053 sizeof(pdp->qos_neg0), pdp->qos_neg0);
2054
2055 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
2056 gsn->restart_counter);
2057
2058 if (version == 0) {
2059 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
2060 pdp->fllu);
2061 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
2062 pdp->fllc);
2063 }
2064
2065 if (version == 1) {
2066 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2067 pdp->teid_own);
2068
2069 if (!pdp->teic_confirmed)
2070 gtpie_tv4(&packet, &length, GTP_MAX,
2071 GTPIE_TEI_C, pdp->teic_own);
2072 }
2073
2074 /* TODO we use teid_own as charging ID address */
2075 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
2076 pdp->teid_own);
2077
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002078 /* If ggsn
2079 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01002080 pdp->eua.l, pdp->eua.v); */
2081
2082 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2083 pdp->gsnlc.l, pdp->gsnlc.v);
2084 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2085 pdp->gsnlu.l, pdp->gsnlu.v);
2086
2087 if (version == 1)
2088 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2089 pdp->qos_neg.l, pdp->qos_neg.v);
2090
2091 /* TODO: Charging gateway address */
2092 }
2093
2094 return gtp_resp(version, gsn, pdp, &packet, length, peer,
2095 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00002096}
2097
jjako52c24142002-12-16 13:33:51 +00002098/* Handle Update PDP Context Request */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002099static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002100 struct sockaddr_in *peer, int fd,
2101 void *pack, unsigned len)
2102{
2103 struct pdp_t *pdp;
2104 struct pdp_t pdp_backup;
2105 union gtpie_member *ie[GTPIE_SIZE];
2106 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002107
Harald Weltebed35df2011-11-02 13:06:18 +01002108 uint16_t seq = get_seq(pack);
2109 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002110
Harald Weltebed35df2011-11-02 13:06:18 +01002111 uint64_t imsi;
2112 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002113
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002114 /* Is this a duplicate ? */
2115 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002116 return 0; /* We allready send of response once */
2117 }
jjako08d331d2003-10-13 20:33:30 +00002118
Harald Weltebed35df2011-11-02 13:06:18 +01002119 /* Decode information elements */
2120 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2121 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002122 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2123 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002124 if (0 == version)
2125 return EOF;
2126 else
2127 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2128 len, NULL,
2129 GTPCAUSE_INVALID_MESSAGE);
2130 }
jjako08d331d2003-10-13 20:33:30 +00002131
Harald Weltebed35df2011-11-02 13:06:18 +01002132 /* Finding PDP: */
2133 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2134 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2135 /* we have to use the tunnel endpoint identifier */
2136 if (version == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002137 /* Find the context in question */
Vadim Yanitskiy00a61712019-08-30 21:00:22 +02002138 if (gtp_pdp_tidget(gsn, &pdp, get_tid(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002139 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002140 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2141 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002142 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2143 len, NULL,
2144 GTPCAUSE_NON_EXIST);
2145 }
Vadim Yanitskiy00a61712019-08-30 21:00:22 +02002146
2147 /* Update IMSI and NSAPI */
2148 pdp_set_imsi_nsapi(pdp, get_tid(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002149 } else if (version == 1) {
2150 /* NSAPI (mandatory) */
2151 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2152 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002153 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2154 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002155 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2156 len, NULL,
2157 GTPCAUSE_MAN_IE_MISSING);
2158 }
jjako08d331d2003-10-13 20:33:30 +00002159
Harald Weltebed35df2011-11-02 13:06:18 +01002160 /* IMSI (conditional) */
2161 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2162 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002163 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002164 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002165 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002166 pack, len, "Unknown PDP context: %u\n",
2167 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002168 return gtp_update_pdp_resp(gsn, version, peer,
2169 fd, pack, len, NULL,
2170 GTPCAUSE_NON_EXIST);
2171 }
2172 } else {
2173 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002174 if (gtp_pdp_getimsi(gsn, &pdp, imsi, nsapi)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002175 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002176 GTP_LOGPKG(LOGL_ERROR, peer,
2177 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002178 return gtp_update_pdp_resp(gsn, version, peer,
2179 fd, pack, len, NULL,
2180 GTPCAUSE_NON_EXIST);
2181 }
2182 }
2183 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002184 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002185 return EOF;
2186 }
jjako08d331d2003-10-13 20:33:30 +00002187
Harald Weltebed35df2011-11-02 13:06:18 +01002188 /* Make a backup copy in case anything is wrong */
2189 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002190
Harald Weltebed35df2011-11-02 13:06:18 +01002191 if (version == 0) {
2192 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2193 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2194 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002195 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2196 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002197 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2198 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2199 len, pdp,
2200 GTPCAUSE_MAN_IE_MISSING);
2201 }
2202 }
jjako52c24142002-12-16 13:33:51 +00002203
Harald Weltebed35df2011-11-02 13:06:18 +01002204 /* Recovery (optional) */
2205 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002206 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002207 }
jjako08d331d2003-10-13 20:33:30 +00002208
Harald Weltebed35df2011-11-02 13:06:18 +01002209 if (version == 0) {
2210 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2211 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002212 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2213 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002214 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2215 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2216 len, pdp,
2217 GTPCAUSE_MAN_IE_MISSING);
2218 }
jjako52c24142002-12-16 13:33:51 +00002219
Harald Weltebed35df2011-11-02 13:06:18 +01002220 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2221 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002222 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2223 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002224 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2225 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2226 len, pdp,
2227 GTPCAUSE_MAN_IE_MISSING);
2228 }
2229 }
jjako52c24142002-12-16 13:33:51 +00002230
Harald Weltebed35df2011-11-02 13:06:18 +01002231 if (version == 1) {
2232 /* TEID (mandatory) */
2233 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2234 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002235 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2236 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002237 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2238 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2239 len, pdp,
2240 GTPCAUSE_MAN_IE_MISSING);
2241 }
jjako52c24142002-12-16 13:33:51 +00002242
Harald Weltebed35df2011-11-02 13:06:18 +01002243 /* TEIC (conditional) */
2244 /* If TEIC is not included it means that we have allready received it */
2245 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2246 /* all updated contexts, or only for one of the linked contexts */
2247 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2248
2249 /* NSAPI (mandatory) */
2250 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2251 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002252 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2253 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002254 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2255 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2256 len, pdp,
2257 GTPCAUSE_MAN_IE_MISSING);
2258 }
2259 }
2260
2261 /* Trace reference (optional) */
2262 /* Trace type (optional) */
2263
2264 /* End User Address (conditional) TODO: GGSN Initiated
2265 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2266 &pdp->eua.v, sizeof(pdp->eua.v))) {
2267 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002268 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002269 "Missing mandatory information field");
2270 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002271 return gtp_update_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01002272 GTPCAUSE_MAN_IE_MISSING);
2273 } */
2274
2275 /* SGSN address for signalling (mandatory) */
2276 /* It is weird that this is mandatory when TEIC is conditional */
2277 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2278 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2279 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002280 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2281 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002282 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2283 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2284 pdp, GTPCAUSE_MAN_IE_MISSING);
2285 }
2286
2287 /* SGSN address for user traffic (mandatory) */
2288 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2289 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2290 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002291 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2292 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002293 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2294 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2295 pdp, GTPCAUSE_MAN_IE_MISSING);
2296 }
2297
2298 if (version == 1) {
2299 /* QoS (mandatory) */
2300 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2301 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2302 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002303 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2304 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002305 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2306 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2307 len, pdp,
2308 GTPCAUSE_MAN_IE_MISSING);
2309 }
2310
2311 /* TFT (conditional) */
2312 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2313 &pdp->tft.v, sizeof(pdp->tft.v))) {
2314 }
2315
2316 /* OMC identity */
2317 }
2318
2319 /* Confirm to peer that things were "successful" */
2320 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2321 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002322}
2323
jjako52c24142002-12-16 13:33:51 +00002324/* Handle Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002325static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002326 struct sockaddr_in *peer, void *pack, unsigned len)
2327{
2328 struct pdp_t *pdp;
2329 union gtpie_member *ie[GTPIE_SIZE];
2330 uint8_t cause, recovery;
2331 void *cbp = NULL;
2332 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002333 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002334
Harald Weltebed35df2011-11-02 13:06:18 +01002335 /* Remove packet from queue */
2336 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2337 return EOF;
jjako52c24142002-12-16 13:33:51 +00002338
Harald Weltebed35df2011-11-02 13:06:18 +01002339 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002340 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002341 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002342 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002343 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002344 pdp = NULL;
2345 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002346 }
jjako2c381332003-10-21 19:09:53 +00002347
Harald Weltebed35df2011-11-02 13:06:18 +01002348 /* Register that we have received a valid teic from GGSN */
2349 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002350
Harald Weltebed35df2011-11-02 13:06:18 +01002351 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002352 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002353 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002354 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2355 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002356 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002357 }
jjako52c24142002-12-16 13:33:51 +00002358
Harald Weltebed35df2011-11-02 13:06:18 +01002359 /* Extract cause value (mandatory) */
2360 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002361 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002362 }
jjako52c24142002-12-16 13:33:51 +00002363
Harald Weltebed35df2011-11-02 13:06:18 +01002364 /* Extract recovery (optional) */
2365 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002366 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002367 }
2368
2369 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002370 /* TODO: This does not handle GGSN-initiated update responses */
2371 if (GTPCAUSE_ACC_REQ == cause) {
2372 if (version == 0) {
2373 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2374 &pdp->qos_neg0,
2375 sizeof(pdp->qos_neg0))) {
2376 goto err_missing;
2377 }
2378
2379 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2380 goto err_missing;
2381 }
2382
2383 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2384 goto err_missing;
2385 }
Harald Weltebed35df2011-11-02 13:06:18 +01002386 }
2387
Daniel Willmannd9975522016-02-04 15:38:12 +01002388 if (version == 1) {
2389 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2390 goto err_missing;
2391 }
Harald Weltebed35df2011-11-02 13:06:18 +01002392
Daniel Willmannd9975522016-02-04 15:38:12 +01002393 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2394 goto err_missing;
2395 }
2396 }
2397
2398 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2399 goto err_missing;
2400 }
2401
2402 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2403 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2404 goto err_missing;
2405 }
2406
2407 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2408 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2409 goto err_missing;
2410 }
2411
2412 if (version == 1) {
2413 if (gtpie_gettlv
2414 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2415 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2416 goto err_missing;
2417 }
2418 }
Harald Weltebed35df2011-11-02 13:06:18 +01002419 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002420
2421 if (gsn->cb_conf)
2422 gsn->cb_conf(type, cause, pdp, cbp);
2423 return 0; /* Succes */
2424
2425err_missing:
2426 gsn->missing++;
2427 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2428 "Missing information field\n");
2429err_out:
2430 if (gsn->cb_conf)
2431 gsn->cb_conf(type, EOF, pdp, cbp);
2432 return EOF;
jjako52c24142002-12-16 13:33:51 +00002433}
2434
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002435/* API: Deprecated. Send Delete PDP Context Request And free pdp ctx. */
jjako2c381332003-10-21 19:09:53 +00002436int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002437 int teardown)
2438{
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002439 struct pdp_t *linked_pdp;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002440
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002441 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002442 LOGP(DLGTP, LOGL_ERROR,
2443 "Unknown linked PDP context: %u\n", pdp->teic_own);
2444 return EOF;
2445 }
2446
2447 if (gtp_delete_context_req2(gsn, pdp, cbp, teardown) == EOF)
2448 return EOF;
2449
2450 if (teardown) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002451 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002452 } else {
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002453 /* If we end up here (no teardown) it means we still
2454 have at least another pdp context active for this
2455 PDN connection (since last DeleteReq should come
2456 with teardown enabled). If the ctx to delete is a
2457 secondary ctx, simply free it. If it's the primary
2458 ctx, mark it as nodata but don't free it since we
2459 need it to hold data linked together and we'll
2460 require it later to tear down the entire tree. Still,
2461 we announce its deletion through cb_delete_context
2462 because we don't want user to release its related
2463 data and not use it anymore.
2464 */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002465 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002466 if (gsn->cb_delete_context)
2467 gsn->cb_delete_context(pdp);
2468 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2469 pdp->nodata = 1;
2470 } else {
2471 gtp_freepdp(gsn, pdp);
2472 }
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002473 }
2474
2475 return 0;
2476}
2477
Oliver Smith1cde2c12019-05-13 11:35:03 +02002478/* API: Send Delete PDP Context Request. PDP CTX shall be free'd by user at any
Pau Espin Pedrol4e605b32019-08-29 13:54:28 +02002479 point in time later than this function through a call to pdp_freepdp(pdp) (or
2480 through gtp_freepdp() if willing to receive cb_delete_context() callback),
2481 but it must be freed no later than during cb_conf(GTP_DELETE_PDP_REQ, pdp) */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002482int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2483 int teardown)
2484{
Harald Weltebed35df2011-11-02 13:06:18 +01002485 union gtp_packet packet;
2486 unsigned int length =
2487 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2488 struct in_addr addr;
2489 struct pdp_t *linked_pdp;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002490 int count;
jjako2c381332003-10-21 19:09:53 +00002491
Harald Weltebed35df2011-11-02 13:06:18 +01002492 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2493 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002494 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002495 return EOF;
jjako2c381332003-10-21 19:09:53 +00002496 }
jjako2c381332003-10-21 19:09:53 +00002497
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002498 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002499 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002500 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002501 return EOF;
2502 }
2503
2504 if (!teardown) {
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002505 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002506 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002507 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002508 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002509 return EOF;
2510 }
2511 }
2512
2513 if (pdp->version == 1) {
2514 if (teardown)
2515 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2516 0xff);
2517
2518 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2519 }
2520
2521 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2522
Harald Weltebed35df2011-11-02 13:06:18 +01002523 return 0;
jjako2c381332003-10-21 19:09:53 +00002524}
jjako08d331d2003-10-13 20:33:30 +00002525
jjako52c24142002-12-16 13:33:51 +00002526/* Send Delete PDP Context Response */
2527int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002528 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002529 void *pack, unsigned len,
2530 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002531 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002532{
Harald Weltebed35df2011-11-02 13:06:18 +01002533 union gtp_packet packet;
Harald Weltebed35df2011-11-02 13:06:18 +01002534 unsigned int length =
2535 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00002536
Harald Weltebed35df2011-11-02 13:06:18 +01002537 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002538
Harald Weltebed35df2011-11-02 13:06:18 +01002539 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2540 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002541
Harald Weltebed35df2011-11-02 13:06:18 +01002542 if (cause == GTPCAUSE_ACC_REQ) {
2543 if ((teardown) || (version == 0)) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002544 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002545 } else {
2546 /* If we end up here (no teardown) it means we still
2547 have at least another pdp context active for this
2548 PDN connection (since last DeleteReq should come
2549 with teardown enabled). If the ctx to delete is a
2550 secondary ctx, simply free it. If it's the primary
2551 ctx, mark it as nodata but don't free it since we
2552 need it to hold data linked together and we'll
2553 require it later to tear down the entire tree. Still,
2554 we announce its deletion through cb_delete_context
2555 because we don't want user to release its related
2556 data and not use it anymore.
2557 */
Harald Weltebed35df2011-11-02 13:06:18 +01002558 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002559 if (gsn->cb_delete_context)
2560 gsn->cb_delete_context(pdp);
2561 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2562 pdp->nodata = 1;
2563 } else {
2564 gtp_freepdp(gsn, pdp);
2565 }
Harald Weltebed35df2011-11-02 13:06:18 +01002566 }
jjako2c381332003-10-21 19:09:53 +00002567 }
Harald Weltebed35df2011-11-02 13:06:18 +01002568 /* if (cause == GTPCAUSE_ACC_REQ) */
2569 return 0;
jjako52c24142002-12-16 13:33:51 +00002570}
2571
2572/* Handle Delete PDP Context Request */
2573int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002574 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002575 void *pack, unsigned len)
2576{
2577 struct pdp_t *pdp = NULL;
2578 struct pdp_t *linked_pdp = NULL;
2579 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002580
Harald Weltebed35df2011-11-02 13:06:18 +01002581 uint16_t seq = get_seq(pack);
2582 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002583
Harald Weltebed35df2011-11-02 13:06:18 +01002584 uint8_t nsapi;
2585 uint8_t teardown = 0;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002586 int count;
jjako52c24142002-12-16 13:33:51 +00002587
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002588 /* Is this a duplicate ? */
2589 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002590 return 0; /* We allready send off response once */
2591 }
jjako2c381332003-10-21 19:09:53 +00002592
Harald Weltebed35df2011-11-02 13:06:18 +01002593 /* Find the linked context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002594 if (gtp_pdp_getgtp1(gsn, &linked_pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002595 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002596 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002597 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002598 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2599 NULL, NULL, GTPCAUSE_NON_EXIST,
2600 teardown);
2601 }
jjako2c381332003-10-21 19:09:53 +00002602
Harald Weltebed35df2011-11-02 13:06:18 +01002603 /* If version 0 this is also the secondary context */
2604 if (version == 0)
2605 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002606
Harald Weltebed35df2011-11-02 13:06:18 +01002607 /* Decode information elements */
2608 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2609 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002610 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2611 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002612 if (0 == version)
2613 return EOF;
2614 else
2615 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2616 len, NULL, NULL,
2617 GTPCAUSE_INVALID_MESSAGE,
2618 teardown);
2619 }
2620
2621 if (version == 1) {
2622 /* NSAPI (mandatory) */
2623 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2624 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002625 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2626 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002627 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2628 len, NULL, NULL,
2629 GTPCAUSE_MAN_IE_MISSING,
2630 teardown);
2631 }
2632
2633 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002634 if (gtp_pdp_getgtp1(gsn, &pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
Harald Weltebed35df2011-11-02 13:06:18 +01002635 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002636 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2637 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002638 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2639 len, NULL, NULL,
2640 GTPCAUSE_NON_EXIST,
2641 teardown);
2642 }
2643
2644 /* Teardown (conditional) */
2645 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2646
2647 if (!teardown) {
Pau Espin Pedrol742a6b52019-05-30 13:36:10 +02002648 /* TS 29.060 section 7.3.5: If a GSN receives a Delete PDP context
2649 * without a Teardown Indicator or with a Teardown Indicator with
2650 * value set to "0" and only that PDP context is active for a PDN
2651 * connection, then the GSN shall ignore the message. (Note:
2652 * This is symptom of a race condition. The reliable delivery of
2653 * signalling messages will eventually lead to a consistent
2654 * situation, allowing the teardown of the PDP context.)
2655 */
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002656 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002657 if (count <= 1) {
Pau Espin Pedrold1bd6fc2018-07-13 19:11:45 +02002658 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2659 "Ignoring CTX DEL without teardown and count=%d\n",
2660 count);
Harald Weltebed35df2011-11-02 13:06:18 +01002661 return 0; /* 29.060 7.3.5 Ignore message */
2662 }
2663 }
2664 }
2665
2666 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2667 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002668}
2669
jjako52c24142002-12-16 13:33:51 +00002670/* Handle Delete PDP Context Response */
2671int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002672 struct sockaddr_in *peer, void *pack, unsigned len)
2673{
2674 union gtpie_member *ie[GTPIE_SIZE];
2675 uint8_t cause;
2676 void *cbp = NULL;
2677 uint8_t type = 0;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002678 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002679 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002680
Harald Weltebed35df2011-11-02 13:06:18 +01002681 /* Remove packet from queue */
2682 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2683 return EOF;
jjako52c24142002-12-16 13:33:51 +00002684
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002685 /* Find the context in question. It may not be available if gtp_delete_context_req
2686 * was used and as a result the PDP ctx was already freed */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002687 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002688 gsn->err_unknownpdp++;
2689 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
Oliver Smith1cde2c12019-05-13 11:35:03 +02002690 "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 +02002691 get_tei(pack));
2692 if (gsn->cb_conf)
2693 gsn->cb_conf(type, EOF, NULL, cbp);
2694 return EOF;
2695 }
2696
Harald Weltebed35df2011-11-02 13:06:18 +01002697 /* Decode information elements */
2698 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2699 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002700 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2701 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002702 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002703 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002704 return EOF;
2705 }
2706
2707 /* Extract cause value (mandatory) */
2708 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2709 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002710 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2711 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002712 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002713 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002714 return EOF;
2715 }
2716
2717 /* Check the cause value (again) */
2718 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2719 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002720 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2721 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002722 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002723 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002724 return EOF;
2725 }
2726
2727 /* Callback function to notify application */
2728 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002729 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002730
2731 return 0;
jjako52c24142002-12-16 13:33:51 +00002732}
2733
Harald Welte54d082e2017-08-12 22:43:21 +02002734/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002735static int gtp_error_ind_resp(struct gsn_t *gsn, uint8_t version,
jjako08d331d2003-10-13 20:33:30 +00002736 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002737 void *pack, unsigned len)
2738{
Harald Weltebed35df2011-11-02 13:06:18 +01002739 union gtp_packet packet;
2740 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2741
Harald Welte54d082e2017-08-12 22:43:21 +02002742 if (version == 1) {
2743 /* Mandatory 7.7.13 TEI Data I */
2744 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2745 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2746
2747 /* Mandatory 7.7.32 GSN Address */
2748 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2749 sizeof(gsn->gsnu), &gsn->gsnu);
2750 }
2751
Harald Weltebed35df2011-11-02 13:06:18 +01002752 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2753 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002754}
2755
2756/* Handle Error Indication */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002757static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002758 struct sockaddr_in *peer, void *pack, unsigned len)
2759{
Harald Welte37d5b152017-08-12 23:58:29 +02002760 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002761 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002762
Harald Weltebed35df2011-11-02 13:06:18 +01002763 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002764 if (version == 0) {
Vadim Yanitskiy68c5a742019-08-30 21:04:19 +02002765 if (gtp_pdp_tidget(gsn, &pdp, get_tid(pack))) {
Harald Welte37d5b152017-08-12 23:58:29 +02002766 gsn->err_unknownpdp++;
2767 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2768 "Unknown PDP context\n");
2769 return EOF;
2770 }
2771 } else if (version == 1) {
2772 /* we have to look-up based on the *peer* TEID */
2773 int hlen = get_hlen(pack);
2774 uint32_t teid_gn;
2775
2776 /* Decode information elements */
2777 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2778 gsn->invalid++;
2779 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2780 "Invalid message format\n");
2781 return EOF;
2782 }
2783
2784 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2785 gsn->missing++;
2786 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2787 "Missing mandatory information field\n");
2788 return EOF;
2789 }
2790
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002791 if (gtp_pdp_getgtp1_peer_d(gsn, &pdp, peer, teid_gn)) {
Harald Welte37d5b152017-08-12 23:58:29 +02002792 gsn->err_unknownpdp++;
2793 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2794 return EOF;
2795 }
Vadim Yanitskiybdf2cf92019-08-30 21:23:11 +02002796 } else {
2797 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
2798 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002799 }
jjako52c24142002-12-16 13:33:51 +00002800
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002801 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2802 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002803
Harald Weltebd228242017-11-06 03:16:49 +09002804 /* This is obvious from above code, given the semantics of the
2805 * functions above, but Coverity doesn't figure this out, so
2806 * let's make it clear. It's good style anyway in case above
2807 * code should ever change. */
2808 OSMO_ASSERT(pdp);
2809
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002810 gtp_freepdp(gsn, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002811 return 0;
jjako52c24142002-12-16 13:33:51 +00002812}
2813
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002814static int gtp_gpdu_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002815 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2816{
jjako08d331d2003-10-13 20:33:30 +00002817
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002818 int hlen;
jjako52c24142002-12-16 13:33:51 +00002819
Harald Weltebed35df2011-11-02 13:06:18 +01002820 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002821
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002822 switch (version) {
2823 case 0:
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002824 if (gtp_pdp_getgtp0(gsn, &pdp,
2825 ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002826 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002827 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002828 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002829 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2830 len);
2831 }
2832 hlen = GTP0_HEADER_SIZE;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002833 break;
2834 case 1:
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002835 if (gtp_pdp_getgtp1(gsn, &pdp,
2836 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002837 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002838 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002839 len, "Unknown PDP context, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002840 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2841 len);
2842 }
jjako08d331d2003-10-13 20:33:30 +00002843
Harald Weltebed35df2011-11-02 13:06:18 +01002844 /* Is this a long or a short header ? */
2845 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2846 hlen = GTP1_HEADER_SIZE_LONG;
2847 else
2848 hlen = GTP1_HEADER_SIZE_SHORT;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002849 break;
2850 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002851 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002852 "Unknown version: %d\n", version);
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002853 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002854 }
jjako08d331d2003-10-13 20:33:30 +00002855
Harald Weltebed35df2011-11-02 13:06:18 +01002856 /* If the GPDU was not from the peer GSN tell him to delete context */
2857 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2858 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002859 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002860 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2861 }
jjako52c24142002-12-16 13:33:51 +00002862
Harald Weltebed35df2011-11-02 13:06:18 +01002863 /* Callback function */
2864 if (gsn->cb_data_ind != 0)
2865 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2866
2867 return 0;
jjako52c24142002-12-16 13:33:51 +00002868}
2869
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002870/* Receives GTP packet and sends off for further processing
jjako52c24142002-12-16 13:33:51 +00002871 * Function will check the validity of the header. If the header
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002872 * is not valid the packet is either dropped or a version not
2873 * supported is returned to the peer.
jjako52c24142002-12-16 13:33:51 +00002874 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002875int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002876{
Harald Weltebed35df2011-11-02 13:06:18 +01002877 unsigned char buffer[PACKET_MAX];
2878 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002879 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002880 int status;
2881 struct gtp0_header *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002882 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002883 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002884
Harald Weltebed35df2011-11-02 13:06:18 +01002885 /* TODO: Need strategy of userspace buffering and blocking */
2886 /* Currently read is non-blocking and send is blocking. */
2887 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002888
Harald Weltebed35df2011-11-02 13:06:18 +01002889 while (1) { /* Loop until no more to read */
2890 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002891 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002892 return -1;
2893 }
2894 peerlen = sizeof(peer);
2895 if ((status =
2896 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2897 (struct sockaddr *)&peer, &peerlen)) < 0) {
2898 if (errno == EAGAIN)
2899 return 0;
2900 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002901 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002902 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002903 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2904 status, status ? strerror(errno) : "No error");
2905 return -1;
2906 }
jjako1db1c812003-07-06 20:53:57 +00002907
Harald Weltebed35df2011-11-02 13:06:18 +01002908 /* Need at least 1 byte in order to check version */
2909 if (status < (1)) {
2910 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002911 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2912 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002913 continue;
2914 }
jjako08d331d2003-10-13 20:33:30 +00002915
Harald Weltebed35df2011-11-02 13:06:18 +01002916 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002917
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002918 version = GTPHDR_F_GET_VER(pheader->flags);
2919
Harald Weltebed35df2011-11-02 13:06:18 +01002920 /* Version should be gtp0 (or earlier) */
2921 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2922 /* GTP 0 messages. If other version message is received we reply that we */
2923 /* only support version 0, implying that this is the only version */
2924 /* supported on this port */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002925 if (version > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002926 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01002927 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2928 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002929 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2930 continue;
2931 }
2932
2933 /* Check length of gtp0 packet */
2934 if (status < GTP0_HEADER_SIZE) {
2935 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002936 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2937 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002938 continue; /* Silently discard 29.60: 11.1.2 */
2939 }
2940
2941 /* Check packet length field versus length of packet */
2942 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2943 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002944 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002945 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002946 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002947 continue; /* Silently discard */
2948 }
2949
2950 if ((gsn->mode == GTP_MODE_GGSN) &&
2951 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002952 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002953 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002954 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002955 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002956 "Unexpected GTPv0 Signalling Message '%s'\n",
2957 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002958 continue; /* Silently discard 29.60: 11.1.4 */
2959 }
2960
2961 if ((gsn->mode == GTP_MODE_SGSN) &&
2962 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002963 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002964 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002965 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002966 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002967 "Unexpected GTPv0 Signalling Message '%s'\n",
2968 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002969 continue; /* Silently discard 29.60: 11.1.4 */
2970 }
2971
2972 switch (pheader->type) {
2973 case GTP_ECHO_REQ:
2974 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2975 break;
2976 case GTP_ECHO_RSP:
2977 gtp_echo_conf(gsn, version, &peer, buffer, status);
2978 break;
2979 case GTP_NOT_SUPPORTED:
2980 gtp_unsup_ind(gsn, &peer, buffer, status);
2981 break;
2982 case GTP_CREATE_PDP_REQ:
2983 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2984 status);
2985 break;
2986 case GTP_CREATE_PDP_RSP:
2987 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2988 status);
2989 break;
2990 case GTP_UPDATE_PDP_REQ:
2991 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2992 status);
2993 break;
2994 case GTP_UPDATE_PDP_RSP:
2995 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2996 status);
2997 break;
2998 case GTP_DELETE_PDP_REQ:
2999 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3000 status);
3001 break;
3002 case GTP_DELETE_PDP_RSP:
3003 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3004 status);
3005 break;
3006 case GTP_ERROR:
3007 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3008 break;
3009 case GTP_GPDU:
3010 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3011 break;
3012 default:
3013 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003014 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3015 "Unknown GTP message type received: %d\n",
3016 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003017 break;
3018 }
3019 }
jjako08d331d2003-10-13 20:33:30 +00003020}
3021
jjako08d331d2003-10-13 20:33:30 +00003022int gtp_decaps1c(struct gsn_t *gsn)
3023{
Harald Weltebed35df2011-11-02 13:06:18 +01003024 unsigned char buffer[PACKET_MAX];
3025 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003026 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003027 int status;
3028 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003029 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003030 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00003031
Harald Weltebed35df2011-11-02 13:06:18 +01003032 /* TODO: Need strategy of userspace buffering and blocking */
3033 /* Currently read is non-blocking and send is blocking. */
3034 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003035
Harald Weltebed35df2011-11-02 13:06:18 +01003036 while (1) { /* Loop until no more to read */
3037 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003038 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003039 return -1;
3040 }
3041 peerlen = sizeof(peer);
3042 if ((status =
3043 recvfrom(fd, buffer, sizeof(buffer), 0,
3044 (struct sockaddr *)&peer, &peerlen)) < 0) {
3045 if (errno == EAGAIN)
3046 return 0;
3047 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003048 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003049 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003050 fd, (unsigned long)buffer, sizeof(buffer),
3051 status, status ? strerror(errno) : "No error");
3052 return -1;
3053 }
jjako08d331d2003-10-13 20:33:30 +00003054
Harald Weltebed35df2011-11-02 13:06:18 +01003055 /* Need at least 1 byte in order to check version */
3056 if (status < (1)) {
3057 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003058 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3059 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003060 continue;
3061 }
jjako08d331d2003-10-13 20:33:30 +00003062
Harald Weltebed35df2011-11-02 13:06:18 +01003063 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003064
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003065 version = GTPHDR_F_GET_VER(pheader->flags);
3066
Harald Weltebed35df2011-11-02 13:06:18 +01003067 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003068 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003069 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003070 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3071 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003072 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
3073 /*29.60: 11.1.1 */
3074 continue;
3075 }
jjako08d331d2003-10-13 20:33:30 +00003076
Harald Weltebed35df2011-11-02 13:06:18 +01003077 /* Version must be at least GTP 1 */
3078 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3079 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3080 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003081 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003082 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003083 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3084 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003085 continue;
3086 }
jjako08d331d2003-10-13 20:33:30 +00003087
Harald Weltebed35df2011-11-02 13:06:18 +01003088 /* Check packet flag field */
3089 if (((pheader->flags & 0xf7) != 0x32)) {
3090 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003091 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003092 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003093 continue;
3094 }
jjako2c381332003-10-21 19:09:53 +00003095
Harald Weltebed35df2011-11-02 13:06:18 +01003096 /* Check length of packet */
3097 if (status < GTP1_HEADER_SIZE_LONG) {
3098 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003099 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3100 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003101 continue; /* Silently discard 29.60: 11.1.2 */
3102 }
jjako2c381332003-10-21 19:09:53 +00003103
Harald Weltebed35df2011-11-02 13:06:18 +01003104 /* Check packet length field versus length of packet */
3105 if (status !=
3106 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3107 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003108 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003109 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003110 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003111 continue; /* Silently discard */
3112 }
jjako1db1c812003-07-06 20:53:57 +00003113
Harald Weltebed35df2011-11-02 13:06:18 +01003114 /* Check for extension headers */
3115 /* TODO: We really should cycle through the headers and determine */
3116 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003117 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003118 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003119 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3120 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003121 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3122 status);
jjako1db1c812003-07-06 20:53:57 +00003123
Harald Weltebed35df2011-11-02 13:06:18 +01003124 continue;
3125 }
3126
3127 if ((gsn->mode == GTP_MODE_GGSN) &&
3128 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003129 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003130 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003131 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003132 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003133 "Unexpected GTPv1 Signalling Message '%s'\n",
3134 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003135 continue; /* Silently discard 29.60: 11.1.4 */
3136 }
3137
3138 if ((gsn->mode == GTP_MODE_SGSN) &&
3139 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003140 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003141 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003142 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003143 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003144 "Unexpected GTPv1 Signalling Message '%s'\n",
3145 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003146 continue; /* Silently discard 29.60: 11.1.4 */
3147 }
3148
3149 switch (pheader->type) {
3150 case GTP_ECHO_REQ:
3151 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3152 break;
3153 case GTP_ECHO_RSP:
3154 gtp_echo_conf(gsn, version, &peer, buffer, status);
3155 break;
3156 case GTP_NOT_SUPPORTED:
3157 gtp_unsup_ind(gsn, &peer, buffer, status);
3158 break;
3159 case GTP_SUPP_EXT_HEADER:
3160 gtp_extheader_ind(gsn, &peer, buffer, status);
3161 break;
3162 case GTP_CREATE_PDP_REQ:
3163 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3164 status);
3165 break;
3166 case GTP_CREATE_PDP_RSP:
3167 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3168 status);
3169 break;
3170 case GTP_UPDATE_PDP_REQ:
3171 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3172 status);
3173 break;
3174 case GTP_UPDATE_PDP_RSP:
3175 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3176 status);
3177 break;
3178 case GTP_DELETE_PDP_REQ:
3179 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3180 status);
3181 break;
3182 case GTP_DELETE_PDP_RSP:
3183 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3184 status);
3185 break;
3186 case GTP_ERROR:
3187 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3188 break;
3189 default:
3190 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003191 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3192 "Unknown GTP message type received: %u\n",
3193 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003194 break;
3195 }
3196 }
jjako52c24142002-12-16 13:33:51 +00003197}
3198
jjako08d331d2003-10-13 20:33:30 +00003199int gtp_decaps1u(struct gsn_t *gsn)
3200{
Harald Weltebed35df2011-11-02 13:06:18 +01003201 unsigned char buffer[PACKET_MAX];
3202 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003203 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003204 int status;
3205 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003206 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003207 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003208
Harald Weltebed35df2011-11-02 13:06:18 +01003209 /* TODO: Need strategy of userspace buffering and blocking */
3210 /* Currently read is non-blocking and send is blocking. */
3211 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003212
Harald Weltebed35df2011-11-02 13:06:18 +01003213 while (1) { /* Loop until no more to read */
3214 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003215 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003216 return -1;
3217 }
3218 peerlen = sizeof(peer);
3219 if ((status =
3220 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3221 (struct sockaddr *)&peer, &peerlen)) < 0) {
3222 if (errno == EAGAIN)
3223 return 0;
3224 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003225 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003226 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003227 gsn->fd1u, (unsigned long)buffer,
3228 sizeof(buffer), status,
3229 status ? strerror(errno) : "No error");
3230 return -1;
3231 }
jjako08d331d2003-10-13 20:33:30 +00003232
Harald Weltebed35df2011-11-02 13:06:18 +01003233 /* Need at least 1 byte in order to check version */
3234 if (status < (1)) {
3235 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003236 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3237 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003238 continue;
3239 }
jjako08d331d2003-10-13 20:33:30 +00003240
Harald Weltebed35df2011-11-02 13:06:18 +01003241 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003242
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003243 version = GTPHDR_F_GET_VER(pheader->flags);
3244
Harald Weltebed35df2011-11-02 13:06:18 +01003245 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003246 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003247 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003248 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3249 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003250 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3251 continue;
3252 }
jjako08d331d2003-10-13 20:33:30 +00003253
Harald Weltebed35df2011-11-02 13:06:18 +01003254 /* Version must be at least GTP 1 */
3255 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3256 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3257 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003258 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003259 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003260 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3261 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003262 continue;
3263 }
jjako2c381332003-10-21 19:09:53 +00003264
Harald Weltebed35df2011-11-02 13:06:18 +01003265 /* Check packet flag field (allow both with and without sequence number) */
3266 if (((pheader->flags & 0xf5) != 0x30)) {
3267 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003268 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003269 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003270 continue;
3271 }
jjako2c381332003-10-21 19:09:53 +00003272
Harald Weltebed35df2011-11-02 13:06:18 +01003273 /* Check length of packet */
3274 if (status < GTP1_HEADER_SIZE_SHORT) {
3275 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003276 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3277 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003278 continue; /* Silently discard 29.60: 11.1.2 */
3279 }
3280
3281 /* Check packet length field versus length of packet */
3282 if (status !=
3283 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3284 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003285 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003286 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003287 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003288 continue; /* Silently discard */
3289 }
3290
3291 /* Check for extension headers */
3292 /* TODO: We really should cycle through the headers and determine */
3293 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003294 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003295 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003296 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3297 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003298 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3299 status);
3300
3301 continue;
3302 }
3303
3304 switch (pheader->type) {
3305 case GTP_ECHO_REQ:
3306 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3307 break;
3308 case GTP_ECHO_RSP:
3309 gtp_echo_conf(gsn, version, &peer, buffer, status);
3310 break;
3311 case GTP_SUPP_EXT_HEADER:
3312 gtp_extheader_ind(gsn, &peer, buffer, status);
3313 break;
3314 case GTP_ERROR:
3315 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3316 break;
3317 /* Supported header extensions */
3318 case GTP_GPDU:
3319 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3320 break;
3321 default:
3322 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003323 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3324 "Unknown GTP message type received: %u\n",
3325 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003326 break;
3327 }
3328 }
jjako08d331d2003-10-13 20:33:30 +00003329}
3330
Harald Weltebed35df2011-11-02 13:06:18 +01003331int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003332{
Harald Weltebed35df2011-11-02 13:06:18 +01003333 union gtp_packet packet;
3334 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003335 struct msghdr msgh;
3336 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003337 int fd;
jjako52c24142002-12-16 13:33:51 +00003338
Harald Welte471e3492017-09-24 16:12:39 +08003339 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003340 memset(&addr, 0, sizeof(addr));
3341 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003342#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003343 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003344#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003345 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003346
Harald Welte471e3492017-09-24 16:12:39 +08003347 /* prepare msghdr */
3348 memset(&msgh, 0, sizeof(msgh));
3349 msgh.msg_name = &addr;
3350 msgh.msg_namelen = sizeof(addr);
3351 msgh.msg_iov = iov;
3352 msgh.msg_iovlen = ARRAY_SIZE(iov);
3353
3354 /* prepare iovectors */
3355 iov[0].iov_base = &packet;
3356 /* iov[0].iov_len is not known here yet */
3357 iov[1].iov_base = pack;
3358 iov[1].iov_len = len;
3359
Harald Weltebed35df2011-11-02 13:06:18 +01003360 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003361
Harald Welte471e3492017-09-24 16:12:39 +08003362 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003363 addr.sin_port = htons(GTP0_PORT);
3364 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003365
Harald Weltebed35df2011-11-02 13:06:18 +01003366 get_default_gtp(0, GTP_GPDU, &packet);
3367 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003368 if (pdp->tx_gpdu_seq)
3369 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3370 else
3371 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003372 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003373 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003374 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003375
Harald Weltebed35df2011-11-02 13:06:18 +01003376 addr.sin_port = htons(GTP1U_PORT);
3377 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003378
Harald Weltebed35df2011-11-02 13:06:18 +01003379 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003380 if (pdp->tx_gpdu_seq) {
3381 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3382 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3383 GTP1_HEADER_SIZE_LONG);
3384 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3385 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3386 } else {
3387 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3388 packet.gtp1s.h.length = hton16(len);
3389 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3390 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3391 }
Harald Weltebed35df2011-11-02 13:06:18 +01003392 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003393 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003394 return EOF;
3395 }
3396
3397 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003398 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003399 return -1;
3400 }
3401
Harald Welte471e3492017-09-24 16:12:39 +08003402 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003403 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003404 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003405 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003406 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3407 strerror(errno));
3408 return EOF;
3409 }
3410 return 0;
jjako52c24142002-12-16 13:33:51 +00003411}
3412
jjako52c24142002-12-16 13:33:51 +00003413/* ***********************************************************
3414 * Conversion functions
3415 *************************************************************/
3416
jjako52c24142002-12-16 13:33:51 +00003417/* ***********************************************************
3418 * IP address conversion functions
3419 * There exist several types of address representations:
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01003420 * - eua: End User Address. (29.060, 7.7.27, message type 128)
jjako52c24142002-12-16 13:33:51 +00003421 * Used for signalling address to mobile station. Supports IPv4
3422 * IPv6 x.25 etc. etc.
3423 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3424 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3425 * - in_addr: IPv4 address struct.
3426 * - sockaddr_in: Socket API representation of IP address and
3427 * port number.
3428 *************************************************************/
3429
Harald Weltebed35df2011-11-02 13:06:18 +01003430int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3431{
Harald Weltecee75462017-09-24 17:45:05 +08003432 eua->v[0] = PDP_EUA_ORG_IETF;
3433 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003434 if (src) {
3435 eua->l = 6;
3436 memcpy(&eua->v[2], src, 4);
3437 } else {
3438 eua->l = 2;
3439 }
3440 return 0;
jjako52c24142002-12-16 13:33:51 +00003441}
3442
Harald Weltebed35df2011-11-02 13:06:18 +01003443int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3444{
Harald Weltecee75462017-09-24 17:45:05 +08003445 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 +01003446 return -1; /* Not IPv4 address */
3447 memcpy(dst, &eua->v[2], 4);
3448 return 0;
jjako52c24142002-12-16 13:33:51 +00003449}
3450
Harald Weltebed35df2011-11-02 13:06:18 +01003451int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3452{
3453 memset(dst, 0, sizeof(struct in_addr));
3454 if (gsna->l != 4)
3455 return EOF; /* Return if not IPv4 */
3456 memcpy(dst, gsna->v, gsna->l);
3457 return 0;
jjako52c24142002-12-16 13:33:51 +00003458}
3459
Harald Weltebed35df2011-11-02 13:06:18 +01003460int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3461{
3462 memset(gsna, 0, sizeof(struct ul16_t));
3463 gsna->l = 4;
3464 memcpy(gsna->v, src, gsna->l);
3465 return 0;
jjako52c24142002-12-16 13:33:51 +00003466}
Harald Welteb10ee082017-08-12 19:29:16 +02003467
3468/* TS 29.060 has yet again a different encoding for IMSIs than
3469 * what we have in other places, so we cannot use the gsm48
3470 * decoding functions. Also, libgtp uses an uint64_t in
3471 * _network byte order_ to contain BCD digits ?!? */
3472const char *imsi_gtp2str(const uint64_t *imsi)
3473{
Harald Weltea06120d2017-11-06 03:12:54 +09003474 static char buf[sizeof(*imsi)*2+1];
Harald Welteb10ee082017-08-12 19:29:16 +02003475 const uint8_t *imsi8 = (const uint8_t *) imsi;
3476 unsigned int i, j = 0;
3477
3478 for (i = 0; i < sizeof(*imsi); i++) {
3479 uint8_t nibble;
3480
3481 nibble = imsi8[i] & 0xf;
3482 if (nibble == 0xf)
3483 break;
3484 buf[j++] = osmo_bcd2char(nibble);
3485
3486 nibble = imsi8[i] >> 4;
3487 if (nibble == 0xf)
3488 break;
3489 buf[j++] = osmo_bcd2char(nibble);
3490 }
3491
3492 buf[j++] = '\0';
3493 return buf;
3494}
Keithcbc07bd2020-10-10 12:17:26 +02003495
3496/* Encode an IMSI with gtp encoding according to TS 29.060 - the
3497 reverse of imsi_gtp2str(). The hash index used for context
3498 lookups is generated from the IMSI in gtp format. User input
3499 in the vty (for example) needs to be converted to match. */
3500const uint64_t imsi_str2gtp(const char *imsi)
3501{
3502 uint64_t ret = 0xf000000000000000ull;
3503 unsigned int i, imsi_length = strlen(imsi);
3504
3505 for (i = 0; i < imsi_length; i++)
3506 ret |= ((uint64_t) (imsi[i] - '0')) << (i * 4);
3507 return ret;
3508}