blob: 84b88445d52224a78227a839ced6cb8092675be7 [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]) {
159 if (pdp_getgtp1
160 (&secondary_pdp,
161 pdp->secondary_tei[n])) {
162 LOGP(DLGTP, LOGL_ERROR,
163 "Unknown secondary PDP context\n");
164 continue;
165 }
166 if (pdp != secondary_pdp) {
167 gtp_freepdp(gsn, secondary_pdp);
168 }
169 }
170 }
171
172 return gtp_freepdp(gsn, pdp);
173}
174
jjako52c24142002-12-16 13:33:51 +0000175/* gtp_gpdu */
176
Harald Weltebed35df2011-11-02 13:06:18 +0100177extern int gtp_fd(struct gsn_t *gsn)
178{
179 return gsn->fd0;
jjako52c24142002-12-16 13:33:51 +0000180}
181
182/* gtp_decaps */
183/* gtp_retrans */
184/* gtp_retranstimeout */
185
jjako08d331d2003-10-13 20:33:30 +0000186int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100187 int (*cb) (struct sockaddr_in * peer))
188{
189 gsn->cb_unsup_ind = cb;
190 return 0;
jjako08d331d2003-10-13 20:33:30 +0000191}
192
jjako2c381332003-10-21 19:09:53 +0000193int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100194 int (*cb) (struct sockaddr_in * peer))
195{
196 gsn->cb_extheader_ind = cb;
197 return 0;
jjako2c381332003-10-21 19:09:53 +0000198}
199
jjako08d331d2003-10-13 20:33:30 +0000200/* API: Initialise delete context callback */
201/* Called whenever a pdp context is deleted for any reason */
Harald Weltebed35df2011-11-02 13:06:18 +0100202int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
jjako52c24142002-12-16 13:33:51 +0000203{
Harald Weltebed35df2011-11-02 13:06:18 +0100204 gsn->cb_delete_context = cb;
205 return 0;
jjako52c24142002-12-16 13:33:51 +0000206}
207
jjako52c24142002-12-16 13:33:51 +0000208int gtp_set_cb_conf(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100209 int (*cb) (int type, int cause,
210 struct pdp_t * pdp, void *cbp))
211{
212 gsn->cb_conf = cb;
213 return 0;
jjako52c24142002-12-16 13:33:51 +0000214}
215
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200216static void emit_cb_recovery(struct gsn_t *gsn, struct sockaddr_in * peer,
217 struct pdp_t * pdp, uint8_t recovery)
218{
219 if (gsn->cb_recovery)
220 gsn->cb_recovery(peer, recovery);
221 if (gsn->cb_recovery2)
222 gsn->cb_recovery2(peer, pdp, recovery);
223}
224
Harald Welte629e9862010-12-24 20:58:09 +0100225int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100226 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
227{
228 gsn->cb_recovery = cb;
229 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100230}
231
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200232/* cb_recovery()
233 * pdp may be NULL if Recovery IE was received from a message independent
234 * of any PDP ctx (such as Echo Response), or because pdp ctx is unknown to the
235 * local setup. In case pdp is known, caller may want to keep that pdp alive to
236 * handle subsequent msg cb as this specific pdp ctx is still valid according to
237 * specs.
238 */
239int gtp_set_cb_recovery2(struct gsn_t *gsn,
240 int (*cb_recovery2) (struct sockaddr_in * peer, struct pdp_t * pdp, uint8_t recovery))
241{
242 gsn->cb_recovery2 = cb_recovery2;
243 return 0;
244}
245
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +0100246int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100247 int (*cb_data_ind) (struct pdp_t * pdp,
248 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000249{
Harald Weltebed35df2011-11-02 13:06:18 +0100250 gsn->cb_data_ind = cb_data_ind;
251 return 0;
jjako52c24142002-12-16 13:33:51 +0000252}
253
jjako08d331d2003-10-13 20:33:30 +0000254/**
255 * get_default_gtp()
256 * Generate a GPRS Tunneling Protocol signalling packet header, depending
257 * on GTP version and message type. pdp is used for teid/flow label.
258 * *packet must be allocated by the calling function, and be large enough
259 * to hold the packet header.
260 * returns the length of the header. 0 on error.
261 **/
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100262static unsigned int get_default_gtp(uint8_t version, uint8_t type, void *packet)
Harald Weltebed35df2011-11-02 13:06:18 +0100263{
264 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
265 struct gtp1_header_long *gtp1_default =
266 (struct gtp1_header_long *)packet;
267 switch (version) {
268 case 0:
269 /* Initialise "standard" GTP0 header */
270 memset(gtp0_default, 0, sizeof(struct gtp0_header));
271 gtp0_default->flags = 0x1e;
272 gtp0_default->type = hton8(type);
273 gtp0_default->spare1 = 0xff;
274 gtp0_default->spare2 = 0xff;
275 gtp0_default->spare3 = 0xff;
276 gtp0_default->number = 0xff;
277 return GTP0_HEADER_SIZE;
278 case 1:
279 /* Initialise "standard" GTP1 header */
280 /* 29.060: 8.2: S=1 and PN=0 */
281 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
282 /* and Supported Extension Headers Notification, the S field shall be */
283 /* set to 1 */
284 /* Currently extension headers are not supported */
285 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
Harald Weltefed598f2017-09-24 16:39:22 +0800286 /* No extension, enable sequence, no N-PDU */
287 gtp1_default->flags = GTPHDR_F_VER(1) | GTP1HDR_F_GTP1 | GTP1HDR_F_SEQ;
Harald Weltebed35df2011-11-02 13:06:18 +0100288 gtp1_default->type = hton8(type);
289 return GTP1_HEADER_SIZE_LONG;
290 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100291 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100292 "Unknown GTP packet version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +0100293 return 0;
294 }
jjako52c24142002-12-16 13:33:51 +0000295}
296
jjako08d331d2003-10-13 20:33:30 +0000297/**
298 * get_seq()
299 * Get sequence number of a packet.
300 * Returns 0 on error
301 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100302static uint16_t get_seq(void *pack)
303{
304 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800305 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000306
Harald Weltefed598f2017-09-24 16:39:22 +0800307 if (ver == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +0100308 return ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800309 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100310 return ntoh16(packet->gtp1l.h.seq);
311 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100312 return 0;
313 }
jjako08d331d2003-10-13 20:33:30 +0000314}
315
316/**
317 * get_tid()
318 * Get tunnel identifier of a packet.
319 * Returns 0 on error
320 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100321static uint64_t get_tid(void *pack)
322{
323 union gtp_packet *packet = (union gtp_packet *)pack;
324
Harald Weltefed598f2017-09-24 16:39:22 +0800325 if (GTPHDR_F_GET_VER(packet->flags) == 0) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100326 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100327 }
328 return 0;
jjako08d331d2003-10-13 20:33:30 +0000329}
330
331/**
332 * get_hlen()
333 * Get the header length of a packet.
334 * Returns 0 on error
335 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100336static uint16_t get_hlen(void *pack)
337{
338 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800339 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000340
Harald Weltefed598f2017-09-24 16:39:22 +0800341 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100342 return GTP0_HEADER_SIZE;
Harald Weltefed598f2017-09-24 16:39:22 +0800343 } else if (ver == 1 && (packet->flags & 0x07) == 0) { /* Short version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100344 return GTP1_HEADER_SIZE_SHORT;
Harald Weltefed598f2017-09-24 16:39:22 +0800345 } else if (ver == 1) { /* Version 1 with seq/n-pdu/ext */
346 return GTP1_HEADER_SIZE_LONG;
Harald Weltebed35df2011-11-02 13:06:18 +0100347 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100348 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100349 return 0;
350 }
jjako08d331d2003-10-13 20:33:30 +0000351}
352
353/**
354 * get_tei()
355 * Get the tunnel endpoint identifier (flow label) of a packet.
356 * Returns 0xffffffff on error.
357 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100358static uint32_t get_tei(void *pack)
359{
360 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800361 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000362
Harald Weltefed598f2017-09-24 16:39:22 +0800363 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100364 return ntoh16(packet->gtp0.h.flow);
Harald Weltefed598f2017-09-24 16:39:22 +0800365 } else if (ver == 1) { /* Version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100366 return ntoh32(packet->gtp1l.h.tei);
367 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100368 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100369 return 0xffffffff;
370 }
jjako08d331d2003-10-13 20:33:30 +0000371}
jjakoa7cd2492003-04-11 09:40:12 +0000372
jjako52c24142002-12-16 13:33:51 +0000373/* ***********************************************************
374 * Reliable delivery of signalling messages
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100375 *
jjako52c24142002-12-16 13:33:51 +0000376 * Sequence numbers are used for both signalling messages and
377 * data messages.
378 *
379 * For data messages each tunnel maintains a sequence counter,
380 * which is incremented by one each time a new data message
381 * is sent. The sequence number starts at (0) zero at tunnel
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100382 * establishment, and wraps around at 65535 (29.060 9.3.1.1
jjako52c24142002-12-16 13:33:51 +0000383 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
384 * or can be used to check the validity of the message in the
385 * receiver, or for reordering af packets.
386 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100387 * For signalling messages the sequence number is used by
jjako52c24142002-12-16 13:33:51 +0000388 * signalling messages for which a response is defined. A response
389 * message should copy the sequence from the corresponding request
390 * message. The sequence number "unambiguously" identifies a request
391 * message within a given path, with a path being defined as a set of
392 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
393 * messages shall be responded to, and all response messages associated
394 * with a certain request shall always include the same information"
395 *
396 * We take this to mean that the GSN transmitting a request is free to
397 * choose the sequence number, as long as it is unique within a given path.
398 * It means that we are allowed to count backwards, or roll over at 17
399 * if we prefer that. It also means that we can use the same counter for
400 * all paths. This has the advantage that the transmitted request sequence
401 * numbers are unique within each GSN, and also we dont have to mess around
402 * with path setup and teardown.
403 *
404 * If a response message is lost, the request will be retransmitted, and
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100405 * the receiving GSN will receive a "duplicated" request. The standard
jjako52c24142002-12-16 13:33:51 +0000406 * requires the receiving GSN to send a response, with the same information
407 * as in the original response. For most messages this happens automatically:
408 *
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200409 * Echo: Automatically duplicates the original response
jjako52c24142002-12-16 13:33:51 +0000410 * Create pdp context: The SGSN may send create context request even if
411 * a context allready exist (imsi+nsapi?). This means that the reply will
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200412 automatically duplicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000413 * side effects in the application which is asked twice to validate
414 * the login.
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200415 * Update pdp context: Automatically duplicates the original response???
jjako52c24142002-12-16 13:33:51 +0000416 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
417 * a nonexist reply message.
418 *
419 * The correct solution will be to make a queue containing response messages.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100420 * This queue should be checked whenever a request is received. If the
jjako52c24142002-12-16 13:33:51 +0000421 * response is allready in the queue that response should be transmitted.
422 * It should be possible to find messages in this queue on the basis of
423 * the sequence number and peer GSN IP address (The sequense number is unique
424 * within each path). This need to be implemented by a hash table. Furthermore
425 * it should be possibly to delete messages based on a timeout. This can be
426 * achieved by means of a linked list. The timeout value need to be larger
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100427 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
jjako52c24142002-12-16 13:33:51 +0000428 * set in the peer GSN, so there is no way to know these parameters. On the
429 * other hand the timeout value need to be so small that we do not receive
430 * wraparound sequence numbere before the message is deleted. 60 seconds is
431 * probably not a bad choise.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100432 *
jjako52c24142002-12-16 13:33:51 +0000433 * This queue however is first really needed from gtp1.
434 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100435 * gtp_req:
jjako52c24142002-12-16 13:33:51 +0000436 * Send off a signalling message with appropiate sequence
437 * number. Store packet in queue.
438 * gtp_conf:
439 * Remove an incoming confirmation from the queue
440 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000441 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000442 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000443 * gtp_notification:
444 * Send off a notification message. This is neither a request nor
445 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000446 * gtp_retrans:
447 * Retransmit any outstanding packets which have exceeded
448 * a predefined timeout.
449 *************************************************************/
450
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100451static int gtp_req(struct gsn_t *gsn, uint8_t version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100452 union gtp_packet *packet, int len,
453 struct in_addr *inetaddr, void *cbp)
454{
Harald Weltefed598f2017-09-24 16:39:22 +0800455 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100456 struct sockaddr_in addr;
457 struct qmsg_t *qmsg;
458 int fd;
jjako08d331d2003-10-13 20:33:30 +0000459
Harald Weltebed35df2011-11-02 13:06:18 +0100460 memset(&addr, 0, sizeof(addr));
461 addr.sin_family = AF_INET;
462 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000463#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100464 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000465#endif
jjako52c24142002-12-16 13:33:51 +0000466
Harald Weltefed598f2017-09-24 16:39:22 +0800467 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100468 addr.sin_port = htons(GTP0_PORT);
469 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
470 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100471 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100472 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100473 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100474 }
Harald Weltebed35df2011-11-02 13:06:18 +0100475 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
476 || (packet->gtp0.h.type == GTP_ERROR)))
477 packet->gtp0.h.flow = hton16(pdp->flru);
478 else if (pdp)
479 packet->gtp0.h.flow = hton16(pdp->flrc);
480 fd = gsn->fd0;
Harald Weltefed598f2017-09-24 16:39:22 +0800481 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100482 addr.sin_port = htons(GTP1C_PORT);
483 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
484 packet->gtp1l.h.seq = hton16(gsn->seq_next);
485 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
486 (packet->gtp1l.h.type == GTP_ERROR)))
487 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
488 else if (pdp)
489 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
490 fd = gsn->fd1c;
491 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100492 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100493 return -1;
494 }
jjako52c24142002-12-16 13:33:51 +0000495
Harald Weltebed35df2011-11-02 13:06:18 +0100496 if (sendto(fd, packet, len, 0,
497 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
498 gsn->err_sendto++;
Max14b1b632017-08-21 20:14:59 +0200499 LOGP(DLGTP, LOGL_ERROR, "Sendto(fd=%d, msg=%lx, len=%d, dst=%s) failed: Error = %s\n", fd,
500 (unsigned long)&packet, len, inet_ntoa(addr.sin_addr), strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100501 return -1;
502 }
503
504 /* Use new queue structure */
505 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
506 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100507 LOGP(DLGTP, LOGL_ERROR,
508 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100509 } else {
510 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
511 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100512 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100513 qmsg->retrans = 0; /* No retransmissions so far */
514 qmsg->cbp = cbp;
515 qmsg->type = ntoh8(packet->gtp0.h.type);
516 qmsg->fd = fd;
517 }
518 gsn->seq_next++; /* Count up this time */
519 return 0;
jjako52c24142002-12-16 13:33:51 +0000520}
521
Alexander Couzense1412d92018-09-16 05:10:03 +0200522
523/**
524 * @brief clear the request and response queue. Useful for debugging to reset "some" state.
525 * @param gsn The GGSN instance
526 */
527void gtp_clear_queues(struct gsn_t *gsn)
528{
529 struct qmsg_t *qmsg;
530
531 while (!queue_getfirst(gsn->queue_req, &qmsg)) {
532 queue_freemsg(gsn->queue_req, qmsg);
533 }
534
535 while (!queue_getfirst(gsn->queue_resp, &qmsg)) {
536 queue_freemsg(gsn->queue_resp, qmsg);
537 }
538}
539
jjako52c24142002-12-16 13:33:51 +0000540/* gtp_conf
541 * Remove signalling packet from retransmission queue.
542 * return 0 on success, EOF if packet was not found */
543
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100544static int gtp_conf(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100545 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
546{
Harald Weltefed598f2017-09-24 16:39:22 +0800547 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100548 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000549
Harald Weltefed598f2017-09-24 16:39:22 +0800550 if (ver == 0)
Harald Weltebed35df2011-11-02 13:06:18 +0100551 seq = ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800552 else if (ver == 1 && (packet->gtp1l.h.flags & GTP1HDR_F_SEQ))
Harald Weltebed35df2011-11-02 13:06:18 +0100553 seq = ntoh16(packet->gtp1l.h.seq);
554 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100555 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
556 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100557 return EOF;
558 }
jjako08d331d2003-10-13 20:33:30 +0000559
Harald Weltebed35df2011-11-02 13:06:18 +0100560 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
561 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100562 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
563 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100564 return EOF;
565 }
jjako52c24142002-12-16 13:33:51 +0000566
Harald Weltebed35df2011-11-02 13:06:18 +0100567 return 0;
jjako52c24142002-12-16 13:33:51 +0000568}
569
Harald Weltebed35df2011-11-02 13:06:18 +0100570int gtp_retrans(struct gsn_t *gsn)
571{
572 /* Retransmit any outstanding packets */
573 /* Remove from queue if maxretrans exceeded */
574 time_t now;
575 struct qmsg_t *qmsg;
576 now = time(NULL);
577 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000578
Harald Welte95848ba2011-11-02 18:17:50 +0100579 /* get first element in queue, as long as the timeout of that
580 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100581 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
582 (qmsg->timeout <= now)) {
583 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100584 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100585 if (gsn->cb_conf)
586 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
587 queue_freemsg(gsn->queue_req, qmsg);
588 } else {
589 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
590 (struct sockaddr *)&qmsg->peer,
591 sizeof(struct sockaddr_in)) < 0) {
592 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100593 LOGP(DLGTP, LOGL_ERROR,
594 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100595 gsn->fd0, (unsigned long)&qmsg->p,
596 qmsg->l, strerror(errno));
597 }
598 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100599 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100600 qmsg->retrans++;
601 }
602 }
jjako52c24142002-12-16 13:33:51 +0000603
Harald Weltebed35df2011-11-02 13:06:18 +0100604 /* Also clean up reply timeouts */
605 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
606 (qmsg->timeout < now)) {
607 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
608 queue_freemsg(gsn->queue_resp, qmsg);
609 }
jjako52c24142002-12-16 13:33:51 +0000610
Harald Weltebed35df2011-11-02 13:06:18 +0100611 return 0;
jjako52c24142002-12-16 13:33:51 +0000612}
613
Harald Weltebed35df2011-11-02 13:06:18 +0100614int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
615{
Pau Espin Pedrolceac0782019-05-27 17:39:45 +0200616 time_t now, later, diff;
Harald Weltebed35df2011-11-02 13:06:18 +0100617 struct qmsg_t *qmsg;
Pau Espin Pedrolceac0782019-05-27 17:39:45 +0200618 timeout->tv_usec = 0;
jjako52c24142002-12-16 13:33:51 +0000619
Harald Weltebed35df2011-11-02 13:06:18 +0100620 if (queue_getfirst(gsn->queue_req, &qmsg)) {
621 timeout->tv_sec = 10;
Harald Weltebed35df2011-11-02 13:06:18 +0100622 } else {
623 now = time(NULL);
624 later = qmsg->timeout;
625 timeout->tv_sec = later - now;
Harald Weltebed35df2011-11-02 13:06:18 +0100626 if (timeout->tv_sec < 0)
627 timeout->tv_sec = 0; /* No negative allowed */
628 if (timeout->tv_sec > 10)
629 timeout->tv_sec = 10; /* Max sleep for 10 sec */
630 }
Pau Espin Pedrolceac0782019-05-27 17:39:45 +0200631
632 if (queue_getfirst(gsn->queue_resp, &qmsg)) {
633 /* already set by queue_req, do nothing */
634 } else { /* trigger faster if earlier timeout exists in queue_resp */
635 now = time(NULL);
636 later = qmsg->timeout;
637 diff = later - now;
638 if (diff < 0)
639 diff = 0;
640 if (diff < timeout->tv_sec)
641 timeout->tv_sec = diff;
642 }
643
Harald Weltebed35df2011-11-02 13:06:18 +0100644 return 0;
jjako52c24142002-12-16 13:33:51 +0000645}
646
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100647static int gtp_resp(uint8_t version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000648 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100649 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
650{
Harald Weltefed598f2017-09-24 16:39:22 +0800651 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100652 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000653
Harald Weltefed598f2017-09-24 16:39:22 +0800654 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100655 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
656 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100657 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100658 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
659 (packet->gtp0.h.type == GTP_ERROR)))
660 packet->gtp0.h.flow = hton16(pdp->flru);
661 else if (pdp)
662 packet->gtp0.h.flow = hton16(pdp->flrc);
Harald Weltefed598f2017-09-24 16:39:22 +0800663 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100664 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
665 packet->gtp1l.h.seq = hton16(seq);
666 if (pdp && (fd == gsn->fd1u))
667 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
668 else if (pdp)
669 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
670 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100671 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100672 return -1;
673 }
jjako08d331d2003-10-13 20:33:30 +0000674
Harald Weltebed35df2011-11-02 13:06:18 +0100675 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100676 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100677 return -1;
678 }
jjako52c24142002-12-16 13:33:51 +0000679
Harald Weltebed35df2011-11-02 13:06:18 +0100680 if (sendto(fd, packet, len, 0,
681 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
682 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100683 LOGP(DLGTP, LOGL_ERROR,
684 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100685 (unsigned long)&packet, len, strerror(errno));
686 return -1;
687 }
688
689 /* Use new queue structure */
690 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
691 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100692 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100693 } else {
694 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
695 qmsg->l = len;
696 qmsg->timeout = time(NULL) + 60; /* When to timeout */
697 qmsg->retrans = 0; /* No retransmissions so far */
698 qmsg->cbp = NULL;
699 qmsg->type = 0;
700 qmsg->fd = fd;
701 }
702 return 0;
jjako52c24142002-12-16 13:33:51 +0000703}
704
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100705static int gtp_notification(struct gsn_t *gsn, uint8_t version,
jjako2c381332003-10-21 19:09:53 +0000706 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100707 struct sockaddr_in *peer, int fd, uint16_t seq)
708{
jjako2c381332003-10-21 19:09:53 +0000709
Harald Weltefed598f2017-09-24 16:39:22 +0800710 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100711 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000712
Harald Weltebed35df2011-11-02 13:06:18 +0100713 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000714
Harald Weltebed35df2011-11-02 13:06:18 +0100715 /* In GTP0 notifications are treated as replies. In GTP1 they
716 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000717
Harald Weltebed35df2011-11-02 13:06:18 +0100718 if (fd == gsn->fd1c)
719 addr.sin_port = htons(GTP1C_PORT);
720 else if (fd == gsn->fd1u)
721 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000722
Harald Weltefed598f2017-09-24 16:39:22 +0800723 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100724 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
725 packet->gtp0.h.seq = hton16(seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800726 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100727 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
728 packet->gtp1l.h.seq = hton16(seq);
729 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100730 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100731 return -1;
732 }
733
734 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100735 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100736 return -1;
737 }
738
739 if (sendto(fd, packet, len, 0,
740 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
741 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100742 LOGP(DLGTP, LOGL_ERROR,
743 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100744 (unsigned long)&packet, len, strerror(errno));
745 return -1;
746 }
747 return 0;
jjako2c381332003-10-21 19:09:53 +0000748}
749
Pau Espin Pedrolde72d262019-05-29 18:17:05 +0200750static int gtp_duplicate(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +0100751 struct sockaddr_in *peer, uint16_t seq)
752{
753 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000754
Harald Weltebed35df2011-11-02 13:06:18 +0100755 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
756 return EOF; /* Notfound */
757 }
jjakoa7cd2492003-04-11 09:40:12 +0000758
Harald Weltebed35df2011-11-02 13:06:18 +0100759 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100760 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100761 return -1;
762 }
763
764 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
765 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
766 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100767 LOGP(DLGTP, LOGL_ERROR,
768 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100769 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
770 strerror(errno));
771 }
772 return 0;
jjako52c24142002-12-16 13:33:51 +0000773}
774
jjako52c24142002-12-16 13:33:51 +0000775/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100776static void log_restart(struct gsn_t *gsn)
777{
jjako52c24142002-12-16 13:33:51 +0000778 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200779 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000780 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200781 char *filename;
jjako52c24142002-12-16 13:33:51 +0000782
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200783 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
784 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000785
786 /* We try to open file. On failure we will later try to create file */
787 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100788 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100789 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100790 filename);
791 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100792 rc = fscanf(f, "%d", &counter);
793 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100794 LOGP(DLGTP, LOGL_ERROR,
795 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100796 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100797 }
798 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100799 LOGP(DLGTP, LOGL_ERROR,
800 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100801 }
jjako52c24142002-12-16 13:33:51 +0000802 }
Harald Weltebed35df2011-11-02 13:06:18 +0100803
804 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000805 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100806
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200807 /* Keep the umask closely wrapped around our fopen() call in case the
808 * log outputs cause file creation. */
809 i = umask(022);
810 f = fopen(filename, "w");
811 umask(i);
812 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100813 LOGP(DLGTP, LOGL_ERROR,
814 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100815 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200816 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000817 }
818
jjako52c24142002-12-16 13:33:51 +0000819 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100820close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200821 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100822 LOGP(DLGTP, LOGL_ERROR,
823 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200824free_filename:
825 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000826}
827
jjako1db1c812003-07-06 20:53:57 +0000828int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100829 int mode)
jjako52c24142002-12-16 13:33:51 +0000830{
Harald Weltebed35df2011-11-02 13:06:18 +0100831 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000832
Max14b1b632017-08-21 20:14:59 +0200833 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
jjako52c24142002-12-16 13:33:51 +0000834
Harald Weltebed35df2011-11-02 13:06:18 +0100835 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000836
Harald Weltebed35df2011-11-02 13:06:18 +0100837 (*gsn)->statedir = statedir;
838 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000839
Harald Weltebed35df2011-11-02 13:06:18 +0100840 /* Initialise sequence number */
841 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000842
Harald Weltebed35df2011-11-02 13:06:18 +0100843 /* Initialise request retransmit queue */
844 queue_new(&(*gsn)->queue_req);
845 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000846
Harald Weltebed35df2011-11-02 13:06:18 +0100847 /* Initialise pdp table */
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +0200848 pdp_init(*gsn);
jjako08d331d2003-10-13 20:33:30 +0000849
Harald Weltebed35df2011-11-02 13:06:18 +0100850 /* Initialise call back functions */
851 (*gsn)->cb_create_context_ind = 0;
852 (*gsn)->cb_delete_context = 0;
853 (*gsn)->cb_unsup_ind = 0;
854 (*gsn)->cb_conf = 0;
855 (*gsn)->cb_data_ind = 0;
856
857 /* Store function parameters */
858 (*gsn)->gsnc = *listen;
859 (*gsn)->gsnu = *listen;
860 (*gsn)->mode = mode;
861
862 /* Create GTP version 0 socket */
863 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
864 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100865 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200866 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100867 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200868 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100869 }
870
871 memset(&addr, 0, sizeof(addr));
872 addr.sin_family = AF_INET;
873 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
874 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000875#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100876 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000877#endif
jjako08d331d2003-10-13 20:33:30 +0000878
Harald Weltebed35df2011-11-02 13:06:18 +0100879 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
880 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200881 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
882 "bind(fd0=%d) failed: Error = %s\n",
883 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200884 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100885 }
jjako08d331d2003-10-13 20:33:30 +0000886
Harald Weltebed35df2011-11-02 13:06:18 +0100887 /* Create GTP version 1 control plane socket */
888 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
889 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100890 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200891 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100892 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200893 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100894 }
895
896 memset(&addr, 0, sizeof(addr));
897 addr.sin_family = AF_INET;
898 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
899 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000900#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100901 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000902#endif
jjako08d331d2003-10-13 20:33:30 +0000903
Harald Weltebed35df2011-11-02 13:06:18 +0100904 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
905 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200906 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
907 "bind(fd1c=%d) failed: Error = %s\n",
908 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200909 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100910 }
jjako08d331d2003-10-13 20:33:30 +0000911
Harald Weltebed35df2011-11-02 13:06:18 +0100912 /* Create GTP version 1 user plane socket */
913 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
914 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100915 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200916 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100917 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200918 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100919 }
920
921 memset(&addr, 0, sizeof(addr));
922 addr.sin_family = AF_INET;
923 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
924 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000925#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100926 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000927#endif
jjako52c24142002-12-16 13:33:51 +0000928
Harald Weltebed35df2011-11-02 13:06:18 +0100929 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
930 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200931 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +0200932 "bind(fd1u=%d) failed: Error = %s\n",
933 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +0200934 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100935 }
936
937 return 0;
jjako52c24142002-12-16 13:33:51 +0000938}
939
Harald Weltebed35df2011-11-02 13:06:18 +0100940int gtp_free(struct gsn_t *gsn)
941{
jjako52c24142002-12-16 13:33:51 +0000942
Harald Weltebed35df2011-11-02 13:06:18 +0100943 /* Clean up retransmit queues */
944 queue_free(gsn->queue_req);
945 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000946
Harald Weltebed35df2011-11-02 13:06:18 +0100947 close(gsn->fd0);
948 close(gsn->fd1c);
949 close(gsn->fd1u);
950
951 free(gsn);
952 return 0;
jjako52c24142002-12-16 13:33:51 +0000953}
954
955/* ***********************************************************
956 * Path management messages
957 * Messages: echo and version not supported.
958 * A path is connection between two UDP/IP endpoints
959 *
960 * A path is either using GTP0 or GTP1. A path can be
961 * established by any kind of GTP message??
962
963 * Which source port to use?
964 * GTP-C request destination port is 2123/3386
965 * GTP-U request destination port is 2152/3386
966 * T-PDU destination port is 2152/3386.
967 * For the above messages the source port is locally allocated.
968 * For response messages src=rx-dst and dst=rx-src.
969 * For simplicity we should probably use 2123+2152/3386 as
970 * src port even for the cases where src can be locally
971 * allocated. This also means that we have to listen only to
972 * the same ports.
973 * For response messages we need to be able to respond to
974 * the relevant src port even if it is locally allocated by
975 * the peer.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100976 *
jjako52c24142002-12-16 13:33:51 +0000977 * The need for path management!
978 * We might need to keep a list of active paths. This might
979 * be in the form of remote IP address + UDP port numbers.
980 * (We will consider a path astablished if we have a context
981 * with the node in question)
982 *************************************************************/
983
984/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000985int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
986 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000987{
Harald Weltebed35df2011-11-02 13:06:18 +0100988 union gtp_packet packet;
989 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
990 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000991}
992
jjako08d331d2003-10-13 20:33:30 +0000993/* Send off an echo reply */
994int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100995 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000996{
Harald Weltebed35df2011-11-02 13:06:18 +0100997 union gtp_packet packet;
998 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
999 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1000 gsn->restart_counter);
1001 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
1002 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00001003}
1004
jjako52c24142002-12-16 13:33:51 +00001005/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +01001006int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1007 int fd, void *pack, unsigned len)
1008{
jjako52c24142002-12-16 13:33:51 +00001009
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02001010 /* Check if it was a duplicate request */
1011 if (!gtp_duplicate(gsn, 0, peer, get_seq(pack)))
Harald Weltebed35df2011-11-02 13:06:18 +01001012 return 0;
jjako52c24142002-12-16 13:33:51 +00001013
Harald Weltebed35df2011-11-02 13:06:18 +01001014 /* Send off reply to request */
1015 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +00001016}
1017
1018/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +00001019int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001020 void *pack, unsigned len)
1021{
1022 union gtpie_member *ie[GTPIE_SIZE];
1023 unsigned char recovery;
1024 void *cbp = NULL;
1025 uint8_t type = 0;
1026 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001027
Harald Weltebed35df2011-11-02 13:06:18 +01001028 /* Remove packet from queue */
1029 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1030 return EOF;
jjako52c24142002-12-16 13:33:51 +00001031
Harald Weltebed35df2011-11-02 13:06:18 +01001032 /* Extract information elements into a pointer array */
1033 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1034 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001035 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1036 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001037 if (gsn->cb_conf)
1038 gsn->cb_conf(type, EOF, NULL, cbp);
1039 return EOF;
1040 }
jjako52c24142002-12-16 13:33:51 +00001041
Harald Weltebed35df2011-11-02 13:06:18 +01001042 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1043 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001044 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1045 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001046 if (gsn->cb_conf)
1047 gsn->cb_conf(type, EOF, NULL, cbp);
1048 return EOF;
1049 }
jjako52c24142002-12-16 13:33:51 +00001050
Harald Weltebed35df2011-11-02 13:06:18 +01001051 /* Echo reply packages does not have a cause information element */
1052 /* Instead we return the recovery number in the callback function */
1053 if (gsn->cb_conf)
1054 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +01001055
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001056 emit_cb_recovery(gsn, peer, NULL, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001057
1058 return 0;
jjako52c24142002-12-16 13:33:51 +00001059}
1060
1061/* Send off a Version Not Supported message */
1062/* This message is somewhat special in that it actually is a
1063 * response to some other message with unsupported GTP version
1064 * For this reason it has parameters like a response, and does
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001065 * its own message transmission. No signalling queue is used
jjako52c24142002-12-16 13:33:51 +00001066 * The reply is sent to the peer IP and peer UDP. This means that
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001067 * the peer will be receiving a GTP0 message on a GTP1 port!
jjako52c24142002-12-16 13:33:51 +00001068 * In practice however this will never happen as a GTP0 GSN will
1069 * only listen to the GTP0 port, and therefore will never receive
1070 * anything else than GTP0 */
1071
jjako08d331d2003-10-13 20:33:30 +00001072int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1073 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001074{
Harald Weltebed35df2011-11-02 13:06:18 +01001075 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +00001076
Harald Weltebed35df2011-11-02 13:06:18 +01001077 /* GTP 1 is the highest supported protocol */
1078 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
1079 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +00001080}
1081
1082/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +01001083int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1084 void *pack, unsigned len)
1085{
jjako52c24142002-12-16 13:33:51 +00001086
Harald Weltebed35df2011-11-02 13:06:18 +01001087 if (gsn->cb_unsup_ind)
1088 gsn->cb_unsup_ind(peer);
1089
1090 return 0;
jjako52c24142002-12-16 13:33:51 +00001091}
1092
jjako2c381332003-10-21 19:09:53 +00001093/* Send off an Supported Extension Headers Notification */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001094static int gtp_extheader_req(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
jjako2c381332003-10-21 19:09:53 +00001095 int fd, void *pack, unsigned len)
1096{
Harald Weltebed35df2011-11-02 13:06:18 +01001097 union gtp_packet packet;
1098 unsigned int length =
1099 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +00001100
Harald Weltebed35df2011-11-02 13:06:18 +01001101 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +00001102
Harald Weltebed35df2011-11-02 13:06:18 +01001103 if (version < 1)
1104 return 0;
jjako2c381332003-10-21 19:09:53 +00001105
Harald Weltebed35df2011-11-02 13:06:18 +01001106 /* We report back that we support only PDCP PDU headers */
1107 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
1108 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +00001109
Harald Weltebed35df2011-11-02 13:06:18 +01001110 return gtp_notification(gsn, version, &packet, length,
1111 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +00001112}
1113
1114/* Handle a Supported Extension Headers Notification */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001115static int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001116 void *pack, unsigned len)
1117{
jjako2c381332003-10-21 19:09:53 +00001118
Harald Weltebed35df2011-11-02 13:06:18 +01001119 if (gsn->cb_extheader_ind)
1120 gsn->cb_extheader_ind(peer);
1121
1122 return 0;
jjako2c381332003-10-21 19:09:53 +00001123}
1124
jjako52c24142002-12-16 13:33:51 +00001125/* ***********************************************************
1126 * Session management messages
1127 * Messages: create, update and delete PDP context
1128 *
1129 * Information storage
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001130 * Information storage for each PDP context is defined in
jjako52c24142002-12-16 13:33:51 +00001131 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1132 * PDP-address (IP address), sequence numbers, charging ID.
1133 * For the SGSN it also includes radio related mobility
1134 * information.
1135 *************************************************************/
1136
Harald Welte7b3347b2010-05-15 12:18:46 +02001137/* API: Send Create PDP Context Request (7.3.1) */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001138int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001139 void *cbp)
1140{
1141 union gtp_packet packet;
1142 unsigned int length =
1143 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1144 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001145
Harald Weltebed35df2011-11-02 13:06:18 +01001146 /* TODO: Secondary PDP Context Activation Procedure */
1147 /* In secondary activation procedure the PDP context is identified
1148 by tei in the header. The following fields are omitted: Selection
1149 mode, IMSI, MSISDN, End User Address, Access Point Name and
1150 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001151
Harald Weltebed35df2011-11-02 13:06:18 +01001152 if (pdp->secondary) {
1153 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001154 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001155 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001156 return EOF;
1157 }
1158 }
jjako2c381332003-10-21 19:09:53 +00001159
Harald Weltebed35df2011-11-02 13:06:18 +01001160 if (pdp->version == 0) {
1161 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1162 sizeof(pdp->qos_req0), pdp->qos_req0);
1163 }
jjako52c24142002-12-16 13:33:51 +00001164
Harald Weltebed35df2011-11-02 13:06:18 +01001165 /* Section 7.7.2 */
1166 if (pdp->version == 1) {
1167 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1168 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1169 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1170 }
jjako52c24142002-12-16 13:33:51 +00001171
Harald Weltebed35df2011-11-02 13:06:18 +01001172 /* Section 7.7.3 Routing Area Information */
1173 if (pdp->rai_given == 1)
1174 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1175 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001176
Harald Weltebed35df2011-11-02 13:06:18 +01001177 /* Section 7.7.11 */
1178 if (pdp->norecovery_given == 0)
1179 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1180 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001181
Harald Weltebed35df2011-11-02 13:06:18 +01001182 /* Section 7.7.12 */
1183 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1184 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1185 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001186
Harald Weltebed35df2011-11-02 13:06:18 +01001187 if (pdp->version == 0) {
1188 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1189 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1190 }
jjako08d331d2003-10-13 20:33:30 +00001191
Harald Weltebed35df2011-11-02 13:06:18 +01001192 /* Section 7.7.13 */
1193 if (pdp->version == 1) {
1194 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1195 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001196
Harald Weltebed35df2011-11-02 13:06:18 +01001197 /* Section 7.7.14 */
1198 if (!pdp->teic_confirmed)
1199 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1200 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001201
Harald Weltebed35df2011-11-02 13:06:18 +01001202 /* Section 7.7.17 */
1203 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001204
Harald Weltebed35df2011-11-02 13:06:18 +01001205 /* Section 7.7.17 */
1206 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1207 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1208 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001209
Harald Weltebed35df2011-11-02 13:06:18 +01001210 /* Section 7.7.23 */
1211 if (pdp->cch_pdp) /* Only include charging if flags are set */
1212 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1213 pdp->cch_pdp);
1214 }
jjako9b4971d2004-05-27 20:30:19 +00001215
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001216 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001217 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1218 pdp->traceref);
1219 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1220 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001221
Harald Weltebed35df2011-11-02 13:06:18 +01001222 /* Section 7.7.27 */
1223 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1224 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1225 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001226
Harald Weltebed35df2011-11-02 13:06:18 +01001227 /* Section 7.7.30 */
1228 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1229 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1230 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001231
Harald Weltebed35df2011-11-02 13:06:18 +01001232 /* Section 7.7.31 */
1233 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1234 if (pdp->pco_req.l)
1235 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1236 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001237
Harald Weltebed35df2011-11-02 13:06:18 +01001238 /* Section 7.7.32 */
1239 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1240 pdp->gsnlc.l, pdp->gsnlc.v);
1241 /* Section 7.7.32 */
1242 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1243 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001244
Harald Weltebed35df2011-11-02 13:06:18 +01001245 /* Section 7.7.33 */
1246 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1247 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1248 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001249
Harald Weltebed35df2011-11-02 13:06:18 +01001250 /* Section 7.7.34 */
1251 if (pdp->version == 1)
1252 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1253 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001254
Harald Weltebed35df2011-11-02 13:06:18 +01001255 /* Section 7.7.36 */
1256 if ((pdp->version == 1) && pdp->tft.l)
1257 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1258 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001259
Harald Weltebed35df2011-11-02 13:06:18 +01001260 /* Section 7.7.41 */
1261 if ((pdp->version == 1) && pdp->triggerid.l)
1262 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1263 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001264
Harald Weltebed35df2011-11-02 13:06:18 +01001265 /* Section 7.7.42 */
1266 if ((pdp->version == 1) && pdp->omcid.l)
1267 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1268 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001269
Harald Weltebed35df2011-11-02 13:06:18 +01001270 /* new R7 fields */
1271 if (pdp->rattype_given == 1)
1272 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1273 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001274
Harald Weltebed35df2011-11-02 13:06:18 +01001275 if (pdp->userloc_given == 1)
1276 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1277 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001278
Harald Weltebed35df2011-11-02 13:06:18 +01001279 if (pdp->mstz_given == 1)
1280 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1281 pdp->mstz.l, pdp->mstz.v);
1282
1283 if (pdp->imeisv_given == 1)
1284 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1285 pdp->imeisv.l, pdp->imeisv.v);
1286
1287 /* TODO hisaddr0 */
1288 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1289
1290 return 0;
jjako52c24142002-12-16 13:33:51 +00001291}
1292
jjako08d331d2003-10-13 20:33:30 +00001293/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001294int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1295{
jjako08d331d2003-10-13 20:33:30 +00001296
Harald Weltebed35df2011-11-02 13:06:18 +01001297 /* Now send off a reply to the peer */
1298 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1299
1300 if (cause != GTPCAUSE_ACC_REQ) {
1301 pdp_freepdp(pdp);
1302 }
1303
1304 return 0;
jjako08d331d2003-10-13 20:33:30 +00001305}
1306
1307/* API: Register create context indication callback */
1308int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001309 int (*cb_create_context_ind) (struct pdp_t *
1310 pdp))
jjako52c24142002-12-16 13:33:51 +00001311{
Harald Weltebed35df2011-11-02 13:06:18 +01001312 gsn->cb_create_context_ind = cb_create_context_ind;
1313 return 0;
jjako08d331d2003-10-13 20:33:30 +00001314}
1315
jjako08d331d2003-10-13 20:33:30 +00001316/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001317int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1318 uint8_t cause)
1319{
1320 union gtp_packet packet;
1321 unsigned int length =
1322 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001323
Harald Weltebed35df2011-11-02 13:06:18 +01001324 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001325
Harald Weltebed35df2011-11-02 13:06:18 +01001326 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001327
Harald Weltebed35df2011-11-02 13:06:18 +01001328 if (version == 0)
1329 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1330 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001331
Harald Weltebed35df2011-11-02 13:06:18 +01001332 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1333 pdp->reorder);
1334 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1335 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001336
Harald Weltebed35df2011-11-02 13:06:18 +01001337 if (version == 0) {
1338 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1339 pdp->fllu);
1340 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1341 pdp->fllc);
1342 }
jjako08d331d2003-10-13 20:33:30 +00001343
Harald Weltebed35df2011-11-02 13:06:18 +01001344 if (version == 1) {
1345 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1346 pdp->teid_own);
1347 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1348 pdp->teic_own);
1349 }
jjako08d331d2003-10-13 20:33:30 +00001350
Harald Weltebed35df2011-11-02 13:06:18 +01001351 /* TODO: We use teic_own as charging ID */
1352 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1353 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001354
Harald Weltebed35df2011-11-02 13:06:18 +01001355 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1356 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001357
Harald Weltebed35df2011-11-02 13:06:18 +01001358 if (pdp->pco_neg.l) { /* Optional PCO */
1359 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1360 pdp->pco_neg.l, pdp->pco_neg.v);
1361 }
jjako52c24142002-12-16 13:33:51 +00001362
Harald Weltebed35df2011-11-02 13:06:18 +01001363 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1364 pdp->gsnlc.l, pdp->gsnlc.v);
1365 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1366 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001367
Harald Weltebed35df2011-11-02 13:06:18 +01001368 if (version == 1)
1369 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1370 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001371
Harald Weltebed35df2011-11-02 13:06:18 +01001372 /* TODO: Charging gateway address */
1373 }
jjako52c24142002-12-16 13:33:51 +00001374
Harald Weltebed35df2011-11-02 13:06:18 +01001375 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1376 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001377}
1378
1379/* Handle Create PDP Context Request */
1380int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001381 struct sockaddr_in *peer, int fd,
1382 void *pack, unsigned len)
1383{
1384 struct pdp_t *pdp, *pdp_old;
1385 struct pdp_t pdp_buf;
1386 union gtpie_member *ie[GTPIE_SIZE];
1387 uint8_t recovery;
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001388 bool recovery_recvd = false;
1389 int rc;
jjako52c24142002-12-16 13:33:51 +00001390
Harald Weltebed35df2011-11-02 13:06:18 +01001391 uint16_t seq = get_seq(pack);
1392 int hlen = get_hlen(pack);
1393 uint8_t linked_nsapi = 0;
1394 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001395
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02001396 if (!gtp_duplicate(gsn, version, peer, seq))
Harald Weltebed35df2011-11-02 13:06:18 +01001397 return 0;
jjako08d331d2003-10-13 20:33:30 +00001398
Harald Weltebed35df2011-11-02 13:06:18 +01001399 pdp = &pdp_buf;
1400 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001401
Harald Weltebed35df2011-11-02 13:06:18 +01001402 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001403 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1404
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001405 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001406 }
jjako52c24142002-12-16 13:33:51 +00001407
Harald Weltebed35df2011-11-02 13:06:18 +01001408 pdp->seq = seq;
1409 pdp->sa_peer = *peer;
1410 pdp->fd = fd;
1411 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001412
Harald Weltebed35df2011-11-02 13:06:18 +01001413 /* Decode information elements */
1414 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1415 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001416 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1417 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001418 if (0 == version)
1419 return EOF;
1420 else
1421 return gtp_create_pdp_resp(gsn, version, pdp,
1422 GTPCAUSE_INVALID_MESSAGE);
1423 }
jjako52c24142002-12-16 13:33:51 +00001424
Harald Weltebed35df2011-11-02 13:06:18 +01001425 if (version == 1) {
1426 /* Linked NSAPI (conditional) */
1427 /* If included this is the Secondary PDP Context Activation Procedure */
1428 /* In secondary activation IMSI is not included, so the context must be */
1429 /* identified by the tei */
1430 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001431
Harald Weltebed35df2011-11-02 13:06:18 +01001432 /* Find the primary PDP context */
1433 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1434 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001435 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001436 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001437 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001438 return gtp_create_pdp_resp(gsn, version, pdp,
1439 GTPCAUSE_OPT_IE_INCORRECT);
1440 }
jjako2c381332003-10-21 19:09:53 +00001441
Harald Weltebed35df2011-11-02 13:06:18 +01001442 /* Check that the primary PDP context matches linked nsapi */
1443 if (linked_pdp->nsapi != linked_nsapi) {
1444 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001445 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001446 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001447 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001448 return gtp_create_pdp_resp(gsn, version, pdp,
1449 GTPCAUSE_OPT_IE_INCORRECT);
1450 }
jjako52c24142002-12-16 13:33:51 +00001451
Harald Weltebed35df2011-11-02 13:06:18 +01001452 /* Copy parameters from primary context */
1453 pdp->selmode = linked_pdp->selmode;
1454 pdp->imsi = linked_pdp->imsi;
1455 pdp->msisdn = linked_pdp->msisdn;
1456 pdp->eua = linked_pdp->eua;
1457 pdp->pco_req = linked_pdp->pco_req;
1458 pdp->apn_req = linked_pdp->apn_req;
1459 pdp->teic_gn = linked_pdp->teic_gn;
1460 pdp->secondary = 1;
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001461 } else {
1462 /* Not Secondary PDP Context Activation Procedure */
1463 /* IMSI (conditional): If the MS is emergency attached
1464 and the MS is UICCless, the IMSI cannot be included
1465 in the message and therefore IMSI shall not be
1466 included in the message. */
1467 if (gtpie_gettv0
1468 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1469 gsn->missing++;
1470 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1471 len, "Missing IMSI not supported\n");
1472 return gtp_create_pdp_resp(gsn, version, pdp,
1473 GTPCAUSE_MAN_IE_MISSING);
1474 }
1475 }
1476
1477 /* TEID (mandatory) */
1478 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1479 gsn->missing++;
1480 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1481 len, "Missing mandatory information field\n");
1482 return gtp_create_pdp_resp(gsn, version, pdp,
1483 GTPCAUSE_MAN_IE_MISSING);
1484 }
1485 /* TEIC (conditional) */
1486 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1487 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1488 gsn->missing++;
1489 GTP_LOGPKG(LOGL_ERROR, peer,
1490 pack, len,
1491 "Missing mandatory information field\n");
1492 return gtp_create_pdp_resp(gsn, version, pdp,
1493 GTPCAUSE_MAN_IE_MISSING);
1494 }
1495 }
1496 /* NSAPI (mandatory) */
1497 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1498 gsn->missing++;
1499 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1500 len, "Missing mandatory information field\n");
1501 return gtp_create_pdp_resp(gsn, version, pdp,
1502 GTPCAUSE_MAN_IE_MISSING);
1503 }
1504 /* QoS (mandatory) */
1505 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1506 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1507 gsn->missing++;
1508 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1509 len, "Missing mandatory information field\n");
1510 return gtp_create_pdp_resp(gsn, version, pdp,
1511 GTPCAUSE_MAN_IE_MISSING);
1512 }
1513 /* TFT (conditional) */
1514 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1515 &pdp->tft.v, sizeof(pdp->tft.v))) {
Harald Weltebed35df2011-11-02 13:06:18 +01001516 }
1517 }
1518 /* if (version == 1) */
1519 if (version == 0) {
1520 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1521 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1522 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001523 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1524 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001525 return gtp_create_pdp_resp(gsn, version, pdp,
1526 GTPCAUSE_MAN_IE_MISSING);
1527 }
Harald Weltebed35df2011-11-02 13:06:18 +01001528 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1529 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001530 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1531 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001532 return gtp_create_pdp_resp(gsn, version, pdp,
1533 GTPCAUSE_MAN_IE_MISSING);
1534 }
Harald Weltebed35df2011-11-02 13:06:18 +01001535 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1536 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001537 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1538 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001539 return gtp_create_pdp_resp(gsn, version, pdp,
1540 GTPCAUSE_MAN_IE_MISSING);
1541 }
1542 }
jjako08d331d2003-10-13 20:33:30 +00001543
Harald Weltebed35df2011-11-02 13:06:18 +01001544 /* SGSN address for signalling (mandatory) */
1545 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1546 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1547 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001548 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1549 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001550 return gtp_create_pdp_resp(gsn, version, pdp,
1551 GTPCAUSE_MAN_IE_MISSING);
1552 }
jjako2e840a32003-01-28 16:05:18 +00001553
Harald Weltebed35df2011-11-02 13:06:18 +01001554 /* SGSN address for user traffic (mandatory) */
1555 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1556 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1557 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001558 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1559 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001560 return gtp_create_pdp_resp(gsn, version, pdp,
1561 GTPCAUSE_MAN_IE_MISSING);
1562 }
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001563 /* Recovery (optional) */
1564 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1565 /* we use recovery futher down after announcing new pdp ctx to user */
1566 recovery_recvd = true;
1567 }
jjako52c24142002-12-16 13:33:51 +00001568
Harald Weltebed35df2011-11-02 13:06:18 +01001569 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001570 /* Selection mode (conditional) */
1571 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1572 &pdp->selmode, sizeof(pdp->selmode))) {
1573 gsn->missing++;
1574 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1575 len, "Missing mandatory information field\n");
1576 return gtp_create_pdp_resp(gsn, version, pdp,
1577 GTPCAUSE_MAN_IE_MISSING);
1578 }
1579 /* End User Address (conditional) */
1580 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1581 &pdp->eua.v, sizeof(pdp->eua.v))) {
1582 gsn->missing++;
1583 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1584 len, "Missing mandatory information field\n");
1585 return gtp_create_pdp_resp(gsn, version, pdp,
1586 GTPCAUSE_MAN_IE_MISSING);
1587 }
1588 /* APN */
1589 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1590 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1591 gsn->missing++;
1592 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1593 len, "Missing mandatory information field\n");
1594 return gtp_create_pdp_resp(gsn, version, pdp,
1595 GTPCAUSE_MAN_IE_MISSING);
1596 }
1597 /* Extract protocol configuration options (optional) */
1598 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1599 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1600 }
Harald Weltebed35df2011-11-02 13:06:18 +01001601 /* MSISDN (conditional) */
1602 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1603 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1604 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001605 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1606 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001607 return gtp_create_pdp_resp(gsn, version, pdp,
1608 GTPCAUSE_MAN_IE_MISSING);
1609 }
1610 }
jjako52c24142002-12-16 13:33:51 +00001611
Harald Weltebed35df2011-11-02 13:06:18 +01001612 /* Initialize our own IP addresses */
1613 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1614 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1615
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001616 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001617
1618 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1619 /* Found old pdp with same tid. Now the voodoo begins! */
1620 /* 09.60 / 29.060 allows create on existing context to "steal" */
1621 /* the context which was allready established */
1622 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001623 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001624 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1625 &&
1626 (!memcmp
1627 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1628 && (pdp->selmode == pdp_old->selmode)
1629 && (pdp->msisdn.l == pdp_old->msisdn.l)
1630 &&
1631 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1632 {
1633 /* OK! We are dealing with the same APN. We will copy new
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001634 * parameters to the old pdp and send off confirmation
Harald Weltebed35df2011-11-02 13:06:18 +01001635 * We ignore the following information elements:
1636 * QoS: MS will get originally negotiated QoS.
1637 * End user address (EUA). MS will get old EUA anyway.
1638 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001639 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001640
1641 /* Copy remote flow label */
1642 pdp_old->flru = pdp->flru;
1643 pdp_old->flrc = pdp->flrc;
1644
1645 /* Copy remote tei */
1646 pdp_old->teid_gn = pdp->teid_gn;
1647 pdp_old->teic_gn = pdp->teic_gn;
1648
1649 /* Copy peer GSN address */
1650 pdp_old->gsnrc.l = pdp->gsnrc.l;
1651 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1652 pdp_old->gsnru.l = pdp->gsnru.l;
1653 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1654
1655 /* Copy request parameters */
1656 pdp_old->seq = pdp->seq;
1657 pdp_old->sa_peer = pdp->sa_peer;
1658 pdp_old->fd = pdp->fd = fd;
1659 pdp_old->version = pdp->version = version;
1660
1661 /* Switch to using the old pdp context */
1662 pdp = pdp_old;
1663
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001664 if (recovery_recvd)
1665 emit_cb_recovery(gsn, peer, pdp, recovery);
1666
Harald Weltebed35df2011-11-02 13:06:18 +01001667 /* Confirm to peer that things were "successful" */
1668 return gtp_create_pdp_resp(gsn, version, pdp,
1669 GTPCAUSE_ACC_REQ);
1670 } else { /* This is not the same PDP context. Delete the old one. */
1671
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001672 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001673
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02001674 gtp_freepdp(gsn, pdp_old);
Harald Weltebed35df2011-11-02 13:06:18 +01001675
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001676 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001677 }
1678 }
1679
Pau Espin Pedroleefa30d2019-05-31 15:42:49 +02001680 gtp_pdp_newpdp(gsn, &pdp, pdp->imsi, pdp->nsapi, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001681
Pau Espin Pedrolaad77a02019-05-30 12:44:20 +02001682 /* Callback function to validate login */
Harald Weltebed35df2011-11-02 13:06:18 +01001683 if (gsn->cb_create_context_ind != 0)
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001684 rc = gsn->cb_create_context_ind(pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001685 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001686 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1687 "No create_context_ind callback defined\n");
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001688 rc = gtp_create_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001689 GTPCAUSE_NOT_SUPPORTED);
1690 }
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001691 if (recovery_recvd)
1692 emit_cb_recovery(gsn, peer, pdp, recovery);
1693 return rc;
jjako52c24142002-12-16 13:33:51 +00001694}
1695
jjako52c24142002-12-16 13:33:51 +00001696/* Handle Create PDP Context Response */
1697int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001698 struct sockaddr_in *peer, void *pack, unsigned len)
1699{
1700 struct pdp_t *pdp;
1701 union gtpie_member *ie[GTPIE_SIZE];
1702 uint8_t cause, recovery;
1703 void *cbp = NULL;
1704 uint8_t type = 0;
1705 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001706
Harald Weltebed35df2011-11-02 13:06:18 +01001707 /* Remove packet from queue */
1708 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1709 return EOF;
jjako52c24142002-12-16 13:33:51 +00001710
Harald Weltebed35df2011-11-02 13:06:18 +01001711 /* Find the context in question */
1712 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1713 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001714 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001715 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001716 if (gsn->cb_conf)
1717 gsn->cb_conf(type, EOF, NULL, cbp);
1718 return EOF;
1719 }
jjako2c381332003-10-21 19:09:53 +00001720
Harald Weltebed35df2011-11-02 13:06:18 +01001721 /* Register that we have received a valid teic from GGSN */
1722 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001723
Harald Weltebed35df2011-11-02 13:06:18 +01001724 /* Decode information elements */
1725 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1726 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001727 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1728 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001729 if (gsn->cb_conf)
1730 gsn->cb_conf(type, EOF, pdp, cbp);
1731 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1732 pdp_freepdp(pdp); */
1733 return EOF;
1734 }
jjako52c24142002-12-16 13:33:51 +00001735
Harald Weltebed35df2011-11-02 13:06:18 +01001736 /* Extract cause value (mandatory) */
1737 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1738 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001739 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1740 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001741 if (gsn->cb_conf)
1742 gsn->cb_conf(type, EOF, pdp, cbp);
1743 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1744 pdp_freepdp(pdp); */
1745 return EOF;
1746 }
jjako52c24142002-12-16 13:33:51 +00001747
Harald Weltebed35df2011-11-02 13:06:18 +01001748 /* Extract recovery (optional) */
1749 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001750 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001751 }
jjako52c24142002-12-16 13:33:51 +00001752
Harald Weltebed35df2011-11-02 13:06:18 +01001753 /* Extract protocol configuration options (optional) */
1754 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1755 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1756 }
jjako52c24142002-12-16 13:33:51 +00001757
Harald Weltebed35df2011-11-02 13:06:18 +01001758 /* Check all conditional information elements */
1759 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001760
Harald Weltebed35df2011-11-02 13:06:18 +01001761 if (version == 0) {
1762 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1763 &pdp->qos_neg0,
1764 sizeof(pdp->qos_neg0))) {
1765 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001766 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001767 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001768 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001769 if (gsn->cb_conf)
1770 gsn->cb_conf(type, EOF, pdp, cbp);
1771 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1772 pdp_freepdp(pdp); */
1773 return EOF;
1774 }
1775 }
jjako08d331d2003-10-13 20:33:30 +00001776
Harald Weltebed35df2011-11-02 13:06:18 +01001777 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1778 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001779 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001780 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001781 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001782 if (gsn->cb_conf)
1783 gsn->cb_conf(type, EOF, pdp, cbp);
1784 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1785 pdp_freepdp(pdp); */
1786 return EOF;
1787 }
jjako52c24142002-12-16 13:33:51 +00001788
Harald Weltebed35df2011-11-02 13:06:18 +01001789 if (version == 0) {
1790 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1791 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001792 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001793 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001794 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001795 if (gsn->cb_conf)
1796 gsn->cb_conf(type, EOF, pdp, cbp);
1797 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1798 pdp_freepdp(pdp); */
1799 return EOF;
1800 }
jjako52c24142002-12-16 13:33:51 +00001801
Harald Weltebed35df2011-11-02 13:06:18 +01001802 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1803 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001804 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001805 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001806 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001807 if (gsn->cb_conf)
1808 gsn->cb_conf(type, EOF, pdp, cbp);
1809 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1810 pdp_freepdp(pdp); */
1811 return EOF;
1812 }
1813 }
1814
1815 if (version == 1) {
1816 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1817 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001818 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001819 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001820 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001821 if (gsn->cb_conf)
1822 gsn->cb_conf(type, EOF, pdp, cbp);
1823 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1824 pdp_freepdp(pdp); */
1825 return EOF;
1826 }
1827
1828 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1829 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001830 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001831 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001832 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001833 if (gsn->cb_conf)
1834 gsn->cb_conf(type, EOF, pdp, cbp);
1835 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1836 pdp_freepdp(pdp); */
1837 return EOF;
1838 }
1839 }
1840
1841 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1842 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001843 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001844 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001845 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001846 if (gsn->cb_conf)
1847 gsn->cb_conf(type, EOF, pdp, cbp);
1848 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1849 pdp_freepdp(pdp); */
1850 }
1851
1852 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1853 &pdp->eua.v, sizeof(pdp->eua.v))) {
1854 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001855 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001856 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001857 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001858 if (gsn->cb_conf)
1859 gsn->cb_conf(type, EOF, pdp, cbp);
1860 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1861 pdp_freepdp(pdp); */
1862 return EOF;
1863 }
1864
1865 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1866 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1867 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001868 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001869 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001870 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001871 if (gsn->cb_conf)
1872 gsn->cb_conf(type, EOF, pdp, cbp);
1873 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1874 pdp_freepdp(pdp); */
1875 return EOF;
1876 }
1877
1878 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1879 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1880 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001881 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001882 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001883 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001884 if (gsn->cb_conf)
1885 gsn->cb_conf(type, EOF, pdp, cbp);
1886 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1887 pdp_freepdp(pdp); */
1888 return EOF;
1889 }
1890
1891 if (version == 1) {
1892 if (gtpie_gettlv
1893 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1894 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1895 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001896 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001897 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001898 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001899 if (gsn->cb_conf)
1900 gsn->cb_conf(type, EOF, pdp, cbp);
1901 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1902 pdp_freepdp(pdp); */
1903 return EOF;
1904 }
1905 }
1906
1907 }
1908
1909 if (gsn->cb_conf)
1910 gsn->cb_conf(type, cause, pdp, cbp);
1911
1912 return 0;
jjako52c24142002-12-16 13:33:51 +00001913}
1914
jjako08d331d2003-10-13 20:33:30 +00001915/* API: Send Update PDP Context Request */
1916int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001917 struct in_addr *inetaddr)
1918{
1919 union gtp_packet packet;
1920 unsigned int length =
1921 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001922
Harald Weltebed35df2011-11-02 13:06:18 +01001923 if (pdp->version == 0)
1924 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1925 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001926
Harald Weltebed35df2011-11-02 13:06:18 +01001927 /* Include IMSI if updating with unknown teic_gn */
1928 if ((pdp->version == 1) && (!pdp->teic_gn))
1929 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1930 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1931
1932 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1933 gsn->restart_counter);
1934
1935 if (pdp->version == 0) {
1936 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1937 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1938 }
1939
1940 if (pdp->version == 1) {
1941 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1942 pdp->teid_own);
1943
1944 if (!pdp->teic_confirmed)
1945 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1946 pdp->teic_own);
1947 }
1948
1949 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1950
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001951 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001952 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1953 pdp->traceref);
1954 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1955 pdp->tracetype); */
1956
1957 /* TODO if ggsn update message
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001958 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01001959 pdp->eua.l, pdp->eua.v);
1960 */
1961
1962 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1963 pdp->gsnlc.l, pdp->gsnlc.v);
1964 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1965 pdp->gsnlu.l, pdp->gsnlu.v);
1966
1967 if (pdp->version == 1)
1968 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1969 pdp->qos_req.l, pdp->qos_req.v);
1970
1971 if ((pdp->version == 1) && pdp->tft.l)
1972 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1973 pdp->tft.l, pdp->tft.v);
1974
1975 if ((pdp->version == 1) && pdp->triggerid.l)
1976 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1977 pdp->triggerid.l, pdp->triggerid.v);
1978
1979 if ((pdp->version == 1) && pdp->omcid.l)
1980 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1981 pdp->omcid.l, pdp->omcid.v);
1982
Daniel Willmann134a7752016-02-03 18:53:29 +01001983 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001984
1985 return 0;
jjako52c24142002-12-16 13:33:51 +00001986}
1987
jjako08d331d2003-10-13 20:33:30 +00001988/* Send Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001989static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01001990 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001991 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001992 struct pdp_t *pdp, uint8_t cause)
1993{
jjako08d331d2003-10-13 20:33:30 +00001994
Harald Weltebed35df2011-11-02 13:06:18 +01001995 union gtp_packet packet;
1996 unsigned int length =
1997 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001998
Harald Weltebed35df2011-11-02 13:06:18 +01001999 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00002000
Harald Weltebed35df2011-11-02 13:06:18 +01002001 if (cause == GTPCAUSE_ACC_REQ) {
2002
2003 if (version == 0)
2004 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
2005 sizeof(pdp->qos_neg0), pdp->qos_neg0);
2006
2007 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
2008 gsn->restart_counter);
2009
2010 if (version == 0) {
2011 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
2012 pdp->fllu);
2013 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
2014 pdp->fllc);
2015 }
2016
2017 if (version == 1) {
2018 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2019 pdp->teid_own);
2020
2021 if (!pdp->teic_confirmed)
2022 gtpie_tv4(&packet, &length, GTP_MAX,
2023 GTPIE_TEI_C, pdp->teic_own);
2024 }
2025
2026 /* TODO we use teid_own as charging ID address */
2027 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
2028 pdp->teid_own);
2029
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002030 /* If ggsn
2031 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01002032 pdp->eua.l, pdp->eua.v); */
2033
2034 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2035 pdp->gsnlc.l, pdp->gsnlc.v);
2036 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2037 pdp->gsnlu.l, pdp->gsnlu.v);
2038
2039 if (version == 1)
2040 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2041 pdp->qos_neg.l, pdp->qos_neg.v);
2042
2043 /* TODO: Charging gateway address */
2044 }
2045
2046 return gtp_resp(version, gsn, pdp, &packet, length, peer,
2047 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00002048}
2049
jjako52c24142002-12-16 13:33:51 +00002050/* Handle Update PDP Context Request */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002051static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002052 struct sockaddr_in *peer, int fd,
2053 void *pack, unsigned len)
2054{
2055 struct pdp_t *pdp;
2056 struct pdp_t pdp_backup;
2057 union gtpie_member *ie[GTPIE_SIZE];
2058 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002059
Harald Weltebed35df2011-11-02 13:06:18 +01002060 uint16_t seq = get_seq(pack);
2061 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002062
Harald Weltebed35df2011-11-02 13:06:18 +01002063 uint64_t imsi;
2064 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002065
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002066 /* Is this a duplicate ? */
2067 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002068 return 0; /* We allready send of response once */
2069 }
jjako08d331d2003-10-13 20:33:30 +00002070
Harald Weltebed35df2011-11-02 13:06:18 +01002071 /* Decode information elements */
2072 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2073 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002074 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2075 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002076 if (0 == version)
2077 return EOF;
2078 else
2079 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2080 len, NULL,
2081 GTPCAUSE_INVALID_MESSAGE);
2082 }
jjako08d331d2003-10-13 20:33:30 +00002083
Harald Weltebed35df2011-11-02 13:06:18 +01002084 /* Finding PDP: */
2085 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2086 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2087 /* we have to use the tunnel endpoint identifier */
2088 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002089 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
2090
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01002091 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00002092
Harald Weltebed35df2011-11-02 13:06:18 +01002093 /* Find the context in question */
2094 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2095 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002096 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2097 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002098 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2099 len, NULL,
2100 GTPCAUSE_NON_EXIST);
2101 }
2102 } else if (version == 1) {
2103 /* NSAPI (mandatory) */
2104 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2105 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002106 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2107 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002108 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2109 len, NULL,
2110 GTPCAUSE_MAN_IE_MISSING);
2111 }
jjako08d331d2003-10-13 20:33:30 +00002112
Harald Weltebed35df2011-11-02 13:06:18 +01002113 /* IMSI (conditional) */
2114 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2115 /* Find the context in question */
2116 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2117 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002118 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002119 pack, len, "Unknown PDP context: %u\n",
2120 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002121 return gtp_update_pdp_resp(gsn, version, peer,
2122 fd, pack, len, NULL,
2123 GTPCAUSE_NON_EXIST);
2124 }
2125 } else {
2126 /* Find the context in question */
2127 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2128 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002129 GTP_LOGPKG(LOGL_ERROR, peer,
2130 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002131 return gtp_update_pdp_resp(gsn, version, peer,
2132 fd, pack, len, NULL,
2133 GTPCAUSE_NON_EXIST);
2134 }
2135 }
2136 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002137 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002138 return EOF;
2139 }
jjako08d331d2003-10-13 20:33:30 +00002140
Harald Weltebed35df2011-11-02 13:06:18 +01002141 /* Make a backup copy in case anything is wrong */
2142 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002143
Harald Weltebed35df2011-11-02 13:06:18 +01002144 if (version == 0) {
2145 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2146 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2147 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002148 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2149 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002150 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2151 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2152 len, pdp,
2153 GTPCAUSE_MAN_IE_MISSING);
2154 }
2155 }
jjako52c24142002-12-16 13:33:51 +00002156
Harald Weltebed35df2011-11-02 13:06:18 +01002157 /* Recovery (optional) */
2158 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002159 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002160 }
jjako08d331d2003-10-13 20:33:30 +00002161
Harald Weltebed35df2011-11-02 13:06:18 +01002162 if (version == 0) {
2163 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2164 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002165 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2166 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002167 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2168 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2169 len, pdp,
2170 GTPCAUSE_MAN_IE_MISSING);
2171 }
jjako52c24142002-12-16 13:33:51 +00002172
Harald Weltebed35df2011-11-02 13:06:18 +01002173 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2174 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002175 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2176 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002177 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2178 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2179 len, pdp,
2180 GTPCAUSE_MAN_IE_MISSING);
2181 }
2182 }
jjako52c24142002-12-16 13:33:51 +00002183
Harald Weltebed35df2011-11-02 13:06:18 +01002184 if (version == 1) {
2185 /* TEID (mandatory) */
2186 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2187 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002188 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2189 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002190 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2191 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2192 len, pdp,
2193 GTPCAUSE_MAN_IE_MISSING);
2194 }
jjako52c24142002-12-16 13:33:51 +00002195
Harald Weltebed35df2011-11-02 13:06:18 +01002196 /* TEIC (conditional) */
2197 /* If TEIC is not included it means that we have allready received it */
2198 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2199 /* all updated contexts, or only for one of the linked contexts */
2200 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2201
2202 /* NSAPI (mandatory) */
2203 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2204 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002205 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2206 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002207 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2208 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2209 len, pdp,
2210 GTPCAUSE_MAN_IE_MISSING);
2211 }
2212 }
2213
2214 /* Trace reference (optional) */
2215 /* Trace type (optional) */
2216
2217 /* End User Address (conditional) TODO: GGSN Initiated
2218 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2219 &pdp->eua.v, sizeof(pdp->eua.v))) {
2220 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002221 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002222 "Missing mandatory information field");
2223 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002224 return gtp_update_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01002225 GTPCAUSE_MAN_IE_MISSING);
2226 } */
2227
2228 /* SGSN address for signalling (mandatory) */
2229 /* It is weird that this is mandatory when TEIC is conditional */
2230 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2231 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2232 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002233 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2234 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002235 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2236 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2237 pdp, GTPCAUSE_MAN_IE_MISSING);
2238 }
2239
2240 /* SGSN address for user traffic (mandatory) */
2241 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2242 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2243 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002244 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2245 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002246 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2247 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2248 pdp, GTPCAUSE_MAN_IE_MISSING);
2249 }
2250
2251 if (version == 1) {
2252 /* QoS (mandatory) */
2253 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2254 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2255 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002256 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2257 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002258 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2259 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2260 len, pdp,
2261 GTPCAUSE_MAN_IE_MISSING);
2262 }
2263
2264 /* TFT (conditional) */
2265 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2266 &pdp->tft.v, sizeof(pdp->tft.v))) {
2267 }
2268
2269 /* OMC identity */
2270 }
2271
2272 /* Confirm to peer that things were "successful" */
2273 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2274 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002275}
2276
jjako52c24142002-12-16 13:33:51 +00002277/* Handle Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002278static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002279 struct sockaddr_in *peer, void *pack, unsigned len)
2280{
2281 struct pdp_t *pdp;
2282 union gtpie_member *ie[GTPIE_SIZE];
2283 uint8_t cause, recovery;
2284 void *cbp = NULL;
2285 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002286 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002287
Harald Weltebed35df2011-11-02 13:06:18 +01002288 /* Remove packet from queue */
2289 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2290 return EOF;
jjako52c24142002-12-16 13:33:51 +00002291
Harald Weltebed35df2011-11-02 13:06:18 +01002292 /* Find the context in question */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002293 if (pdp_getgtp1(&pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002294 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002295 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002296 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002297 pdp = NULL;
2298 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002299 }
jjako2c381332003-10-21 19:09:53 +00002300
Harald Weltebed35df2011-11-02 13:06:18 +01002301 /* Register that we have received a valid teic from GGSN */
2302 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002303
Harald Weltebed35df2011-11-02 13:06:18 +01002304 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002305 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002306 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002307 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2308 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002309 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002310 }
jjako52c24142002-12-16 13:33:51 +00002311
Harald Weltebed35df2011-11-02 13:06:18 +01002312 /* Extract cause value (mandatory) */
2313 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002314 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002315 }
jjako52c24142002-12-16 13:33:51 +00002316
Harald Weltebed35df2011-11-02 13:06:18 +01002317 /* Extract recovery (optional) */
2318 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002319 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002320 }
2321
2322 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002323 /* TODO: This does not handle GGSN-initiated update responses */
2324 if (GTPCAUSE_ACC_REQ == cause) {
2325 if (version == 0) {
2326 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2327 &pdp->qos_neg0,
2328 sizeof(pdp->qos_neg0))) {
2329 goto err_missing;
2330 }
2331
2332 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2333 goto err_missing;
2334 }
2335
2336 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2337 goto err_missing;
2338 }
Harald Weltebed35df2011-11-02 13:06:18 +01002339 }
2340
Daniel Willmannd9975522016-02-04 15:38:12 +01002341 if (version == 1) {
2342 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2343 goto err_missing;
2344 }
Harald Weltebed35df2011-11-02 13:06:18 +01002345
Daniel Willmannd9975522016-02-04 15:38:12 +01002346 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2347 goto err_missing;
2348 }
2349 }
2350
2351 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2352 goto err_missing;
2353 }
2354
2355 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2356 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2357 goto err_missing;
2358 }
2359
2360 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2361 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2362 goto err_missing;
2363 }
2364
2365 if (version == 1) {
2366 if (gtpie_gettlv
2367 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2368 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2369 goto err_missing;
2370 }
2371 }
Harald Weltebed35df2011-11-02 13:06:18 +01002372 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002373
2374 if (gsn->cb_conf)
2375 gsn->cb_conf(type, cause, pdp, cbp);
2376 return 0; /* Succes */
2377
2378err_missing:
2379 gsn->missing++;
2380 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2381 "Missing information field\n");
2382err_out:
2383 if (gsn->cb_conf)
2384 gsn->cb_conf(type, EOF, pdp, cbp);
2385 return EOF;
jjako52c24142002-12-16 13:33:51 +00002386}
2387
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002388/* API: Deprecated. Send Delete PDP Context Request And free pdp ctx. */
jjako2c381332003-10-21 19:09:53 +00002389int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002390 int teardown)
2391{
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002392 struct pdp_t *linked_pdp;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002393
2394 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
2395 LOGP(DLGTP, LOGL_ERROR,
2396 "Unknown linked PDP context: %u\n", pdp->teic_own);
2397 return EOF;
2398 }
2399
2400 if (gtp_delete_context_req2(gsn, pdp, cbp, teardown) == EOF)
2401 return EOF;
2402
2403 if (teardown) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002404 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002405 } else {
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002406 /* If we end up here (no teardown) it means we still
2407 have at least another pdp context active for this
2408 PDN connection (since last DeleteReq should come
2409 with teardown enabled). If the ctx to delete is a
2410 secondary ctx, simply free it. If it's the primary
2411 ctx, mark it as nodata but don't free it since we
2412 need it to hold data linked together and we'll
2413 require it later to tear down the entire tree. Still,
2414 we announce its deletion through cb_delete_context
2415 because we don't want user to release its related
2416 data and not use it anymore.
2417 */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002418 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002419 if (gsn->cb_delete_context)
2420 gsn->cb_delete_context(pdp);
2421 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2422 pdp->nodata = 1;
2423 } else {
2424 gtp_freepdp(gsn, pdp);
2425 }
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002426 }
2427
2428 return 0;
2429}
2430
Oliver Smith1cde2c12019-05-13 11:35:03 +02002431/* API: Send Delete PDP Context Request. PDP CTX shall be free'd by user at any
2432 point in time later than this function through a call to pdp_freepdp(pdp), but
2433 it must be freed no later than during cb_conf(GTP_DELETE_PDP_REQ, pdp) */
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002434int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2435 int teardown)
2436{
Harald Weltebed35df2011-11-02 13:06:18 +01002437 union gtp_packet packet;
2438 unsigned int length =
2439 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2440 struct in_addr addr;
2441 struct pdp_t *linked_pdp;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002442 int count;
jjako2c381332003-10-21 19:09:53 +00002443
Harald Weltebed35df2011-11-02 13:06:18 +01002444 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2445 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002446 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002447 return EOF;
jjako2c381332003-10-21 19:09:53 +00002448 }
jjako2c381332003-10-21 19:09:53 +00002449
Harald Weltebed35df2011-11-02 13:06:18 +01002450 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002451 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002452 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002453 return EOF;
2454 }
2455
2456 if (!teardown) {
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002457 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002458 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002459 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002460 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002461 return EOF;
2462 }
2463 }
2464
2465 if (pdp->version == 1) {
2466 if (teardown)
2467 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2468 0xff);
2469
2470 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2471 }
2472
2473 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2474
Harald Weltebed35df2011-11-02 13:06:18 +01002475 return 0;
jjako2c381332003-10-21 19:09:53 +00002476}
jjako08d331d2003-10-13 20:33:30 +00002477
jjako52c24142002-12-16 13:33:51 +00002478/* Send Delete PDP Context Response */
2479int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002480 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002481 void *pack, unsigned len,
2482 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002483 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002484{
Harald Weltebed35df2011-11-02 13:06:18 +01002485 union gtp_packet packet;
Harald Weltebed35df2011-11-02 13:06:18 +01002486 unsigned int length =
2487 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00002488
Harald Weltebed35df2011-11-02 13:06:18 +01002489 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002490
Harald Weltebed35df2011-11-02 13:06:18 +01002491 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2492 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002493
Harald Weltebed35df2011-11-02 13:06:18 +01002494 if (cause == GTPCAUSE_ACC_REQ) {
2495 if ((teardown) || (version == 0)) { /* Remove all contexts */
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002496 gtp_freepdp_teardown(gsn, linked_pdp);
Pau Espin Pedrol86515732019-05-31 16:40:37 +02002497 } else {
2498 /* If we end up here (no teardown) it means we still
2499 have at least another pdp context active for this
2500 PDN connection (since last DeleteReq should come
2501 with teardown enabled). If the ctx to delete is a
2502 secondary ctx, simply free it. If it's the primary
2503 ctx, mark it as nodata but don't free it since we
2504 need it to hold data linked together and we'll
2505 require it later to tear down the entire tree. Still,
2506 we announce its deletion through cb_delete_context
2507 because we don't want user to release its related
2508 data and not use it anymore.
2509 */
Harald Weltebed35df2011-11-02 13:06:18 +01002510 if (pdp == linked_pdp) {
Pau Espin Pedrol93dd7982019-05-31 16:42:05 +02002511 if (gsn->cb_delete_context)
2512 gsn->cb_delete_context(pdp);
2513 pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2514 pdp->nodata = 1;
2515 } else {
2516 gtp_freepdp(gsn, pdp);
2517 }
Harald Weltebed35df2011-11-02 13:06:18 +01002518 }
jjako2c381332003-10-21 19:09:53 +00002519 }
Harald Weltebed35df2011-11-02 13:06:18 +01002520 /* if (cause == GTPCAUSE_ACC_REQ) */
2521 return 0;
jjako52c24142002-12-16 13:33:51 +00002522}
2523
2524/* Handle Delete PDP Context Request */
2525int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002526 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002527 void *pack, unsigned len)
2528{
2529 struct pdp_t *pdp = NULL;
2530 struct pdp_t *linked_pdp = NULL;
2531 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002532
Harald Weltebed35df2011-11-02 13:06:18 +01002533 uint16_t seq = get_seq(pack);
2534 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002535
Harald Weltebed35df2011-11-02 13:06:18 +01002536 uint8_t nsapi;
2537 uint8_t teardown = 0;
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002538 int count;
jjako52c24142002-12-16 13:33:51 +00002539
Pau Espin Pedrolde72d262019-05-29 18:17:05 +02002540 /* Is this a duplicate ? */
2541 if (!gtp_duplicate(gsn, version, peer, seq)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002542 return 0; /* We allready send off response once */
2543 }
jjako2c381332003-10-21 19:09:53 +00002544
Harald Weltebed35df2011-11-02 13:06:18 +01002545 /* Find the linked context in question */
2546 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2547 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002548 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002549 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002550 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2551 NULL, NULL, GTPCAUSE_NON_EXIST,
2552 teardown);
2553 }
jjako2c381332003-10-21 19:09:53 +00002554
Harald Weltebed35df2011-11-02 13:06:18 +01002555 /* If version 0 this is also the secondary context */
2556 if (version == 0)
2557 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002558
Harald Weltebed35df2011-11-02 13:06:18 +01002559 /* Decode information elements */
2560 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2561 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002562 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2563 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002564 if (0 == version)
2565 return EOF;
2566 else
2567 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2568 len, NULL, NULL,
2569 GTPCAUSE_INVALID_MESSAGE,
2570 teardown);
2571 }
2572
2573 if (version == 1) {
2574 /* NSAPI (mandatory) */
2575 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2576 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002577 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2578 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002579 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2580 len, NULL, NULL,
2581 GTPCAUSE_MAN_IE_MISSING,
2582 teardown);
2583 }
2584
2585 /* Find the context in question */
2586 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2587 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002588 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2589 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002590 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2591 len, NULL, NULL,
2592 GTPCAUSE_NON_EXIST,
2593 teardown);
2594 }
2595
2596 /* Teardown (conditional) */
2597 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2598
2599 if (!teardown) {
Pau Espin Pedrol742a6b52019-05-30 13:36:10 +02002600 /* TS 29.060 section 7.3.5: If a GSN receives a Delete PDP context
2601 * without a Teardown Indicator or with a Teardown Indicator with
2602 * value set to "0" and only that PDP context is active for a PDN
2603 * connection, then the GSN shall ignore the message. (Note:
2604 * This is symptom of a race condition. The reliable delivery of
2605 * signalling messages will eventually lead to a consistent
2606 * situation, allowing the teardown of the PDP context.)
2607 */
Pau Espin Pedrol9ee8d322019-05-30 14:11:22 +02002608 count = pdp_count_secondary(linked_pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002609 if (count <= 1) {
Pau Espin Pedrold1bd6fc2018-07-13 19:11:45 +02002610 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2611 "Ignoring CTX DEL without teardown and count=%d\n",
2612 count);
Harald Weltebed35df2011-11-02 13:06:18 +01002613 return 0; /* 29.060 7.3.5 Ignore message */
2614 }
2615 }
2616 }
2617
2618 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2619 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002620}
2621
jjako52c24142002-12-16 13:33:51 +00002622/* Handle Delete PDP Context Response */
2623int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002624 struct sockaddr_in *peer, void *pack, unsigned len)
2625{
2626 union gtpie_member *ie[GTPIE_SIZE];
2627 uint8_t cause;
2628 void *cbp = NULL;
2629 uint8_t type = 0;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002630 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002631 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002632
Harald Weltebed35df2011-11-02 13:06:18 +01002633 /* Remove packet from queue */
2634 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2635 return EOF;
jjako52c24142002-12-16 13:33:51 +00002636
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002637 /* Find the context in question. It may not be available if gtp_delete_context_req
2638 * was used and as a result the PDP ctx was already freed */
2639 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2640 gsn->err_unknownpdp++;
2641 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
Oliver Smith1cde2c12019-05-13 11:35:03 +02002642 "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 +02002643 get_tei(pack));
2644 if (gsn->cb_conf)
2645 gsn->cb_conf(type, EOF, NULL, cbp);
2646 return EOF;
2647 }
2648
Harald Weltebed35df2011-11-02 13:06:18 +01002649 /* Decode information elements */
2650 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2651 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002652 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2653 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002654 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002655 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002656 return EOF;
2657 }
2658
2659 /* Extract cause value (mandatory) */
2660 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2661 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002662 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2663 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002664 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002665 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002666 return EOF;
2667 }
2668
2669 /* Check the cause value (again) */
2670 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2671 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002672 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2673 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002674 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002675 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002676 return EOF;
2677 }
2678
2679 /* Callback function to notify application */
2680 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002681 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002682
2683 return 0;
jjako52c24142002-12-16 13:33:51 +00002684}
2685
Harald Welte54d082e2017-08-12 22:43:21 +02002686/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002687static int gtp_error_ind_resp(struct gsn_t *gsn, uint8_t version,
jjako08d331d2003-10-13 20:33:30 +00002688 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002689 void *pack, unsigned len)
2690{
Harald Weltebed35df2011-11-02 13:06:18 +01002691 union gtp_packet packet;
2692 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2693
Harald Welte54d082e2017-08-12 22:43:21 +02002694 if (version == 1) {
2695 /* Mandatory 7.7.13 TEI Data I */
2696 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2697 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2698
2699 /* Mandatory 7.7.32 GSN Address */
2700 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2701 sizeof(gsn->gsnu), &gsn->gsnu);
2702 }
2703
Harald Weltebed35df2011-11-02 13:06:18 +01002704 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2705 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002706}
2707
2708/* Handle Error Indication */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002709static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002710 struct sockaddr_in *peer, void *pack, unsigned len)
2711{
Harald Welte37d5b152017-08-12 23:58:29 +02002712 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002713 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002714
Harald Weltebed35df2011-11-02 13:06:18 +01002715 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002716 if (version == 0) {
2717 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
2718 gsn->err_unknownpdp++;
2719 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2720 "Unknown PDP context\n");
2721 return EOF;
2722 }
2723 } else if (version == 1) {
2724 /* we have to look-up based on the *peer* TEID */
2725 int hlen = get_hlen(pack);
2726 uint32_t teid_gn;
2727
2728 /* Decode information elements */
2729 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2730 gsn->invalid++;
2731 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2732 "Invalid message format\n");
2733 return EOF;
2734 }
2735
2736 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2737 gsn->missing++;
2738 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2739 "Missing mandatory information field\n");
2740 return EOF;
2741 }
2742
2743 if (pdp_getgtp1_peer_d(&pdp, peer, teid_gn)) {
2744 gsn->err_unknownpdp++;
2745 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2746 return EOF;
2747 }
Harald Weltebed35df2011-11-02 13:06:18 +01002748 }
jjako52c24142002-12-16 13:33:51 +00002749
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002750 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2751 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002752
Harald Weltebd228242017-11-06 03:16:49 +09002753 /* This is obvious from above code, given the semantics of the
2754 * functions above, but Coverity doesn't figure this out, so
2755 * let's make it clear. It's good style anyway in case above
2756 * code should ever change. */
2757 OSMO_ASSERT(pdp);
2758
Pau Espin Pedrol0d0b0592019-05-29 20:42:09 +02002759 gtp_freepdp(gsn, pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01002760 return 0;
jjako52c24142002-12-16 13:33:51 +00002761}
2762
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002763static int gtp_gpdu_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002764 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2765{
jjako08d331d2003-10-13 20:33:30 +00002766
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002767 int hlen;
jjako52c24142002-12-16 13:33:51 +00002768
Harald Weltebed35df2011-11-02 13:06:18 +01002769 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002770
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002771 switch (version) {
2772 case 0:
Harald Weltebed35df2011-11-02 13:06:18 +01002773 if (pdp_getgtp0
2774 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2775 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002776 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002777 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002778 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2779 len);
2780 }
2781 hlen = GTP0_HEADER_SIZE;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002782 break;
2783 case 1:
Harald Weltebed35df2011-11-02 13:06:18 +01002784 if (pdp_getgtp1
2785 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2786 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002787 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002788 len, "Unknown PDP context, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002789 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2790 len);
2791 }
jjako08d331d2003-10-13 20:33:30 +00002792
Harald Weltebed35df2011-11-02 13:06:18 +01002793 /* Is this a long or a short header ? */
2794 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2795 hlen = GTP1_HEADER_SIZE_LONG;
2796 else
2797 hlen = GTP1_HEADER_SIZE_SHORT;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002798 break;
2799 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002800 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002801 "Unknown version: %d\n", version);
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002802 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002803 }
jjako08d331d2003-10-13 20:33:30 +00002804
Harald Weltebed35df2011-11-02 13:06:18 +01002805 /* If the GPDU was not from the peer GSN tell him to delete context */
2806 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2807 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002808 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002809 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2810 }
jjako52c24142002-12-16 13:33:51 +00002811
Harald Weltebed35df2011-11-02 13:06:18 +01002812 /* Callback function */
2813 if (gsn->cb_data_ind != 0)
2814 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2815
2816 return 0;
jjako52c24142002-12-16 13:33:51 +00002817}
2818
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002819/* Receives GTP packet and sends off for further processing
jjako52c24142002-12-16 13:33:51 +00002820 * Function will check the validity of the header. If the header
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002821 * is not valid the packet is either dropped or a version not
2822 * supported is returned to the peer.
jjako52c24142002-12-16 13:33:51 +00002823 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002824int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002825{
Harald Weltebed35df2011-11-02 13:06:18 +01002826 unsigned char buffer[PACKET_MAX];
2827 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002828 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002829 int status;
2830 struct gtp0_header *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002831 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002832 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002833
Harald Weltebed35df2011-11-02 13:06:18 +01002834 /* TODO: Need strategy of userspace buffering and blocking */
2835 /* Currently read is non-blocking and send is blocking. */
2836 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002837
Harald Weltebed35df2011-11-02 13:06:18 +01002838 while (1) { /* Loop until no more to read */
2839 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002840 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002841 return -1;
2842 }
2843 peerlen = sizeof(peer);
2844 if ((status =
2845 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2846 (struct sockaddr *)&peer, &peerlen)) < 0) {
2847 if (errno == EAGAIN)
2848 return 0;
2849 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002850 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002851 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002852 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2853 status, status ? strerror(errno) : "No error");
2854 return -1;
2855 }
jjako1db1c812003-07-06 20:53:57 +00002856
Harald Weltebed35df2011-11-02 13:06:18 +01002857 /* Need at least 1 byte in order to check version */
2858 if (status < (1)) {
2859 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002860 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2861 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002862 continue;
2863 }
jjako08d331d2003-10-13 20:33:30 +00002864
Harald Weltebed35df2011-11-02 13:06:18 +01002865 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002866
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002867 version = GTPHDR_F_GET_VER(pheader->flags);
2868
Harald Weltebed35df2011-11-02 13:06:18 +01002869 /* Version should be gtp0 (or earlier) */
2870 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2871 /* GTP 0 messages. If other version message is received we reply that we */
2872 /* only support version 0, implying that this is the only version */
2873 /* supported on this port */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002874 if (version > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002875 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01002876 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2877 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002878 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2879 continue;
2880 }
2881
2882 /* Check length of gtp0 packet */
2883 if (status < GTP0_HEADER_SIZE) {
2884 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002885 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2886 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002887 continue; /* Silently discard 29.60: 11.1.2 */
2888 }
2889
2890 /* Check packet length field versus length of packet */
2891 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2892 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002893 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002894 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002895 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002896 continue; /* Silently discard */
2897 }
2898
2899 if ((gsn->mode == GTP_MODE_GGSN) &&
2900 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002901 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002902 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002903 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002904 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002905 "Unexpected GTPv0 Signalling Message '%s'\n",
2906 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002907 continue; /* Silently discard 29.60: 11.1.4 */
2908 }
2909
2910 if ((gsn->mode == GTP_MODE_SGSN) &&
2911 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002912 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002913 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002914 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002915 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002916 "Unexpected GTPv0 Signalling Message '%s'\n",
2917 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002918 continue; /* Silently discard 29.60: 11.1.4 */
2919 }
2920
2921 switch (pheader->type) {
2922 case GTP_ECHO_REQ:
2923 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2924 break;
2925 case GTP_ECHO_RSP:
2926 gtp_echo_conf(gsn, version, &peer, buffer, status);
2927 break;
2928 case GTP_NOT_SUPPORTED:
2929 gtp_unsup_ind(gsn, &peer, buffer, status);
2930 break;
2931 case GTP_CREATE_PDP_REQ:
2932 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2933 status);
2934 break;
2935 case GTP_CREATE_PDP_RSP:
2936 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2937 status);
2938 break;
2939 case GTP_UPDATE_PDP_REQ:
2940 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2941 status);
2942 break;
2943 case GTP_UPDATE_PDP_RSP:
2944 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2945 status);
2946 break;
2947 case GTP_DELETE_PDP_REQ:
2948 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2949 status);
2950 break;
2951 case GTP_DELETE_PDP_RSP:
2952 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2953 status);
2954 break;
2955 case GTP_ERROR:
2956 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2957 break;
2958 case GTP_GPDU:
2959 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2960 break;
2961 default:
2962 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002963 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2964 "Unknown GTP message type received: %d\n",
2965 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002966 break;
2967 }
2968 }
jjako08d331d2003-10-13 20:33:30 +00002969}
2970
jjako08d331d2003-10-13 20:33:30 +00002971int gtp_decaps1c(struct gsn_t *gsn)
2972{
Harald Weltebed35df2011-11-02 13:06:18 +01002973 unsigned char buffer[PACKET_MAX];
2974 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002975 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002976 int status;
2977 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002978 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002979 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002980
Harald Weltebed35df2011-11-02 13:06:18 +01002981 /* TODO: Need strategy of userspace buffering and blocking */
2982 /* Currently read is non-blocking and send is blocking. */
2983 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002984
Harald Weltebed35df2011-11-02 13:06:18 +01002985 while (1) { /* Loop until no more to read */
2986 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002987 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002988 return -1;
2989 }
2990 peerlen = sizeof(peer);
2991 if ((status =
2992 recvfrom(fd, buffer, sizeof(buffer), 0,
2993 (struct sockaddr *)&peer, &peerlen)) < 0) {
2994 if (errno == EAGAIN)
2995 return 0;
2996 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002997 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002998 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002999 fd, (unsigned long)buffer, sizeof(buffer),
3000 status, status ? strerror(errno) : "No error");
3001 return -1;
3002 }
jjako08d331d2003-10-13 20:33:30 +00003003
Harald Weltebed35df2011-11-02 13:06:18 +01003004 /* Need at least 1 byte in order to check version */
3005 if (status < (1)) {
3006 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003007 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3008 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003009 continue;
3010 }
jjako08d331d2003-10-13 20:33:30 +00003011
Harald Weltebed35df2011-11-02 13:06:18 +01003012 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003013
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003014 version = GTPHDR_F_GET_VER(pheader->flags);
3015
Harald Weltebed35df2011-11-02 13:06:18 +01003016 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003017 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003018 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003019 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3020 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003021 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
3022 /*29.60: 11.1.1 */
3023 continue;
3024 }
jjako08d331d2003-10-13 20:33:30 +00003025
Harald Weltebed35df2011-11-02 13:06:18 +01003026 /* Version must be at least GTP 1 */
3027 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3028 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3029 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003030 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003031 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003032 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3033 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003034 continue;
3035 }
jjako08d331d2003-10-13 20:33:30 +00003036
Harald Weltebed35df2011-11-02 13:06:18 +01003037 /* Check packet flag field */
3038 if (((pheader->flags & 0xf7) != 0x32)) {
3039 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003040 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003041 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003042 continue;
3043 }
jjako2c381332003-10-21 19:09:53 +00003044
Harald Weltebed35df2011-11-02 13:06:18 +01003045 /* Check length of packet */
3046 if (status < GTP1_HEADER_SIZE_LONG) {
3047 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003048 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3049 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003050 continue; /* Silently discard 29.60: 11.1.2 */
3051 }
jjako2c381332003-10-21 19:09:53 +00003052
Harald Weltebed35df2011-11-02 13:06:18 +01003053 /* Check packet length field versus length of packet */
3054 if (status !=
3055 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3056 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003057 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003058 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003059 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003060 continue; /* Silently discard */
3061 }
jjako1db1c812003-07-06 20:53:57 +00003062
Harald Weltebed35df2011-11-02 13:06:18 +01003063 /* Check for extension headers */
3064 /* TODO: We really should cycle through the headers and determine */
3065 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003066 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003067 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003068 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3069 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003070 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3071 status);
jjako1db1c812003-07-06 20:53:57 +00003072
Harald Weltebed35df2011-11-02 13:06:18 +01003073 continue;
3074 }
3075
3076 if ((gsn->mode == GTP_MODE_GGSN) &&
3077 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003078 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003079 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003080 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003081 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003082 "Unexpected GTPv1 Signalling Message '%s'\n",
3083 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003084 continue; /* Silently discard 29.60: 11.1.4 */
3085 }
3086
3087 if ((gsn->mode == GTP_MODE_SGSN) &&
3088 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003089 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003090 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003091 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003092 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003093 "Unexpected GTPv1 Signalling Message '%s'\n",
3094 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003095 continue; /* Silently discard 29.60: 11.1.4 */
3096 }
3097
3098 switch (pheader->type) {
3099 case GTP_ECHO_REQ:
3100 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3101 break;
3102 case GTP_ECHO_RSP:
3103 gtp_echo_conf(gsn, version, &peer, buffer, status);
3104 break;
3105 case GTP_NOT_SUPPORTED:
3106 gtp_unsup_ind(gsn, &peer, buffer, status);
3107 break;
3108 case GTP_SUPP_EXT_HEADER:
3109 gtp_extheader_ind(gsn, &peer, buffer, status);
3110 break;
3111 case GTP_CREATE_PDP_REQ:
3112 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3113 status);
3114 break;
3115 case GTP_CREATE_PDP_RSP:
3116 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3117 status);
3118 break;
3119 case GTP_UPDATE_PDP_REQ:
3120 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3121 status);
3122 break;
3123 case GTP_UPDATE_PDP_RSP:
3124 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3125 status);
3126 break;
3127 case GTP_DELETE_PDP_REQ:
3128 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3129 status);
3130 break;
3131 case GTP_DELETE_PDP_RSP:
3132 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3133 status);
3134 break;
3135 case GTP_ERROR:
3136 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3137 break;
3138 default:
3139 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003140 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3141 "Unknown GTP message type received: %u\n",
3142 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003143 break;
3144 }
3145 }
jjako52c24142002-12-16 13:33:51 +00003146}
3147
jjako08d331d2003-10-13 20:33:30 +00003148int gtp_decaps1u(struct gsn_t *gsn)
3149{
Harald Weltebed35df2011-11-02 13:06:18 +01003150 unsigned char buffer[PACKET_MAX];
3151 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003152 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003153 int status;
3154 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003155 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003156 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003157
Harald Weltebed35df2011-11-02 13:06:18 +01003158 /* TODO: Need strategy of userspace buffering and blocking */
3159 /* Currently read is non-blocking and send is blocking. */
3160 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003161
Harald Weltebed35df2011-11-02 13:06:18 +01003162 while (1) { /* Loop until no more to read */
3163 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003164 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003165 return -1;
3166 }
3167 peerlen = sizeof(peer);
3168 if ((status =
3169 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3170 (struct sockaddr *)&peer, &peerlen)) < 0) {
3171 if (errno == EAGAIN)
3172 return 0;
3173 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003174 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003175 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003176 gsn->fd1u, (unsigned long)buffer,
3177 sizeof(buffer), status,
3178 status ? strerror(errno) : "No error");
3179 return -1;
3180 }
jjako08d331d2003-10-13 20:33:30 +00003181
Harald Weltebed35df2011-11-02 13:06:18 +01003182 /* Need at least 1 byte in order to check version */
3183 if (status < (1)) {
3184 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003185 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3186 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003187 continue;
3188 }
jjako08d331d2003-10-13 20:33:30 +00003189
Harald Weltebed35df2011-11-02 13:06:18 +01003190 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003191
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003192 version = GTPHDR_F_GET_VER(pheader->flags);
3193
Harald Weltebed35df2011-11-02 13:06:18 +01003194 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003195 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003196 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003197 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3198 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003199 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3200 continue;
3201 }
jjako08d331d2003-10-13 20:33:30 +00003202
Harald Weltebed35df2011-11-02 13:06:18 +01003203 /* Version must be at least GTP 1 */
3204 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3205 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3206 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003207 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003208 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003209 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3210 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003211 continue;
3212 }
jjako2c381332003-10-21 19:09:53 +00003213
Harald Weltebed35df2011-11-02 13:06:18 +01003214 /* Check packet flag field (allow both with and without sequence number) */
3215 if (((pheader->flags & 0xf5) != 0x30)) {
3216 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003217 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003218 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003219 continue;
3220 }
jjako2c381332003-10-21 19:09:53 +00003221
Harald Weltebed35df2011-11-02 13:06:18 +01003222 /* Check length of packet */
3223 if (status < GTP1_HEADER_SIZE_SHORT) {
3224 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003225 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3226 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003227 continue; /* Silently discard 29.60: 11.1.2 */
3228 }
3229
3230 /* Check packet length field versus length of packet */
3231 if (status !=
3232 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3233 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003234 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003235 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003236 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003237 continue; /* Silently discard */
3238 }
3239
3240 /* Check for extension headers */
3241 /* TODO: We really should cycle through the headers and determine */
3242 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003243 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003244 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003245 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3246 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003247 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3248 status);
3249
3250 continue;
3251 }
3252
3253 switch (pheader->type) {
3254 case GTP_ECHO_REQ:
3255 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3256 break;
3257 case GTP_ECHO_RSP:
3258 gtp_echo_conf(gsn, version, &peer, buffer, status);
3259 break;
3260 case GTP_SUPP_EXT_HEADER:
3261 gtp_extheader_ind(gsn, &peer, buffer, status);
3262 break;
3263 case GTP_ERROR:
3264 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3265 break;
3266 /* Supported header extensions */
3267 case GTP_GPDU:
3268 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3269 break;
3270 default:
3271 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003272 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3273 "Unknown GTP message type received: %u\n",
3274 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003275 break;
3276 }
3277 }
jjako08d331d2003-10-13 20:33:30 +00003278}
3279
Harald Weltebed35df2011-11-02 13:06:18 +01003280int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003281{
Harald Weltebed35df2011-11-02 13:06:18 +01003282 union gtp_packet packet;
3283 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003284 struct msghdr msgh;
3285 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003286 int fd;
jjako52c24142002-12-16 13:33:51 +00003287
Harald Welte471e3492017-09-24 16:12:39 +08003288 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003289 memset(&addr, 0, sizeof(addr));
3290 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003291#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003292 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003293#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003294 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003295
Harald Welte471e3492017-09-24 16:12:39 +08003296 /* prepare msghdr */
3297 memset(&msgh, 0, sizeof(msgh));
3298 msgh.msg_name = &addr;
3299 msgh.msg_namelen = sizeof(addr);
3300 msgh.msg_iov = iov;
3301 msgh.msg_iovlen = ARRAY_SIZE(iov);
3302
3303 /* prepare iovectors */
3304 iov[0].iov_base = &packet;
3305 /* iov[0].iov_len is not known here yet */
3306 iov[1].iov_base = pack;
3307 iov[1].iov_len = len;
3308
Harald Weltebed35df2011-11-02 13:06:18 +01003309 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003310
Harald Welte471e3492017-09-24 16:12:39 +08003311 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003312 addr.sin_port = htons(GTP0_PORT);
3313 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003314
Harald Weltebed35df2011-11-02 13:06:18 +01003315 get_default_gtp(0, GTP_GPDU, &packet);
3316 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003317 if (pdp->tx_gpdu_seq)
3318 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3319 else
3320 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003321 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003322 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003323 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003324
Harald Weltebed35df2011-11-02 13:06:18 +01003325 addr.sin_port = htons(GTP1U_PORT);
3326 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003327
Harald Weltebed35df2011-11-02 13:06:18 +01003328 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003329 if (pdp->tx_gpdu_seq) {
3330 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3331 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3332 GTP1_HEADER_SIZE_LONG);
3333 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3334 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3335 } else {
3336 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3337 packet.gtp1s.h.length = hton16(len);
3338 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3339 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3340 }
Harald Weltebed35df2011-11-02 13:06:18 +01003341 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003342 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003343 return EOF;
3344 }
3345
3346 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003347 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003348 return -1;
3349 }
3350
Harald Welte471e3492017-09-24 16:12:39 +08003351 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003352 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003353 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003354 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003355 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3356 strerror(errno));
3357 return EOF;
3358 }
3359 return 0;
jjako52c24142002-12-16 13:33:51 +00003360}
3361
jjako52c24142002-12-16 13:33:51 +00003362/* ***********************************************************
3363 * Conversion functions
3364 *************************************************************/
3365
jjako52c24142002-12-16 13:33:51 +00003366/* ***********************************************************
3367 * IP address conversion functions
3368 * There exist several types of address representations:
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01003369 * - eua: End User Address. (29.060, 7.7.27, message type 128)
jjako52c24142002-12-16 13:33:51 +00003370 * Used for signalling address to mobile station. Supports IPv4
3371 * IPv6 x.25 etc. etc.
3372 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3373 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3374 * - in_addr: IPv4 address struct.
3375 * - sockaddr_in: Socket API representation of IP address and
3376 * port number.
3377 *************************************************************/
3378
Harald Weltebed35df2011-11-02 13:06:18 +01003379int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3380{
Harald Weltecee75462017-09-24 17:45:05 +08003381 eua->v[0] = PDP_EUA_ORG_IETF;
3382 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003383 if (src) {
3384 eua->l = 6;
3385 memcpy(&eua->v[2], src, 4);
3386 } else {
3387 eua->l = 2;
3388 }
3389 return 0;
jjako52c24142002-12-16 13:33:51 +00003390}
3391
Harald Weltebed35df2011-11-02 13:06:18 +01003392int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3393{
Harald Weltecee75462017-09-24 17:45:05 +08003394 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 +01003395 return -1; /* Not IPv4 address */
3396 memcpy(dst, &eua->v[2], 4);
3397 return 0;
jjako52c24142002-12-16 13:33:51 +00003398}
3399
Harald Weltebed35df2011-11-02 13:06:18 +01003400int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3401{
3402 memset(dst, 0, sizeof(struct in_addr));
3403 if (gsna->l != 4)
3404 return EOF; /* Return if not IPv4 */
3405 memcpy(dst, gsna->v, gsna->l);
3406 return 0;
jjako52c24142002-12-16 13:33:51 +00003407}
3408
Harald Weltebed35df2011-11-02 13:06:18 +01003409int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3410{
3411 memset(gsna, 0, sizeof(struct ul16_t));
3412 gsna->l = 4;
3413 memcpy(gsna->v, src, gsna->l);
3414 return 0;
jjako52c24142002-12-16 13:33:51 +00003415}
Harald Welteb10ee082017-08-12 19:29:16 +02003416
3417/* TS 29.060 has yet again a different encoding for IMSIs than
3418 * what we have in other places, so we cannot use the gsm48
3419 * decoding functions. Also, libgtp uses an uint64_t in
3420 * _network byte order_ to contain BCD digits ?!? */
3421const char *imsi_gtp2str(const uint64_t *imsi)
3422{
Harald Weltea06120d2017-11-06 03:12:54 +09003423 static char buf[sizeof(*imsi)*2+1];
Harald Welteb10ee082017-08-12 19:29:16 +02003424 const uint8_t *imsi8 = (const uint8_t *) imsi;
3425 unsigned int i, j = 0;
3426
3427 for (i = 0; i < sizeof(*imsi); i++) {
3428 uint8_t nibble;
3429
3430 nibble = imsi8[i] & 0xf;
3431 if (nibble == 0xf)
3432 break;
3433 buf[j++] = osmo_bcd2char(nibble);
3434
3435 nibble = imsi8[i] >> 4;
3436 if (nibble == 0xf)
3437 break;
3438 buf[j++] = osmo_bcd2char(nibble);
3439 }
3440
3441 buf[j++] = '\0';
3442 return buf;
3443}