blob: 94c3245db80c9c8842ad70cc54c4fb0d5d6db8a4 [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);
222}
223
Harald Welte629e9862010-12-24 20:58:09 +0100224int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100225 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
226{
227 gsn->cb_recovery = cb;
228 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100229}
230
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200231/* cb_recovery()
232 * pdp may be NULL if Recovery IE was received from a message independent
233 * of any PDP ctx (such as Echo Response), or because pdp ctx is unknown to the
234 * local setup. In case pdp is known, caller may want to keep that pdp alive to
235 * handle subsequent msg cb as this specific pdp ctx is still valid according to
236 * specs.
237 */
238int gtp_set_cb_recovery2(struct gsn_t *gsn,
239 int (*cb_recovery2) (struct sockaddr_in * peer, struct pdp_t * pdp, uint8_t recovery))
240{
241 gsn->cb_recovery2 = cb_recovery2;
242 return 0;
243}
244
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +0100245int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100246 int (*cb_data_ind) (struct pdp_t * pdp,
247 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000248{
Harald Weltebed35df2011-11-02 13:06:18 +0100249 gsn->cb_data_ind = cb_data_ind;
250 return 0;
jjako52c24142002-12-16 13:33:51 +0000251}
252
jjako08d331d2003-10-13 20:33:30 +0000253/**
254 * get_default_gtp()
255 * Generate a GPRS Tunneling Protocol signalling packet header, depending
256 * on GTP version and message type. pdp is used for teid/flow label.
257 * *packet must be allocated by the calling function, and be large enough
258 * to hold the packet header.
259 * returns the length of the header. 0 on error.
260 **/
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100261static unsigned int get_default_gtp(uint8_t version, uint8_t type, void *packet)
Harald Weltebed35df2011-11-02 13:06:18 +0100262{
263 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
264 struct gtp1_header_long *gtp1_default =
265 (struct gtp1_header_long *)packet;
266 switch (version) {
267 case 0:
268 /* Initialise "standard" GTP0 header */
269 memset(gtp0_default, 0, sizeof(struct gtp0_header));
270 gtp0_default->flags = 0x1e;
271 gtp0_default->type = hton8(type);
272 gtp0_default->spare1 = 0xff;
273 gtp0_default->spare2 = 0xff;
274 gtp0_default->spare3 = 0xff;
275 gtp0_default->number = 0xff;
276 return GTP0_HEADER_SIZE;
277 case 1:
278 /* Initialise "standard" GTP1 header */
279 /* 29.060: 8.2: S=1 and PN=0 */
280 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
281 /* and Supported Extension Headers Notification, the S field shall be */
282 /* set to 1 */
283 /* Currently extension headers are not supported */
284 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
Harald Weltefed598f2017-09-24 16:39:22 +0800285 /* No extension, enable sequence, no N-PDU */
286 gtp1_default->flags = GTPHDR_F_VER(1) | GTP1HDR_F_GTP1 | GTP1HDR_F_SEQ;
Harald Weltebed35df2011-11-02 13:06:18 +0100287 gtp1_default->type = hton8(type);
288 return GTP1_HEADER_SIZE_LONG;
289 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100290 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100291 "Unknown GTP packet version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +0100292 return 0;
293 }
jjako52c24142002-12-16 13:33:51 +0000294}
295
jjako08d331d2003-10-13 20:33:30 +0000296/**
297 * get_seq()
298 * Get sequence number of a packet.
299 * Returns 0 on error
300 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100301static uint16_t get_seq(void *pack)
302{
303 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800304 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000305
Harald Weltefed598f2017-09-24 16:39:22 +0800306 if (ver == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +0100307 return ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800308 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100309 return ntoh16(packet->gtp1l.h.seq);
310 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100311 return 0;
312 }
jjako08d331d2003-10-13 20:33:30 +0000313}
314
315/**
316 * get_tid()
317 * Get tunnel identifier of a packet.
318 * Returns 0 on error
319 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100320static uint64_t get_tid(void *pack)
321{
322 union gtp_packet *packet = (union gtp_packet *)pack;
323
Harald Weltefed598f2017-09-24 16:39:22 +0800324 if (GTPHDR_F_GET_VER(packet->flags) == 0) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100325 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100326 }
327 return 0;
jjako08d331d2003-10-13 20:33:30 +0000328}
329
330/**
331 * get_hlen()
332 * Get the header length of a packet.
333 * Returns 0 on error
334 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100335static uint16_t get_hlen(void *pack)
336{
337 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800338 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000339
Harald Weltefed598f2017-09-24 16:39:22 +0800340 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100341 return GTP0_HEADER_SIZE;
Harald Weltefed598f2017-09-24 16:39:22 +0800342 } else if (ver == 1 && (packet->flags & 0x07) == 0) { /* Short version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100343 return GTP1_HEADER_SIZE_SHORT;
Harald Weltefed598f2017-09-24 16:39:22 +0800344 } else if (ver == 1) { /* Version 1 with seq/n-pdu/ext */
345 return GTP1_HEADER_SIZE_LONG;
Harald Weltebed35df2011-11-02 13:06:18 +0100346 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100347 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100348 return 0;
349 }
jjako08d331d2003-10-13 20:33:30 +0000350}
351
352/**
353 * get_tei()
354 * Get the tunnel endpoint identifier (flow label) of a packet.
355 * Returns 0xffffffff on error.
356 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100357static uint32_t get_tei(void *pack)
358{
359 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800360 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000361
Harald Weltefed598f2017-09-24 16:39:22 +0800362 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100363 return ntoh16(packet->gtp0.h.flow);
Harald Weltefed598f2017-09-24 16:39:22 +0800364 } else if (ver == 1) { /* Version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100365 return ntoh32(packet->gtp1l.h.tei);
366 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100367 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100368 return 0xffffffff;
369 }
jjako08d331d2003-10-13 20:33:30 +0000370}
jjakoa7cd2492003-04-11 09:40:12 +0000371
jjako52c24142002-12-16 13:33:51 +0000372/* ***********************************************************
373 * Reliable delivery of signalling messages
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100374 *
jjako52c24142002-12-16 13:33:51 +0000375 * Sequence numbers are used for both signalling messages and
376 * data messages.
377 *
378 * For data messages each tunnel maintains a sequence counter,
379 * which is incremented by one each time a new data message
380 * is sent. The sequence number starts at (0) zero at tunnel
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100381 * establishment, and wraps around at 65535 (29.060 9.3.1.1
jjako52c24142002-12-16 13:33:51 +0000382 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
383 * or can be used to check the validity of the message in the
384 * receiver, or for reordering af packets.
385 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100386 * For signalling messages the sequence number is used by
jjako52c24142002-12-16 13:33:51 +0000387 * signalling messages for which a response is defined. A response
388 * message should copy the sequence from the corresponding request
389 * message. The sequence number "unambiguously" identifies a request
390 * message within a given path, with a path being defined as a set of
391 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
392 * messages shall be responded to, and all response messages associated
393 * with a certain request shall always include the same information"
394 *
395 * We take this to mean that the GSN transmitting a request is free to
396 * choose the sequence number, as long as it is unique within a given path.
397 * It means that we are allowed to count backwards, or roll over at 17
398 * if we prefer that. It also means that we can use the same counter for
399 * all paths. This has the advantage that the transmitted request sequence
400 * numbers are unique within each GSN, and also we dont have to mess around
401 * with path setup and teardown.
402 *
403 * If a response message is lost, the request will be retransmitted, and
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100404 * the receiving GSN will receive a "duplicated" request. The standard
jjako52c24142002-12-16 13:33:51 +0000405 * requires the receiving GSN to send a response, with the same information
406 * as in the original response. For most messages this happens automatically:
407 *
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200408 * Echo: Automatically duplicates the original response
jjako52c24142002-12-16 13:33:51 +0000409 * Create pdp context: The SGSN may send create context request even if
410 * a context allready exist (imsi+nsapi?). This means that the reply will
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200411 automatically duplicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000412 * side effects in the application which is asked twice to validate
413 * the login.
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200414 * Update pdp context: Automatically duplicates the original response???
jjako52c24142002-12-16 13:33:51 +0000415 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
416 * a nonexist reply message.
417 *
418 * The correct solution will be to make a queue containing response messages.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100419 * This queue should be checked whenever a request is received. If the
jjako52c24142002-12-16 13:33:51 +0000420 * response is allready in the queue that response should be transmitted.
421 * It should be possible to find messages in this queue on the basis of
422 * the sequence number and peer GSN IP address (The sequense number is unique
423 * within each path). This need to be implemented by a hash table. Furthermore
424 * it should be possibly to delete messages based on a timeout. This can be
425 * achieved by means of a linked list. The timeout value need to be larger
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100426 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
jjako52c24142002-12-16 13:33:51 +0000427 * set in the peer GSN, so there is no way to know these parameters. On the
428 * other hand the timeout value need to be so small that we do not receive
429 * wraparound sequence numbere before the message is deleted. 60 seconds is
430 * probably not a bad choise.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100431 *
jjako52c24142002-12-16 13:33:51 +0000432 * This queue however is first really needed from gtp1.
433 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100434 * gtp_req:
jjako52c24142002-12-16 13:33:51 +0000435 * Send off a signalling message with appropiate sequence
436 * number. Store packet in queue.
437 * gtp_conf:
438 * Remove an incoming confirmation from the queue
439 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000440 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000441 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000442 * gtp_notification:
443 * Send off a notification message. This is neither a request nor
444 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000445 * gtp_retrans:
446 * Retransmit any outstanding packets which have exceeded
447 * a predefined timeout.
448 *************************************************************/
449
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100450static int gtp_req(struct gsn_t *gsn, uint8_t version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100451 union gtp_packet *packet, int len,
452 struct in_addr *inetaddr, void *cbp)
453{
Harald Weltefed598f2017-09-24 16:39:22 +0800454 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100455 struct sockaddr_in addr;
456 struct qmsg_t *qmsg;
457 int fd;
jjako08d331d2003-10-13 20:33:30 +0000458
Harald Weltebed35df2011-11-02 13:06:18 +0100459 memset(&addr, 0, sizeof(addr));
460 addr.sin_family = AF_INET;
461 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000462#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100463 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000464#endif
jjako52c24142002-12-16 13:33:51 +0000465
Harald Weltefed598f2017-09-24 16:39:22 +0800466 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100467 addr.sin_port = htons(GTP0_PORT);
468 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
469 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100470 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100471 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100472 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100473 }
Harald Weltebed35df2011-11-02 13:06:18 +0100474 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
475 || (packet->gtp0.h.type == GTP_ERROR)))
476 packet->gtp0.h.flow = hton16(pdp->flru);
477 else if (pdp)
478 packet->gtp0.h.flow = hton16(pdp->flrc);
479 fd = gsn->fd0;
Harald Weltefed598f2017-09-24 16:39:22 +0800480 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100481 addr.sin_port = htons(GTP1C_PORT);
482 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
483 packet->gtp1l.h.seq = hton16(gsn->seq_next);
484 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
485 (packet->gtp1l.h.type == GTP_ERROR)))
486 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
487 else if (pdp)
488 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
489 fd = gsn->fd1c;
490 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100491 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100492 return -1;
493 }
jjako52c24142002-12-16 13:33:51 +0000494
Harald Weltebed35df2011-11-02 13:06:18 +0100495 if (sendto(fd, packet, len, 0,
496 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
497 gsn->err_sendto++;
Max14b1b632017-08-21 20:14:59 +0200498 LOGP(DLGTP, LOGL_ERROR, "Sendto(fd=%d, msg=%lx, len=%d, dst=%s) failed: Error = %s\n", fd,
499 (unsigned long)&packet, len, inet_ntoa(addr.sin_addr), strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100500 return -1;
501 }
502
503 /* Use new queue structure */
504 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
505 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100506 LOGP(DLGTP, LOGL_ERROR,
507 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100508 } else {
509 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
510 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100511 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100512 qmsg->retrans = 0; /* No retransmissions so far */
513 qmsg->cbp = cbp;
514 qmsg->type = ntoh8(packet->gtp0.h.type);
515 qmsg->fd = fd;
516 }
517 gsn->seq_next++; /* Count up this time */
518 return 0;
jjako52c24142002-12-16 13:33:51 +0000519}
520
Alexander Couzense1412d92018-09-16 05:10:03 +0200521
522/**
523 * @brief clear the request and response queue. Useful for debugging to reset "some" state.
524 * @param gsn The GGSN instance
525 */
526void gtp_clear_queues(struct gsn_t *gsn)
527{
528 struct qmsg_t *qmsg;
529
530 while (!queue_getfirst(gsn->queue_req, &qmsg)) {
531 queue_freemsg(gsn->queue_req, qmsg);
532 }
533
534 while (!queue_getfirst(gsn->queue_resp, &qmsg)) {
535 queue_freemsg(gsn->queue_resp, qmsg);
536 }
537}
538
jjako52c24142002-12-16 13:33:51 +0000539/* gtp_conf
540 * Remove signalling packet from retransmission queue.
541 * return 0 on success, EOF if packet was not found */
542
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100543static int gtp_conf(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100544 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
545{
Harald Weltefed598f2017-09-24 16:39:22 +0800546 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100547 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000548
Harald Weltefed598f2017-09-24 16:39:22 +0800549 if (ver == 0)
Harald Weltebed35df2011-11-02 13:06:18 +0100550 seq = ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800551 else if (ver == 1 && (packet->gtp1l.h.flags & GTP1HDR_F_SEQ))
Harald Weltebed35df2011-11-02 13:06:18 +0100552 seq = ntoh16(packet->gtp1l.h.seq);
553 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100554 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
555 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100556 return EOF;
557 }
jjako08d331d2003-10-13 20:33:30 +0000558
Harald Weltebed35df2011-11-02 13:06:18 +0100559 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
560 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100561 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
562 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100563 return EOF;
564 }
jjako52c24142002-12-16 13:33:51 +0000565
Harald Weltebed35df2011-11-02 13:06:18 +0100566 return 0;
jjako52c24142002-12-16 13:33:51 +0000567}
568
Harald Weltebed35df2011-11-02 13:06:18 +0100569int gtp_retrans(struct gsn_t *gsn)
570{
571 /* Retransmit any outstanding packets */
572 /* Remove from queue if maxretrans exceeded */
573 time_t now;
574 struct qmsg_t *qmsg;
575 now = time(NULL);
576 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000577
Harald Welte95848ba2011-11-02 18:17:50 +0100578 /* get first element in queue, as long as the timeout of that
579 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100580 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
581 (qmsg->timeout <= now)) {
582 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100583 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100584 if (gsn->cb_conf)
585 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
586 queue_freemsg(gsn->queue_req, qmsg);
587 } else {
588 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
589 (struct sockaddr *)&qmsg->peer,
590 sizeof(struct sockaddr_in)) < 0) {
591 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100592 LOGP(DLGTP, LOGL_ERROR,
593 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100594 gsn->fd0, (unsigned long)&qmsg->p,
595 qmsg->l, strerror(errno));
596 }
597 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100598 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100599 qmsg->retrans++;
600 }
601 }
jjako52c24142002-12-16 13:33:51 +0000602
Harald Weltebed35df2011-11-02 13:06:18 +0100603 /* Also clean up reply timeouts */
604 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
605 (qmsg->timeout < now)) {
606 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
607 queue_freemsg(gsn->queue_resp, qmsg);
608 }
jjako52c24142002-12-16 13:33:51 +0000609
Harald Weltebed35df2011-11-02 13:06:18 +0100610 return 0;
jjako52c24142002-12-16 13:33:51 +0000611}
612
Harald Weltebed35df2011-11-02 13:06:18 +0100613int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
614{
Pau Espin Pedrolceac0782019-05-27 17:39:45 +0200615 time_t now, later, diff;
Harald Weltebed35df2011-11-02 13:06:18 +0100616 struct qmsg_t *qmsg;
Pau Espin Pedrolceac0782019-05-27 17:39:45 +0200617 timeout->tv_usec = 0;
jjako52c24142002-12-16 13:33:51 +0000618
Harald Weltebed35df2011-11-02 13:06:18 +0100619 if (queue_getfirst(gsn->queue_req, &qmsg)) {
620 timeout->tv_sec = 10;
Harald Weltebed35df2011-11-02 13:06:18 +0100621 } else {
622 now = time(NULL);
623 later = qmsg->timeout;
624 timeout->tv_sec = later - now;
Harald Weltebed35df2011-11-02 13:06:18 +0100625 if (timeout->tv_sec < 0)
626 timeout->tv_sec = 0; /* No negative allowed */
627 if (timeout->tv_sec > 10)
628 timeout->tv_sec = 10; /* Max sleep for 10 sec */
629 }
Pau Espin Pedrolceac0782019-05-27 17:39:45 +0200630
631 if (queue_getfirst(gsn->queue_resp, &qmsg)) {
632 /* already set by queue_req, do nothing */
633 } else { /* trigger faster if earlier timeout exists in queue_resp */
634 now = time(NULL);
635 later = qmsg->timeout;
636 diff = later - now;
637 if (diff < 0)
638 diff = 0;
639 if (diff < timeout->tv_sec)
640 timeout->tv_sec = diff;
641 }
642
Harald Weltebed35df2011-11-02 13:06:18 +0100643 return 0;
jjako52c24142002-12-16 13:33:51 +0000644}
645
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100646static int gtp_resp(uint8_t version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000647 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100648 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
649{
Harald Weltefed598f2017-09-24 16:39:22 +0800650 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100651 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000652
Harald Weltefed598f2017-09-24 16:39:22 +0800653 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100654 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
655 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100656 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100657 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
658 (packet->gtp0.h.type == GTP_ERROR)))
659 packet->gtp0.h.flow = hton16(pdp->flru);
660 else if (pdp)
661 packet->gtp0.h.flow = hton16(pdp->flrc);
Harald Weltefed598f2017-09-24 16:39:22 +0800662 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100663 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
664 packet->gtp1l.h.seq = hton16(seq);
665 if (pdp && (fd == gsn->fd1u))
666 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
667 else if (pdp)
668 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
669 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100670 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100671 return -1;
672 }
jjako08d331d2003-10-13 20:33:30 +0000673
Harald Weltebed35df2011-11-02 13:06:18 +0100674 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100675 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100676 return -1;
677 }
jjako52c24142002-12-16 13:33:51 +0000678
Harald Weltebed35df2011-11-02 13:06:18 +0100679 if (sendto(fd, packet, len, 0,
680 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
681 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100682 LOGP(DLGTP, LOGL_ERROR,
683 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100684 (unsigned long)&packet, len, strerror(errno));
685 return -1;
686 }
687
688 /* Use new queue structure */
689 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
690 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100691 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100692 } else {
693 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
694 qmsg->l = len;
695 qmsg->timeout = time(NULL) + 60; /* When to timeout */
696 qmsg->retrans = 0; /* No retransmissions so far */
697 qmsg->cbp = NULL;
698 qmsg->type = 0;
699 qmsg->fd = fd;
700 }
701 return 0;
jjako52c24142002-12-16 13:33:51 +0000702}
703
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100704static int gtp_notification(struct gsn_t *gsn, uint8_t version,
jjako2c381332003-10-21 19:09:53 +0000705 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100706 struct sockaddr_in *peer, int fd, uint16_t seq)
707{
jjako2c381332003-10-21 19:09:53 +0000708
Harald Weltefed598f2017-09-24 16:39:22 +0800709 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100710 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000711
Harald Weltebed35df2011-11-02 13:06:18 +0100712 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000713
Harald Weltebed35df2011-11-02 13:06:18 +0100714 /* In GTP0 notifications are treated as replies. In GTP1 they
715 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000716
Harald Weltebed35df2011-11-02 13:06:18 +0100717 if (fd == gsn->fd1c)
718 addr.sin_port = htons(GTP1C_PORT);
719 else if (fd == gsn->fd1u)
720 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000721
Harald Weltefed598f2017-09-24 16:39:22 +0800722 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100723 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
724 packet->gtp0.h.seq = hton16(seq);
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 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100729 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100730 return -1;
731 }
732
733 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100734 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100735 return -1;
736 }
737
738 if (sendto(fd, packet, len, 0,
739 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
740 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100741 LOGP(DLGTP, LOGL_ERROR,
742 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100743 (unsigned long)&packet, len, strerror(errno));
744 return -1;
745 }
746 return 0;
jjako2c381332003-10-21 19:09:53 +0000747}
748
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200749static int gtp_duplicate(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +0100750 struct sockaddr_in *peer, uint16_t seq)
751{
752 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000753
Harald Weltebed35df2011-11-02 13:06:18 +0100754 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
755 return EOF; /* Notfound */
756 }
jjakoa7cd2492003-04-11 09:40:12 +0000757
Harald Weltebed35df2011-11-02 13:06:18 +0100758 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100759 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100760 return -1;
761 }
762
763 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
764 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
765 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100766 LOGP(DLGTP, LOGL_ERROR,
767 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100768 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
769 strerror(errno));
770 }
771 return 0;
jjako52c24142002-12-16 13:33:51 +0000772}
773
jjako52c24142002-12-16 13:33:51 +0000774/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100775static void log_restart(struct gsn_t *gsn)
776{
jjako52c24142002-12-16 13:33:51 +0000777 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200778 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000779 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200780 char *filename;
jjako52c24142002-12-16 13:33:51 +0000781
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200782 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
783 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000784
785 /* We try to open file. On failure we will later try to create file */
786 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100787 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100788 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100789 filename);
790 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100791 rc = fscanf(f, "%d", &counter);
792 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100793 LOGP(DLGTP, LOGL_ERROR,
794 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100795 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100796 }
797 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100798 LOGP(DLGTP, LOGL_ERROR,
799 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100800 }
jjako52c24142002-12-16 13:33:51 +0000801 }
Harald Weltebed35df2011-11-02 13:06:18 +0100802
803 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000804 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100805
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200806 /* Keep the umask closely wrapped around our fopen() call in case the
807 * log outputs cause file creation. */
808 i = umask(022);
809 f = fopen(filename, "w");
810 umask(i);
811 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100812 LOGP(DLGTP, LOGL_ERROR,
813 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100814 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200815 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000816 }
817
jjako52c24142002-12-16 13:33:51 +0000818 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100819close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200820 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100821 LOGP(DLGTP, LOGL_ERROR,
822 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200823free_filename:
824 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000825}
826
jjako1db1c812003-07-06 20:53:57 +0000827int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100828 int mode)
jjako52c24142002-12-16 13:33:51 +0000829{
Harald Weltebed35df2011-11-02 13:06:18 +0100830 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000831
Max14b1b632017-08-21 20:14:59 +0200832 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
jjako52c24142002-12-16 13:33:51 +0000833
Harald Weltebed35df2011-11-02 13:06:18 +0100834 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000835
Harald Weltebed35df2011-11-02 13:06:18 +0100836 (*gsn)->statedir = statedir;
837 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000838
Harald Weltebed35df2011-11-02 13:06:18 +0100839 /* Initialise sequence number */
840 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000841
Harald Weltebed35df2011-11-02 13:06:18 +0100842 /* Initialise request retransmit queue */
843 queue_new(&(*gsn)->queue_req);
844 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000845
Harald Weltebed35df2011-11-02 13:06:18 +0100846 /* Initialise pdp table */
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +0200847 pdp_init(*gsn);
jjako08d331d2003-10-13 20:33:30 +0000848
Harald Weltebed35df2011-11-02 13:06:18 +0100849 /* Initialise call back functions */
850 (*gsn)->cb_create_context_ind = 0;
851 (*gsn)->cb_delete_context = 0;
852 (*gsn)->cb_unsup_ind = 0;
853 (*gsn)->cb_conf = 0;
854 (*gsn)->cb_data_ind = 0;
855
856 /* Store function parameters */
857 (*gsn)->gsnc = *listen;
858 (*gsn)->gsnu = *listen;
859 (*gsn)->mode = mode;
860
861 /* Create GTP version 0 socket */
862 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
863 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100864 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200865 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100866 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200867 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100868 }
869
870 memset(&addr, 0, sizeof(addr));
871 addr.sin_family = AF_INET;
872 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
873 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000874#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100875 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000876#endif
jjako08d331d2003-10-13 20:33:30 +0000877
Harald Weltebed35df2011-11-02 13:06:18 +0100878 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
879 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200880 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
881 "bind(fd0=%d) failed: Error = %s\n",
882 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200883 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100884 }
jjako08d331d2003-10-13 20:33:30 +0000885
Harald Weltebed35df2011-11-02 13:06:18 +0100886 /* Create GTP version 1 control plane socket */
887 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
888 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100889 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200890 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100891 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200892 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100893 }
894
895 memset(&addr, 0, sizeof(addr));
896 addr.sin_family = AF_INET;
897 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
898 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000899#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100900 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000901#endif
jjako08d331d2003-10-13 20:33:30 +0000902
Harald Weltebed35df2011-11-02 13:06:18 +0100903 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
904 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200905 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
906 "bind(fd1c=%d) failed: Error = %s\n",
907 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200908 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100909 }
jjako08d331d2003-10-13 20:33:30 +0000910
Harald Weltebed35df2011-11-02 13:06:18 +0100911 /* Create GTP version 1 user plane socket */
912 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
913 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100914 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200915 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100916 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200917 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100918 }
919
920 memset(&addr, 0, sizeof(addr));
921 addr.sin_family = AF_INET;
922 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
923 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000924#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100925 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000926#endif
jjako52c24142002-12-16 13:33:51 +0000927
Harald Weltebed35df2011-11-02 13:06:18 +0100928 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
929 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200930 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +0200931 "bind(fd1u=%d) failed: Error = %s\n",
932 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +0200933 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100934 }
935
936 return 0;
jjako52c24142002-12-16 13:33:51 +0000937}
938
Harald Weltebed35df2011-11-02 13:06:18 +0100939int gtp_free(struct gsn_t *gsn)
940{
jjako52c24142002-12-16 13:33:51 +0000941
Harald Weltebed35df2011-11-02 13:06:18 +0100942 /* Clean up retransmit queues */
943 queue_free(gsn->queue_req);
944 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000945
Harald Weltebed35df2011-11-02 13:06:18 +0100946 close(gsn->fd0);
947 close(gsn->fd1c);
948 close(gsn->fd1u);
949
950 free(gsn);
951 return 0;
jjako52c24142002-12-16 13:33:51 +0000952}
953
954/* ***********************************************************
955 * Path management messages
956 * Messages: echo and version not supported.
957 * A path is connection between two UDP/IP endpoints
958 *
959 * A path is either using GTP0 or GTP1. A path can be
960 * established by any kind of GTP message??
961
962 * Which source port to use?
963 * GTP-C request destination port is 2123/3386
964 * GTP-U request destination port is 2152/3386
965 * T-PDU destination port is 2152/3386.
966 * For the above messages the source port is locally allocated.
967 * For response messages src=rx-dst and dst=rx-src.
968 * For simplicity we should probably use 2123+2152/3386 as
969 * src port even for the cases where src can be locally
970 * allocated. This also means that we have to listen only to
971 * the same ports.
972 * For response messages we need to be able to respond to
973 * the relevant src port even if it is locally allocated by
974 * the peer.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100975 *
jjako52c24142002-12-16 13:33:51 +0000976 * The need for path management!
977 * We might need to keep a list of active paths. This might
978 * be in the form of remote IP address + UDP port numbers.
979 * (We will consider a path astablished if we have a context
980 * with the node in question)
981 *************************************************************/
982
983/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000984int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
985 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000986{
Harald Weltebed35df2011-11-02 13:06:18 +0100987 union gtp_packet packet;
988 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
989 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000990}
991
jjako08d331d2003-10-13 20:33:30 +0000992/* Send off an echo reply */
993int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100994 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000995{
Harald Weltebed35df2011-11-02 13:06:18 +0100996 union gtp_packet packet;
997 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
998 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
999 gsn->restart_counter);
1000 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
1001 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00001002}
1003
jjako52c24142002-12-16 13:33:51 +00001004/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +01001005int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1006 int fd, void *pack, unsigned len)
1007{
jjako52c24142002-12-16 13:33:51 +00001008
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02001009 /* Check if it was a duplicate request */
1010 if (!gtp_duplicate(gsn, 0, peer, get_seq(pack)))
Harald Weltebed35df2011-11-02 13:06:18 +01001011 return 0;
jjako52c24142002-12-16 13:33:51 +00001012
Harald Weltebed35df2011-11-02 13:06:18 +01001013 /* Send off reply to request */
1014 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +00001015}
1016
1017/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +00001018int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001019 void *pack, unsigned len)
1020{
1021 union gtpie_member *ie[GTPIE_SIZE];
1022 unsigned char recovery;
1023 void *cbp = NULL;
1024 uint8_t type = 0;
1025 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001026
Harald Weltebed35df2011-11-02 13:06:18 +01001027 /* Remove packet from queue */
1028 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1029 return EOF;
jjako52c24142002-12-16 13:33:51 +00001030
Harald Weltebed35df2011-11-02 13:06:18 +01001031 /* Extract information elements into a pointer array */
1032 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1033 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001034 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1035 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001036 if (gsn->cb_conf)
1037 gsn->cb_conf(type, EOF, NULL, cbp);
1038 return EOF;
1039 }
jjako52c24142002-12-16 13:33:51 +00001040
Harald Weltebed35df2011-11-02 13:06:18 +01001041 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1042 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001043 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1044 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001045 if (gsn->cb_conf)
1046 gsn->cb_conf(type, EOF, NULL, cbp);
1047 return EOF;
1048 }
jjako52c24142002-12-16 13:33:51 +00001049
Harald Weltebed35df2011-11-02 13:06:18 +01001050 /* Echo reply packages does not have a cause information element */
1051 /* Instead we return the recovery number in the callback function */
1052 if (gsn->cb_conf)
1053 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +01001054
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001055 emit_cb_recovery(gsn, peer, NULL, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001056
1057 return 0;
jjako52c24142002-12-16 13:33:51 +00001058}
1059
1060/* Send off a Version Not Supported message */
1061/* This message is somewhat special in that it actually is a
1062 * response to some other message with unsupported GTP version
1063 * For this reason it has parameters like a response, and does
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001064 * its own message transmission. No signalling queue is used
jjako52c24142002-12-16 13:33:51 +00001065 * The reply is sent to the peer IP and peer UDP. This means that
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001066 * the peer will be receiving a GTP0 message on a GTP1 port!
jjako52c24142002-12-16 13:33:51 +00001067 * In practice however this will never happen as a GTP0 GSN will
1068 * only listen to the GTP0 port, and therefore will never receive
1069 * anything else than GTP0 */
1070
jjako08d331d2003-10-13 20:33:30 +00001071int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1072 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001073{
Harald Weltebed35df2011-11-02 13:06:18 +01001074 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +00001075
Harald Weltebed35df2011-11-02 13:06:18 +01001076 /* GTP 1 is the highest supported protocol */
1077 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
1078 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +00001079}
1080
1081/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +01001082int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1083 void *pack, unsigned len)
1084{
jjako52c24142002-12-16 13:33:51 +00001085
Harald Weltebed35df2011-11-02 13:06:18 +01001086 if (gsn->cb_unsup_ind)
1087 gsn->cb_unsup_ind(peer);
1088
1089 return 0;
jjako52c24142002-12-16 13:33:51 +00001090}
1091
jjako2c381332003-10-21 19:09:53 +00001092/* Send off an Supported Extension Headers Notification */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001093static int gtp_extheader_req(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
jjako2c381332003-10-21 19:09:53 +00001094 int fd, void *pack, unsigned len)
1095{
Harald Weltebed35df2011-11-02 13:06:18 +01001096 union gtp_packet packet;
1097 unsigned int length =
1098 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +00001099
Harald Weltebed35df2011-11-02 13:06:18 +01001100 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +00001101
Harald Weltebed35df2011-11-02 13:06:18 +01001102 if (version < 1)
1103 return 0;
jjako2c381332003-10-21 19:09:53 +00001104
Harald Weltebed35df2011-11-02 13:06:18 +01001105 /* We report back that we support only PDCP PDU headers */
1106 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
1107 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +00001108
Harald Weltebed35df2011-11-02 13:06:18 +01001109 return gtp_notification(gsn, version, &packet, length,
1110 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +00001111}
1112
1113/* Handle a Supported Extension Headers Notification */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001114static int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001115 void *pack, unsigned len)
1116{
jjako2c381332003-10-21 19:09:53 +00001117
Harald Weltebed35df2011-11-02 13:06:18 +01001118 if (gsn->cb_extheader_ind)
1119 gsn->cb_extheader_ind(peer);
1120
1121 return 0;
jjako2c381332003-10-21 19:09:53 +00001122}
1123
jjako52c24142002-12-16 13:33:51 +00001124/* ***********************************************************
1125 * Session management messages
1126 * Messages: create, update and delete PDP context
1127 *
1128 * Information storage
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001129 * Information storage for each PDP context is defined in
jjako52c24142002-12-16 13:33:51 +00001130 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1131 * PDP-address (IP address), sequence numbers, charging ID.
1132 * For the SGSN it also includes radio related mobility
1133 * information.
1134 *************************************************************/
1135
Harald Welte7b3347b2010-05-15 12:18:46 +02001136/* API: Send Create PDP Context Request (7.3.1) */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001137int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001138 void *cbp)
1139{
1140 union gtp_packet packet;
1141 unsigned int length =
1142 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1143 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001144
Harald Weltebed35df2011-11-02 13:06:18 +01001145 /* TODO: Secondary PDP Context Activation Procedure */
1146 /* In secondary activation procedure the PDP context is identified
1147 by tei in the header. The following fields are omitted: Selection
1148 mode, IMSI, MSISDN, End User Address, Access Point Name and
1149 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001150
Harald Weltebed35df2011-11-02 13:06:18 +01001151 if (pdp->secondary) {
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001152 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001153 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001154 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001155 return EOF;
1156 }
1157 }
jjako2c381332003-10-21 19:09:53 +00001158
Harald Weltebed35df2011-11-02 13:06:18 +01001159 if (pdp->version == 0) {
1160 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1161 sizeof(pdp->qos_req0), pdp->qos_req0);
1162 }
jjako52c24142002-12-16 13:33:51 +00001163
Harald Weltebed35df2011-11-02 13:06:18 +01001164 /* Section 7.7.2 */
1165 if (pdp->version == 1) {
1166 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1167 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1168 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1169 }
jjako52c24142002-12-16 13:33:51 +00001170
Harald Weltebed35df2011-11-02 13:06:18 +01001171 /* Section 7.7.3 Routing Area Information */
1172 if (pdp->rai_given == 1)
1173 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1174 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001175
Harald Weltebed35df2011-11-02 13:06:18 +01001176 /* Section 7.7.11 */
1177 if (pdp->norecovery_given == 0)
1178 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1179 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001180
Harald Weltebed35df2011-11-02 13:06:18 +01001181 /* Section 7.7.12 */
1182 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1183 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1184 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001185
Harald Weltebed35df2011-11-02 13:06:18 +01001186 if (pdp->version == 0) {
1187 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1188 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1189 }
jjako08d331d2003-10-13 20:33:30 +00001190
Harald Weltebed35df2011-11-02 13:06:18 +01001191 /* Section 7.7.13 */
1192 if (pdp->version == 1) {
1193 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1194 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001195
Harald Weltebed35df2011-11-02 13:06:18 +01001196 /* Section 7.7.14 */
1197 if (!pdp->teic_confirmed)
1198 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1199 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001200
Harald Weltebed35df2011-11-02 13:06:18 +01001201 /* Section 7.7.17 */
1202 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001203
Harald Weltebed35df2011-11-02 13:06:18 +01001204 /* Section 7.7.17 */
1205 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1206 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1207 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001208
Harald Weltebed35df2011-11-02 13:06:18 +01001209 /* Section 7.7.23 */
1210 if (pdp->cch_pdp) /* Only include charging if flags are set */
1211 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1212 pdp->cch_pdp);
1213 }
jjako9b4971d2004-05-27 20:30:19 +00001214
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001215 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001216 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1217 pdp->traceref);
1218 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1219 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001220
Harald Weltebed35df2011-11-02 13:06:18 +01001221 /* Section 7.7.27 */
1222 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1223 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1224 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001225
Harald Weltebed35df2011-11-02 13:06:18 +01001226 /* Section 7.7.30 */
1227 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1228 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1229 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001230
Harald Weltebed35df2011-11-02 13:06:18 +01001231 /* Section 7.7.31 */
1232 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1233 if (pdp->pco_req.l)
1234 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1235 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001236
Harald Weltebed35df2011-11-02 13:06:18 +01001237 /* Section 7.7.32 */
1238 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1239 pdp->gsnlc.l, pdp->gsnlc.v);
1240 /* Section 7.7.32 */
1241 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1242 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001243
Harald Weltebed35df2011-11-02 13:06:18 +01001244 /* Section 7.7.33 */
1245 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1246 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1247 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001248
Harald Weltebed35df2011-11-02 13:06:18 +01001249 /* Section 7.7.34 */
1250 if (pdp->version == 1)
1251 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1252 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001253
Harald Weltebed35df2011-11-02 13:06:18 +01001254 /* Section 7.7.36 */
1255 if ((pdp->version == 1) && pdp->tft.l)
1256 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1257 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001258
Harald Weltebed35df2011-11-02 13:06:18 +01001259 /* Section 7.7.41 */
1260 if ((pdp->version == 1) && pdp->triggerid.l)
1261 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1262 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001263
Harald Weltebed35df2011-11-02 13:06:18 +01001264 /* Section 7.7.42 */
1265 if ((pdp->version == 1) && pdp->omcid.l)
1266 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1267 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001268
Harald Weltebed35df2011-11-02 13:06:18 +01001269 /* new R7 fields */
1270 if (pdp->rattype_given == 1)
1271 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1272 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001273
Harald Weltebed35df2011-11-02 13:06:18 +01001274 if (pdp->userloc_given == 1)
1275 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1276 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001277
Harald Weltebed35df2011-11-02 13:06:18 +01001278 if (pdp->mstz_given == 1)
1279 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1280 pdp->mstz.l, pdp->mstz.v);
1281
1282 if (pdp->imeisv_given == 1)
1283 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1284 pdp->imeisv.l, pdp->imeisv.v);
1285
1286 /* TODO hisaddr0 */
1287 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1288
1289 return 0;
jjako52c24142002-12-16 13:33:51 +00001290}
1291
jjako08d331d2003-10-13 20:33:30 +00001292/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001293int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1294{
jjako08d331d2003-10-13 20:33:30 +00001295
Harald Weltebed35df2011-11-02 13:06:18 +01001296 /* Now send off a reply to the peer */
1297 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1298
1299 if (cause != GTPCAUSE_ACC_REQ) {
1300 pdp_freepdp(pdp);
1301 }
1302
1303 return 0;
jjako08d331d2003-10-13 20:33:30 +00001304}
1305
1306/* API: Register create context indication callback */
1307int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001308 int (*cb_create_context_ind) (struct pdp_t *
1309 pdp))
jjako52c24142002-12-16 13:33:51 +00001310{
Harald Weltebed35df2011-11-02 13:06:18 +01001311 gsn->cb_create_context_ind = cb_create_context_ind;
1312 return 0;
jjako08d331d2003-10-13 20:33:30 +00001313}
1314
jjako08d331d2003-10-13 20:33:30 +00001315/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001316int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1317 uint8_t cause)
1318{
1319 union gtp_packet packet;
1320 unsigned int length =
1321 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001322
Harald Weltebed35df2011-11-02 13:06:18 +01001323 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001324
Harald Weltebed35df2011-11-02 13:06:18 +01001325 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001326
Harald Weltebed35df2011-11-02 13:06:18 +01001327 if (version == 0)
1328 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1329 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001330
Harald Weltebed35df2011-11-02 13:06:18 +01001331 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1332 pdp->reorder);
1333 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1334 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001335
Harald Weltebed35df2011-11-02 13:06:18 +01001336 if (version == 0) {
1337 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1338 pdp->fllu);
1339 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1340 pdp->fllc);
1341 }
jjako08d331d2003-10-13 20:33:30 +00001342
Harald Weltebed35df2011-11-02 13:06:18 +01001343 if (version == 1) {
1344 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1345 pdp->teid_own);
1346 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1347 pdp->teic_own);
1348 }
jjako08d331d2003-10-13 20:33:30 +00001349
Harald Weltebed35df2011-11-02 13:06:18 +01001350 /* TODO: We use teic_own as charging ID */
1351 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1352 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001353
Harald Weltebed35df2011-11-02 13:06:18 +01001354 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1355 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001356
Harald Weltebed35df2011-11-02 13:06:18 +01001357 if (pdp->pco_neg.l) { /* Optional PCO */
1358 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1359 pdp->pco_neg.l, pdp->pco_neg.v);
1360 }
jjako52c24142002-12-16 13:33:51 +00001361
Harald Weltebed35df2011-11-02 13:06:18 +01001362 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1363 pdp->gsnlc.l, pdp->gsnlc.v);
1364 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1365 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001366
Harald Weltebed35df2011-11-02 13:06:18 +01001367 if (version == 1)
1368 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1369 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001370
Harald Weltebed35df2011-11-02 13:06:18 +01001371 /* TODO: Charging gateway address */
1372 }
jjako52c24142002-12-16 13:33:51 +00001373
Harald Weltebed35df2011-11-02 13:06:18 +01001374 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1375 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001376}
1377
1378/* Handle Create PDP Context Request */
1379int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001380 struct sockaddr_in *peer, int fd,
1381 void *pack, unsigned len)
1382{
1383 struct pdp_t *pdp, *pdp_old;
1384 struct pdp_t pdp_buf;
1385 union gtpie_member *ie[GTPIE_SIZE];
1386 uint8_t recovery;
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001387 bool recovery_recvd = false;
1388 int rc;
jjako52c24142002-12-16 13:33:51 +00001389
Harald Weltebed35df2011-11-02 13:06:18 +01001390 uint16_t seq = get_seq(pack);
1391 int hlen = get_hlen(pack);
1392 uint8_t linked_nsapi = 0;
1393 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001394
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02001395 if (!gtp_duplicate(gsn, version, peer, seq))
Harald Weltebed35df2011-11-02 13:06:18 +01001396 return 0;
jjako08d331d2003-10-13 20:33:30 +00001397
Harald Weltebed35df2011-11-02 13:06:18 +01001398 pdp = &pdp_buf;
1399 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001400
Harald Weltebed35df2011-11-02 13:06:18 +01001401 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001402 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1403
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001404 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001405 }
jjako52c24142002-12-16 13:33:51 +00001406
Harald Weltebed35df2011-11-02 13:06:18 +01001407 pdp->seq = seq;
1408 pdp->sa_peer = *peer;
1409 pdp->fd = fd;
1410 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001411
Harald Weltebed35df2011-11-02 13:06:18 +01001412 /* Decode information elements */
1413 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1414 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001415 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1416 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001417 if (0 == version)
1418 return EOF;
1419 else
1420 return gtp_create_pdp_resp(gsn, version, pdp,
1421 GTPCAUSE_INVALID_MESSAGE);
1422 }
jjako52c24142002-12-16 13:33:51 +00001423
Harald Weltebed35df2011-11-02 13:06:18 +01001424 if (version == 1) {
1425 /* Linked NSAPI (conditional) */
1426 /* If included this is the Secondary PDP Context Activation Procedure */
1427 /* In secondary activation IMSI is not included, so the context must be */
1428 /* identified by the tei */
1429 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001430
Harald Weltebed35df2011-11-02 13:06:18 +01001431 /* Find the primary PDP context */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001432 if (gtp_pdp_getgtp1(gsn, &linked_pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001433 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001434 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001435 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001436 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001437 return gtp_create_pdp_resp(gsn, version, pdp,
1438 GTPCAUSE_OPT_IE_INCORRECT);
1439 }
jjako2c381332003-10-21 19:09:53 +00001440
Harald Weltebed35df2011-11-02 13:06:18 +01001441 /* Check that the primary PDP context matches linked nsapi */
1442 if (linked_pdp->nsapi != linked_nsapi) {
1443 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001444 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001445 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001446 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001447 return gtp_create_pdp_resp(gsn, version, pdp,
1448 GTPCAUSE_OPT_IE_INCORRECT);
1449 }
jjako52c24142002-12-16 13:33:51 +00001450
Harald Weltebed35df2011-11-02 13:06:18 +01001451 /* Copy parameters from primary context */
1452 pdp->selmode = linked_pdp->selmode;
1453 pdp->imsi = linked_pdp->imsi;
1454 pdp->msisdn = linked_pdp->msisdn;
1455 pdp->eua = linked_pdp->eua;
1456 pdp->pco_req = linked_pdp->pco_req;
1457 pdp->apn_req = linked_pdp->apn_req;
1458 pdp->teic_gn = linked_pdp->teic_gn;
1459 pdp->secondary = 1;
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001460 } else {
1461 /* Not Secondary PDP Context Activation Procedure */
1462 /* IMSI (conditional): If the MS is emergency attached
1463 and the MS is UICCless, the IMSI cannot be included
1464 in the message and therefore IMSI shall not be
1465 included in the message. */
1466 if (gtpie_gettv0
1467 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1468 gsn->missing++;
1469 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1470 len, "Missing IMSI not supported\n");
1471 return gtp_create_pdp_resp(gsn, version, pdp,
1472 GTPCAUSE_MAN_IE_MISSING);
1473 }
1474 }
1475
1476 /* TEID (mandatory) */
1477 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1478 gsn->missing++;
1479 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1480 len, "Missing mandatory information field\n");
1481 return gtp_create_pdp_resp(gsn, version, pdp,
1482 GTPCAUSE_MAN_IE_MISSING);
1483 }
1484 /* TEIC (conditional) */
1485 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1486 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1487 gsn->missing++;
1488 GTP_LOGPKG(LOGL_ERROR, peer,
1489 pack, len,
1490 "Missing mandatory information field\n");
1491 return gtp_create_pdp_resp(gsn, version, pdp,
1492 GTPCAUSE_MAN_IE_MISSING);
1493 }
1494 }
1495 /* NSAPI (mandatory) */
1496 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1497 gsn->missing++;
1498 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1499 len, "Missing mandatory information field\n");
1500 return gtp_create_pdp_resp(gsn, version, pdp,
1501 GTPCAUSE_MAN_IE_MISSING);
1502 }
1503 /* QoS (mandatory) */
1504 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1505 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1506 gsn->missing++;
1507 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1508 len, "Missing mandatory information field\n");
1509 return gtp_create_pdp_resp(gsn, version, pdp,
1510 GTPCAUSE_MAN_IE_MISSING);
1511 }
1512 /* TFT (conditional) */
1513 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1514 &pdp->tft.v, sizeof(pdp->tft.v))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001515 }
1516 }
1517 /* if (version == 1) */
1518 if (version == 0) {
1519 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1520 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1521 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001522 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1523 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001524 return gtp_create_pdp_resp(gsn, version, pdp,
1525 GTPCAUSE_MAN_IE_MISSING);
1526 }
Harald Weltebed35df2011-11-02 13:06:18 +01001527 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1528 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001529 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1530 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001531 return gtp_create_pdp_resp(gsn, version, pdp,
1532 GTPCAUSE_MAN_IE_MISSING);
1533 }
Harald Weltebed35df2011-11-02 13:06:18 +01001534 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1535 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001536 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1537 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001538 return gtp_create_pdp_resp(gsn, version, pdp,
1539 GTPCAUSE_MAN_IE_MISSING);
1540 }
1541 }
jjako08d331d2003-10-13 20:33:30 +00001542
Harald Weltebed35df2011-11-02 13:06:18 +01001543 /* SGSN address for signalling (mandatory) */
1544 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1545 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1546 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001547 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1548 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001549 return gtp_create_pdp_resp(gsn, version, pdp,
1550 GTPCAUSE_MAN_IE_MISSING);
1551 }
jjako2e840a32003-01-28 16:05:18 +00001552
Harald Weltebed35df2011-11-02 13:06:18 +01001553 /* SGSN address for user traffic (mandatory) */
1554 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1555 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1556 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001557 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1558 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001559 return gtp_create_pdp_resp(gsn, version, pdp,
1560 GTPCAUSE_MAN_IE_MISSING);
1561 }
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001562 /* Recovery (optional) */
1563 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1564 /* we use recovery futher down after announcing new pdp ctx to user */
1565 recovery_recvd = true;
1566 }
jjako52c24142002-12-16 13:33:51 +00001567
Harald Weltebed35df2011-11-02 13:06:18 +01001568 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001569 /* Selection mode (conditional) */
1570 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1571 &pdp->selmode, sizeof(pdp->selmode))) {
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 /* End User Address (conditional) */
1579 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1580 &pdp->eua.v, sizeof(pdp->eua.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 /* APN */
1588 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1589 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1590 gsn->missing++;
1591 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1592 len, "Missing mandatory information field\n");
1593 return gtp_create_pdp_resp(gsn, version, pdp,
1594 GTPCAUSE_MAN_IE_MISSING);
1595 }
1596 /* Extract protocol configuration options (optional) */
1597 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1598 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1599 }
Harald Weltebed35df2011-11-02 13:06:18 +01001600 /* MSISDN (conditional) */
1601 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1602 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
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 }
1609 }
jjako52c24142002-12-16 13:33:51 +00001610
Harald Weltebed35df2011-11-02 13:06:18 +01001611 /* Initialize our own IP addresses */
1612 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1613 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1614
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001615 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before gtp_pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001616
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001617 if (!gtp_pdp_getimsi(gsn, &pdp_old, pdp->imsi, pdp->nsapi)) {
Harald Weltebed35df2011-11-02 13:06:18 +01001618 /* Found old pdp with same tid. Now the voodoo begins! */
1619 /* 09.60 / 29.060 allows create on existing context to "steal" */
1620 /* the context which was allready established */
1621 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001622 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001623 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1624 &&
1625 (!memcmp
1626 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1627 && (pdp->selmode == pdp_old->selmode)
1628 && (pdp->msisdn.l == pdp_old->msisdn.l)
1629 &&
1630 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1631 {
1632 /* OK! We are dealing with the same APN. We will copy new
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001633 * parameters to the old pdp and send off confirmation
Harald Weltebed35df2011-11-02 13:06:18 +01001634 * We ignore the following information elements:
1635 * QoS: MS will get originally negotiated QoS.
1636 * End user address (EUA). MS will get old EUA anyway.
1637 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001638 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001639
1640 /* Copy remote flow label */
1641 pdp_old->flru = pdp->flru;
1642 pdp_old->flrc = pdp->flrc;
1643
1644 /* Copy remote tei */
1645 pdp_old->teid_gn = pdp->teid_gn;
1646 pdp_old->teic_gn = pdp->teic_gn;
1647
1648 /* Copy peer GSN address */
1649 pdp_old->gsnrc.l = pdp->gsnrc.l;
1650 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1651 pdp_old->gsnru.l = pdp->gsnru.l;
1652 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1653
1654 /* Copy request parameters */
1655 pdp_old->seq = pdp->seq;
1656 pdp_old->sa_peer = pdp->sa_peer;
1657 pdp_old->fd = pdp->fd = fd;
1658 pdp_old->version = pdp->version = version;
1659
1660 /* Switch to using the old pdp context */
1661 pdp = pdp_old;
1662
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001663 if (recovery_recvd)
1664 emit_cb_recovery(gsn, peer, pdp, recovery);
1665
Harald Weltebed35df2011-11-02 13:06:18 +01001666 /* Confirm to peer that things were "successful" */
1667 return gtp_create_pdp_resp(gsn, version, pdp,
1668 GTPCAUSE_ACC_REQ);
1669 } else { /* This is not the same PDP context. Delete the old one. */
1670
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001671 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001672
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02001673 gtp_freepdp(gsn, pdp_old);
Harald Weltebed35df2011-11-02 13:06:18 +01001674
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001675 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001676 }
1677 }
1678
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +02001679 gtp_pdp_newpdp(gsn, &pdp, pdp->imsi, pdp->nsapi, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001680
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001681 /* Callback function to validate login */
Harald Weltebed35df2011-11-02 13:06:18 +01001682 if (gsn->cb_create_context_ind != 0)
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001683 rc = gsn->cb_create_context_ind(pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001684 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001685 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1686 "No create_context_ind callback defined\n");
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001687 rc = gtp_create_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001688 GTPCAUSE_NOT_SUPPORTED);
1689 }
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001690 if (recovery_recvd)
1691 emit_cb_recovery(gsn, peer, pdp, recovery);
1692 return rc;
jjako52c24142002-12-16 13:33:51 +00001693}
1694
jjako52c24142002-12-16 13:33:51 +00001695/* Handle Create PDP Context Response */
1696int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001697 struct sockaddr_in *peer, void *pack, unsigned len)
1698{
1699 struct pdp_t *pdp;
1700 union gtpie_member *ie[GTPIE_SIZE];
1701 uint8_t cause, recovery;
1702 void *cbp = NULL;
1703 uint8_t type = 0;
1704 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001705
Harald Weltebed35df2011-11-02 13:06:18 +01001706 /* Remove packet from queue */
1707 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1708 return EOF;
jjako52c24142002-12-16 13:33:51 +00001709
Harald Weltebed35df2011-11-02 13:06:18 +01001710 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02001711 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001712 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001713 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001714 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001715 if (gsn->cb_conf)
1716 gsn->cb_conf(type, EOF, NULL, cbp);
1717 return EOF;
1718 }
jjako2c381332003-10-21 19:09:53 +00001719
Harald Weltebed35df2011-11-02 13:06:18 +01001720 /* Register that we have received a valid teic from GGSN */
1721 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001722
Harald Weltebed35df2011-11-02 13:06:18 +01001723 /* Decode information elements */
1724 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1725 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001726 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1727 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001728 if (gsn->cb_conf)
1729 gsn->cb_conf(type, EOF, pdp, cbp);
1730 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1731 pdp_freepdp(pdp); */
1732 return EOF;
1733 }
jjako52c24142002-12-16 13:33:51 +00001734
Harald Weltebed35df2011-11-02 13:06:18 +01001735 /* Extract cause value (mandatory) */
1736 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1737 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001738 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1739 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001740 if (gsn->cb_conf)
1741 gsn->cb_conf(type, EOF, pdp, cbp);
1742 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1743 pdp_freepdp(pdp); */
1744 return EOF;
1745 }
jjako52c24142002-12-16 13:33:51 +00001746
Harald Weltebed35df2011-11-02 13:06:18 +01001747 /* Extract recovery (optional) */
1748 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001749 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001750 }
jjako52c24142002-12-16 13:33:51 +00001751
Harald Weltebed35df2011-11-02 13:06:18 +01001752 /* Extract protocol configuration options (optional) */
1753 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1754 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1755 }
jjako52c24142002-12-16 13:33:51 +00001756
Harald Weltebed35df2011-11-02 13:06:18 +01001757 /* Check all conditional information elements */
1758 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001759
Harald Weltebed35df2011-11-02 13:06:18 +01001760 if (version == 0) {
1761 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1762 &pdp->qos_neg0,
1763 sizeof(pdp->qos_neg0))) {
1764 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001765 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001766 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001767 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001768 if (gsn->cb_conf)
1769 gsn->cb_conf(type, EOF, pdp, cbp);
1770 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1771 pdp_freepdp(pdp); */
1772 return EOF;
1773 }
1774 }
jjako08d331d2003-10-13 20:33:30 +00001775
Harald Weltebed35df2011-11-02 13:06:18 +01001776 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1777 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001778 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001779 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001780 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001781 if (gsn->cb_conf)
1782 gsn->cb_conf(type, EOF, pdp, cbp);
1783 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1784 pdp_freepdp(pdp); */
1785 return EOF;
1786 }
jjako52c24142002-12-16 13:33:51 +00001787
Harald Weltebed35df2011-11-02 13:06:18 +01001788 if (version == 0) {
1789 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1790 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001791 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001792 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001793 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001794 if (gsn->cb_conf)
1795 gsn->cb_conf(type, EOF, pdp, cbp);
1796 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1797 pdp_freepdp(pdp); */
1798 return EOF;
1799 }
jjako52c24142002-12-16 13:33:51 +00001800
Harald Weltebed35df2011-11-02 13:06:18 +01001801 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1802 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001803 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001804 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001805 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001806 if (gsn->cb_conf)
1807 gsn->cb_conf(type, EOF, pdp, cbp);
1808 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1809 pdp_freepdp(pdp); */
1810 return EOF;
1811 }
1812 }
1813
1814 if (version == 1) {
1815 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1816 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001817 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001818 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001819 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001820 if (gsn->cb_conf)
1821 gsn->cb_conf(type, EOF, pdp, cbp);
1822 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1823 pdp_freepdp(pdp); */
1824 return EOF;
1825 }
1826
1827 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1828 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001829 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001830 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001831 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001832 if (gsn->cb_conf)
1833 gsn->cb_conf(type, EOF, pdp, cbp);
1834 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1835 pdp_freepdp(pdp); */
1836 return EOF;
1837 }
1838 }
1839
1840 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1841 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001842 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001843 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001844 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001845 if (gsn->cb_conf)
1846 gsn->cb_conf(type, EOF, pdp, cbp);
1847 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1848 pdp_freepdp(pdp); */
1849 }
1850
1851 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1852 &pdp->eua.v, sizeof(pdp->eua.v))) {
1853 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001854 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001855 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001856 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001857 if (gsn->cb_conf)
1858 gsn->cb_conf(type, EOF, pdp, cbp);
1859 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1860 pdp_freepdp(pdp); */
1861 return EOF;
1862 }
1863
1864 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1865 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1866 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001867 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001868 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001869 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001870 if (gsn->cb_conf)
1871 gsn->cb_conf(type, EOF, pdp, cbp);
1872 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1873 pdp_freepdp(pdp); */
1874 return EOF;
1875 }
1876
1877 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1878 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1879 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001880 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001881 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);
1885 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1886 pdp_freepdp(pdp); */
1887 return EOF;
1888 }
1889
1890 if (version == 1) {
1891 if (gtpie_gettlv
1892 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1893 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1894 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001895 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001896 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001897 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001898 if (gsn->cb_conf)
1899 gsn->cb_conf(type, EOF, pdp, cbp);
1900 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1901 pdp_freepdp(pdp); */
1902 return EOF;
1903 }
1904 }
1905
1906 }
1907
1908 if (gsn->cb_conf)
1909 gsn->cb_conf(type, cause, pdp, cbp);
1910
1911 return 0;
jjako52c24142002-12-16 13:33:51 +00001912}
1913
jjako08d331d2003-10-13 20:33:30 +00001914/* API: Send Update PDP Context Request */
1915int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001916 struct in_addr *inetaddr)
1917{
1918 union gtp_packet packet;
1919 unsigned int length =
1920 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001921
Harald Weltebed35df2011-11-02 13:06:18 +01001922 if (pdp->version == 0)
1923 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1924 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001925
Harald Weltebed35df2011-11-02 13:06:18 +01001926 /* Include IMSI if updating with unknown teic_gn */
1927 if ((pdp->version == 1) && (!pdp->teic_gn))
1928 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1929 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1930
1931 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1932 gsn->restart_counter);
1933
1934 if (pdp->version == 0) {
1935 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1936 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1937 }
1938
1939 if (pdp->version == 1) {
1940 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1941 pdp->teid_own);
1942
1943 if (!pdp->teic_confirmed)
1944 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1945 pdp->teic_own);
1946 }
1947
1948 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1949
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001950 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001951 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1952 pdp->traceref);
1953 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1954 pdp->tracetype); */
1955
1956 /* TODO if ggsn update message
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001957 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01001958 pdp->eua.l, pdp->eua.v);
1959 */
1960
1961 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1962 pdp->gsnlc.l, pdp->gsnlc.v);
1963 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1964 pdp->gsnlu.l, pdp->gsnlu.v);
1965
1966 if (pdp->version == 1)
1967 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1968 pdp->qos_req.l, pdp->qos_req.v);
1969
1970 if ((pdp->version == 1) && pdp->tft.l)
1971 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1972 pdp->tft.l, pdp->tft.v);
1973
1974 if ((pdp->version == 1) && pdp->triggerid.l)
1975 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1976 pdp->triggerid.l, pdp->triggerid.v);
1977
1978 if ((pdp->version == 1) && pdp->omcid.l)
1979 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1980 pdp->omcid.l, pdp->omcid.v);
1981
Daniel Willmann134a7752016-02-03 18:53:29 +01001982 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001983
1984 return 0;
jjako52c24142002-12-16 13:33:51 +00001985}
1986
jjako08d331d2003-10-13 20:33:30 +00001987/* Send Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001988static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01001989 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001990 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001991 struct pdp_t *pdp, uint8_t cause)
1992{
jjako08d331d2003-10-13 20:33:30 +00001993
Harald Weltebed35df2011-11-02 13:06:18 +01001994 union gtp_packet packet;
1995 unsigned int length =
1996 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001997
Harald Weltebed35df2011-11-02 13:06:18 +01001998 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001999
Harald Weltebed35df2011-11-02 13:06:18 +01002000 if (cause == GTPCAUSE_ACC_REQ) {
2001
2002 if (version == 0)
2003 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
2004 sizeof(pdp->qos_neg0), pdp->qos_neg0);
2005
2006 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
2007 gsn->restart_counter);
2008
2009 if (version == 0) {
2010 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
2011 pdp->fllu);
2012 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
2013 pdp->fllc);
2014 }
2015
2016 if (version == 1) {
2017 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2018 pdp->teid_own);
2019
2020 if (!pdp->teic_confirmed)
2021 gtpie_tv4(&packet, &length, GTP_MAX,
2022 GTPIE_TEI_C, pdp->teic_own);
2023 }
2024
2025 /* TODO we use teid_own as charging ID address */
2026 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
2027 pdp->teid_own);
2028
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002029 /* If ggsn
2030 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01002031 pdp->eua.l, pdp->eua.v); */
2032
2033 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2034 pdp->gsnlc.l, pdp->gsnlc.v);
2035 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2036 pdp->gsnlu.l, pdp->gsnlu.v);
2037
2038 if (version == 1)
2039 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2040 pdp->qos_neg.l, pdp->qos_neg.v);
2041
2042 /* TODO: Charging gateway address */
2043 }
2044
2045 return gtp_resp(version, gsn, pdp, &packet, length, peer,
2046 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00002047}
2048
jjako52c24142002-12-16 13:33:51 +00002049/* Handle Update PDP Context Request */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002050static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002051 struct sockaddr_in *peer, int fd,
2052 void *pack, unsigned len)
2053{
2054 struct pdp_t *pdp;
2055 struct pdp_t pdp_backup;
2056 union gtpie_member *ie[GTPIE_SIZE];
2057 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002058
Harald Weltebed35df2011-11-02 13:06:18 +01002059 uint16_t seq = get_seq(pack);
2060 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002061
Harald Weltebed35df2011-11-02 13:06:18 +01002062 uint64_t imsi;
2063 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002064
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002065 /* Is this a duplicate ? */
2066 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002067 return 0; /* We allready send of response once */
2068 }
jjako08d331d2003-10-13 20:33:30 +00002069
Harald Weltebed35df2011-11-02 13:06:18 +01002070 /* Decode information elements */
2071 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2072 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002073 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2074 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002075 if (0 == version)
2076 return EOF;
2077 else
2078 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2079 len, NULL,
2080 GTPCAUSE_INVALID_MESSAGE);
2081 }
jjako08d331d2003-10-13 20:33:30 +00002082
Harald Weltebed35df2011-11-02 13:06:18 +01002083 /* Finding PDP: */
2084 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2085 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2086 /* we have to use the tunnel endpoint identifier */
2087 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002088 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
2089
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01002090 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00002091
Harald Weltebed35df2011-11-02 13:06:18 +01002092 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002093 if (gtp_pdp_getimsi(gsn, &pdp, imsi, nsapi)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002094 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002095 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2096 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002097 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2098 len, NULL,
2099 GTPCAUSE_NON_EXIST);
2100 }
2101 } else if (version == 1) {
2102 /* NSAPI (mandatory) */
2103 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2104 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002105 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2106 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002107 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2108 len, NULL,
2109 GTPCAUSE_MAN_IE_MISSING);
2110 }
jjako08d331d2003-10-13 20:33:30 +00002111
Harald Weltebed35df2011-11-02 13:06:18 +01002112 /* IMSI (conditional) */
2113 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2114 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002115 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002116 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002117 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002118 pack, len, "Unknown PDP context: %u\n",
2119 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002120 return gtp_update_pdp_resp(gsn, version, peer,
2121 fd, pack, len, NULL,
2122 GTPCAUSE_NON_EXIST);
2123 }
2124 } else {
2125 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002126 if (gtp_pdp_getimsi(gsn, &pdp, imsi, nsapi)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002127 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002128 GTP_LOGPKG(LOGL_ERROR, peer,
2129 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002130 return gtp_update_pdp_resp(gsn, version, peer,
2131 fd, pack, len, NULL,
2132 GTPCAUSE_NON_EXIST);
2133 }
2134 }
2135 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002136 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002137 return EOF;
2138 }
jjako08d331d2003-10-13 20:33:30 +00002139
Harald Weltebed35df2011-11-02 13:06:18 +01002140 /* Make a backup copy in case anything is wrong */
2141 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002142
Harald Weltebed35df2011-11-02 13:06:18 +01002143 if (version == 0) {
2144 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2145 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2146 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002147 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2148 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002149 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2150 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2151 len, pdp,
2152 GTPCAUSE_MAN_IE_MISSING);
2153 }
2154 }
jjako52c24142002-12-16 13:33:51 +00002155
Harald Weltebed35df2011-11-02 13:06:18 +01002156 /* Recovery (optional) */
2157 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002158 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002159 }
jjako08d331d2003-10-13 20:33:30 +00002160
Harald Weltebed35df2011-11-02 13:06:18 +01002161 if (version == 0) {
2162 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2163 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002164 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2165 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002166 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2167 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2168 len, pdp,
2169 GTPCAUSE_MAN_IE_MISSING);
2170 }
jjako52c24142002-12-16 13:33:51 +00002171
Harald Weltebed35df2011-11-02 13:06:18 +01002172 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2173 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002174 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2175 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002176 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2177 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2178 len, pdp,
2179 GTPCAUSE_MAN_IE_MISSING);
2180 }
2181 }
jjako52c24142002-12-16 13:33:51 +00002182
Harald Weltebed35df2011-11-02 13:06:18 +01002183 if (version == 1) {
2184 /* TEID (mandatory) */
2185 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2186 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002187 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2188 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002189 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2190 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2191 len, pdp,
2192 GTPCAUSE_MAN_IE_MISSING);
2193 }
jjako52c24142002-12-16 13:33:51 +00002194
Harald Weltebed35df2011-11-02 13:06:18 +01002195 /* TEIC (conditional) */
2196 /* If TEIC is not included it means that we have allready received it */
2197 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2198 /* all updated contexts, or only for one of the linked contexts */
2199 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2200
2201 /* NSAPI (mandatory) */
2202 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2203 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002204 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2205 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002206 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2207 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2208 len, pdp,
2209 GTPCAUSE_MAN_IE_MISSING);
2210 }
2211 }
2212
2213 /* Trace reference (optional) */
2214 /* Trace type (optional) */
2215
2216 /* End User Address (conditional) TODO: GGSN Initiated
2217 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2218 &pdp->eua.v, sizeof(pdp->eua.v))) {
2219 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002220 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002221 "Missing mandatory information field");
2222 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002223 return gtp_update_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01002224 GTPCAUSE_MAN_IE_MISSING);
2225 } */
2226
2227 /* SGSN address for signalling (mandatory) */
2228 /* It is weird that this is mandatory when TEIC is conditional */
2229 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2230 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2231 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002232 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2233 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002234 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2235 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2236 pdp, GTPCAUSE_MAN_IE_MISSING);
2237 }
2238
2239 /* SGSN address for user traffic (mandatory) */
2240 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2241 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2242 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002243 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2244 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002245 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2246 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2247 pdp, GTPCAUSE_MAN_IE_MISSING);
2248 }
2249
2250 if (version == 1) {
2251 /* QoS (mandatory) */
2252 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2253 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2254 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002255 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2256 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002257 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2258 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2259 len, pdp,
2260 GTPCAUSE_MAN_IE_MISSING);
2261 }
2262
2263 /* TFT (conditional) */
2264 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2265 &pdp->tft.v, sizeof(pdp->tft.v))) {
2266 }
2267
2268 /* OMC identity */
2269 }
2270
2271 /* Confirm to peer that things were "successful" */
2272 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2273 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002274}
2275
jjako52c24142002-12-16 13:33:51 +00002276/* Handle Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002277static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002278 struct sockaddr_in *peer, void *pack, unsigned len)
2279{
2280 struct pdp_t *pdp;
2281 union gtpie_member *ie[GTPIE_SIZE];
2282 uint8_t cause, recovery;
2283 void *cbp = NULL;
2284 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002285 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002286
Harald Weltebed35df2011-11-02 13:06:18 +01002287 /* Remove packet from queue */
2288 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2289 return EOF;
jjako52c24142002-12-16 13:33:51 +00002290
Harald Weltebed35df2011-11-02 13:06:18 +01002291 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002292 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002293 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002294 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002295 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002296 pdp = NULL;
2297 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002298 }
jjako2c381332003-10-21 19:09:53 +00002299
Harald Weltebed35df2011-11-02 13:06:18 +01002300 /* Register that we have received a valid teic from GGSN */
2301 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002302
Harald Weltebed35df2011-11-02 13:06:18 +01002303 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002304 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002305 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002306 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2307 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002308 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002309 }
jjako52c24142002-12-16 13:33:51 +00002310
Harald Weltebed35df2011-11-02 13:06:18 +01002311 /* Extract cause value (mandatory) */
2312 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002313 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002314 }
jjako52c24142002-12-16 13:33:51 +00002315
Harald Weltebed35df2011-11-02 13:06:18 +01002316 /* Extract recovery (optional) */
2317 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002318 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002319 }
2320
2321 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002322 /* TODO: This does not handle GGSN-initiated update responses */
2323 if (GTPCAUSE_ACC_REQ == cause) {
2324 if (version == 0) {
2325 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2326 &pdp->qos_neg0,
2327 sizeof(pdp->qos_neg0))) {
2328 goto err_missing;
2329 }
2330
2331 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2332 goto err_missing;
2333 }
2334
2335 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2336 goto err_missing;
2337 }
Harald Weltebed35df2011-11-02 13:06:18 +01002338 }
2339
Daniel Willmannd9975522016-02-04 15:38:12 +01002340 if (version == 1) {
2341 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2342 goto err_missing;
2343 }
Harald Weltebed35df2011-11-02 13:06:18 +01002344
Daniel Willmannd9975522016-02-04 15:38:12 +01002345 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2346 goto err_missing;
2347 }
2348 }
2349
2350 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2351 goto err_missing;
2352 }
2353
2354 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2355 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2356 goto err_missing;
2357 }
2358
2359 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2360 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2361 goto err_missing;
2362 }
2363
2364 if (version == 1) {
2365 if (gtpie_gettlv
2366 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2367 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2368 goto err_missing;
2369 }
2370 }
Harald Weltebed35df2011-11-02 13:06:18 +01002371 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002372
2373 if (gsn->cb_conf)
2374 gsn->cb_conf(type, cause, pdp, cbp);
2375 return 0; /* Succes */
2376
2377err_missing:
2378 gsn->missing++;
2379 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2380 "Missing information field\n");
2381err_out:
2382 if (gsn->cb_conf)
2383 gsn->cb_conf(type, EOF, pdp, cbp);
2384 return EOF;
jjako52c24142002-12-16 13:33:51 +00002385}
2386
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002387/* API: Deprecated. Send Delete PDP Context Request And free pdp ctx. */
jjako2c381332003-10-21 19:09:53 +00002388int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002389 int teardown)
2390{
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002391 struct pdp_t *linked_pdp;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002392
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002393 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002394 LOGP(DLGTP, LOGL_ERROR,
2395 "Unknown linked PDP context: %u\n", pdp->teic_own);
2396 return EOF;
2397 }
2398
2399 if (gtp_delete_context_req2(gsn, pdp, cbp, teardown) == EOF)
2400 return EOF;
2401
2402 if (teardown) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002403 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002404 } else {
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002405 /* If we end up here (no teardown) it means we still
2406 have at least another pdp context active for this
2407 PDN connection (since last DeleteReq should come
2408 with teardown enabled). If the ctx to delete is a
2409 secondary ctx, simply free it. If it's the primary
2410 ctx, mark it as nodata but don't free it since we
2411 need it to hold data linked together and we'll
2412 require it later to tear down the entire tree. Still,
2413 we announce its deletion through cb_delete_context
2414 because we don't want user to release its related
2415 data and not use it anymore.
2416 */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002417 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002418 if (gsn->cb_delete_context)
2419 gsn->cb_delete_context(pdp);
2420 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2421 pdp->nodata = 1;
2422 } else {
2423 gtp_freepdp(gsn, pdp);
2424 }
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002425 }
2426
2427 return 0;
2428}
2429
Oliver Smith1cde2c12019-05-13 11:35:03 +02002430/* API: Send Delete PDP Context Request. PDP CTX shall be free'd by user at any
2431 point in time later than this function through a call to pdp_freepdp(pdp), but
2432 it must be freed no later than during cb_conf(GTP_DELETE_PDP_REQ, pdp) */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002433int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2434 int teardown)
2435{
Harald Weltebed35df2011-11-02 13:06:18 +01002436 union gtp_packet packet;
2437 unsigned int length =
2438 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2439 struct in_addr addr;
2440 struct pdp_t *linked_pdp;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002441 int count;
jjako2c381332003-10-21 19:09:53 +00002442
Harald Weltebed35df2011-11-02 13:06:18 +01002443 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2444 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002445 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002446 return EOF;
jjako2c381332003-10-21 19:09:53 +00002447 }
jjako2c381332003-10-21 19:09:53 +00002448
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002449 if (gtp_pdp_getgtp1(gsn, &linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002450 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002451 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002452 return EOF;
2453 }
2454
2455 if (!teardown) {
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002456 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002457 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002458 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002459 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002460 return EOF;
2461 }
2462 }
2463
2464 if (pdp->version == 1) {
2465 if (teardown)
2466 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2467 0xff);
2468
2469 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2470 }
2471
2472 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2473
Harald Weltebed35df2011-11-02 13:06:18 +01002474 return 0;
jjako2c381332003-10-21 19:09:53 +00002475}
jjako08d331d2003-10-13 20:33:30 +00002476
jjako52c24142002-12-16 13:33:51 +00002477/* Send Delete PDP Context Response */
2478int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002479 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002480 void *pack, unsigned len,
2481 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002482 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002483{
Harald Weltebed35df2011-11-02 13:06:18 +01002484 union gtp_packet packet;
Harald Weltebed35df2011-11-02 13:06:18 +01002485 unsigned int length =
2486 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00002487
Harald Weltebed35df2011-11-02 13:06:18 +01002488 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002489
Harald Weltebed35df2011-11-02 13:06:18 +01002490 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2491 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002492
Harald Weltebed35df2011-11-02 13:06:18 +01002493 if (cause == GTPCAUSE_ACC_REQ) {
2494 if ((teardown) || (version == 0)) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002495 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002496 } else {
2497 /* If we end up here (no teardown) it means we still
2498 have at least another pdp context active for this
2499 PDN connection (since last DeleteReq should come
2500 with teardown enabled). If the ctx to delete is a
2501 secondary ctx, simply free it. If it's the primary
2502 ctx, mark it as nodata but don't free it since we
2503 need it to hold data linked together and we'll
2504 require it later to tear down the entire tree. Still,
2505 we announce its deletion through cb_delete_context
2506 because we don't want user to release its related
2507 data and not use it anymore.
2508 */
Harald Weltebed35df2011-11-02 13:06:18 +01002509 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002510 if (gsn->cb_delete_context)
2511 gsn->cb_delete_context(pdp);
2512 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2513 pdp->nodata = 1;
2514 } else {
2515 gtp_freepdp(gsn, pdp);
2516 }
Harald Weltebed35df2011-11-02 13:06:18 +01002517 }
jjako2c381332003-10-21 19:09:53 +00002518 }
Harald Weltebed35df2011-11-02 13:06:18 +01002519 /* if (cause == GTPCAUSE_ACC_REQ) */
2520 return 0;
jjako52c24142002-12-16 13:33:51 +00002521}
2522
2523/* Handle Delete PDP Context Request */
2524int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002525 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002526 void *pack, unsigned len)
2527{
2528 struct pdp_t *pdp = NULL;
2529 struct pdp_t *linked_pdp = NULL;
2530 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002531
Harald Weltebed35df2011-11-02 13:06:18 +01002532 uint16_t seq = get_seq(pack);
2533 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002534
Harald Weltebed35df2011-11-02 13:06:18 +01002535 uint8_t nsapi;
2536 uint8_t teardown = 0;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002537 int count;
jjako52c24142002-12-16 13:33:51 +00002538
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002539 /* Is this a duplicate ? */
2540 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002541 return 0; /* We allready send off response once */
2542 }
jjako2c381332003-10-21 19:09:53 +00002543
Harald Weltebed35df2011-11-02 13:06:18 +01002544 /* Find the linked context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002545 if (gtp_pdp_getgtp1(gsn, &linked_pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002546 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002547 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002548 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002549 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2550 NULL, NULL, GTPCAUSE_NON_EXIST,
2551 teardown);
2552 }
jjako2c381332003-10-21 19:09:53 +00002553
Harald Weltebed35df2011-11-02 13:06:18 +01002554 /* If version 0 this is also the secondary context */
2555 if (version == 0)
2556 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002557
Harald Weltebed35df2011-11-02 13:06:18 +01002558 /* Decode information elements */
2559 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2560 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002561 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2562 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002563 if (0 == version)
2564 return EOF;
2565 else
2566 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2567 len, NULL, NULL,
2568 GTPCAUSE_INVALID_MESSAGE,
2569 teardown);
2570 }
2571
2572 if (version == 1) {
2573 /* NSAPI (mandatory) */
2574 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2575 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002576 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2577 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002578 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2579 len, NULL, NULL,
2580 GTPCAUSE_MAN_IE_MISSING,
2581 teardown);
2582 }
2583
2584 /* Find the context in question */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002585 if (gtp_pdp_getgtp1(gsn, &pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
Harald Weltebed35df2011-11-02 13:06:18 +01002586 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002587 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2588 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002589 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2590 len, NULL, NULL,
2591 GTPCAUSE_NON_EXIST,
2592 teardown);
2593 }
2594
2595 /* Teardown (conditional) */
2596 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2597
2598 if (!teardown) {
Pau Espin Pedrol742a6b52019-05-30 13:36:10 +02002599 /* TS 29.060 section 7.3.5: If a GSN receives a Delete PDP context
2600 * without a Teardown Indicator or with a Teardown Indicator with
2601 * value set to "0" and only that PDP context is active for a PDN
2602 * connection, then the GSN shall ignore the message. (Note:
2603 * This is symptom of a race condition. The reliable delivery of
2604 * signalling messages will eventually lead to a consistent
2605 * situation, allowing the teardown of the PDP context.)
2606 */
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002607 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002608 if (count <= 1) {
Pau Espin Pedrold1bd6fc2018-07-13 19:11:45 +02002609 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2610 "Ignoring CTX DEL without teardown and count=%d\n",
2611 count);
Harald Weltebed35df2011-11-02 13:06:18 +01002612 return 0; /* 29.060 7.3.5 Ignore message */
2613 }
2614 }
2615 }
2616
2617 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2618 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002619}
2620
jjako52c24142002-12-16 13:33:51 +00002621/* Handle Delete PDP Context Response */
2622int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002623 struct sockaddr_in *peer, void *pack, unsigned len)
2624{
2625 union gtpie_member *ie[GTPIE_SIZE];
2626 uint8_t cause;
2627 void *cbp = NULL;
2628 uint8_t type = 0;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002629 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002630 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002631
Harald Weltebed35df2011-11-02 13:06:18 +01002632 /* Remove packet from queue */
2633 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2634 return EOF;
jjako52c24142002-12-16 13:33:51 +00002635
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002636 /* Find the context in question. It may not be available if gtp_delete_context_req
2637 * was used and as a result the PDP ctx was already freed */
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002638 if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002639 gsn->err_unknownpdp++;
2640 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
Oliver Smith1cde2c12019-05-13 11:35:03 +02002641 "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 +02002642 get_tei(pack));
2643 if (gsn->cb_conf)
2644 gsn->cb_conf(type, EOF, NULL, cbp);
2645 return EOF;
2646 }
2647
Harald Weltebed35df2011-11-02 13:06:18 +01002648 /* Decode information elements */
2649 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2650 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002651 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2652 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002653 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002654 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002655 return EOF;
2656 }
2657
2658 /* Extract cause value (mandatory) */
2659 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2660 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002661 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2662 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002663 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002664 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002665 return EOF;
2666 }
2667
2668 /* Check the cause value (again) */
2669 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2670 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002671 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2672 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002673 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002674 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002675 return EOF;
2676 }
2677
2678 /* Callback function to notify application */
2679 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002680 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002681
2682 return 0;
jjako52c24142002-12-16 13:33:51 +00002683}
2684
Harald Welte54d082e2017-08-12 22:43:21 +02002685/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002686static int gtp_error_ind_resp(struct gsn_t *gsn, uint8_t version,
jjako08d331d2003-10-13 20:33:30 +00002687 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002688 void *pack, unsigned len)
2689{
Harald Weltebed35df2011-11-02 13:06:18 +01002690 union gtp_packet packet;
2691 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2692
Harald Welte54d082e2017-08-12 22:43:21 +02002693 if (version == 1) {
2694 /* Mandatory 7.7.13 TEI Data I */
2695 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2696 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2697
2698 /* Mandatory 7.7.32 GSN Address */
2699 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2700 sizeof(gsn->gsnu), &gsn->gsnu);
2701 }
2702
Harald Weltebed35df2011-11-02 13:06:18 +01002703 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2704 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002705}
2706
2707/* Handle Error Indication */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002708static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002709 struct sockaddr_in *peer, void *pack, unsigned len)
2710{
Harald Welte37d5b152017-08-12 23:58:29 +02002711 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002712 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002713
Harald Weltebed35df2011-11-02 13:06:18 +01002714 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002715 if (version == 0) {
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002716 if (gtp_pdp_tidget(gsn, &pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
Harald Welte37d5b152017-08-12 23:58:29 +02002717 gsn->err_unknownpdp++;
2718 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2719 "Unknown PDP context\n");
2720 return EOF;
2721 }
2722 } else if (version == 1) {
2723 /* we have to look-up based on the *peer* TEID */
2724 int hlen = get_hlen(pack);
2725 uint32_t teid_gn;
2726
2727 /* Decode information elements */
2728 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2729 gsn->invalid++;
2730 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2731 "Invalid message format\n");
2732 return EOF;
2733 }
2734
2735 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2736 gsn->missing++;
2737 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2738 "Missing mandatory information field\n");
2739 return EOF;
2740 }
2741
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002742 if (gtp_pdp_getgtp1_peer_d(gsn, &pdp, peer, teid_gn)) {
Harald Welte37d5b152017-08-12 23:58:29 +02002743 gsn->err_unknownpdp++;
2744 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2745 return EOF;
2746 }
Harald Weltebed35df2011-11-02 13:06:18 +01002747 }
jjako52c24142002-12-16 13:33:51 +00002748
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002749 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2750 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002751
Harald Weltebd228242017-11-06 03:16:49 +09002752 /* This is obvious from above code, given the semantics of the
2753 * functions above, but Coverity doesn't figure this out, so
2754 * let's make it clear. It's good style anyway in case above
2755 * code should ever change. */
2756 OSMO_ASSERT(pdp);
2757
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002758 gtp_freepdp(gsn, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002759 return 0;
jjako52c24142002-12-16 13:33:51 +00002760}
2761
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002762static int gtp_gpdu_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002763 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2764{
jjako08d331d2003-10-13 20:33:30 +00002765
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002766 int hlen;
jjako52c24142002-12-16 13:33:51 +00002767
Harald Weltebed35df2011-11-02 13:06:18 +01002768 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002769
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002770 switch (version) {
2771 case 0:
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002772 if (gtp_pdp_getgtp0(gsn, &pdp,
2773 ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002774 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002775 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002776 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002777 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2778 len);
2779 }
2780 hlen = GTP0_HEADER_SIZE;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002781 break;
2782 case 1:
Pau Espin Pedrol9fbcb102019-05-31 16:29:32 +02002783 if (gtp_pdp_getgtp1(gsn, &pdp,
2784 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002785 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002786 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002787 len, "Unknown PDP context, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002788 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2789 len);
2790 }
jjako08d331d2003-10-13 20:33:30 +00002791
Harald Weltebed35df2011-11-02 13:06:18 +01002792 /* Is this a long or a short header ? */
2793 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2794 hlen = GTP1_HEADER_SIZE_LONG;
2795 else
2796 hlen = GTP1_HEADER_SIZE_SHORT;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002797 break;
2798 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002799 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002800 "Unknown version: %d\n", version);
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002801 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002802 }
jjako08d331d2003-10-13 20:33:30 +00002803
Harald Weltebed35df2011-11-02 13:06:18 +01002804 /* If the GPDU was not from the peer GSN tell him to delete context */
2805 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2806 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002807 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002808 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2809 }
jjako52c24142002-12-16 13:33:51 +00002810
Harald Weltebed35df2011-11-02 13:06:18 +01002811 /* Callback function */
2812 if (gsn->cb_data_ind != 0)
2813 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2814
2815 return 0;
jjako52c24142002-12-16 13:33:51 +00002816}
2817
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002818/* Receives GTP packet and sends off for further processing
jjako52c24142002-12-16 13:33:51 +00002819 * Function will check the validity of the header. If the header
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002820 * is not valid the packet is either dropped or a version not
2821 * supported is returned to the peer.
jjako52c24142002-12-16 13:33:51 +00002822 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002823int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002824{
Harald Weltebed35df2011-11-02 13:06:18 +01002825 unsigned char buffer[PACKET_MAX];
2826 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002827 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002828 int status;
2829 struct gtp0_header *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002830 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002831 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002832
Harald Weltebed35df2011-11-02 13:06:18 +01002833 /* TODO: Need strategy of userspace buffering and blocking */
2834 /* Currently read is non-blocking and send is blocking. */
2835 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002836
Harald Weltebed35df2011-11-02 13:06:18 +01002837 while (1) { /* Loop until no more to read */
2838 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002839 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002840 return -1;
2841 }
2842 peerlen = sizeof(peer);
2843 if ((status =
2844 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2845 (struct sockaddr *)&peer, &peerlen)) < 0) {
2846 if (errno == EAGAIN)
2847 return 0;
2848 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002849 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002850 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002851 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2852 status, status ? strerror(errno) : "No error");
2853 return -1;
2854 }
jjako1db1c812003-07-06 20:53:57 +00002855
Harald Weltebed35df2011-11-02 13:06:18 +01002856 /* Need at least 1 byte in order to check version */
2857 if (status < (1)) {
2858 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002859 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2860 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002861 continue;
2862 }
jjako08d331d2003-10-13 20:33:30 +00002863
Harald Weltebed35df2011-11-02 13:06:18 +01002864 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002865
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002866 version = GTPHDR_F_GET_VER(pheader->flags);
2867
Harald Weltebed35df2011-11-02 13:06:18 +01002868 /* Version should be gtp0 (or earlier) */
2869 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2870 /* GTP 0 messages. If other version message is received we reply that we */
2871 /* only support version 0, implying that this is the only version */
2872 /* supported on this port */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002873 if (version > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002874 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01002875 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2876 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002877 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2878 continue;
2879 }
2880
2881 /* Check length of gtp0 packet */
2882 if (status < GTP0_HEADER_SIZE) {
2883 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002884 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2885 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002886 continue; /* Silently discard 29.60: 11.1.2 */
2887 }
2888
2889 /* Check packet length field versus length of packet */
2890 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2891 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002892 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002893 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002894 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002895 continue; /* Silently discard */
2896 }
2897
2898 if ((gsn->mode == GTP_MODE_GGSN) &&
2899 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002900 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002901 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002902 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002903 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002904 "Unexpected GTPv0 Signalling Message '%s'\n",
2905 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002906 continue; /* Silently discard 29.60: 11.1.4 */
2907 }
2908
2909 if ((gsn->mode == GTP_MODE_SGSN) &&
2910 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002911 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002912 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002913 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002914 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002915 "Unexpected GTPv0 Signalling Message '%s'\n",
2916 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002917 continue; /* Silently discard 29.60: 11.1.4 */
2918 }
2919
2920 switch (pheader->type) {
2921 case GTP_ECHO_REQ:
2922 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2923 break;
2924 case GTP_ECHO_RSP:
2925 gtp_echo_conf(gsn, version, &peer, buffer, status);
2926 break;
2927 case GTP_NOT_SUPPORTED:
2928 gtp_unsup_ind(gsn, &peer, buffer, status);
2929 break;
2930 case GTP_CREATE_PDP_REQ:
2931 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2932 status);
2933 break;
2934 case GTP_CREATE_PDP_RSP:
2935 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2936 status);
2937 break;
2938 case GTP_UPDATE_PDP_REQ:
2939 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2940 status);
2941 break;
2942 case GTP_UPDATE_PDP_RSP:
2943 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2944 status);
2945 break;
2946 case GTP_DELETE_PDP_REQ:
2947 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2948 status);
2949 break;
2950 case GTP_DELETE_PDP_RSP:
2951 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2952 status);
2953 break;
2954 case GTP_ERROR:
2955 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2956 break;
2957 case GTP_GPDU:
2958 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2959 break;
2960 default:
2961 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002962 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2963 "Unknown GTP message type received: %d\n",
2964 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002965 break;
2966 }
2967 }
jjako08d331d2003-10-13 20:33:30 +00002968}
2969
jjako08d331d2003-10-13 20:33:30 +00002970int gtp_decaps1c(struct gsn_t *gsn)
2971{
Harald Weltebed35df2011-11-02 13:06:18 +01002972 unsigned char buffer[PACKET_MAX];
2973 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002974 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002975 int status;
2976 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002977 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002978 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002979
Harald Weltebed35df2011-11-02 13:06:18 +01002980 /* TODO: Need strategy of userspace buffering and blocking */
2981 /* Currently read is non-blocking and send is blocking. */
2982 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002983
Harald Weltebed35df2011-11-02 13:06:18 +01002984 while (1) { /* Loop until no more to read */
2985 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002986 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002987 return -1;
2988 }
2989 peerlen = sizeof(peer);
2990 if ((status =
2991 recvfrom(fd, buffer, sizeof(buffer), 0,
2992 (struct sockaddr *)&peer, &peerlen)) < 0) {
2993 if (errno == EAGAIN)
2994 return 0;
2995 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002996 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002997 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002998 fd, (unsigned long)buffer, sizeof(buffer),
2999 status, status ? strerror(errno) : "No error");
3000 return -1;
3001 }
jjako08d331d2003-10-13 20:33:30 +00003002
Harald Weltebed35df2011-11-02 13:06:18 +01003003 /* Need at least 1 byte in order to check version */
3004 if (status < (1)) {
3005 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003006 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3007 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003008 continue;
3009 }
jjako08d331d2003-10-13 20:33:30 +00003010
Harald Weltebed35df2011-11-02 13:06:18 +01003011 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003012
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003013 version = GTPHDR_F_GET_VER(pheader->flags);
3014
Harald Weltebed35df2011-11-02 13:06:18 +01003015 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003016 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003017 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003018 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3019 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003020 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
3021 /*29.60: 11.1.1 */
3022 continue;
3023 }
jjako08d331d2003-10-13 20:33:30 +00003024
Harald Weltebed35df2011-11-02 13:06:18 +01003025 /* Version must be at least GTP 1 */
3026 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3027 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3028 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003029 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003030 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003031 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3032 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003033 continue;
3034 }
jjako08d331d2003-10-13 20:33:30 +00003035
Harald Weltebed35df2011-11-02 13:06:18 +01003036 /* Check packet flag field */
3037 if (((pheader->flags & 0xf7) != 0x32)) {
3038 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003039 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003040 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003041 continue;
3042 }
jjako2c381332003-10-21 19:09:53 +00003043
Harald Weltebed35df2011-11-02 13:06:18 +01003044 /* Check length of packet */
3045 if (status < GTP1_HEADER_SIZE_LONG) {
3046 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003047 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3048 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003049 continue; /* Silently discard 29.60: 11.1.2 */
3050 }
jjako2c381332003-10-21 19:09:53 +00003051
Harald Weltebed35df2011-11-02 13:06:18 +01003052 /* Check packet length field versus length of packet */
3053 if (status !=
3054 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3055 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003056 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003057 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003058 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003059 continue; /* Silently discard */
3060 }
jjako1db1c812003-07-06 20:53:57 +00003061
Harald Weltebed35df2011-11-02 13:06:18 +01003062 /* Check for extension headers */
3063 /* TODO: We really should cycle through the headers and determine */
3064 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003065 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003066 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003067 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3068 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003069 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3070 status);
jjako1db1c812003-07-06 20:53:57 +00003071
Harald Weltebed35df2011-11-02 13:06:18 +01003072 continue;
3073 }
3074
3075 if ((gsn->mode == GTP_MODE_GGSN) &&
3076 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003077 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003078 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003079 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003080 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003081 "Unexpected GTPv1 Signalling Message '%s'\n",
3082 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003083 continue; /* Silently discard 29.60: 11.1.4 */
3084 }
3085
3086 if ((gsn->mode == GTP_MODE_SGSN) &&
3087 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003088 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003089 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003090 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003091 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003092 "Unexpected GTPv1 Signalling Message '%s'\n",
3093 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003094 continue; /* Silently discard 29.60: 11.1.4 */
3095 }
3096
3097 switch (pheader->type) {
3098 case GTP_ECHO_REQ:
3099 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3100 break;
3101 case GTP_ECHO_RSP:
3102 gtp_echo_conf(gsn, version, &peer, buffer, status);
3103 break;
3104 case GTP_NOT_SUPPORTED:
3105 gtp_unsup_ind(gsn, &peer, buffer, status);
3106 break;
3107 case GTP_SUPP_EXT_HEADER:
3108 gtp_extheader_ind(gsn, &peer, buffer, status);
3109 break;
3110 case GTP_CREATE_PDP_REQ:
3111 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3112 status);
3113 break;
3114 case GTP_CREATE_PDP_RSP:
3115 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3116 status);
3117 break;
3118 case GTP_UPDATE_PDP_REQ:
3119 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3120 status);
3121 break;
3122 case GTP_UPDATE_PDP_RSP:
3123 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3124 status);
3125 break;
3126 case GTP_DELETE_PDP_REQ:
3127 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3128 status);
3129 break;
3130 case GTP_DELETE_PDP_RSP:
3131 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3132 status);
3133 break;
3134 case GTP_ERROR:
3135 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3136 break;
3137 default:
3138 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003139 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3140 "Unknown GTP message type received: %u\n",
3141 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003142 break;
3143 }
3144 }
jjako52c24142002-12-16 13:33:51 +00003145}
3146
jjako08d331d2003-10-13 20:33:30 +00003147int gtp_decaps1u(struct gsn_t *gsn)
3148{
Harald Weltebed35df2011-11-02 13:06:18 +01003149 unsigned char buffer[PACKET_MAX];
3150 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003151 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003152 int status;
3153 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003154 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003155 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003156
Harald Weltebed35df2011-11-02 13:06:18 +01003157 /* TODO: Need strategy of userspace buffering and blocking */
3158 /* Currently read is non-blocking and send is blocking. */
3159 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003160
Harald Weltebed35df2011-11-02 13:06:18 +01003161 while (1) { /* Loop until no more to read */
3162 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003163 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003164 return -1;
3165 }
3166 peerlen = sizeof(peer);
3167 if ((status =
3168 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3169 (struct sockaddr *)&peer, &peerlen)) < 0) {
3170 if (errno == EAGAIN)
3171 return 0;
3172 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003173 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003174 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003175 gsn->fd1u, (unsigned long)buffer,
3176 sizeof(buffer), status,
3177 status ? strerror(errno) : "No error");
3178 return -1;
3179 }
jjako08d331d2003-10-13 20:33:30 +00003180
Harald Weltebed35df2011-11-02 13:06:18 +01003181 /* Need at least 1 byte in order to check version */
3182 if (status < (1)) {
3183 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003184 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3185 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003186 continue;
3187 }
jjako08d331d2003-10-13 20:33:30 +00003188
Harald Weltebed35df2011-11-02 13:06:18 +01003189 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003190
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003191 version = GTPHDR_F_GET_VER(pheader->flags);
3192
Harald Weltebed35df2011-11-02 13:06:18 +01003193 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003194 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003195 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003196 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3197 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003198 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3199 continue;
3200 }
jjako08d331d2003-10-13 20:33:30 +00003201
Harald Weltebed35df2011-11-02 13:06:18 +01003202 /* Version must be at least GTP 1 */
3203 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3204 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3205 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003206 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003207 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003208 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3209 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003210 continue;
3211 }
jjako2c381332003-10-21 19:09:53 +00003212
Harald Weltebed35df2011-11-02 13:06:18 +01003213 /* Check packet flag field (allow both with and without sequence number) */
3214 if (((pheader->flags & 0xf5) != 0x30)) {
3215 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003216 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003217 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003218 continue;
3219 }
jjako2c381332003-10-21 19:09:53 +00003220
Harald Weltebed35df2011-11-02 13:06:18 +01003221 /* Check length of packet */
3222 if (status < GTP1_HEADER_SIZE_SHORT) {
3223 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003224 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3225 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003226 continue; /* Silently discard 29.60: 11.1.2 */
3227 }
3228
3229 /* Check packet length field versus length of packet */
3230 if (status !=
3231 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3232 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003233 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003234 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003235 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003236 continue; /* Silently discard */
3237 }
3238
3239 /* Check for extension headers */
3240 /* TODO: We really should cycle through the headers and determine */
3241 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003242 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003243 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003244 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3245 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003246 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3247 status);
3248
3249 continue;
3250 }
3251
3252 switch (pheader->type) {
3253 case GTP_ECHO_REQ:
3254 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3255 break;
3256 case GTP_ECHO_RSP:
3257 gtp_echo_conf(gsn, version, &peer, buffer, status);
3258 break;
3259 case GTP_SUPP_EXT_HEADER:
3260 gtp_extheader_ind(gsn, &peer, buffer, status);
3261 break;
3262 case GTP_ERROR:
3263 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3264 break;
3265 /* Supported header extensions */
3266 case GTP_GPDU:
3267 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3268 break;
3269 default:
3270 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003271 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3272 "Unknown GTP message type received: %u\n",
3273 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003274 break;
3275 }
3276 }
jjako08d331d2003-10-13 20:33:30 +00003277}
3278
Harald Weltebed35df2011-11-02 13:06:18 +01003279int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003280{
Harald Weltebed35df2011-11-02 13:06:18 +01003281 union gtp_packet packet;
3282 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003283 struct msghdr msgh;
3284 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003285 int fd;
jjako52c24142002-12-16 13:33:51 +00003286
Harald Welte471e3492017-09-24 16:12:39 +08003287 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003288 memset(&addr, 0, sizeof(addr));
3289 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003290#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003291 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003292#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003293 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003294
Harald Welte471e3492017-09-24 16:12:39 +08003295 /* prepare msghdr */
3296 memset(&msgh, 0, sizeof(msgh));
3297 msgh.msg_name = &addr;
3298 msgh.msg_namelen = sizeof(addr);
3299 msgh.msg_iov = iov;
3300 msgh.msg_iovlen = ARRAY_SIZE(iov);
3301
3302 /* prepare iovectors */
3303 iov[0].iov_base = &packet;
3304 /* iov[0].iov_len is not known here yet */
3305 iov[1].iov_base = pack;
3306 iov[1].iov_len = len;
3307
Harald Weltebed35df2011-11-02 13:06:18 +01003308 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003309
Harald Welte471e3492017-09-24 16:12:39 +08003310 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003311 addr.sin_port = htons(GTP0_PORT);
3312 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003313
Harald Weltebed35df2011-11-02 13:06:18 +01003314 get_default_gtp(0, GTP_GPDU, &packet);
3315 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003316 if (pdp->tx_gpdu_seq)
3317 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3318 else
3319 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003320 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003321 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003322 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003323
Harald Weltebed35df2011-11-02 13:06:18 +01003324 addr.sin_port = htons(GTP1U_PORT);
3325 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003326
Harald Weltebed35df2011-11-02 13:06:18 +01003327 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003328 if (pdp->tx_gpdu_seq) {
3329 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3330 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3331 GTP1_HEADER_SIZE_LONG);
3332 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3333 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3334 } else {
3335 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3336 packet.gtp1s.h.length = hton16(len);
3337 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3338 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3339 }
Harald Weltebed35df2011-11-02 13:06:18 +01003340 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003341 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003342 return EOF;
3343 }
3344
3345 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003346 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003347 return -1;
3348 }
3349
Harald Welte471e3492017-09-24 16:12:39 +08003350 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003351 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003352 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003353 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003354 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3355 strerror(errno));
3356 return EOF;
3357 }
3358 return 0;
jjako52c24142002-12-16 13:33:51 +00003359}
3360
jjako52c24142002-12-16 13:33:51 +00003361/* ***********************************************************
3362 * Conversion functions
3363 *************************************************************/
3364
jjako52c24142002-12-16 13:33:51 +00003365/* ***********************************************************
3366 * IP address conversion functions
3367 * There exist several types of address representations:
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01003368 * - eua: End User Address. (29.060, 7.7.27, message type 128)
jjako52c24142002-12-16 13:33:51 +00003369 * Used for signalling address to mobile station. Supports IPv4
3370 * IPv6 x.25 etc. etc.
3371 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3372 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3373 * - in_addr: IPv4 address struct.
3374 * - sockaddr_in: Socket API representation of IP address and
3375 * port number.
3376 *************************************************************/
3377
Harald Weltebed35df2011-11-02 13:06:18 +01003378int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3379{
Harald Weltecee75462017-09-24 17:45:05 +08003380 eua->v[0] = PDP_EUA_ORG_IETF;
3381 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003382 if (src) {
3383 eua->l = 6;
3384 memcpy(&eua->v[2], src, 4);
3385 } else {
3386 eua->l = 2;
3387 }
3388 return 0;
jjako52c24142002-12-16 13:33:51 +00003389}
3390
Harald Weltebed35df2011-11-02 13:06:18 +01003391int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3392{
Harald Weltecee75462017-09-24 17:45:05 +08003393 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 +01003394 return -1; /* Not IPv4 address */
3395 memcpy(dst, &eua->v[2], 4);
3396 return 0;
jjako52c24142002-12-16 13:33:51 +00003397}
3398
Harald Weltebed35df2011-11-02 13:06:18 +01003399int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3400{
3401 memset(dst, 0, sizeof(struct in_addr));
3402 if (gsna->l != 4)
3403 return EOF; /* Return if not IPv4 */
3404 memcpy(dst, gsna->v, gsna->l);
3405 return 0;
jjako52c24142002-12-16 13:33:51 +00003406}
3407
Harald Weltebed35df2011-11-02 13:06:18 +01003408int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3409{
3410 memset(gsna, 0, sizeof(struct ul16_t));
3411 gsna->l = 4;
3412 memcpy(gsna->v, src, gsna->l);
3413 return 0;
jjako52c24142002-12-16 13:33:51 +00003414}
Harald Welteb10ee082017-08-12 19:29:16 +02003415
3416/* TS 29.060 has yet again a different encoding for IMSIs than
3417 * what we have in other places, so we cannot use the gsm48
3418 * decoding functions. Also, libgtp uses an uint64_t in
3419 * _network byte order_ to contain BCD digits ?!? */
3420const char *imsi_gtp2str(const uint64_t *imsi)
3421{
Harald Weltea06120d2017-11-06 03:12:54 +09003422 static char buf[sizeof(*imsi)*2+1];
Harald Welteb10ee082017-08-12 19:29:16 +02003423 const uint8_t *imsi8 = (const uint8_t *) imsi;
3424 unsigned int i, j = 0;
3425
3426 for (i = 0; i < sizeof(*imsi); i++) {
3427 uint8_t nibble;
3428
3429 nibble = imsi8[i] & 0xf;
3430 if (nibble == 0xf)
3431 break;
3432 buf[j++] = osmo_bcd2char(nibble);
3433
3434 nibble = imsi8[i] >> 4;
3435 if (nibble == 0xf)
3436 break;
3437 buf[j++] = osmo_bcd2char(nibble);
3438 }
3439
3440 buf[j++] = '\0';
3441 return buf;
3442}