blob: 95abbef38cc73958e55f2a409ef313bf63fd8112 [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
jjako52c24142002-12-16 13:33:51 +0000134/* gtp_new */
135/* gtp_free */
136
Harald Weltebed35df2011-11-02 13:06:18 +0100137int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
138 uint64_t imsi, uint8_t nsapi)
139{
Harald Weltee257be12017-08-12 14:55:09 +0200140 int rc;
141 rc = pdp_newpdp(pdp, imsi, nsapi, NULL);
142 if (!rc && *pdp)
143 (*pdp)->gsn = gsn;
144 return rc;
jjako52c24142002-12-16 13:33:51 +0000145}
146
Harald Weltebed35df2011-11-02 13:06:18 +0100147int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp)
148{
149 return pdp_freepdp(pdp);
jjako52c24142002-12-16 13:33:51 +0000150}
151
jjako52c24142002-12-16 13:33:51 +0000152/* gtp_gpdu */
153
Harald Weltebed35df2011-11-02 13:06:18 +0100154extern int gtp_fd(struct gsn_t *gsn)
155{
156 return gsn->fd0;
jjako52c24142002-12-16 13:33:51 +0000157}
158
159/* gtp_decaps */
160/* gtp_retrans */
161/* gtp_retranstimeout */
162
jjako08d331d2003-10-13 20:33:30 +0000163int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100164 int (*cb) (struct sockaddr_in * peer))
165{
166 gsn->cb_unsup_ind = cb;
167 return 0;
jjako08d331d2003-10-13 20:33:30 +0000168}
169
jjako2c381332003-10-21 19:09:53 +0000170int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100171 int (*cb) (struct sockaddr_in * peer))
172{
173 gsn->cb_extheader_ind = cb;
174 return 0;
jjako2c381332003-10-21 19:09:53 +0000175}
176
jjako08d331d2003-10-13 20:33:30 +0000177/* API: Initialise delete context callback */
178/* Called whenever a pdp context is deleted for any reason */
Harald Weltebed35df2011-11-02 13:06:18 +0100179int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
jjako52c24142002-12-16 13:33:51 +0000180{
Harald Weltebed35df2011-11-02 13:06:18 +0100181 gsn->cb_delete_context = cb;
182 return 0;
jjako52c24142002-12-16 13:33:51 +0000183}
184
jjako52c24142002-12-16 13:33:51 +0000185int gtp_set_cb_conf(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100186 int (*cb) (int type, int cause,
187 struct pdp_t * pdp, void *cbp))
188{
189 gsn->cb_conf = cb;
190 return 0;
jjako52c24142002-12-16 13:33:51 +0000191}
192
Harald Welte629e9862010-12-24 20:58:09 +0100193int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100194 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
195{
196 gsn->cb_recovery = cb;
197 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100198}
199
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +0100200int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100201 int (*cb_data_ind) (struct pdp_t * pdp,
202 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000203{
Harald Weltebed35df2011-11-02 13:06:18 +0100204 gsn->cb_data_ind = cb_data_ind;
205 return 0;
jjako52c24142002-12-16 13:33:51 +0000206}
207
jjako08d331d2003-10-13 20:33:30 +0000208/**
209 * get_default_gtp()
210 * Generate a GPRS Tunneling Protocol signalling packet header, depending
211 * on GTP version and message type. pdp is used for teid/flow label.
212 * *packet must be allocated by the calling function, and be large enough
213 * to hold the packet header.
214 * returns the length of the header. 0 on error.
215 **/
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100216static unsigned int get_default_gtp(uint8_t version, uint8_t type, void *packet)
Harald Weltebed35df2011-11-02 13:06:18 +0100217{
218 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
219 struct gtp1_header_long *gtp1_default =
220 (struct gtp1_header_long *)packet;
221 switch (version) {
222 case 0:
223 /* Initialise "standard" GTP0 header */
224 memset(gtp0_default, 0, sizeof(struct gtp0_header));
225 gtp0_default->flags = 0x1e;
226 gtp0_default->type = hton8(type);
227 gtp0_default->spare1 = 0xff;
228 gtp0_default->spare2 = 0xff;
229 gtp0_default->spare3 = 0xff;
230 gtp0_default->number = 0xff;
231 return GTP0_HEADER_SIZE;
232 case 1:
233 /* Initialise "standard" GTP1 header */
234 /* 29.060: 8.2: S=1 and PN=0 */
235 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
236 /* and Supported Extension Headers Notification, the S field shall be */
237 /* set to 1 */
238 /* Currently extension headers are not supported */
239 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
Harald Weltefed598f2017-09-24 16:39:22 +0800240 /* No extension, enable sequence, no N-PDU */
241 gtp1_default->flags = GTPHDR_F_VER(1) | GTP1HDR_F_GTP1 | GTP1HDR_F_SEQ;
Harald Weltebed35df2011-11-02 13:06:18 +0100242 gtp1_default->type = hton8(type);
243 return GTP1_HEADER_SIZE_LONG;
244 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100245 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100246 "Unknown GTP packet version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +0100247 return 0;
248 }
jjako52c24142002-12-16 13:33:51 +0000249}
250
jjako08d331d2003-10-13 20:33:30 +0000251/**
252 * get_seq()
253 * Get sequence number of a packet.
254 * Returns 0 on error
255 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100256static uint16_t get_seq(void *pack)
257{
258 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800259 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000260
Harald Weltefed598f2017-09-24 16:39:22 +0800261 if (ver == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +0100262 return ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800263 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100264 return ntoh16(packet->gtp1l.h.seq);
265 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100266 return 0;
267 }
jjako08d331d2003-10-13 20:33:30 +0000268}
269
270/**
271 * get_tid()
272 * Get tunnel identifier of a packet.
273 * Returns 0 on error
274 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100275static uint64_t get_tid(void *pack)
276{
277 union gtp_packet *packet = (union gtp_packet *)pack;
278
Harald Weltefed598f2017-09-24 16:39:22 +0800279 if (GTPHDR_F_GET_VER(packet->flags) == 0) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100280 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100281 }
282 return 0;
jjako08d331d2003-10-13 20:33:30 +0000283}
284
285/**
286 * get_hlen()
287 * Get the header length of a packet.
288 * Returns 0 on error
289 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100290static uint16_t get_hlen(void *pack)
291{
292 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800293 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000294
Harald Weltefed598f2017-09-24 16:39:22 +0800295 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100296 return GTP0_HEADER_SIZE;
Harald Weltefed598f2017-09-24 16:39:22 +0800297 } else if (ver == 1 && (packet->flags & 0x07) == 0) { /* Short version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100298 return GTP1_HEADER_SIZE_SHORT;
Harald Weltefed598f2017-09-24 16:39:22 +0800299 } else if (ver == 1) { /* Version 1 with seq/n-pdu/ext */
300 return GTP1_HEADER_SIZE_LONG;
Harald Weltebed35df2011-11-02 13:06:18 +0100301 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100302 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100303 return 0;
304 }
jjako08d331d2003-10-13 20:33:30 +0000305}
306
307/**
308 * get_tei()
309 * Get the tunnel endpoint identifier (flow label) of a packet.
310 * Returns 0xffffffff on error.
311 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100312static uint32_t get_tei(void *pack)
313{
314 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800315 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000316
Harald Weltefed598f2017-09-24 16:39:22 +0800317 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100318 return ntoh16(packet->gtp0.h.flow);
Harald Weltefed598f2017-09-24 16:39:22 +0800319 } else if (ver == 1) { /* Version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100320 return ntoh32(packet->gtp1l.h.tei);
321 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100322 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100323 return 0xffffffff;
324 }
jjako08d331d2003-10-13 20:33:30 +0000325}
jjakoa7cd2492003-04-11 09:40:12 +0000326
jjako52c24142002-12-16 13:33:51 +0000327/* ***********************************************************
328 * Reliable delivery of signalling messages
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100329 *
jjako52c24142002-12-16 13:33:51 +0000330 * Sequence numbers are used for both signalling messages and
331 * data messages.
332 *
333 * For data messages each tunnel maintains a sequence counter,
334 * which is incremented by one each time a new data message
335 * is sent. The sequence number starts at (0) zero at tunnel
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100336 * establishment, and wraps around at 65535 (29.060 9.3.1.1
jjako52c24142002-12-16 13:33:51 +0000337 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
338 * or can be used to check the validity of the message in the
339 * receiver, or for reordering af packets.
340 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100341 * For signalling messages the sequence number is used by
jjako52c24142002-12-16 13:33:51 +0000342 * signalling messages for which a response is defined. A response
343 * message should copy the sequence from the corresponding request
344 * message. The sequence number "unambiguously" identifies a request
345 * message within a given path, with a path being defined as a set of
346 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
347 * messages shall be responded to, and all response messages associated
348 * with a certain request shall always include the same information"
349 *
350 * We take this to mean that the GSN transmitting a request is free to
351 * choose the sequence number, as long as it is unique within a given path.
352 * It means that we are allowed to count backwards, or roll over at 17
353 * if we prefer that. It also means that we can use the same counter for
354 * all paths. This has the advantage that the transmitted request sequence
355 * numbers are unique within each GSN, and also we dont have to mess around
356 * with path setup and teardown.
357 *
358 * If a response message is lost, the request will be retransmitted, and
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100359 * the receiving GSN will receive a "duplicated" request. The standard
jjako52c24142002-12-16 13:33:51 +0000360 * requires the receiving GSN to send a response, with the same information
361 * as in the original response. For most messages this happens automatically:
362 *
363 * Echo: Automatically dublicates the original response
364 * Create pdp context: The SGSN may send create context request even if
365 * a context allready exist (imsi+nsapi?). This means that the reply will
366 automatically dublicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000367 * side effects in the application which is asked twice to validate
368 * the login.
jjako52c24142002-12-16 13:33:51 +0000369 * Update pdp context: Automatically dublicates the original response???
370 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
371 * a nonexist reply message.
372 *
373 * The correct solution will be to make a queue containing response messages.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100374 * This queue should be checked whenever a request is received. If the
jjako52c24142002-12-16 13:33:51 +0000375 * response is allready in the queue that response should be transmitted.
376 * It should be possible to find messages in this queue on the basis of
377 * the sequence number and peer GSN IP address (The sequense number is unique
378 * within each path). This need to be implemented by a hash table. Furthermore
379 * it should be possibly to delete messages based on a timeout. This can be
380 * achieved by means of a linked list. The timeout value need to be larger
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100381 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
jjako52c24142002-12-16 13:33:51 +0000382 * set in the peer GSN, so there is no way to know these parameters. On the
383 * other hand the timeout value need to be so small that we do not receive
384 * wraparound sequence numbere before the message is deleted. 60 seconds is
385 * probably not a bad choise.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100386 *
jjako52c24142002-12-16 13:33:51 +0000387 * This queue however is first really needed from gtp1.
388 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100389 * gtp_req:
jjako52c24142002-12-16 13:33:51 +0000390 * Send off a signalling message with appropiate sequence
391 * number. Store packet in queue.
392 * gtp_conf:
393 * Remove an incoming confirmation from the queue
394 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000395 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000396 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000397 * gtp_notification:
398 * Send off a notification message. This is neither a request nor
399 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000400 * gtp_retrans:
401 * Retransmit any outstanding packets which have exceeded
402 * a predefined timeout.
403 *************************************************************/
404
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100405static int gtp_req(struct gsn_t *gsn, uint8_t version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100406 union gtp_packet *packet, int len,
407 struct in_addr *inetaddr, void *cbp)
408{
Harald Weltefed598f2017-09-24 16:39:22 +0800409 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100410 struct sockaddr_in addr;
411 struct qmsg_t *qmsg;
412 int fd;
jjako08d331d2003-10-13 20:33:30 +0000413
Harald Weltebed35df2011-11-02 13:06:18 +0100414 memset(&addr, 0, sizeof(addr));
415 addr.sin_family = AF_INET;
416 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000417#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100418 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000419#endif
jjako52c24142002-12-16 13:33:51 +0000420
Harald Weltefed598f2017-09-24 16:39:22 +0800421 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100422 addr.sin_port = htons(GTP0_PORT);
423 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
424 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100425 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100426 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100427 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100428 }
Harald Weltebed35df2011-11-02 13:06:18 +0100429 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
430 || (packet->gtp0.h.type == GTP_ERROR)))
431 packet->gtp0.h.flow = hton16(pdp->flru);
432 else if (pdp)
433 packet->gtp0.h.flow = hton16(pdp->flrc);
434 fd = gsn->fd0;
Harald Weltefed598f2017-09-24 16:39:22 +0800435 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100436 addr.sin_port = htons(GTP1C_PORT);
437 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
438 packet->gtp1l.h.seq = hton16(gsn->seq_next);
439 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
440 (packet->gtp1l.h.type == GTP_ERROR)))
441 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
442 else if (pdp)
443 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
444 fd = gsn->fd1c;
445 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100446 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100447 return -1;
448 }
jjako52c24142002-12-16 13:33:51 +0000449
Harald Weltebed35df2011-11-02 13:06:18 +0100450 if (sendto(fd, packet, len, 0,
451 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
452 gsn->err_sendto++;
Max14b1b632017-08-21 20:14:59 +0200453 LOGP(DLGTP, LOGL_ERROR, "Sendto(fd=%d, msg=%lx, len=%d, dst=%s) failed: Error = %s\n", fd,
454 (unsigned long)&packet, len, inet_ntoa(addr.sin_addr), strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100455 return -1;
456 }
457
458 /* Use new queue structure */
459 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
460 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100461 LOGP(DLGTP, LOGL_ERROR,
462 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100463 } else {
464 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
465 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100466 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100467 qmsg->retrans = 0; /* No retransmissions so far */
468 qmsg->cbp = cbp;
469 qmsg->type = ntoh8(packet->gtp0.h.type);
470 qmsg->fd = fd;
471 }
472 gsn->seq_next++; /* Count up this time */
473 return 0;
jjako52c24142002-12-16 13:33:51 +0000474}
475
476/* gtp_conf
477 * Remove signalling packet from retransmission queue.
478 * return 0 on success, EOF if packet was not found */
479
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100480static int gtp_conf(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100481 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
482{
Harald Weltefed598f2017-09-24 16:39:22 +0800483 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100484 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000485
Harald Weltefed598f2017-09-24 16:39:22 +0800486 if (ver == 0)
Harald Weltebed35df2011-11-02 13:06:18 +0100487 seq = ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800488 else if (ver == 1 && (packet->gtp1l.h.flags & GTP1HDR_F_SEQ))
Harald Weltebed35df2011-11-02 13:06:18 +0100489 seq = ntoh16(packet->gtp1l.h.seq);
490 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100491 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
492 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100493 return EOF;
494 }
jjako08d331d2003-10-13 20:33:30 +0000495
Harald Weltebed35df2011-11-02 13:06:18 +0100496 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
497 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100498 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
499 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100500 return EOF;
501 }
jjako52c24142002-12-16 13:33:51 +0000502
Harald Weltebed35df2011-11-02 13:06:18 +0100503 return 0;
jjako52c24142002-12-16 13:33:51 +0000504}
505
Harald Weltebed35df2011-11-02 13:06:18 +0100506int gtp_retrans(struct gsn_t *gsn)
507{
508 /* Retransmit any outstanding packets */
509 /* Remove from queue if maxretrans exceeded */
510 time_t now;
511 struct qmsg_t *qmsg;
512 now = time(NULL);
513 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000514
Harald Welte95848ba2011-11-02 18:17:50 +0100515 /* get first element in queue, as long as the timeout of that
516 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100517 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
518 (qmsg->timeout <= now)) {
519 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100520 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100521 if (gsn->cb_conf)
522 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
523 queue_freemsg(gsn->queue_req, qmsg);
524 } else {
525 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
526 (struct sockaddr *)&qmsg->peer,
527 sizeof(struct sockaddr_in)) < 0) {
528 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100529 LOGP(DLGTP, LOGL_ERROR,
530 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100531 gsn->fd0, (unsigned long)&qmsg->p,
532 qmsg->l, strerror(errno));
533 }
534 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100535 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100536 qmsg->retrans++;
537 }
538 }
jjako52c24142002-12-16 13:33:51 +0000539
Harald Weltebed35df2011-11-02 13:06:18 +0100540 /* Also clean up reply timeouts */
541 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
542 (qmsg->timeout < now)) {
543 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
544 queue_freemsg(gsn->queue_resp, qmsg);
545 }
jjako52c24142002-12-16 13:33:51 +0000546
Harald Weltebed35df2011-11-02 13:06:18 +0100547 return 0;
jjako52c24142002-12-16 13:33:51 +0000548}
549
Harald Weltebed35df2011-11-02 13:06:18 +0100550int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
551{
552 time_t now, later;
553 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000554
Harald Weltebed35df2011-11-02 13:06:18 +0100555 if (queue_getfirst(gsn->queue_req, &qmsg)) {
556 timeout->tv_sec = 10;
557 timeout->tv_usec = 0;
558 } else {
559 now = time(NULL);
560 later = qmsg->timeout;
561 timeout->tv_sec = later - now;
562 timeout->tv_usec = 0;
563 if (timeout->tv_sec < 0)
564 timeout->tv_sec = 0; /* No negative allowed */
565 if (timeout->tv_sec > 10)
566 timeout->tv_sec = 10; /* Max sleep for 10 sec */
567 }
568 return 0;
jjako52c24142002-12-16 13:33:51 +0000569}
570
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100571static int gtp_resp(uint8_t version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000572 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100573 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
574{
Harald Weltefed598f2017-09-24 16:39:22 +0800575 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100576 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000577
Harald Weltefed598f2017-09-24 16:39:22 +0800578 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100579 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
580 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100581 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100582 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
583 (packet->gtp0.h.type == GTP_ERROR)))
584 packet->gtp0.h.flow = hton16(pdp->flru);
585 else if (pdp)
586 packet->gtp0.h.flow = hton16(pdp->flrc);
Harald Weltefed598f2017-09-24 16:39:22 +0800587 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100588 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
589 packet->gtp1l.h.seq = hton16(seq);
590 if (pdp && (fd == gsn->fd1u))
591 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
592 else if (pdp)
593 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
594 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100595 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100596 return -1;
597 }
jjako08d331d2003-10-13 20:33:30 +0000598
Harald Weltebed35df2011-11-02 13:06:18 +0100599 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100600 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100601 return -1;
602 }
jjako52c24142002-12-16 13:33:51 +0000603
Harald Weltebed35df2011-11-02 13:06:18 +0100604 if (sendto(fd, packet, len, 0,
605 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
606 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100607 LOGP(DLGTP, LOGL_ERROR,
608 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100609 (unsigned long)&packet, len, strerror(errno));
610 return -1;
611 }
612
613 /* Use new queue structure */
614 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
615 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100616 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100617 } else {
618 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
619 qmsg->l = len;
620 qmsg->timeout = time(NULL) + 60; /* When to timeout */
621 qmsg->retrans = 0; /* No retransmissions so far */
622 qmsg->cbp = NULL;
623 qmsg->type = 0;
624 qmsg->fd = fd;
625 }
626 return 0;
jjako52c24142002-12-16 13:33:51 +0000627}
628
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100629static int gtp_notification(struct gsn_t *gsn, uint8_t version,
jjako2c381332003-10-21 19:09:53 +0000630 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100631 struct sockaddr_in *peer, int fd, uint16_t seq)
632{
jjako2c381332003-10-21 19:09:53 +0000633
Harald Weltefed598f2017-09-24 16:39:22 +0800634 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100635 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000636
Harald Weltebed35df2011-11-02 13:06:18 +0100637 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000638
Harald Weltebed35df2011-11-02 13:06:18 +0100639 /* In GTP0 notifications are treated as replies. In GTP1 they
640 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000641
Harald Weltebed35df2011-11-02 13:06:18 +0100642 if (fd == gsn->fd1c)
643 addr.sin_port = htons(GTP1C_PORT);
644 else if (fd == gsn->fd1u)
645 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000646
Harald Weltefed598f2017-09-24 16:39:22 +0800647 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100648 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
649 packet->gtp0.h.seq = hton16(seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800650 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100651 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
652 packet->gtp1l.h.seq = hton16(seq);
653 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100654 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100655 return -1;
656 }
657
658 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100659 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100660 return -1;
661 }
662
663 if (sendto(fd, packet, len, 0,
664 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
665 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100666 LOGP(DLGTP, LOGL_ERROR,
667 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100668 (unsigned long)&packet, len, strerror(errno));
669 return -1;
670 }
671 return 0;
jjako2c381332003-10-21 19:09:53 +0000672}
673
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100674static int gtp_dublicate(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +0100675 struct sockaddr_in *peer, uint16_t seq)
676{
677 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000678
Harald Weltebed35df2011-11-02 13:06:18 +0100679 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
680 return EOF; /* Notfound */
681 }
jjakoa7cd2492003-04-11 09:40:12 +0000682
Harald Weltebed35df2011-11-02 13:06:18 +0100683 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100684 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100685 return -1;
686 }
687
688 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
689 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
690 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100691 LOGP(DLGTP, LOGL_ERROR,
692 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100693 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
694 strerror(errno));
695 }
696 return 0;
jjako52c24142002-12-16 13:33:51 +0000697}
698
jjako52c24142002-12-16 13:33:51 +0000699/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100700static void log_restart(struct gsn_t *gsn)
701{
jjako52c24142002-12-16 13:33:51 +0000702 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200703 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000704 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200705 char *filename;
jjako52c24142002-12-16 13:33:51 +0000706
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200707 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
708 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000709
710 /* We try to open file. On failure we will later try to create file */
711 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100712 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100713 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100714 filename);
715 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100716 rc = fscanf(f, "%d", &counter);
717 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100718 LOGP(DLGTP, LOGL_ERROR,
719 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100720 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100721 }
722 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100723 LOGP(DLGTP, LOGL_ERROR,
724 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100725 }
jjako52c24142002-12-16 13:33:51 +0000726 }
Harald Weltebed35df2011-11-02 13:06:18 +0100727
728 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000729 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100730
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200731 /* Keep the umask closely wrapped around our fopen() call in case the
732 * log outputs cause file creation. */
733 i = umask(022);
734 f = fopen(filename, "w");
735 umask(i);
736 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100737 LOGP(DLGTP, LOGL_ERROR,
738 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100739 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200740 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000741 }
742
jjako52c24142002-12-16 13:33:51 +0000743 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100744close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200745 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100746 LOGP(DLGTP, LOGL_ERROR,
747 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200748free_filename:
749 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000750}
751
jjako1db1c812003-07-06 20:53:57 +0000752int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100753 int mode)
jjako52c24142002-12-16 13:33:51 +0000754{
Harald Weltebed35df2011-11-02 13:06:18 +0100755 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000756
Max14b1b632017-08-21 20:14:59 +0200757 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
jjako52c24142002-12-16 13:33:51 +0000758
Harald Weltebed35df2011-11-02 13:06:18 +0100759 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000760
Harald Weltebed35df2011-11-02 13:06:18 +0100761 (*gsn)->statedir = statedir;
762 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000763
Harald Weltebed35df2011-11-02 13:06:18 +0100764 /* Initialise sequence number */
765 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000766
Harald Weltebed35df2011-11-02 13:06:18 +0100767 /* Initialise request retransmit queue */
768 queue_new(&(*gsn)->queue_req);
769 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000770
Harald Weltebed35df2011-11-02 13:06:18 +0100771 /* Initialise pdp table */
772 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000773
Harald Weltebed35df2011-11-02 13:06:18 +0100774 /* Initialise call back functions */
775 (*gsn)->cb_create_context_ind = 0;
776 (*gsn)->cb_delete_context = 0;
777 (*gsn)->cb_unsup_ind = 0;
778 (*gsn)->cb_conf = 0;
779 (*gsn)->cb_data_ind = 0;
780
781 /* Store function parameters */
782 (*gsn)->gsnc = *listen;
783 (*gsn)->gsnu = *listen;
784 (*gsn)->mode = mode;
785
786 /* Create GTP version 0 socket */
787 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
788 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100789 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200790 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100791 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200792 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100793 }
794
795 memset(&addr, 0, sizeof(addr));
796 addr.sin_family = AF_INET;
797 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
798 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000799#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100800 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000801#endif
jjako08d331d2003-10-13 20:33:30 +0000802
Harald Weltebed35df2011-11-02 13:06:18 +0100803 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
804 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200805 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
806 "bind(fd0=%d) failed: Error = %s\n",
807 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200808 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100809 }
jjako08d331d2003-10-13 20:33:30 +0000810
Harald Weltebed35df2011-11-02 13:06:18 +0100811 /* Create GTP version 1 control plane socket */
812 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
813 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100814 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200815 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100816 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200817 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100818 }
819
820 memset(&addr, 0, sizeof(addr));
821 addr.sin_family = AF_INET;
822 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
823 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000824#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100825 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000826#endif
jjako08d331d2003-10-13 20:33:30 +0000827
Harald Weltebed35df2011-11-02 13:06:18 +0100828 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
829 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200830 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
831 "bind(fd1c=%d) failed: Error = %s\n",
832 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200833 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100834 }
jjako08d331d2003-10-13 20:33:30 +0000835
Harald Weltebed35df2011-11-02 13:06:18 +0100836 /* Create GTP version 1 user plane socket */
837 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
838 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100839 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200840 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100841 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200842 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100843 }
844
845 memset(&addr, 0, sizeof(addr));
846 addr.sin_family = AF_INET;
847 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
848 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000849#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100850 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000851#endif
jjako52c24142002-12-16 13:33:51 +0000852
Harald Weltebed35df2011-11-02 13:06:18 +0100853 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
854 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200855 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +0200856 "bind(fd1u=%d) failed: Error = %s\n",
857 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +0200858 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100859 }
860
861 return 0;
jjako52c24142002-12-16 13:33:51 +0000862}
863
Harald Weltebed35df2011-11-02 13:06:18 +0100864int gtp_free(struct gsn_t *gsn)
865{
jjako52c24142002-12-16 13:33:51 +0000866
Harald Weltebed35df2011-11-02 13:06:18 +0100867 /* Clean up retransmit queues */
868 queue_free(gsn->queue_req);
869 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000870
Harald Weltebed35df2011-11-02 13:06:18 +0100871 close(gsn->fd0);
872 close(gsn->fd1c);
873 close(gsn->fd1u);
874
875 free(gsn);
876 return 0;
jjako52c24142002-12-16 13:33:51 +0000877}
878
879/* ***********************************************************
880 * Path management messages
881 * Messages: echo and version not supported.
882 * A path is connection between two UDP/IP endpoints
883 *
884 * A path is either using GTP0 or GTP1. A path can be
885 * established by any kind of GTP message??
886
887 * Which source port to use?
888 * GTP-C request destination port is 2123/3386
889 * GTP-U request destination port is 2152/3386
890 * T-PDU destination port is 2152/3386.
891 * For the above messages the source port is locally allocated.
892 * For response messages src=rx-dst and dst=rx-src.
893 * For simplicity we should probably use 2123+2152/3386 as
894 * src port even for the cases where src can be locally
895 * allocated. This also means that we have to listen only to
896 * the same ports.
897 * For response messages we need to be able to respond to
898 * the relevant src port even if it is locally allocated by
899 * the peer.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100900 *
jjako52c24142002-12-16 13:33:51 +0000901 * The need for path management!
902 * We might need to keep a list of active paths. This might
903 * be in the form of remote IP address + UDP port numbers.
904 * (We will consider a path astablished if we have a context
905 * with the node in question)
906 *************************************************************/
907
908/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000909int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
910 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000911{
Harald Weltebed35df2011-11-02 13:06:18 +0100912 union gtp_packet packet;
913 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
914 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000915}
916
jjako08d331d2003-10-13 20:33:30 +0000917/* Send off an echo reply */
918int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100919 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000920{
Harald Weltebed35df2011-11-02 13:06:18 +0100921 union gtp_packet packet;
922 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
923 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
924 gsn->restart_counter);
925 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
926 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000927}
928
jjako52c24142002-12-16 13:33:51 +0000929/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +0100930int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
931 int fd, void *pack, unsigned len)
932{
jjako52c24142002-12-16 13:33:51 +0000933
Harald Weltebed35df2011-11-02 13:06:18 +0100934 /* Check if it was a dublicate request */
935 if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
936 return 0;
jjako52c24142002-12-16 13:33:51 +0000937
Harald Weltebed35df2011-11-02 13:06:18 +0100938 /* Send off reply to request */
939 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000940}
941
942/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000943int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100944 void *pack, unsigned len)
945{
946 union gtpie_member *ie[GTPIE_SIZE];
947 unsigned char recovery;
948 void *cbp = NULL;
949 uint8_t type = 0;
950 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000951
Harald Weltebed35df2011-11-02 13:06:18 +0100952 /* Remove packet from queue */
953 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
954 return EOF;
jjako52c24142002-12-16 13:33:51 +0000955
Harald Weltebed35df2011-11-02 13:06:18 +0100956 /* Extract information elements into a pointer array */
957 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
958 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100959 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
960 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100961 if (gsn->cb_conf)
962 gsn->cb_conf(type, EOF, NULL, cbp);
963 return EOF;
964 }
jjako52c24142002-12-16 13:33:51 +0000965
Harald Weltebed35df2011-11-02 13:06:18 +0100966 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
967 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100968 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
969 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100970 if (gsn->cb_conf)
971 gsn->cb_conf(type, EOF, NULL, cbp);
972 return EOF;
973 }
jjako52c24142002-12-16 13:33:51 +0000974
Harald Weltebed35df2011-11-02 13:06:18 +0100975 /* Echo reply packages does not have a cause information element */
976 /* Instead we return the recovery number in the callback function */
977 if (gsn->cb_conf)
978 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +0100979
Harald Weltebed35df2011-11-02 13:06:18 +0100980 if (gsn->cb_recovery)
981 gsn->cb_recovery(peer, recovery);
982
983 return 0;
jjako52c24142002-12-16 13:33:51 +0000984}
985
986/* Send off a Version Not Supported message */
987/* This message is somewhat special in that it actually is a
988 * response to some other message with unsupported GTP version
989 * For this reason it has parameters like a response, and does
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100990 * its own message transmission. No signalling queue is used
jjako52c24142002-12-16 13:33:51 +0000991 * The reply is sent to the peer IP and peer UDP. This means that
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100992 * the peer will be receiving a GTP0 message on a GTP1 port!
jjako52c24142002-12-16 13:33:51 +0000993 * In practice however this will never happen as a GTP0 GSN will
994 * only listen to the GTP0 port, and therefore will never receive
995 * anything else than GTP0 */
996
jjako08d331d2003-10-13 20:33:30 +0000997int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
998 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000999{
Harald Weltebed35df2011-11-02 13:06:18 +01001000 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +00001001
Harald Weltebed35df2011-11-02 13:06:18 +01001002 /* GTP 1 is the highest supported protocol */
1003 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
1004 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +00001005}
1006
1007/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +01001008int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1009 void *pack, unsigned len)
1010{
jjako52c24142002-12-16 13:33:51 +00001011
Harald Weltebed35df2011-11-02 13:06:18 +01001012 if (gsn->cb_unsup_ind)
1013 gsn->cb_unsup_ind(peer);
1014
1015 return 0;
jjako52c24142002-12-16 13:33:51 +00001016}
1017
jjako2c381332003-10-21 19:09:53 +00001018/* Send off an Supported Extension Headers Notification */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001019static int gtp_extheader_req(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
jjako2c381332003-10-21 19:09:53 +00001020 int fd, void *pack, unsigned len)
1021{
Harald Weltebed35df2011-11-02 13:06:18 +01001022 union gtp_packet packet;
1023 unsigned int length =
1024 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +00001025
Harald Weltebed35df2011-11-02 13:06:18 +01001026 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +00001027
Harald Weltebed35df2011-11-02 13:06:18 +01001028 if (version < 1)
1029 return 0;
jjako2c381332003-10-21 19:09:53 +00001030
Harald Weltebed35df2011-11-02 13:06:18 +01001031 /* We report back that we support only PDCP PDU headers */
1032 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
1033 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +00001034
Harald Weltebed35df2011-11-02 13:06:18 +01001035 return gtp_notification(gsn, version, &packet, length,
1036 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +00001037}
1038
1039/* Handle a Supported Extension Headers Notification */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001040static int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001041 void *pack, unsigned len)
1042{
jjako2c381332003-10-21 19:09:53 +00001043
Harald Weltebed35df2011-11-02 13:06:18 +01001044 if (gsn->cb_extheader_ind)
1045 gsn->cb_extheader_ind(peer);
1046
1047 return 0;
jjako2c381332003-10-21 19:09:53 +00001048}
1049
jjako52c24142002-12-16 13:33:51 +00001050/* ***********************************************************
1051 * Session management messages
1052 * Messages: create, update and delete PDP context
1053 *
1054 * Information storage
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001055 * Information storage for each PDP context is defined in
jjako52c24142002-12-16 13:33:51 +00001056 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1057 * PDP-address (IP address), sequence numbers, charging ID.
1058 * For the SGSN it also includes radio related mobility
1059 * information.
1060 *************************************************************/
1061
Harald Welte7b3347b2010-05-15 12:18:46 +02001062/* API: Send Create PDP Context Request (7.3.1) */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001063int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001064 void *cbp)
1065{
1066 union gtp_packet packet;
1067 unsigned int length =
1068 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1069 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001070
Harald Weltebed35df2011-11-02 13:06:18 +01001071 /* TODO: Secondary PDP Context Activation Procedure */
1072 /* In secondary activation procedure the PDP context is identified
1073 by tei in the header. The following fields are omitted: Selection
1074 mode, IMSI, MSISDN, End User Address, Access Point Name and
1075 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001076
Harald Weltebed35df2011-11-02 13:06:18 +01001077 if (pdp->secondary) {
1078 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001079 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001080 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001081 return EOF;
1082 }
1083 }
jjako2c381332003-10-21 19:09:53 +00001084
Harald Weltebed35df2011-11-02 13:06:18 +01001085 if (pdp->version == 0) {
1086 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1087 sizeof(pdp->qos_req0), pdp->qos_req0);
1088 }
jjako52c24142002-12-16 13:33:51 +00001089
Harald Weltebed35df2011-11-02 13:06:18 +01001090 /* Section 7.7.2 */
1091 if (pdp->version == 1) {
1092 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1093 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1094 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1095 }
jjako52c24142002-12-16 13:33:51 +00001096
Harald Weltebed35df2011-11-02 13:06:18 +01001097 /* Section 7.7.3 Routing Area Information */
1098 if (pdp->rai_given == 1)
1099 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1100 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001101
Harald Weltebed35df2011-11-02 13:06:18 +01001102 /* Section 7.7.11 */
1103 if (pdp->norecovery_given == 0)
1104 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1105 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001106
Harald Weltebed35df2011-11-02 13:06:18 +01001107 /* Section 7.7.12 */
1108 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1109 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1110 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001111
Harald Weltebed35df2011-11-02 13:06:18 +01001112 if (pdp->version == 0) {
1113 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1114 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1115 }
jjako08d331d2003-10-13 20:33:30 +00001116
Harald Weltebed35df2011-11-02 13:06:18 +01001117 /* Section 7.7.13 */
1118 if (pdp->version == 1) {
1119 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1120 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001121
Harald Weltebed35df2011-11-02 13:06:18 +01001122 /* Section 7.7.14 */
1123 if (!pdp->teic_confirmed)
1124 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1125 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001126
Harald Weltebed35df2011-11-02 13:06:18 +01001127 /* Section 7.7.17 */
1128 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001129
Harald Weltebed35df2011-11-02 13:06:18 +01001130 /* Section 7.7.17 */
1131 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1132 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1133 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001134
Harald Weltebed35df2011-11-02 13:06:18 +01001135 /* Section 7.7.23 */
1136 if (pdp->cch_pdp) /* Only include charging if flags are set */
1137 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1138 pdp->cch_pdp);
1139 }
jjako9b4971d2004-05-27 20:30:19 +00001140
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001141 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001142 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1143 pdp->traceref);
1144 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1145 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001146
Harald Weltebed35df2011-11-02 13:06:18 +01001147 /* Section 7.7.27 */
1148 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1149 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1150 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001151
Harald Weltebed35df2011-11-02 13:06:18 +01001152 /* Section 7.7.30 */
1153 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1154 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1155 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001156
Harald Weltebed35df2011-11-02 13:06:18 +01001157 /* Section 7.7.31 */
1158 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1159 if (pdp->pco_req.l)
1160 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1161 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001162
Harald Weltebed35df2011-11-02 13:06:18 +01001163 /* Section 7.7.32 */
1164 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1165 pdp->gsnlc.l, pdp->gsnlc.v);
1166 /* Section 7.7.32 */
1167 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1168 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001169
Harald Weltebed35df2011-11-02 13:06:18 +01001170 /* Section 7.7.33 */
1171 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1172 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1173 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001174
Harald Weltebed35df2011-11-02 13:06:18 +01001175 /* Section 7.7.34 */
1176 if (pdp->version == 1)
1177 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1178 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001179
Harald Weltebed35df2011-11-02 13:06:18 +01001180 /* Section 7.7.36 */
1181 if ((pdp->version == 1) && pdp->tft.l)
1182 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1183 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001184
Harald Weltebed35df2011-11-02 13:06:18 +01001185 /* Section 7.7.41 */
1186 if ((pdp->version == 1) && pdp->triggerid.l)
1187 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1188 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001189
Harald Weltebed35df2011-11-02 13:06:18 +01001190 /* Section 7.7.42 */
1191 if ((pdp->version == 1) && pdp->omcid.l)
1192 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1193 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001194
Harald Weltebed35df2011-11-02 13:06:18 +01001195 /* new R7 fields */
1196 if (pdp->rattype_given == 1)
1197 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1198 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001199
Harald Weltebed35df2011-11-02 13:06:18 +01001200 if (pdp->userloc_given == 1)
1201 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1202 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001203
Harald Weltebed35df2011-11-02 13:06:18 +01001204 if (pdp->mstz_given == 1)
1205 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1206 pdp->mstz.l, pdp->mstz.v);
1207
1208 if (pdp->imeisv_given == 1)
1209 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1210 pdp->imeisv.l, pdp->imeisv.v);
1211
1212 /* TODO hisaddr0 */
1213 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1214
1215 return 0;
jjako52c24142002-12-16 13:33:51 +00001216}
1217
jjako08d331d2003-10-13 20:33:30 +00001218/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001219int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1220{
jjako08d331d2003-10-13 20:33:30 +00001221
Harald Weltebed35df2011-11-02 13:06:18 +01001222 /* Now send off a reply to the peer */
1223 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1224
1225 if (cause != GTPCAUSE_ACC_REQ) {
1226 pdp_freepdp(pdp);
1227 }
1228
1229 return 0;
jjako08d331d2003-10-13 20:33:30 +00001230}
1231
1232/* API: Register create context indication callback */
1233int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001234 int (*cb_create_context_ind) (struct pdp_t *
1235 pdp))
jjako52c24142002-12-16 13:33:51 +00001236{
Harald Weltebed35df2011-11-02 13:06:18 +01001237 gsn->cb_create_context_ind = cb_create_context_ind;
1238 return 0;
jjako08d331d2003-10-13 20:33:30 +00001239}
1240
jjako08d331d2003-10-13 20:33:30 +00001241/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001242int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1243 uint8_t cause)
1244{
1245 union gtp_packet packet;
1246 unsigned int length =
1247 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001248
Harald Weltebed35df2011-11-02 13:06:18 +01001249 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001250
Harald Weltebed35df2011-11-02 13:06:18 +01001251 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001252
Harald Weltebed35df2011-11-02 13:06:18 +01001253 if (version == 0)
1254 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1255 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001256
Harald Weltebed35df2011-11-02 13:06:18 +01001257 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1258 pdp->reorder);
1259 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1260 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001261
Harald Weltebed35df2011-11-02 13:06:18 +01001262 if (version == 0) {
1263 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1264 pdp->fllu);
1265 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1266 pdp->fllc);
1267 }
jjako08d331d2003-10-13 20:33:30 +00001268
Harald Weltebed35df2011-11-02 13:06:18 +01001269 if (version == 1) {
1270 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1271 pdp->teid_own);
1272 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1273 pdp->teic_own);
1274 }
jjako08d331d2003-10-13 20:33:30 +00001275
Harald Weltebed35df2011-11-02 13:06:18 +01001276 /* TODO: We use teic_own as charging ID */
1277 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1278 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001279
Harald Weltebed35df2011-11-02 13:06:18 +01001280 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1281 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001282
Harald Weltebed35df2011-11-02 13:06:18 +01001283 if (pdp->pco_neg.l) { /* Optional PCO */
1284 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1285 pdp->pco_neg.l, pdp->pco_neg.v);
1286 }
jjako52c24142002-12-16 13:33:51 +00001287
Harald Weltebed35df2011-11-02 13:06:18 +01001288 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1289 pdp->gsnlc.l, pdp->gsnlc.v);
1290 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1291 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001292
Harald Weltebed35df2011-11-02 13:06:18 +01001293 if (version == 1)
1294 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1295 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001296
Harald Weltebed35df2011-11-02 13:06:18 +01001297 /* TODO: Charging gateway address */
1298 }
jjako52c24142002-12-16 13:33:51 +00001299
Harald Weltebed35df2011-11-02 13:06:18 +01001300 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1301 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001302}
1303
1304/* Handle Create PDP Context Request */
1305int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001306 struct sockaddr_in *peer, int fd,
1307 void *pack, unsigned len)
1308{
1309 struct pdp_t *pdp, *pdp_old;
1310 struct pdp_t pdp_buf;
1311 union gtpie_member *ie[GTPIE_SIZE];
1312 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001313
Harald Weltebed35df2011-11-02 13:06:18 +01001314 uint16_t seq = get_seq(pack);
1315 int hlen = get_hlen(pack);
1316 uint8_t linked_nsapi = 0;
1317 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001318
Harald Weltebed35df2011-11-02 13:06:18 +01001319 if (!gtp_dublicate(gsn, version, peer, seq))
1320 return 0;
jjako08d331d2003-10-13 20:33:30 +00001321
Harald Weltebed35df2011-11-02 13:06:18 +01001322 pdp = &pdp_buf;
1323 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001324
Harald Weltebed35df2011-11-02 13:06:18 +01001325 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001326 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1327
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001328 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001329 }
jjako52c24142002-12-16 13:33:51 +00001330
Harald Weltebed35df2011-11-02 13:06:18 +01001331 pdp->seq = seq;
1332 pdp->sa_peer = *peer;
1333 pdp->fd = fd;
1334 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001335
Harald Weltebed35df2011-11-02 13:06:18 +01001336 /* Decode information elements */
1337 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1338 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001339 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1340 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001341 if (0 == version)
1342 return EOF;
1343 else
1344 return gtp_create_pdp_resp(gsn, version, pdp,
1345 GTPCAUSE_INVALID_MESSAGE);
1346 }
jjako52c24142002-12-16 13:33:51 +00001347
Harald Weltebed35df2011-11-02 13:06:18 +01001348 if (version == 1) {
1349 /* Linked NSAPI (conditional) */
1350 /* If included this is the Secondary PDP Context Activation Procedure */
1351 /* In secondary activation IMSI is not included, so the context must be */
1352 /* identified by the tei */
1353 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001354
Harald Weltebed35df2011-11-02 13:06:18 +01001355 /* Find the primary PDP context */
1356 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1357 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001358 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001359 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001360 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001361 return gtp_create_pdp_resp(gsn, version, pdp,
1362 GTPCAUSE_OPT_IE_INCORRECT);
1363 }
jjako2c381332003-10-21 19:09:53 +00001364
Harald Weltebed35df2011-11-02 13:06:18 +01001365 /* Check that the primary PDP context matches linked nsapi */
1366 if (linked_pdp->nsapi != linked_nsapi) {
1367 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001368 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001369 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001370 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001371 return gtp_create_pdp_resp(gsn, version, pdp,
1372 GTPCAUSE_OPT_IE_INCORRECT);
1373 }
jjako52c24142002-12-16 13:33:51 +00001374
Harald Weltebed35df2011-11-02 13:06:18 +01001375 /* Copy parameters from primary context */
1376 pdp->selmode = linked_pdp->selmode;
1377 pdp->imsi = linked_pdp->imsi;
1378 pdp->msisdn = linked_pdp->msisdn;
1379 pdp->eua = linked_pdp->eua;
1380 pdp->pco_req = linked_pdp->pco_req;
1381 pdp->apn_req = linked_pdp->apn_req;
1382 pdp->teic_gn = linked_pdp->teic_gn;
1383 pdp->secondary = 1;
1384 }
1385 }
1386 /* if (version == 1) */
1387 if (version == 0) {
1388 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1389 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1390 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001391 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1392 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001393 return gtp_create_pdp_resp(gsn, version, pdp,
1394 GTPCAUSE_MAN_IE_MISSING);
1395 }
1396 }
jjako08d331d2003-10-13 20:33:30 +00001397
Harald Weltebed35df2011-11-02 13:06:18 +01001398 if ((version == 1) && (!linked_pdp)) {
1399 /* Not Secondary PDP Context Activation Procedure */
1400 /* IMSI (conditional) */
1401 if (gtpie_gettv0
1402 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1403 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001404 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1405 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001406 return gtp_create_pdp_resp(gsn, version, pdp,
1407 GTPCAUSE_MAN_IE_MISSING);
1408 }
1409 }
jjako52c24142002-12-16 13:33:51 +00001410
Harald Weltebed35df2011-11-02 13:06:18 +01001411 /* Recovery (optional) */
1412 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1413 if (gsn->cb_recovery)
1414 gsn->cb_recovery(peer, recovery);
1415 }
jjako52c24142002-12-16 13:33:51 +00001416
Harald Weltebed35df2011-11-02 13:06:18 +01001417 /* Selection mode (conditional) */
1418 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1419 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1420 &pdp->selmode, sizeof(pdp->selmode))) {
1421 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001422 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1423 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001424 return gtp_create_pdp_resp(gsn, version, pdp,
1425 GTPCAUSE_MAN_IE_MISSING);
1426 }
1427 }
jjako52c24142002-12-16 13:33:51 +00001428
Harald Weltebed35df2011-11-02 13:06:18 +01001429 if (version == 0) {
1430 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1431 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001432 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1433 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001434 return gtp_create_pdp_resp(gsn, version, pdp,
1435 GTPCAUSE_MAN_IE_MISSING);
1436 }
jjako52c24142002-12-16 13:33:51 +00001437
Harald Weltebed35df2011-11-02 13:06:18 +01001438 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1439 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001440 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1441 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001442 return gtp_create_pdp_resp(gsn, version, pdp,
1443 GTPCAUSE_MAN_IE_MISSING);
1444 }
1445 }
jjako08d331d2003-10-13 20:33:30 +00001446
Harald Weltebed35df2011-11-02 13:06:18 +01001447 if (version == 1) {
1448 /* TEID (mandatory) */
1449 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1450 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001451 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1452 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001453 return gtp_create_pdp_resp(gsn, version, pdp,
1454 GTPCAUSE_MAN_IE_MISSING);
1455 }
jjako2c381332003-10-21 19:09:53 +00001456
Harald Weltebed35df2011-11-02 13:06:18 +01001457 /* TEIC (conditional) */
1458 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1459 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1460 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001461 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001462 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001463 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001464 return gtp_create_pdp_resp(gsn, version, pdp,
1465 GTPCAUSE_MAN_IE_MISSING);
1466 }
1467 }
jjako08d331d2003-10-13 20:33:30 +00001468
Harald Weltebed35df2011-11-02 13:06:18 +01001469 /* NSAPI (mandatory) */
1470 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1471 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001472 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1473 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001474 return gtp_create_pdp_resp(gsn, version, pdp,
1475 GTPCAUSE_MAN_IE_MISSING);
1476 }
1477 }
jjako2e840a32003-01-28 16:05:18 +00001478
Harald Weltebed35df2011-11-02 13:06:18 +01001479 /* Charging Characteriatics (optional) */
1480 /* Trace reference (optional) */
1481 /* Trace type (optional) */
1482 /* Charging Characteriatics (optional) */
jjako52c24142002-12-16 13:33:51 +00001483
Harald Weltebed35df2011-11-02 13:06:18 +01001484 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1485 /* End User Address (conditional) */
1486 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1487 &pdp->eua.v, sizeof(pdp->eua.v))) {
1488 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001489 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1490 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001491 return gtp_create_pdp_resp(gsn, version, pdp,
1492 GTPCAUSE_MAN_IE_MISSING);
1493 }
jjako08d331d2003-10-13 20:33:30 +00001494
Harald Weltebed35df2011-11-02 13:06:18 +01001495 /* APN */
1496 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1497 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1498 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001499 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1500 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001501 return gtp_create_pdp_resp(gsn, version, pdp,
1502 GTPCAUSE_MAN_IE_MISSING);
1503 }
jjako2c381332003-10-21 19:09:53 +00001504
Harald Weltebed35df2011-11-02 13:06:18 +01001505 /* Extract protocol configuration options (optional) */
1506 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1507 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1508 }
1509 }
jjako2c381332003-10-21 19:09:53 +00001510
Harald Weltebed35df2011-11-02 13:06:18 +01001511 /* SGSN address for signalling (mandatory) */
1512 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1513 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1514 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001515 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1516 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001517 return gtp_create_pdp_resp(gsn, version, pdp,
1518 GTPCAUSE_MAN_IE_MISSING);
1519 }
jjako2e840a32003-01-28 16:05:18 +00001520
Harald Weltebed35df2011-11-02 13:06:18 +01001521 /* SGSN address for user traffic (mandatory) */
1522 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1523 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1524 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001525 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1526 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001527 return gtp_create_pdp_resp(gsn, version, pdp,
1528 GTPCAUSE_MAN_IE_MISSING);
1529 }
jjako52c24142002-12-16 13:33:51 +00001530
Harald Weltebed35df2011-11-02 13:06:18 +01001531 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1532 /* MSISDN (conditional) */
1533 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1534 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1535 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001536 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1537 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001538 return gtp_create_pdp_resp(gsn, version, pdp,
1539 GTPCAUSE_MAN_IE_MISSING);
1540 }
1541 }
jjako52c24142002-12-16 13:33:51 +00001542
Harald Weltebed35df2011-11-02 13:06:18 +01001543 if (version == 1) {
1544 /* QoS (mandatory) */
1545 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1546 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1547 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001548 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1549 len, "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 }
1553
1554 /* TFT (conditional) */
1555 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1556 &pdp->tft.v, sizeof(pdp->tft.v))) {
1557 }
1558
1559 /* Trigger ID */
1560 /* OMC identity */
1561 }
1562
1563 /* Initialize our own IP addresses */
1564 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1565 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1566
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001567 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001568
1569 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1570 /* Found old pdp with same tid. Now the voodoo begins! */
1571 /* 09.60 / 29.060 allows create on existing context to "steal" */
1572 /* the context which was allready established */
1573 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001574 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001575 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1576 &&
1577 (!memcmp
1578 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1579 && (pdp->selmode == pdp_old->selmode)
1580 && (pdp->msisdn.l == pdp_old->msisdn.l)
1581 &&
1582 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1583 {
1584 /* OK! We are dealing with the same APN. We will copy new
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001585 * parameters to the old pdp and send off confirmation
Harald Weltebed35df2011-11-02 13:06:18 +01001586 * We ignore the following information elements:
1587 * QoS: MS will get originally negotiated QoS.
1588 * End user address (EUA). MS will get old EUA anyway.
1589 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001590 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001591
1592 /* Copy remote flow label */
1593 pdp_old->flru = pdp->flru;
1594 pdp_old->flrc = pdp->flrc;
1595
1596 /* Copy remote tei */
1597 pdp_old->teid_gn = pdp->teid_gn;
1598 pdp_old->teic_gn = pdp->teic_gn;
1599
1600 /* Copy peer GSN address */
1601 pdp_old->gsnrc.l = pdp->gsnrc.l;
1602 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1603 pdp_old->gsnru.l = pdp->gsnru.l;
1604 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1605
1606 /* Copy request parameters */
1607 pdp_old->seq = pdp->seq;
1608 pdp_old->sa_peer = pdp->sa_peer;
1609 pdp_old->fd = pdp->fd = fd;
1610 pdp_old->version = pdp->version = version;
1611
1612 /* Switch to using the old pdp context */
1613 pdp = pdp_old;
1614
1615 /* Confirm to peer that things were "successful" */
1616 return gtp_create_pdp_resp(gsn, version, pdp,
1617 GTPCAUSE_ACC_REQ);
1618 } else { /* This is not the same PDP context. Delete the old one. */
1619
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001620 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001621
1622 if (gsn->cb_delete_context)
1623 gsn->cb_delete_context(pdp_old);
1624 pdp_freepdp(pdp_old);
1625
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001626 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001627 }
1628 }
1629
1630 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
Harald Weltee257be12017-08-12 14:55:09 +02001631 if (pdp)
1632 pdp->gsn = gsn;
Harald Weltebed35df2011-11-02 13:06:18 +01001633
1634 /* Callback function to validata login */
1635 if (gsn->cb_create_context_ind != 0)
1636 return gsn->cb_create_context_ind(pdp);
1637 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001638 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1639 "No create_context_ind callback defined\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001640 return gtp_create_pdp_resp(gsn, version, pdp,
1641 GTPCAUSE_NOT_SUPPORTED);
1642 }
jjako52c24142002-12-16 13:33:51 +00001643}
1644
jjako52c24142002-12-16 13:33:51 +00001645/* Handle Create PDP Context Response */
1646int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001647 struct sockaddr_in *peer, void *pack, unsigned len)
1648{
1649 struct pdp_t *pdp;
1650 union gtpie_member *ie[GTPIE_SIZE];
1651 uint8_t cause, recovery;
1652 void *cbp = NULL;
1653 uint8_t type = 0;
1654 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001655
Harald Weltebed35df2011-11-02 13:06:18 +01001656 /* Remove packet from queue */
1657 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1658 return EOF;
jjako52c24142002-12-16 13:33:51 +00001659
Harald Weltebed35df2011-11-02 13:06:18 +01001660 /* Find the context in question */
1661 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1662 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001663 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001664 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001665 if (gsn->cb_conf)
1666 gsn->cb_conf(type, EOF, NULL, cbp);
1667 return EOF;
1668 }
jjako2c381332003-10-21 19:09:53 +00001669
Harald Weltebed35df2011-11-02 13:06:18 +01001670 /* Register that we have received a valid teic from GGSN */
1671 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001672
Harald Weltebed35df2011-11-02 13:06:18 +01001673 /* Decode information elements */
1674 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1675 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001676 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1677 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001678 if (gsn->cb_conf)
1679 gsn->cb_conf(type, EOF, pdp, cbp);
1680 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1681 pdp_freepdp(pdp); */
1682 return EOF;
1683 }
jjako52c24142002-12-16 13:33:51 +00001684
Harald Weltebed35df2011-11-02 13:06:18 +01001685 /* Extract cause value (mandatory) */
1686 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1687 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001688 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1689 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001690 if (gsn->cb_conf)
1691 gsn->cb_conf(type, EOF, pdp, cbp);
1692 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1693 pdp_freepdp(pdp); */
1694 return EOF;
1695 }
jjako52c24142002-12-16 13:33:51 +00001696
Harald Weltebed35df2011-11-02 13:06:18 +01001697 /* Extract recovery (optional) */
1698 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1699 if (gsn->cb_recovery)
1700 gsn->cb_recovery(peer, recovery);
1701 }
jjako52c24142002-12-16 13:33:51 +00001702
Harald Weltebed35df2011-11-02 13:06:18 +01001703 /* Extract protocol configuration options (optional) */
1704 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1705 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1706 }
jjako52c24142002-12-16 13:33:51 +00001707
Harald Weltebed35df2011-11-02 13:06:18 +01001708 /* Check all conditional information elements */
1709 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001710
Harald Weltebed35df2011-11-02 13:06:18 +01001711 if (version == 0) {
1712 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1713 &pdp->qos_neg0,
1714 sizeof(pdp->qos_neg0))) {
1715 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001716 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001717 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001718 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001719 if (gsn->cb_conf)
1720 gsn->cb_conf(type, EOF, pdp, cbp);
1721 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1722 pdp_freepdp(pdp); */
1723 return EOF;
1724 }
1725 }
jjako08d331d2003-10-13 20:33:30 +00001726
Harald Weltebed35df2011-11-02 13:06:18 +01001727 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1728 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001729 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001730 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001731 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001732 if (gsn->cb_conf)
1733 gsn->cb_conf(type, EOF, pdp, cbp);
1734 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1735 pdp_freepdp(pdp); */
1736 return EOF;
1737 }
jjako52c24142002-12-16 13:33:51 +00001738
Harald Weltebed35df2011-11-02 13:06:18 +01001739 if (version == 0) {
1740 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1741 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001742 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001743 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001744 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001745 if (gsn->cb_conf)
1746 gsn->cb_conf(type, EOF, pdp, cbp);
1747 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1748 pdp_freepdp(pdp); */
1749 return EOF;
1750 }
jjako52c24142002-12-16 13:33:51 +00001751
Harald Weltebed35df2011-11-02 13:06:18 +01001752 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1753 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001754 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001755 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001756 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001757 if (gsn->cb_conf)
1758 gsn->cb_conf(type, EOF, pdp, cbp);
1759 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1760 pdp_freepdp(pdp); */
1761 return EOF;
1762 }
1763 }
1764
1765 if (version == 1) {
1766 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1767 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001768 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001769 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001770 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001771 if (gsn->cb_conf)
1772 gsn->cb_conf(type, EOF, pdp, cbp);
1773 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1774 pdp_freepdp(pdp); */
1775 return EOF;
1776 }
1777
1778 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1779 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001780 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001781 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001782 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001783 if (gsn->cb_conf)
1784 gsn->cb_conf(type, EOF, pdp, cbp);
1785 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1786 pdp_freepdp(pdp); */
1787 return EOF;
1788 }
1789 }
1790
1791 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1792 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001793 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001794 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001795 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001796 if (gsn->cb_conf)
1797 gsn->cb_conf(type, EOF, pdp, cbp);
1798 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1799 pdp_freepdp(pdp); */
1800 }
1801
1802 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1803 &pdp->eua.v, sizeof(pdp->eua.v))) {
1804 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001805 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001806 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001807 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001808 if (gsn->cb_conf)
1809 gsn->cb_conf(type, EOF, pdp, cbp);
1810 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1811 pdp_freepdp(pdp); */
1812 return EOF;
1813 }
1814
1815 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1816 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1817 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001818 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001819 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_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1829 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1830 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001831 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001832 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001833 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001834 if (gsn->cb_conf)
1835 gsn->cb_conf(type, EOF, pdp, cbp);
1836 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1837 pdp_freepdp(pdp); */
1838 return EOF;
1839 }
1840
1841 if (version == 1) {
1842 if (gtpie_gettlv
1843 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1844 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1845 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001846 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001847 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001848 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001849 if (gsn->cb_conf)
1850 gsn->cb_conf(type, EOF, pdp, cbp);
1851 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1852 pdp_freepdp(pdp); */
1853 return EOF;
1854 }
1855 }
1856
1857 }
1858
1859 if (gsn->cb_conf)
1860 gsn->cb_conf(type, cause, pdp, cbp);
1861
1862 return 0;
jjako52c24142002-12-16 13:33:51 +00001863}
1864
jjako08d331d2003-10-13 20:33:30 +00001865/* API: Send Update PDP Context Request */
1866int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001867 struct in_addr *inetaddr)
1868{
1869 union gtp_packet packet;
1870 unsigned int length =
1871 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001872
Harald Weltebed35df2011-11-02 13:06:18 +01001873 if (pdp->version == 0)
1874 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1875 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001876
Harald Weltebed35df2011-11-02 13:06:18 +01001877 /* Include IMSI if updating with unknown teic_gn */
1878 if ((pdp->version == 1) && (!pdp->teic_gn))
1879 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1880 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1881
1882 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1883 gsn->restart_counter);
1884
1885 if (pdp->version == 0) {
1886 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1887 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1888 }
1889
1890 if (pdp->version == 1) {
1891 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1892 pdp->teid_own);
1893
1894 if (!pdp->teic_confirmed)
1895 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1896 pdp->teic_own);
1897 }
1898
1899 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1900
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001901 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001902 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1903 pdp->traceref);
1904 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1905 pdp->tracetype); */
1906
1907 /* TODO if ggsn update message
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001908 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01001909 pdp->eua.l, pdp->eua.v);
1910 */
1911
1912 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1913 pdp->gsnlc.l, pdp->gsnlc.v);
1914 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1915 pdp->gsnlu.l, pdp->gsnlu.v);
1916
1917 if (pdp->version == 1)
1918 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1919 pdp->qos_req.l, pdp->qos_req.v);
1920
1921 if ((pdp->version == 1) && pdp->tft.l)
1922 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1923 pdp->tft.l, pdp->tft.v);
1924
1925 if ((pdp->version == 1) && pdp->triggerid.l)
1926 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1927 pdp->triggerid.l, pdp->triggerid.v);
1928
1929 if ((pdp->version == 1) && pdp->omcid.l)
1930 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1931 pdp->omcid.l, pdp->omcid.v);
1932
Daniel Willmann134a7752016-02-03 18:53:29 +01001933 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001934
1935 return 0;
jjako52c24142002-12-16 13:33:51 +00001936}
1937
jjako08d331d2003-10-13 20:33:30 +00001938/* Send Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001939static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01001940 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001941 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001942 struct pdp_t *pdp, uint8_t cause)
1943{
jjako08d331d2003-10-13 20:33:30 +00001944
Harald Weltebed35df2011-11-02 13:06:18 +01001945 union gtp_packet packet;
1946 unsigned int length =
1947 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001948
Harald Weltebed35df2011-11-02 13:06:18 +01001949 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001950
Harald Weltebed35df2011-11-02 13:06:18 +01001951 if (cause == GTPCAUSE_ACC_REQ) {
1952
1953 if (version == 0)
1954 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1955 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1956
1957 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1958 gsn->restart_counter);
1959
1960 if (version == 0) {
1961 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1962 pdp->fllu);
1963 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1964 pdp->fllc);
1965 }
1966
1967 if (version == 1) {
1968 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1969 pdp->teid_own);
1970
1971 if (!pdp->teic_confirmed)
1972 gtpie_tv4(&packet, &length, GTP_MAX,
1973 GTPIE_TEI_C, pdp->teic_own);
1974 }
1975
1976 /* TODO we use teid_own as charging ID address */
1977 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1978 pdp->teid_own);
1979
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001980 /* If ggsn
1981 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01001982 pdp->eua.l, pdp->eua.v); */
1983
1984 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1985 pdp->gsnlc.l, pdp->gsnlc.v);
1986 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1987 pdp->gsnlu.l, pdp->gsnlu.v);
1988
1989 if (version == 1)
1990 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1991 pdp->qos_neg.l, pdp->qos_neg.v);
1992
1993 /* TODO: Charging gateway address */
1994 }
1995
1996 return gtp_resp(version, gsn, pdp, &packet, length, peer,
1997 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00001998}
1999
jjako52c24142002-12-16 13:33:51 +00002000/* Handle Update PDP Context Request */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002001static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002002 struct sockaddr_in *peer, int fd,
2003 void *pack, unsigned len)
2004{
2005 struct pdp_t *pdp;
2006 struct pdp_t pdp_backup;
2007 union gtpie_member *ie[GTPIE_SIZE];
2008 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002009
Harald Weltebed35df2011-11-02 13:06:18 +01002010 uint16_t seq = get_seq(pack);
2011 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002012
Harald Weltebed35df2011-11-02 13:06:18 +01002013 uint64_t imsi;
2014 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002015
Harald Weltebed35df2011-11-02 13:06:18 +01002016 /* Is this a dublicate ? */
2017 if (!gtp_dublicate(gsn, version, peer, seq)) {
2018 return 0; /* We allready send of response once */
2019 }
jjako08d331d2003-10-13 20:33:30 +00002020
Harald Weltebed35df2011-11-02 13:06:18 +01002021 /* Decode information elements */
2022 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2023 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002024 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2025 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002026 if (0 == version)
2027 return EOF;
2028 else
2029 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2030 len, NULL,
2031 GTPCAUSE_INVALID_MESSAGE);
2032 }
jjako08d331d2003-10-13 20:33:30 +00002033
Harald Weltebed35df2011-11-02 13:06:18 +01002034 /* Finding PDP: */
2035 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2036 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2037 /* we have to use the tunnel endpoint identifier */
2038 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002039 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
2040
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01002041 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00002042
Harald Weltebed35df2011-11-02 13:06:18 +01002043 /* Find the context in question */
2044 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2045 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002046 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2047 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002048 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2049 len, NULL,
2050 GTPCAUSE_NON_EXIST);
2051 }
2052 } else if (version == 1) {
2053 /* NSAPI (mandatory) */
2054 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2055 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002056 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2057 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002058 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2059 len, NULL,
2060 GTPCAUSE_MAN_IE_MISSING);
2061 }
jjako08d331d2003-10-13 20:33:30 +00002062
Harald Weltebed35df2011-11-02 13:06:18 +01002063 /* IMSI (conditional) */
2064 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2065 /* Find the context in question */
2066 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2067 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002068 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002069 pack, len, "Unknown PDP context: %u\n",
2070 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002071 return gtp_update_pdp_resp(gsn, version, peer,
2072 fd, pack, len, NULL,
2073 GTPCAUSE_NON_EXIST);
2074 }
2075 } else {
2076 /* Find the context in question */
2077 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2078 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002079 GTP_LOGPKG(LOGL_ERROR, peer,
2080 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002081 return gtp_update_pdp_resp(gsn, version, peer,
2082 fd, pack, len, NULL,
2083 GTPCAUSE_NON_EXIST);
2084 }
2085 }
2086 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002087 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002088 return EOF;
2089 }
jjako08d331d2003-10-13 20:33:30 +00002090
Harald Weltebed35df2011-11-02 13:06:18 +01002091 /* Make a backup copy in case anything is wrong */
2092 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002093
Harald Weltebed35df2011-11-02 13:06:18 +01002094 if (version == 0) {
2095 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2096 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2097 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002098 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2099 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002100 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2101 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2102 len, pdp,
2103 GTPCAUSE_MAN_IE_MISSING);
2104 }
2105 }
jjako52c24142002-12-16 13:33:51 +00002106
Harald Weltebed35df2011-11-02 13:06:18 +01002107 /* Recovery (optional) */
2108 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2109 if (gsn->cb_recovery)
2110 gsn->cb_recovery(peer, recovery);
2111 }
jjako08d331d2003-10-13 20:33:30 +00002112
Harald Weltebed35df2011-11-02 13:06:18 +01002113 if (version == 0) {
2114 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2115 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002116 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2117 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002118 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2119 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2120 len, pdp,
2121 GTPCAUSE_MAN_IE_MISSING);
2122 }
jjako52c24142002-12-16 13:33:51 +00002123
Harald Weltebed35df2011-11-02 13:06:18 +01002124 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2125 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002126 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2127 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002128 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2129 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2130 len, pdp,
2131 GTPCAUSE_MAN_IE_MISSING);
2132 }
2133 }
jjako52c24142002-12-16 13:33:51 +00002134
Harald Weltebed35df2011-11-02 13:06:18 +01002135 if (version == 1) {
2136 /* TEID (mandatory) */
2137 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2138 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002139 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2140 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002141 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2142 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2143 len, pdp,
2144 GTPCAUSE_MAN_IE_MISSING);
2145 }
jjako52c24142002-12-16 13:33:51 +00002146
Harald Weltebed35df2011-11-02 13:06:18 +01002147 /* TEIC (conditional) */
2148 /* If TEIC is not included it means that we have allready received it */
2149 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2150 /* all updated contexts, or only for one of the linked contexts */
2151 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2152
2153 /* NSAPI (mandatory) */
2154 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2155 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002156 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2157 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002158 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2159 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2160 len, pdp,
2161 GTPCAUSE_MAN_IE_MISSING);
2162 }
2163 }
2164
2165 /* Trace reference (optional) */
2166 /* Trace type (optional) */
2167
2168 /* End User Address (conditional) TODO: GGSN Initiated
2169 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2170 &pdp->eua.v, sizeof(pdp->eua.v))) {
2171 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002172 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002173 "Missing mandatory information field");
2174 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002175 return gtp_update_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01002176 GTPCAUSE_MAN_IE_MISSING);
2177 } */
2178
2179 /* SGSN address for signalling (mandatory) */
2180 /* It is weird that this is mandatory when TEIC is conditional */
2181 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2182 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2183 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002184 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2185 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002186 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2187 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2188 pdp, GTPCAUSE_MAN_IE_MISSING);
2189 }
2190
2191 /* SGSN address for user traffic (mandatory) */
2192 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2193 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2194 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002195 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2196 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002197 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2198 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2199 pdp, GTPCAUSE_MAN_IE_MISSING);
2200 }
2201
2202 if (version == 1) {
2203 /* QoS (mandatory) */
2204 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2205 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2206 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002207 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2208 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002209 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2210 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2211 len, pdp,
2212 GTPCAUSE_MAN_IE_MISSING);
2213 }
2214
2215 /* TFT (conditional) */
2216 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2217 &pdp->tft.v, sizeof(pdp->tft.v))) {
2218 }
2219
2220 /* OMC identity */
2221 }
2222
2223 /* Confirm to peer that things were "successful" */
2224 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2225 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002226}
2227
jjako52c24142002-12-16 13:33:51 +00002228/* Handle Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002229static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002230 struct sockaddr_in *peer, void *pack, unsigned len)
2231{
2232 struct pdp_t *pdp;
2233 union gtpie_member *ie[GTPIE_SIZE];
2234 uint8_t cause, recovery;
2235 void *cbp = NULL;
2236 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002237 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002238
Harald Weltebed35df2011-11-02 13:06:18 +01002239 /* Remove packet from queue */
2240 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2241 return EOF;
jjako52c24142002-12-16 13:33:51 +00002242
Harald Weltebed35df2011-11-02 13:06:18 +01002243 /* Find the context in question */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002244 if (pdp_getgtp1(&pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002245 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002246 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002247 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002248 pdp = NULL;
2249 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002250 }
jjako2c381332003-10-21 19:09:53 +00002251
Harald Weltebed35df2011-11-02 13:06:18 +01002252 /* Register that we have received a valid teic from GGSN */
2253 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002254
Harald Weltebed35df2011-11-02 13:06:18 +01002255 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002256 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002257 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002258 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2259 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002260 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002261 }
jjako52c24142002-12-16 13:33:51 +00002262
Harald Weltebed35df2011-11-02 13:06:18 +01002263 /* Extract cause value (mandatory) */
2264 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002265 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002266 }
jjako52c24142002-12-16 13:33:51 +00002267
Harald Weltebed35df2011-11-02 13:06:18 +01002268 /* Extract recovery (optional) */
2269 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2270 if (gsn->cb_recovery)
2271 gsn->cb_recovery(peer, recovery);
2272 }
2273
2274 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002275 /* TODO: This does not handle GGSN-initiated update responses */
2276 if (GTPCAUSE_ACC_REQ == cause) {
2277 if (version == 0) {
2278 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2279 &pdp->qos_neg0,
2280 sizeof(pdp->qos_neg0))) {
2281 goto err_missing;
2282 }
2283
2284 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2285 goto err_missing;
2286 }
2287
2288 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2289 goto err_missing;
2290 }
Harald Weltebed35df2011-11-02 13:06:18 +01002291 }
2292
Daniel Willmannd9975522016-02-04 15:38:12 +01002293 if (version == 1) {
2294 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2295 goto err_missing;
2296 }
Harald Weltebed35df2011-11-02 13:06:18 +01002297
Daniel Willmannd9975522016-02-04 15:38:12 +01002298 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2299 goto err_missing;
2300 }
2301 }
2302
2303 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2304 goto err_missing;
2305 }
2306
2307 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2308 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2309 goto err_missing;
2310 }
2311
2312 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2313 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2314 goto err_missing;
2315 }
2316
2317 if (version == 1) {
2318 if (gtpie_gettlv
2319 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2320 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2321 goto err_missing;
2322 }
2323 }
Harald Weltebed35df2011-11-02 13:06:18 +01002324 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002325
2326 if (gsn->cb_conf)
2327 gsn->cb_conf(type, cause, pdp, cbp);
2328 return 0; /* Succes */
2329
2330err_missing:
2331 gsn->missing++;
2332 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2333 "Missing information field\n");
2334err_out:
2335 if (gsn->cb_conf)
2336 gsn->cb_conf(type, EOF, pdp, cbp);
2337 return EOF;
jjako52c24142002-12-16 13:33:51 +00002338}
2339
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002340/* API: Deprecated. Send Delete PDP Context Request And free pdp ctx. */
jjako2c381332003-10-21 19:09:53 +00002341int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002342 int teardown)
2343{
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002344 struct pdp_t *linked_pdp;
2345 struct pdp_t *secondary_pdp;
2346 int n;
2347
2348 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
2349 LOGP(DLGTP, LOGL_ERROR,
2350 "Unknown linked PDP context: %u\n", pdp->teic_own);
2351 return EOF;
2352 }
2353
2354 if (gtp_delete_context_req2(gsn, pdp, cbp, teardown) == EOF)
2355 return EOF;
2356
2357 if (teardown) { /* Remove all contexts */
2358 for (n = 0; n < PDP_MAXNSAPI; n++) {
2359 if (linked_pdp->secondary_tei[n]) {
2360 if (pdp_getgtp1
2361 (&secondary_pdp,
2362 linked_pdp->secondary_tei[n])) {
2363 LOGP(DLGTP, LOGL_ERROR,
2364 "Unknown secondary PDP context\n");
2365 return EOF;
2366 }
2367 if (linked_pdp != secondary_pdp) {
2368 if (gsn->cb_delete_context)
2369 gsn->cb_delete_context
2370 (secondary_pdp);
2371 pdp_freepdp(secondary_pdp);
2372 }
2373 }
2374 }
2375 if (gsn->cb_delete_context)
2376 gsn->cb_delete_context(linked_pdp);
2377 pdp_freepdp(linked_pdp);
2378 } else {
2379 if (gsn->cb_delete_context)
2380 gsn->cb_delete_context(pdp);
2381 if (pdp == linked_pdp) {
2382 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2383 linked_pdp->nodata = 1;
2384 } else
2385 pdp_freepdp(pdp);
2386 }
2387
2388 return 0;
2389}
2390
2391/* API: Send Delete PDP Context Request. PDP CTX shall be free'd by user at cb_conf(GTP_DELETE_PDP_RSP) */
2392int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2393 int teardown)
2394{
Harald Weltebed35df2011-11-02 13:06:18 +01002395 union gtp_packet packet;
2396 unsigned int length =
2397 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2398 struct in_addr addr;
2399 struct pdp_t *linked_pdp;
Harald Weltebed35df2011-11-02 13:06:18 +01002400 int n;
2401 int count = 0;
jjako2c381332003-10-21 19:09:53 +00002402
Harald Weltebed35df2011-11-02 13:06:18 +01002403 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2404 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002405 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002406 return EOF;
jjako2c381332003-10-21 19:09:53 +00002407 }
jjako2c381332003-10-21 19:09:53 +00002408
Harald Weltebed35df2011-11-02 13:06:18 +01002409 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002410 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002411 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002412 return EOF;
2413 }
2414
2415 if (!teardown) {
2416 for (n = 0; n < PDP_MAXNSAPI; n++)
2417 if (linked_pdp->secondary_tei[n])
2418 count++;
2419 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002420 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002421 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002422 return EOF;
2423 }
2424 }
2425
2426 if (pdp->version == 1) {
2427 if (teardown)
2428 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2429 0xff);
2430
2431 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2432 }
2433
2434 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2435
Harald Weltebed35df2011-11-02 13:06:18 +01002436 return 0;
jjako2c381332003-10-21 19:09:53 +00002437}
jjako08d331d2003-10-13 20:33:30 +00002438
jjako52c24142002-12-16 13:33:51 +00002439/* Send Delete PDP Context Response */
2440int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002441 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002442 void *pack, unsigned len,
2443 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002444 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002445{
Harald Weltebed35df2011-11-02 13:06:18 +01002446 union gtp_packet packet;
2447 struct pdp_t *secondary_pdp;
2448 unsigned int length =
2449 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2450 int n;
jjako52c24142002-12-16 13:33:51 +00002451
Harald Weltebed35df2011-11-02 13:06:18 +01002452 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002453
Harald Weltebed35df2011-11-02 13:06:18 +01002454 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2455 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002456
Harald Weltebed35df2011-11-02 13:06:18 +01002457 if (cause == GTPCAUSE_ACC_REQ) {
2458 if ((teardown) || (version == 0)) { /* Remove all contexts */
2459 for (n = 0; n < PDP_MAXNSAPI; n++) {
2460 if (linked_pdp->secondary_tei[n]) {
2461 if (pdp_getgtp1
2462 (&secondary_pdp,
2463 linked_pdp->secondary_tei[n])) {
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002464 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002465 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002466 return EOF;
2467 }
2468 if (linked_pdp != secondary_pdp) {
2469 if (gsn->cb_delete_context)
2470 gsn->cb_delete_context
2471 (secondary_pdp);
2472 pdp_freepdp(secondary_pdp);
2473 }
2474 }
2475 }
2476 if (gsn->cb_delete_context)
2477 gsn->cb_delete_context(linked_pdp);
2478 pdp_freepdp(linked_pdp);
2479 } else { /* Remove only current context */
2480 if (gsn->cb_delete_context)
2481 gsn->cb_delete_context(pdp);
2482 if (pdp == linked_pdp) {
2483 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2484 0;
2485 linked_pdp->nodata = 1;
2486 } else
2487 pdp_freepdp(pdp);
2488 }
jjako2c381332003-10-21 19:09:53 +00002489 }
Harald Weltebed35df2011-11-02 13:06:18 +01002490 /* if (cause == GTPCAUSE_ACC_REQ) */
2491 return 0;
jjako52c24142002-12-16 13:33:51 +00002492}
2493
2494/* Handle Delete PDP Context Request */
2495int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002496 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002497 void *pack, unsigned len)
2498{
2499 struct pdp_t *pdp = NULL;
2500 struct pdp_t *linked_pdp = NULL;
2501 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002502
Harald Weltebed35df2011-11-02 13:06:18 +01002503 uint16_t seq = get_seq(pack);
2504 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002505
Harald Weltebed35df2011-11-02 13:06:18 +01002506 uint8_t nsapi;
2507 uint8_t teardown = 0;
2508 int n;
2509 int count = 0;
jjako52c24142002-12-16 13:33:51 +00002510
Harald Weltebed35df2011-11-02 13:06:18 +01002511 /* Is this a dublicate ? */
2512 if (!gtp_dublicate(gsn, version, peer, seq)) {
2513 return 0; /* We allready send off response once */
2514 }
jjako2c381332003-10-21 19:09:53 +00002515
Harald Weltebed35df2011-11-02 13:06:18 +01002516 /* Find the linked context in question */
2517 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2518 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002519 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002520 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002521 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2522 NULL, NULL, GTPCAUSE_NON_EXIST,
2523 teardown);
2524 }
jjako2c381332003-10-21 19:09:53 +00002525
Harald Weltebed35df2011-11-02 13:06:18 +01002526 /* If version 0 this is also the secondary context */
2527 if (version == 0)
2528 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002529
Harald Weltebed35df2011-11-02 13:06:18 +01002530 /* Decode information elements */
2531 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2532 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002533 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2534 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002535 if (0 == version)
2536 return EOF;
2537 else
2538 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2539 len, NULL, NULL,
2540 GTPCAUSE_INVALID_MESSAGE,
2541 teardown);
2542 }
2543
2544 if (version == 1) {
2545 /* NSAPI (mandatory) */
2546 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2547 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002548 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2549 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002550 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2551 len, NULL, NULL,
2552 GTPCAUSE_MAN_IE_MISSING,
2553 teardown);
2554 }
2555
2556 /* Find the context in question */
2557 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2558 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002559 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2560 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002561 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2562 len, NULL, NULL,
2563 GTPCAUSE_NON_EXIST,
2564 teardown);
2565 }
2566
2567 /* Teardown (conditional) */
2568 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2569
2570 if (!teardown) {
2571 for (n = 0; n < PDP_MAXNSAPI; n++)
2572 if (linked_pdp->secondary_tei[n])
2573 count++;
2574 if (count <= 1) {
Pau Espin Pedrold1bd6fc2018-07-13 19:11:45 +02002575 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2576 "Ignoring CTX DEL without teardown and count=%d\n",
2577 count);
Harald Weltebed35df2011-11-02 13:06:18 +01002578 return 0; /* 29.060 7.3.5 Ignore message */
2579 }
2580 }
2581 }
2582
2583 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2584 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002585}
2586
jjako52c24142002-12-16 13:33:51 +00002587/* Handle Delete PDP Context Response */
2588int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002589 struct sockaddr_in *peer, void *pack, unsigned len)
2590{
2591 union gtpie_member *ie[GTPIE_SIZE];
2592 uint8_t cause;
2593 void *cbp = NULL;
2594 uint8_t type = 0;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002595 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002596 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002597
Harald Weltebed35df2011-11-02 13:06:18 +01002598 /* Remove packet from queue */
2599 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2600 return EOF;
jjako52c24142002-12-16 13:33:51 +00002601
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002602 /* Find the context in question. It may not be available if gtp_delete_context_req
2603 * was used and as a result the PDP ctx was already freed */
2604 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2605 gsn->err_unknownpdp++;
2606 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2607 "Unknown PDP context: %u (expected if gtp_delete_context_req is used)\n",
2608 get_tei(pack));
2609 if (gsn->cb_conf)
2610 gsn->cb_conf(type, EOF, NULL, cbp);
2611 return EOF;
2612 }
2613
Harald Weltebed35df2011-11-02 13:06:18 +01002614 /* Decode information elements */
2615 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2616 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002617 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2618 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002619 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002620 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002621 return EOF;
2622 }
2623
2624 /* Extract cause value (mandatory) */
2625 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2626 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002627 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2628 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002629 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002630 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002631 return EOF;
2632 }
2633
2634 /* Check the cause value (again) */
2635 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2636 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002637 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2638 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002639 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002640 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002641 return EOF;
2642 }
2643
2644 /* Callback function to notify application */
2645 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002646 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002647
2648 return 0;
jjako52c24142002-12-16 13:33:51 +00002649}
2650
Harald Welte54d082e2017-08-12 22:43:21 +02002651/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002652static int gtp_error_ind_resp(struct gsn_t *gsn, uint8_t version,
jjako08d331d2003-10-13 20:33:30 +00002653 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002654 void *pack, unsigned len)
2655{
Harald Weltebed35df2011-11-02 13:06:18 +01002656 union gtp_packet packet;
2657 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2658
Harald Welte54d082e2017-08-12 22:43:21 +02002659 if (version == 1) {
2660 /* Mandatory 7.7.13 TEI Data I */
2661 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2662 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2663
2664 /* Mandatory 7.7.32 GSN Address */
2665 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2666 sizeof(gsn->gsnu), &gsn->gsnu);
2667 }
2668
Harald Weltebed35df2011-11-02 13:06:18 +01002669 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2670 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002671}
2672
2673/* Handle Error Indication */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002674static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002675 struct sockaddr_in *peer, void *pack, unsigned len)
2676{
Harald Welte37d5b152017-08-12 23:58:29 +02002677 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002678 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002679
Harald Weltebed35df2011-11-02 13:06:18 +01002680 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002681 if (version == 0) {
2682 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
2683 gsn->err_unknownpdp++;
2684 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2685 "Unknown PDP context\n");
2686 return EOF;
2687 }
2688 } else if (version == 1) {
2689 /* we have to look-up based on the *peer* TEID */
2690 int hlen = get_hlen(pack);
2691 uint32_t teid_gn;
2692
2693 /* Decode information elements */
2694 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2695 gsn->invalid++;
2696 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2697 "Invalid message format\n");
2698 return EOF;
2699 }
2700
2701 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2702 gsn->missing++;
2703 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2704 "Missing mandatory information field\n");
2705 return EOF;
2706 }
2707
2708 if (pdp_getgtp1_peer_d(&pdp, peer, teid_gn)) {
2709 gsn->err_unknownpdp++;
2710 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2711 return EOF;
2712 }
Harald Weltebed35df2011-11-02 13:06:18 +01002713 }
jjako52c24142002-12-16 13:33:51 +00002714
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002715 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2716 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002717
Harald Weltebd228242017-11-06 03:16:49 +09002718 /* This is obvious from above code, given the semantics of the
2719 * functions above, but Coverity doesn't figure this out, so
2720 * let's make it clear. It's good style anyway in case above
2721 * code should ever change. */
2722 OSMO_ASSERT(pdp);
2723
Harald Weltebed35df2011-11-02 13:06:18 +01002724 if (gsn->cb_delete_context)
2725 gsn->cb_delete_context(pdp);
2726 pdp_freepdp(pdp);
2727 return 0;
jjako52c24142002-12-16 13:33:51 +00002728}
2729
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002730static int gtp_gpdu_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002731 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2732{
jjako08d331d2003-10-13 20:33:30 +00002733
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002734 int hlen;
jjako52c24142002-12-16 13:33:51 +00002735
Harald Weltebed35df2011-11-02 13:06:18 +01002736 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002737
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002738 switch (version) {
2739 case 0:
Harald Weltebed35df2011-11-02 13:06:18 +01002740 if (pdp_getgtp0
2741 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2742 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002743 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002744 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002745 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2746 len);
2747 }
2748 hlen = GTP0_HEADER_SIZE;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002749 break;
2750 case 1:
Harald Weltebed35df2011-11-02 13:06:18 +01002751 if (pdp_getgtp1
2752 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2753 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002754 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002755 len, "Unknown PDP context, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002756 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2757 len);
2758 }
jjako08d331d2003-10-13 20:33:30 +00002759
Harald Weltebed35df2011-11-02 13:06:18 +01002760 /* Is this a long or a short header ? */
2761 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2762 hlen = GTP1_HEADER_SIZE_LONG;
2763 else
2764 hlen = GTP1_HEADER_SIZE_SHORT;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002765 break;
2766 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002767 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002768 "Unknown version: %d\n", version);
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002769 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002770 }
jjako08d331d2003-10-13 20:33:30 +00002771
Harald Weltebed35df2011-11-02 13:06:18 +01002772 /* If the GPDU was not from the peer GSN tell him to delete context */
2773 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2774 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002775 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002776 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2777 }
jjako52c24142002-12-16 13:33:51 +00002778
Harald Weltebed35df2011-11-02 13:06:18 +01002779 /* Callback function */
2780 if (gsn->cb_data_ind != 0)
2781 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2782
2783 return 0;
jjako52c24142002-12-16 13:33:51 +00002784}
2785
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002786/* Receives GTP packet and sends off for further processing
jjako52c24142002-12-16 13:33:51 +00002787 * Function will check the validity of the header. If the header
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002788 * is not valid the packet is either dropped or a version not
2789 * supported is returned to the peer.
jjako52c24142002-12-16 13:33:51 +00002790 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002791int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002792{
Harald Weltebed35df2011-11-02 13:06:18 +01002793 unsigned char buffer[PACKET_MAX];
2794 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002795 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002796 int status;
2797 struct gtp0_header *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002798 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002799 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002800
Harald Weltebed35df2011-11-02 13:06:18 +01002801 /* TODO: Need strategy of userspace buffering and blocking */
2802 /* Currently read is non-blocking and send is blocking. */
2803 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002804
Harald Weltebed35df2011-11-02 13:06:18 +01002805 while (1) { /* Loop until no more to read */
2806 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002807 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002808 return -1;
2809 }
2810 peerlen = sizeof(peer);
2811 if ((status =
2812 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2813 (struct sockaddr *)&peer, &peerlen)) < 0) {
2814 if (errno == EAGAIN)
2815 return 0;
2816 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002817 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002818 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002819 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2820 status, status ? strerror(errno) : "No error");
2821 return -1;
2822 }
jjako1db1c812003-07-06 20:53:57 +00002823
Harald Weltebed35df2011-11-02 13:06:18 +01002824 /* Need at least 1 byte in order to check version */
2825 if (status < (1)) {
2826 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002827 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2828 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002829 continue;
2830 }
jjako08d331d2003-10-13 20:33:30 +00002831
Harald Weltebed35df2011-11-02 13:06:18 +01002832 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002833
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002834 version = GTPHDR_F_GET_VER(pheader->flags);
2835
Harald Weltebed35df2011-11-02 13:06:18 +01002836 /* Version should be gtp0 (or earlier) */
2837 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2838 /* GTP 0 messages. If other version message is received we reply that we */
2839 /* only support version 0, implying that this is the only version */
2840 /* supported on this port */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002841 if (version > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002842 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01002843 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2844 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002845 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2846 continue;
2847 }
2848
2849 /* Check length of gtp0 packet */
2850 if (status < GTP0_HEADER_SIZE) {
2851 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002852 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2853 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002854 continue; /* Silently discard 29.60: 11.1.2 */
2855 }
2856
2857 /* Check packet length field versus length of packet */
2858 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2859 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002860 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002861 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002862 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002863 continue; /* Silently discard */
2864 }
2865
2866 if ((gsn->mode == GTP_MODE_GGSN) &&
2867 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002868 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002869 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002870 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002871 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002872 "Unexpected GTPv0 Signalling Message '%s'\n",
2873 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002874 continue; /* Silently discard 29.60: 11.1.4 */
2875 }
2876
2877 if ((gsn->mode == GTP_MODE_SGSN) &&
2878 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002879 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002880 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002881 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002882 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002883 "Unexpected GTPv0 Signalling Message '%s'\n",
2884 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002885 continue; /* Silently discard 29.60: 11.1.4 */
2886 }
2887
2888 switch (pheader->type) {
2889 case GTP_ECHO_REQ:
2890 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2891 break;
2892 case GTP_ECHO_RSP:
2893 gtp_echo_conf(gsn, version, &peer, buffer, status);
2894 break;
2895 case GTP_NOT_SUPPORTED:
2896 gtp_unsup_ind(gsn, &peer, buffer, status);
2897 break;
2898 case GTP_CREATE_PDP_REQ:
2899 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2900 status);
2901 break;
2902 case GTP_CREATE_PDP_RSP:
2903 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2904 status);
2905 break;
2906 case GTP_UPDATE_PDP_REQ:
2907 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2908 status);
2909 break;
2910 case GTP_UPDATE_PDP_RSP:
2911 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2912 status);
2913 break;
2914 case GTP_DELETE_PDP_REQ:
2915 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2916 status);
2917 break;
2918 case GTP_DELETE_PDP_RSP:
2919 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2920 status);
2921 break;
2922 case GTP_ERROR:
2923 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2924 break;
2925 case GTP_GPDU:
2926 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2927 break;
2928 default:
2929 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002930 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2931 "Unknown GTP message type received: %d\n",
2932 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002933 break;
2934 }
2935 }
jjako08d331d2003-10-13 20:33:30 +00002936}
2937
jjako08d331d2003-10-13 20:33:30 +00002938int gtp_decaps1c(struct gsn_t *gsn)
2939{
Harald Weltebed35df2011-11-02 13:06:18 +01002940 unsigned char buffer[PACKET_MAX];
2941 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002942 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002943 int status;
2944 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002945 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002946 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002947
Harald Weltebed35df2011-11-02 13:06:18 +01002948 /* TODO: Need strategy of userspace buffering and blocking */
2949 /* Currently read is non-blocking and send is blocking. */
2950 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002951
Harald Weltebed35df2011-11-02 13:06:18 +01002952 while (1) { /* Loop until no more to read */
2953 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002954 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002955 return -1;
2956 }
2957 peerlen = sizeof(peer);
2958 if ((status =
2959 recvfrom(fd, buffer, sizeof(buffer), 0,
2960 (struct sockaddr *)&peer, &peerlen)) < 0) {
2961 if (errno == EAGAIN)
2962 return 0;
2963 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002964 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002965 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002966 fd, (unsigned long)buffer, sizeof(buffer),
2967 status, status ? strerror(errno) : "No error");
2968 return -1;
2969 }
jjako08d331d2003-10-13 20:33:30 +00002970
Harald Weltebed35df2011-11-02 13:06:18 +01002971 /* Need at least 1 byte in order to check version */
2972 if (status < (1)) {
2973 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002974 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2975 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002976 continue;
2977 }
jjako08d331d2003-10-13 20:33:30 +00002978
Harald Weltebed35df2011-11-02 13:06:18 +01002979 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002980
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002981 version = GTPHDR_F_GET_VER(pheader->flags);
2982
Harald Weltebed35df2011-11-02 13:06:18 +01002983 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002984 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01002985 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01002986 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2987 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002988 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2989 /*29.60: 11.1.1 */
2990 continue;
2991 }
jjako08d331d2003-10-13 20:33:30 +00002992
Harald Weltebed35df2011-11-02 13:06:18 +01002993 /* Version must be at least GTP 1 */
2994 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2995 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2996 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002997 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01002998 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01002999 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3000 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003001 continue;
3002 }
jjako08d331d2003-10-13 20:33:30 +00003003
Harald Weltebed35df2011-11-02 13:06:18 +01003004 /* Check packet flag field */
3005 if (((pheader->flags & 0xf7) != 0x32)) {
3006 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003007 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003008 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003009 continue;
3010 }
jjako2c381332003-10-21 19:09:53 +00003011
Harald Weltebed35df2011-11-02 13:06:18 +01003012 /* Check length of packet */
3013 if (status < GTP1_HEADER_SIZE_LONG) {
3014 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003015 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3016 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003017 continue; /* Silently discard 29.60: 11.1.2 */
3018 }
jjako2c381332003-10-21 19:09:53 +00003019
Harald Weltebed35df2011-11-02 13:06:18 +01003020 /* Check packet length field versus length of packet */
3021 if (status !=
3022 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3023 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003024 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003025 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003026 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003027 continue; /* Silently discard */
3028 }
jjako1db1c812003-07-06 20:53:57 +00003029
Harald Weltebed35df2011-11-02 13:06:18 +01003030 /* Check for extension headers */
3031 /* TODO: We really should cycle through the headers and determine */
3032 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003033 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003034 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003035 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3036 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003037 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3038 status);
jjako1db1c812003-07-06 20:53:57 +00003039
Harald Weltebed35df2011-11-02 13:06:18 +01003040 continue;
3041 }
3042
3043 if ((gsn->mode == GTP_MODE_GGSN) &&
3044 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003045 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003046 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003047 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003048 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003049 "Unexpected GTPv1 Signalling Message '%s'\n",
3050 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003051 continue; /* Silently discard 29.60: 11.1.4 */
3052 }
3053
3054 if ((gsn->mode == GTP_MODE_SGSN) &&
3055 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003056 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003057 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003058 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003059 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003060 "Unexpected GTPv1 Signalling Message '%s'\n",
3061 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003062 continue; /* Silently discard 29.60: 11.1.4 */
3063 }
3064
3065 switch (pheader->type) {
3066 case GTP_ECHO_REQ:
3067 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3068 break;
3069 case GTP_ECHO_RSP:
3070 gtp_echo_conf(gsn, version, &peer, buffer, status);
3071 break;
3072 case GTP_NOT_SUPPORTED:
3073 gtp_unsup_ind(gsn, &peer, buffer, status);
3074 break;
3075 case GTP_SUPP_EXT_HEADER:
3076 gtp_extheader_ind(gsn, &peer, buffer, status);
3077 break;
3078 case GTP_CREATE_PDP_REQ:
3079 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3080 status);
3081 break;
3082 case GTP_CREATE_PDP_RSP:
3083 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3084 status);
3085 break;
3086 case GTP_UPDATE_PDP_REQ:
3087 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3088 status);
3089 break;
3090 case GTP_UPDATE_PDP_RSP:
3091 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3092 status);
3093 break;
3094 case GTP_DELETE_PDP_REQ:
3095 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3096 status);
3097 break;
3098 case GTP_DELETE_PDP_RSP:
3099 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3100 status);
3101 break;
3102 case GTP_ERROR:
3103 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3104 break;
3105 default:
3106 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003107 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3108 "Unknown GTP message type received: %u\n",
3109 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003110 break;
3111 }
3112 }
jjako52c24142002-12-16 13:33:51 +00003113}
3114
jjako08d331d2003-10-13 20:33:30 +00003115int gtp_decaps1u(struct gsn_t *gsn)
3116{
Harald Weltebed35df2011-11-02 13:06:18 +01003117 unsigned char buffer[PACKET_MAX];
3118 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003119 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003120 int status;
3121 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003122 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003123 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003124
Harald Weltebed35df2011-11-02 13:06:18 +01003125 /* TODO: Need strategy of userspace buffering and blocking */
3126 /* Currently read is non-blocking and send is blocking. */
3127 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003128
Harald Weltebed35df2011-11-02 13:06:18 +01003129 while (1) { /* Loop until no more to read */
3130 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003131 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003132 return -1;
3133 }
3134 peerlen = sizeof(peer);
3135 if ((status =
3136 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3137 (struct sockaddr *)&peer, &peerlen)) < 0) {
3138 if (errno == EAGAIN)
3139 return 0;
3140 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003141 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003142 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003143 gsn->fd1u, (unsigned long)buffer,
3144 sizeof(buffer), status,
3145 status ? strerror(errno) : "No error");
3146 return -1;
3147 }
jjako08d331d2003-10-13 20:33:30 +00003148
Harald Weltebed35df2011-11-02 13:06:18 +01003149 /* Need at least 1 byte in order to check version */
3150 if (status < (1)) {
3151 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003152 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3153 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003154 continue;
3155 }
jjako08d331d2003-10-13 20:33:30 +00003156
Harald Weltebed35df2011-11-02 13:06:18 +01003157 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003158
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003159 version = GTPHDR_F_GET_VER(pheader->flags);
3160
Harald Weltebed35df2011-11-02 13:06:18 +01003161 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003162 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003163 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003164 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3165 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003166 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3167 continue;
3168 }
jjako08d331d2003-10-13 20:33:30 +00003169
Harald Weltebed35df2011-11-02 13:06:18 +01003170 /* Version must be at least GTP 1 */
3171 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3172 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3173 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003174 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003175 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003176 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3177 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003178 continue;
3179 }
jjako2c381332003-10-21 19:09:53 +00003180
Harald Weltebed35df2011-11-02 13:06:18 +01003181 /* Check packet flag field (allow both with and without sequence number) */
3182 if (((pheader->flags & 0xf5) != 0x30)) {
3183 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003184 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003185 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003186 continue;
3187 }
jjako2c381332003-10-21 19:09:53 +00003188
Harald Weltebed35df2011-11-02 13:06:18 +01003189 /* Check length of packet */
3190 if (status < GTP1_HEADER_SIZE_SHORT) {
3191 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003192 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3193 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003194 continue; /* Silently discard 29.60: 11.1.2 */
3195 }
3196
3197 /* Check packet length field versus length of packet */
3198 if (status !=
3199 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3200 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003201 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003202 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003203 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003204 continue; /* Silently discard */
3205 }
3206
3207 /* Check for extension headers */
3208 /* TODO: We really should cycle through the headers and determine */
3209 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003210 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003211 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003212 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3213 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003214 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3215 status);
3216
3217 continue;
3218 }
3219
3220 switch (pheader->type) {
3221 case GTP_ECHO_REQ:
3222 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3223 break;
3224 case GTP_ECHO_RSP:
3225 gtp_echo_conf(gsn, version, &peer, buffer, status);
3226 break;
3227 case GTP_SUPP_EXT_HEADER:
3228 gtp_extheader_ind(gsn, &peer, buffer, status);
3229 break;
3230 case GTP_ERROR:
3231 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3232 break;
3233 /* Supported header extensions */
3234 case GTP_GPDU:
3235 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3236 break;
3237 default:
3238 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003239 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3240 "Unknown GTP message type received: %u\n",
3241 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003242 break;
3243 }
3244 }
jjako08d331d2003-10-13 20:33:30 +00003245}
3246
Harald Weltebed35df2011-11-02 13:06:18 +01003247int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003248{
Harald Weltebed35df2011-11-02 13:06:18 +01003249 union gtp_packet packet;
3250 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003251 struct msghdr msgh;
3252 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003253 int fd;
jjako52c24142002-12-16 13:33:51 +00003254
Harald Welte471e3492017-09-24 16:12:39 +08003255 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003256 memset(&addr, 0, sizeof(addr));
3257 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003258#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003259 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003260#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003261 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003262
Harald Welte471e3492017-09-24 16:12:39 +08003263 /* prepare msghdr */
3264 memset(&msgh, 0, sizeof(msgh));
3265 msgh.msg_name = &addr;
3266 msgh.msg_namelen = sizeof(addr);
3267 msgh.msg_iov = iov;
3268 msgh.msg_iovlen = ARRAY_SIZE(iov);
3269
3270 /* prepare iovectors */
3271 iov[0].iov_base = &packet;
3272 /* iov[0].iov_len is not known here yet */
3273 iov[1].iov_base = pack;
3274 iov[1].iov_len = len;
3275
Harald Weltebed35df2011-11-02 13:06:18 +01003276 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003277
Harald Welte471e3492017-09-24 16:12:39 +08003278 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003279 addr.sin_port = htons(GTP0_PORT);
3280 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003281
Harald Weltebed35df2011-11-02 13:06:18 +01003282 get_default_gtp(0, GTP_GPDU, &packet);
3283 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003284 if (pdp->tx_gpdu_seq)
3285 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3286 else
3287 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003288 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003289 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003290 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003291
Harald Weltebed35df2011-11-02 13:06:18 +01003292 addr.sin_port = htons(GTP1U_PORT);
3293 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003294
Harald Weltebed35df2011-11-02 13:06:18 +01003295 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003296 if (pdp->tx_gpdu_seq) {
3297 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3298 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3299 GTP1_HEADER_SIZE_LONG);
3300 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3301 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3302 } else {
3303 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3304 packet.gtp1s.h.length = hton16(len);
3305 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3306 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3307 }
Harald Weltebed35df2011-11-02 13:06:18 +01003308 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003309 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003310 return EOF;
3311 }
3312
3313 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003314 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003315 return -1;
3316 }
3317
Harald Welte471e3492017-09-24 16:12:39 +08003318 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003319 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003320 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003321 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003322 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3323 strerror(errno));
3324 return EOF;
3325 }
3326 return 0;
jjako52c24142002-12-16 13:33:51 +00003327}
3328
jjako52c24142002-12-16 13:33:51 +00003329/* ***********************************************************
3330 * Conversion functions
3331 *************************************************************/
3332
jjako52c24142002-12-16 13:33:51 +00003333/* ***********************************************************
3334 * IP address conversion functions
3335 * There exist several types of address representations:
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01003336 * - eua: End User Address. (29.060, 7.7.27, message type 128)
jjako52c24142002-12-16 13:33:51 +00003337 * Used for signalling address to mobile station. Supports IPv4
3338 * IPv6 x.25 etc. etc.
3339 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3340 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3341 * - in_addr: IPv4 address struct.
3342 * - sockaddr_in: Socket API representation of IP address and
3343 * port number.
3344 *************************************************************/
3345
Harald Weltebed35df2011-11-02 13:06:18 +01003346int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3347{
Harald Weltecee75462017-09-24 17:45:05 +08003348 eua->v[0] = PDP_EUA_ORG_IETF;
3349 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003350 if (src) {
3351 eua->l = 6;
3352 memcpy(&eua->v[2], src, 4);
3353 } else {
3354 eua->l = 2;
3355 }
3356 return 0;
jjako52c24142002-12-16 13:33:51 +00003357}
3358
Harald Weltebed35df2011-11-02 13:06:18 +01003359int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3360{
Harald Weltecee75462017-09-24 17:45:05 +08003361 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 +01003362 return -1; /* Not IPv4 address */
3363 memcpy(dst, &eua->v[2], 4);
3364 return 0;
jjako52c24142002-12-16 13:33:51 +00003365}
3366
Harald Weltebed35df2011-11-02 13:06:18 +01003367int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3368{
3369 memset(dst, 0, sizeof(struct in_addr));
3370 if (gsna->l != 4)
3371 return EOF; /* Return if not IPv4 */
3372 memcpy(dst, gsna->v, gsna->l);
3373 return 0;
jjako52c24142002-12-16 13:33:51 +00003374}
3375
Harald Weltebed35df2011-11-02 13:06:18 +01003376int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3377{
3378 memset(gsna, 0, sizeof(struct ul16_t));
3379 gsna->l = 4;
3380 memcpy(gsna->v, src, gsna->l);
3381 return 0;
jjako52c24142002-12-16 13:33:51 +00003382}
Harald Welteb10ee082017-08-12 19:29:16 +02003383
3384/* TS 29.060 has yet again a different encoding for IMSIs than
3385 * what we have in other places, so we cannot use the gsm48
3386 * decoding functions. Also, libgtp uses an uint64_t in
3387 * _network byte order_ to contain BCD digits ?!? */
3388const char *imsi_gtp2str(const uint64_t *imsi)
3389{
Harald Weltea06120d2017-11-06 03:12:54 +09003390 static char buf[sizeof(*imsi)*2+1];
Harald Welteb10ee082017-08-12 19:29:16 +02003391 const uint8_t *imsi8 = (const uint8_t *) imsi;
3392 unsigned int i, j = 0;
3393
3394 for (i = 0; i < sizeof(*imsi); i++) {
3395 uint8_t nibble;
3396
3397 nibble = imsi8[i] & 0xf;
3398 if (nibble == 0xf)
3399 break;
3400 buf[j++] = osmo_bcd2char(nibble);
3401
3402 nibble = imsi8[i] >> 4;
3403 if (nibble == 0xf)
3404 break;
3405 buf[j++] = osmo_bcd2char(nibble);
3406 }
3407
3408 buf[j++] = '\0';
3409 return buf;
3410}