blob: 1d58088e9c1d0b8530b26fd910bd25247e7075c3 [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
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200193static void emit_cb_recovery(struct gsn_t *gsn, struct sockaddr_in * peer,
194 struct pdp_t * pdp, uint8_t recovery)
195{
196 if (gsn->cb_recovery)
197 gsn->cb_recovery(peer, recovery);
198 if (gsn->cb_recovery2)
199 gsn->cb_recovery2(peer, pdp, recovery);
200}
201
Harald Welte629e9862010-12-24 20:58:09 +0100202int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100203 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
204{
205 gsn->cb_recovery = cb;
206 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100207}
208
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +0200209/* cb_recovery()
210 * pdp may be NULL if Recovery IE was received from a message independent
211 * of any PDP ctx (such as Echo Response), or because pdp ctx is unknown to the
212 * local setup. In case pdp is known, caller may want to keep that pdp alive to
213 * handle subsequent msg cb as this specific pdp ctx is still valid according to
214 * specs.
215 */
216int gtp_set_cb_recovery2(struct gsn_t *gsn,
217 int (*cb_recovery2) (struct sockaddr_in * peer, struct pdp_t * pdp, uint8_t recovery))
218{
219 gsn->cb_recovery2 = cb_recovery2;
220 return 0;
221}
222
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +0100223int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100224 int (*cb_data_ind) (struct pdp_t * pdp,
225 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000226{
Harald Weltebed35df2011-11-02 13:06:18 +0100227 gsn->cb_data_ind = cb_data_ind;
228 return 0;
jjako52c24142002-12-16 13:33:51 +0000229}
230
jjako08d331d2003-10-13 20:33:30 +0000231/**
232 * get_default_gtp()
233 * Generate a GPRS Tunneling Protocol signalling packet header, depending
234 * on GTP version and message type. pdp is used for teid/flow label.
235 * *packet must be allocated by the calling function, and be large enough
236 * to hold the packet header.
237 * returns the length of the header. 0 on error.
238 **/
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100239static unsigned int get_default_gtp(uint8_t version, uint8_t type, void *packet)
Harald Weltebed35df2011-11-02 13:06:18 +0100240{
241 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
242 struct gtp1_header_long *gtp1_default =
243 (struct gtp1_header_long *)packet;
244 switch (version) {
245 case 0:
246 /* Initialise "standard" GTP0 header */
247 memset(gtp0_default, 0, sizeof(struct gtp0_header));
248 gtp0_default->flags = 0x1e;
249 gtp0_default->type = hton8(type);
250 gtp0_default->spare1 = 0xff;
251 gtp0_default->spare2 = 0xff;
252 gtp0_default->spare3 = 0xff;
253 gtp0_default->number = 0xff;
254 return GTP0_HEADER_SIZE;
255 case 1:
256 /* Initialise "standard" GTP1 header */
257 /* 29.060: 8.2: S=1 and PN=0 */
258 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
259 /* and Supported Extension Headers Notification, the S field shall be */
260 /* set to 1 */
261 /* Currently extension headers are not supported */
262 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
Harald Weltefed598f2017-09-24 16:39:22 +0800263 /* No extension, enable sequence, no N-PDU */
264 gtp1_default->flags = GTPHDR_F_VER(1) | GTP1HDR_F_GTP1 | GTP1HDR_F_SEQ;
Harald Weltebed35df2011-11-02 13:06:18 +0100265 gtp1_default->type = hton8(type);
266 return GTP1_HEADER_SIZE_LONG;
267 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100268 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100269 "Unknown GTP packet version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +0100270 return 0;
271 }
jjako52c24142002-12-16 13:33:51 +0000272}
273
jjako08d331d2003-10-13 20:33:30 +0000274/**
275 * get_seq()
276 * Get sequence number of a packet.
277 * Returns 0 on error
278 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100279static uint16_t get_seq(void *pack)
280{
281 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800282 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000283
Harald Weltefed598f2017-09-24 16:39:22 +0800284 if (ver == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +0100285 return ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800286 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100287 return ntoh16(packet->gtp1l.h.seq);
288 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100289 return 0;
290 }
jjako08d331d2003-10-13 20:33:30 +0000291}
292
293/**
294 * get_tid()
295 * Get tunnel identifier of a packet.
296 * Returns 0 on error
297 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100298static uint64_t get_tid(void *pack)
299{
300 union gtp_packet *packet = (union gtp_packet *)pack;
301
Harald Weltefed598f2017-09-24 16:39:22 +0800302 if (GTPHDR_F_GET_VER(packet->flags) == 0) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100303 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100304 }
305 return 0;
jjako08d331d2003-10-13 20:33:30 +0000306}
307
308/**
309 * get_hlen()
310 * Get the header length of a packet.
311 * Returns 0 on error
312 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100313static uint16_t get_hlen(void *pack)
314{
315 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800316 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000317
Harald Weltefed598f2017-09-24 16:39:22 +0800318 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100319 return GTP0_HEADER_SIZE;
Harald Weltefed598f2017-09-24 16:39:22 +0800320 } else if (ver == 1 && (packet->flags & 0x07) == 0) { /* Short version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100321 return GTP1_HEADER_SIZE_SHORT;
Harald Weltefed598f2017-09-24 16:39:22 +0800322 } else if (ver == 1) { /* Version 1 with seq/n-pdu/ext */
323 return GTP1_HEADER_SIZE_LONG;
Harald Weltebed35df2011-11-02 13:06:18 +0100324 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100325 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100326 return 0;
327 }
jjako08d331d2003-10-13 20:33:30 +0000328}
329
330/**
331 * get_tei()
332 * Get the tunnel endpoint identifier (flow label) of a packet.
333 * Returns 0xffffffff on error.
334 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100335static uint32_t get_tei(void *pack)
336{
337 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800338 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000339
Harald Weltefed598f2017-09-24 16:39:22 +0800340 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100341 return ntoh16(packet->gtp0.h.flow);
Harald Weltefed598f2017-09-24 16:39:22 +0800342 } else if (ver == 1) { /* Version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100343 return ntoh32(packet->gtp1l.h.tei);
344 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100345 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100346 return 0xffffffff;
347 }
jjako08d331d2003-10-13 20:33:30 +0000348}
jjakoa7cd2492003-04-11 09:40:12 +0000349
jjako52c24142002-12-16 13:33:51 +0000350/* ***********************************************************
351 * Reliable delivery of signalling messages
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100352 *
jjako52c24142002-12-16 13:33:51 +0000353 * Sequence numbers are used for both signalling messages and
354 * data messages.
355 *
356 * For data messages each tunnel maintains a sequence counter,
357 * which is incremented by one each time a new data message
358 * is sent. The sequence number starts at (0) zero at tunnel
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100359 * establishment, and wraps around at 65535 (29.060 9.3.1.1
jjako52c24142002-12-16 13:33:51 +0000360 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
361 * or can be used to check the validity of the message in the
362 * receiver, or for reordering af packets.
363 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100364 * For signalling messages the sequence number is used by
jjako52c24142002-12-16 13:33:51 +0000365 * signalling messages for which a response is defined. A response
366 * message should copy the sequence from the corresponding request
367 * message. The sequence number "unambiguously" identifies a request
368 * message within a given path, with a path being defined as a set of
369 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
370 * messages shall be responded to, and all response messages associated
371 * with a certain request shall always include the same information"
372 *
373 * We take this to mean that the GSN transmitting a request is free to
374 * choose the sequence number, as long as it is unique within a given path.
375 * It means that we are allowed to count backwards, or roll over at 17
376 * if we prefer that. It also means that we can use the same counter for
377 * all paths. This has the advantage that the transmitted request sequence
378 * numbers are unique within each GSN, and also we dont have to mess around
379 * with path setup and teardown.
380 *
381 * If a response message is lost, the request will be retransmitted, and
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100382 * the receiving GSN will receive a "duplicated" request. The standard
jjako52c24142002-12-16 13:33:51 +0000383 * requires the receiving GSN to send a response, with the same information
384 * as in the original response. For most messages this happens automatically:
385 *
386 * Echo: Automatically dublicates the original response
387 * Create pdp context: The SGSN may send create context request even if
388 * a context allready exist (imsi+nsapi?). This means that the reply will
389 automatically dublicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000390 * side effects in the application which is asked twice to validate
391 * the login.
jjako52c24142002-12-16 13:33:51 +0000392 * Update pdp context: Automatically dublicates the original response???
393 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
394 * a nonexist reply message.
395 *
396 * The correct solution will be to make a queue containing response messages.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100397 * This queue should be checked whenever a request is received. If the
jjako52c24142002-12-16 13:33:51 +0000398 * response is allready in the queue that response should be transmitted.
399 * It should be possible to find messages in this queue on the basis of
400 * the sequence number and peer GSN IP address (The sequense number is unique
401 * within each path). This need to be implemented by a hash table. Furthermore
402 * it should be possibly to delete messages based on a timeout. This can be
403 * achieved by means of a linked list. The timeout value need to be larger
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100404 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
jjako52c24142002-12-16 13:33:51 +0000405 * set in the peer GSN, so there is no way to know these parameters. On the
406 * other hand the timeout value need to be so small that we do not receive
407 * wraparound sequence numbere before the message is deleted. 60 seconds is
408 * probably not a bad choise.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100409 *
jjako52c24142002-12-16 13:33:51 +0000410 * This queue however is first really needed from gtp1.
411 *
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100412 * gtp_req:
jjako52c24142002-12-16 13:33:51 +0000413 * Send off a signalling message with appropiate sequence
414 * number. Store packet in queue.
415 * gtp_conf:
416 * Remove an incoming confirmation from the queue
417 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000418 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000419 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000420 * gtp_notification:
421 * Send off a notification message. This is neither a request nor
422 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000423 * gtp_retrans:
424 * Retransmit any outstanding packets which have exceeded
425 * a predefined timeout.
426 *************************************************************/
427
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100428static int gtp_req(struct gsn_t *gsn, uint8_t version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100429 union gtp_packet *packet, int len,
430 struct in_addr *inetaddr, void *cbp)
431{
Harald Weltefed598f2017-09-24 16:39:22 +0800432 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100433 struct sockaddr_in addr;
434 struct qmsg_t *qmsg;
435 int fd;
jjako08d331d2003-10-13 20:33:30 +0000436
Harald Weltebed35df2011-11-02 13:06:18 +0100437 memset(&addr, 0, sizeof(addr));
438 addr.sin_family = AF_INET;
439 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000440#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100441 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000442#endif
jjako52c24142002-12-16 13:33:51 +0000443
Harald Weltefed598f2017-09-24 16:39:22 +0800444 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100445 addr.sin_port = htons(GTP0_PORT);
446 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
447 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100448 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100449 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100450 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100451 }
Harald Weltebed35df2011-11-02 13:06:18 +0100452 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
453 || (packet->gtp0.h.type == GTP_ERROR)))
454 packet->gtp0.h.flow = hton16(pdp->flru);
455 else if (pdp)
456 packet->gtp0.h.flow = hton16(pdp->flrc);
457 fd = gsn->fd0;
Harald Weltefed598f2017-09-24 16:39:22 +0800458 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100459 addr.sin_port = htons(GTP1C_PORT);
460 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
461 packet->gtp1l.h.seq = hton16(gsn->seq_next);
462 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
463 (packet->gtp1l.h.type == GTP_ERROR)))
464 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
465 else if (pdp)
466 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
467 fd = gsn->fd1c;
468 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100469 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100470 return -1;
471 }
jjako52c24142002-12-16 13:33:51 +0000472
Harald Weltebed35df2011-11-02 13:06:18 +0100473 if (sendto(fd, packet, len, 0,
474 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
475 gsn->err_sendto++;
Max14b1b632017-08-21 20:14:59 +0200476 LOGP(DLGTP, LOGL_ERROR, "Sendto(fd=%d, msg=%lx, len=%d, dst=%s) failed: Error = %s\n", fd,
477 (unsigned long)&packet, len, inet_ntoa(addr.sin_addr), strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100478 return -1;
479 }
480
481 /* Use new queue structure */
482 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
483 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100484 LOGP(DLGTP, LOGL_ERROR,
485 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100486 } else {
487 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
488 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100489 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100490 qmsg->retrans = 0; /* No retransmissions so far */
491 qmsg->cbp = cbp;
492 qmsg->type = ntoh8(packet->gtp0.h.type);
493 qmsg->fd = fd;
494 }
495 gsn->seq_next++; /* Count up this time */
496 return 0;
jjako52c24142002-12-16 13:33:51 +0000497}
498
499/* gtp_conf
500 * Remove signalling packet from retransmission queue.
501 * return 0 on success, EOF if packet was not found */
502
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100503static int gtp_conf(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100504 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
505{
Harald Weltefed598f2017-09-24 16:39:22 +0800506 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100507 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000508
Harald Weltefed598f2017-09-24 16:39:22 +0800509 if (ver == 0)
Harald Weltebed35df2011-11-02 13:06:18 +0100510 seq = ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800511 else if (ver == 1 && (packet->gtp1l.h.flags & GTP1HDR_F_SEQ))
Harald Weltebed35df2011-11-02 13:06:18 +0100512 seq = ntoh16(packet->gtp1l.h.seq);
513 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100514 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
515 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100516 return EOF;
517 }
jjako08d331d2003-10-13 20:33:30 +0000518
Harald Weltebed35df2011-11-02 13:06:18 +0100519 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
520 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100521 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
522 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100523 return EOF;
524 }
jjako52c24142002-12-16 13:33:51 +0000525
Harald Weltebed35df2011-11-02 13:06:18 +0100526 return 0;
jjako52c24142002-12-16 13:33:51 +0000527}
528
Harald Weltebed35df2011-11-02 13:06:18 +0100529int gtp_retrans(struct gsn_t *gsn)
530{
531 /* Retransmit any outstanding packets */
532 /* Remove from queue if maxretrans exceeded */
533 time_t now;
534 struct qmsg_t *qmsg;
535 now = time(NULL);
536 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000537
Harald Welte95848ba2011-11-02 18:17:50 +0100538 /* get first element in queue, as long as the timeout of that
539 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100540 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
541 (qmsg->timeout <= now)) {
542 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100543 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100544 if (gsn->cb_conf)
545 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
546 queue_freemsg(gsn->queue_req, qmsg);
547 } else {
548 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
549 (struct sockaddr *)&qmsg->peer,
550 sizeof(struct sockaddr_in)) < 0) {
551 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100552 LOGP(DLGTP, LOGL_ERROR,
553 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100554 gsn->fd0, (unsigned long)&qmsg->p,
555 qmsg->l, strerror(errno));
556 }
557 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100558 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100559 qmsg->retrans++;
560 }
561 }
jjako52c24142002-12-16 13:33:51 +0000562
Harald Weltebed35df2011-11-02 13:06:18 +0100563 /* Also clean up reply timeouts */
564 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
565 (qmsg->timeout < now)) {
566 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
567 queue_freemsg(gsn->queue_resp, qmsg);
568 }
jjako52c24142002-12-16 13:33:51 +0000569
Harald Weltebed35df2011-11-02 13:06:18 +0100570 return 0;
jjako52c24142002-12-16 13:33:51 +0000571}
572
Harald Weltebed35df2011-11-02 13:06:18 +0100573int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
574{
575 time_t now, later;
576 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000577
Harald Weltebed35df2011-11-02 13:06:18 +0100578 if (queue_getfirst(gsn->queue_req, &qmsg)) {
579 timeout->tv_sec = 10;
580 timeout->tv_usec = 0;
581 } else {
582 now = time(NULL);
583 later = qmsg->timeout;
584 timeout->tv_sec = later - now;
585 timeout->tv_usec = 0;
586 if (timeout->tv_sec < 0)
587 timeout->tv_sec = 0; /* No negative allowed */
588 if (timeout->tv_sec > 10)
589 timeout->tv_sec = 10; /* Max sleep for 10 sec */
590 }
591 return 0;
jjako52c24142002-12-16 13:33:51 +0000592}
593
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100594static int gtp_resp(uint8_t version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000595 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100596 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
597{
Harald Weltefed598f2017-09-24 16:39:22 +0800598 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100599 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000600
Harald Weltefed598f2017-09-24 16:39:22 +0800601 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100602 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
603 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100604 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100605 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
606 (packet->gtp0.h.type == GTP_ERROR)))
607 packet->gtp0.h.flow = hton16(pdp->flru);
608 else if (pdp)
609 packet->gtp0.h.flow = hton16(pdp->flrc);
Harald Weltefed598f2017-09-24 16:39:22 +0800610 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100611 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
612 packet->gtp1l.h.seq = hton16(seq);
613 if (pdp && (fd == gsn->fd1u))
614 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
615 else if (pdp)
616 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
617 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100618 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100619 return -1;
620 }
jjako08d331d2003-10-13 20:33:30 +0000621
Harald Weltebed35df2011-11-02 13:06:18 +0100622 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100623 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100624 return -1;
625 }
jjako52c24142002-12-16 13:33:51 +0000626
Harald Weltebed35df2011-11-02 13:06:18 +0100627 if (sendto(fd, packet, len, 0,
628 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
629 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100630 LOGP(DLGTP, LOGL_ERROR,
631 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100632 (unsigned long)&packet, len, strerror(errno));
633 return -1;
634 }
635
636 /* Use new queue structure */
637 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
638 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100639 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100640 } else {
641 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
642 qmsg->l = len;
643 qmsg->timeout = time(NULL) + 60; /* When to timeout */
644 qmsg->retrans = 0; /* No retransmissions so far */
645 qmsg->cbp = NULL;
646 qmsg->type = 0;
647 qmsg->fd = fd;
648 }
649 return 0;
jjako52c24142002-12-16 13:33:51 +0000650}
651
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100652static int gtp_notification(struct gsn_t *gsn, uint8_t version,
jjako2c381332003-10-21 19:09:53 +0000653 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100654 struct sockaddr_in *peer, int fd, uint16_t seq)
655{
jjako2c381332003-10-21 19:09:53 +0000656
Harald Weltefed598f2017-09-24 16:39:22 +0800657 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100658 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000659
Harald Weltebed35df2011-11-02 13:06:18 +0100660 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000661
Harald Weltebed35df2011-11-02 13:06:18 +0100662 /* In GTP0 notifications are treated as replies. In GTP1 they
663 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000664
Harald Weltebed35df2011-11-02 13:06:18 +0100665 if (fd == gsn->fd1c)
666 addr.sin_port = htons(GTP1C_PORT);
667 else if (fd == gsn->fd1u)
668 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000669
Harald Weltefed598f2017-09-24 16:39:22 +0800670 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100671 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
672 packet->gtp0.h.seq = hton16(seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800673 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100674 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
675 packet->gtp1l.h.seq = hton16(seq);
676 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100677 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100678 return -1;
679 }
680
681 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100682 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100683 return -1;
684 }
685
686 if (sendto(fd, packet, len, 0,
687 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
688 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100689 LOGP(DLGTP, LOGL_ERROR,
690 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100691 (unsigned long)&packet, len, strerror(errno));
692 return -1;
693 }
694 return 0;
jjako2c381332003-10-21 19:09:53 +0000695}
696
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100697static int gtp_dublicate(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +0100698 struct sockaddr_in *peer, uint16_t seq)
699{
700 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000701
Harald Weltebed35df2011-11-02 13:06:18 +0100702 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
703 return EOF; /* Notfound */
704 }
jjakoa7cd2492003-04-11 09:40:12 +0000705
Harald Weltebed35df2011-11-02 13:06:18 +0100706 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100707 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100708 return -1;
709 }
710
711 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
712 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
713 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100714 LOGP(DLGTP, LOGL_ERROR,
715 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100716 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
717 strerror(errno));
718 }
719 return 0;
jjako52c24142002-12-16 13:33:51 +0000720}
721
jjako52c24142002-12-16 13:33:51 +0000722/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100723static void log_restart(struct gsn_t *gsn)
724{
jjako52c24142002-12-16 13:33:51 +0000725 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200726 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000727 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200728 char *filename;
jjako52c24142002-12-16 13:33:51 +0000729
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200730 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
731 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000732
733 /* We try to open file. On failure we will later try to create file */
734 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100735 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100736 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100737 filename);
738 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100739 rc = fscanf(f, "%d", &counter);
740 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100741 LOGP(DLGTP, LOGL_ERROR,
742 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100743 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100744 }
745 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));
Harald Weltebed35df2011-11-02 13:06:18 +0100748 }
jjako52c24142002-12-16 13:33:51 +0000749 }
Harald Weltebed35df2011-11-02 13:06:18 +0100750
751 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000752 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100753
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200754 /* Keep the umask closely wrapped around our fopen() call in case the
755 * log outputs cause file creation. */
756 i = umask(022);
757 f = fopen(filename, "w");
758 umask(i);
759 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100760 LOGP(DLGTP, LOGL_ERROR,
761 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100762 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200763 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000764 }
765
jjako52c24142002-12-16 13:33:51 +0000766 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100767close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200768 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100769 LOGP(DLGTP, LOGL_ERROR,
770 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200771free_filename:
772 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000773}
774
jjako1db1c812003-07-06 20:53:57 +0000775int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100776 int mode)
jjako52c24142002-12-16 13:33:51 +0000777{
Harald Weltebed35df2011-11-02 13:06:18 +0100778 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000779
Max14b1b632017-08-21 20:14:59 +0200780 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
jjako52c24142002-12-16 13:33:51 +0000781
Harald Weltebed35df2011-11-02 13:06:18 +0100782 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000783
Harald Weltebed35df2011-11-02 13:06:18 +0100784 (*gsn)->statedir = statedir;
785 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000786
Harald Weltebed35df2011-11-02 13:06:18 +0100787 /* Initialise sequence number */
788 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000789
Harald Weltebed35df2011-11-02 13:06:18 +0100790 /* Initialise request retransmit queue */
791 queue_new(&(*gsn)->queue_req);
792 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000793
Harald Weltebed35df2011-11-02 13:06:18 +0100794 /* Initialise pdp table */
795 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000796
Harald Weltebed35df2011-11-02 13:06:18 +0100797 /* Initialise call back functions */
798 (*gsn)->cb_create_context_ind = 0;
799 (*gsn)->cb_delete_context = 0;
800 (*gsn)->cb_unsup_ind = 0;
801 (*gsn)->cb_conf = 0;
802 (*gsn)->cb_data_ind = 0;
803
804 /* Store function parameters */
805 (*gsn)->gsnc = *listen;
806 (*gsn)->gsnu = *listen;
807 (*gsn)->mode = mode;
808
809 /* Create GTP version 0 socket */
810 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
811 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100812 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200813 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100814 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200815 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100816 }
817
818 memset(&addr, 0, sizeof(addr));
819 addr.sin_family = AF_INET;
820 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
821 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000822#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100823 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000824#endif
jjako08d331d2003-10-13 20:33:30 +0000825
Harald Weltebed35df2011-11-02 13:06:18 +0100826 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
827 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200828 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
829 "bind(fd0=%d) failed: Error = %s\n",
830 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200831 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100832 }
jjako08d331d2003-10-13 20:33:30 +0000833
Harald Weltebed35df2011-11-02 13:06:18 +0100834 /* Create GTP version 1 control plane socket */
835 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
836 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100837 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200838 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100839 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200840 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100841 }
842
843 memset(&addr, 0, sizeof(addr));
844 addr.sin_family = AF_INET;
845 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
846 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000847#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100848 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000849#endif
jjako08d331d2003-10-13 20:33:30 +0000850
Harald Weltebed35df2011-11-02 13:06:18 +0100851 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
852 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200853 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
854 "bind(fd1c=%d) failed: Error = %s\n",
855 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200856 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100857 }
jjako08d331d2003-10-13 20:33:30 +0000858
Harald Weltebed35df2011-11-02 13:06:18 +0100859 /* Create GTP version 1 user plane socket */
860 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
861 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100862 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200863 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100864 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200865 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100866 }
867
868 memset(&addr, 0, sizeof(addr));
869 addr.sin_family = AF_INET;
870 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
871 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000872#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100873 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000874#endif
jjako52c24142002-12-16 13:33:51 +0000875
Harald Weltebed35df2011-11-02 13:06:18 +0100876 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
877 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200878 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +0200879 "bind(fd1u=%d) failed: Error = %s\n",
880 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +0200881 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100882 }
883
884 return 0;
jjako52c24142002-12-16 13:33:51 +0000885}
886
Harald Weltebed35df2011-11-02 13:06:18 +0100887int gtp_free(struct gsn_t *gsn)
888{
jjako52c24142002-12-16 13:33:51 +0000889
Harald Weltebed35df2011-11-02 13:06:18 +0100890 /* Clean up retransmit queues */
891 queue_free(gsn->queue_req);
892 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000893
Harald Weltebed35df2011-11-02 13:06:18 +0100894 close(gsn->fd0);
895 close(gsn->fd1c);
896 close(gsn->fd1u);
897
898 free(gsn);
899 return 0;
jjako52c24142002-12-16 13:33:51 +0000900}
901
902/* ***********************************************************
903 * Path management messages
904 * Messages: echo and version not supported.
905 * A path is connection between two UDP/IP endpoints
906 *
907 * A path is either using GTP0 or GTP1. A path can be
908 * established by any kind of GTP message??
909
910 * Which source port to use?
911 * GTP-C request destination port is 2123/3386
912 * GTP-U request destination port is 2152/3386
913 * T-PDU destination port is 2152/3386.
914 * For the above messages the source port is locally allocated.
915 * For response messages src=rx-dst and dst=rx-src.
916 * For simplicity we should probably use 2123+2152/3386 as
917 * src port even for the cases where src can be locally
918 * allocated. This also means that we have to listen only to
919 * the same ports.
920 * For response messages we need to be able to respond to
921 * the relevant src port even if it is locally allocated by
922 * the peer.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100923 *
jjako52c24142002-12-16 13:33:51 +0000924 * The need for path management!
925 * We might need to keep a list of active paths. This might
926 * be in the form of remote IP address + UDP port numbers.
927 * (We will consider a path astablished if we have a context
928 * with the node in question)
929 *************************************************************/
930
931/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000932int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
933 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000934{
Harald Weltebed35df2011-11-02 13:06:18 +0100935 union gtp_packet packet;
936 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
937 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000938}
939
jjako08d331d2003-10-13 20:33:30 +0000940/* Send off an echo reply */
941int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100942 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000943{
Harald Weltebed35df2011-11-02 13:06:18 +0100944 union gtp_packet packet;
945 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
946 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
947 gsn->restart_counter);
948 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
949 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000950}
951
jjako52c24142002-12-16 13:33:51 +0000952/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +0100953int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
954 int fd, void *pack, unsigned len)
955{
jjako52c24142002-12-16 13:33:51 +0000956
Harald Weltebed35df2011-11-02 13:06:18 +0100957 /* Check if it was a dublicate request */
958 if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
959 return 0;
jjako52c24142002-12-16 13:33:51 +0000960
Harald Weltebed35df2011-11-02 13:06:18 +0100961 /* Send off reply to request */
962 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000963}
964
965/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000966int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100967 void *pack, unsigned len)
968{
969 union gtpie_member *ie[GTPIE_SIZE];
970 unsigned char recovery;
971 void *cbp = NULL;
972 uint8_t type = 0;
973 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000974
Harald Weltebed35df2011-11-02 13:06:18 +0100975 /* Remove packet from queue */
976 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
977 return EOF;
jjako52c24142002-12-16 13:33:51 +0000978
Harald Weltebed35df2011-11-02 13:06:18 +0100979 /* Extract information elements into a pointer array */
980 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
981 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100982 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
983 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100984 if (gsn->cb_conf)
985 gsn->cb_conf(type, EOF, NULL, cbp);
986 return EOF;
987 }
jjako52c24142002-12-16 13:33:51 +0000988
Harald Weltebed35df2011-11-02 13:06:18 +0100989 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
990 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100991 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
992 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100993 if (gsn->cb_conf)
994 gsn->cb_conf(type, EOF, NULL, cbp);
995 return EOF;
996 }
jjako52c24142002-12-16 13:33:51 +0000997
Harald Weltebed35df2011-11-02 13:06:18 +0100998 /* Echo reply packages does not have a cause information element */
999 /* Instead we return the recovery number in the callback function */
1000 if (gsn->cb_conf)
1001 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +01001002
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001003 emit_cb_recovery(gsn, peer, NULL, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001004
1005 return 0;
jjako52c24142002-12-16 13:33:51 +00001006}
1007
1008/* Send off a Version Not Supported message */
1009/* This message is somewhat special in that it actually is a
1010 * response to some other message with unsupported GTP version
1011 * For this reason it has parameters like a response, and does
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001012 * its own message transmission. No signalling queue is used
jjako52c24142002-12-16 13:33:51 +00001013 * The reply is sent to the peer IP and peer UDP. This means that
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001014 * the peer will be receiving a GTP0 message on a GTP1 port!
jjako52c24142002-12-16 13:33:51 +00001015 * In practice however this will never happen as a GTP0 GSN will
1016 * only listen to the GTP0 port, and therefore will never receive
1017 * anything else than GTP0 */
1018
jjako08d331d2003-10-13 20:33:30 +00001019int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1020 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001021{
Harald Weltebed35df2011-11-02 13:06:18 +01001022 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +00001023
Harald Weltebed35df2011-11-02 13:06:18 +01001024 /* GTP 1 is the highest supported protocol */
1025 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
1026 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +00001027}
1028
1029/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +01001030int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1031 void *pack, unsigned len)
1032{
jjako52c24142002-12-16 13:33:51 +00001033
Harald Weltebed35df2011-11-02 13:06:18 +01001034 if (gsn->cb_unsup_ind)
1035 gsn->cb_unsup_ind(peer);
1036
1037 return 0;
jjako52c24142002-12-16 13:33:51 +00001038}
1039
jjako2c381332003-10-21 19:09:53 +00001040/* Send off an Supported Extension Headers Notification */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001041static int gtp_extheader_req(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
jjako2c381332003-10-21 19:09:53 +00001042 int fd, void *pack, unsigned len)
1043{
Harald Weltebed35df2011-11-02 13:06:18 +01001044 union gtp_packet packet;
1045 unsigned int length =
1046 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +00001047
Harald Weltebed35df2011-11-02 13:06:18 +01001048 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +00001049
Harald Weltebed35df2011-11-02 13:06:18 +01001050 if (version < 1)
1051 return 0;
jjako2c381332003-10-21 19:09:53 +00001052
Harald Weltebed35df2011-11-02 13:06:18 +01001053 /* We report back that we support only PDCP PDU headers */
1054 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
1055 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +00001056
Harald Weltebed35df2011-11-02 13:06:18 +01001057 return gtp_notification(gsn, version, &packet, length,
1058 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +00001059}
1060
1061/* Handle a Supported Extension Headers Notification */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001062static int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001063 void *pack, unsigned len)
1064{
jjako2c381332003-10-21 19:09:53 +00001065
Harald Weltebed35df2011-11-02 13:06:18 +01001066 if (gsn->cb_extheader_ind)
1067 gsn->cb_extheader_ind(peer);
1068
1069 return 0;
jjako2c381332003-10-21 19:09:53 +00001070}
1071
jjako52c24142002-12-16 13:33:51 +00001072/* ***********************************************************
1073 * Session management messages
1074 * Messages: create, update and delete PDP context
1075 *
1076 * Information storage
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001077 * Information storage for each PDP context is defined in
jjako52c24142002-12-16 13:33:51 +00001078 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1079 * PDP-address (IP address), sequence numbers, charging ID.
1080 * For the SGSN it also includes radio related mobility
1081 * information.
1082 *************************************************************/
1083
Harald Welte7b3347b2010-05-15 12:18:46 +02001084/* API: Send Create PDP Context Request (7.3.1) */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001085int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001086 void *cbp)
1087{
1088 union gtp_packet packet;
1089 unsigned int length =
1090 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1091 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001092
Harald Weltebed35df2011-11-02 13:06:18 +01001093 /* TODO: Secondary PDP Context Activation Procedure */
1094 /* In secondary activation procedure the PDP context is identified
1095 by tei in the header. The following fields are omitted: Selection
1096 mode, IMSI, MSISDN, End User Address, Access Point Name and
1097 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001098
Harald Weltebed35df2011-11-02 13:06:18 +01001099 if (pdp->secondary) {
1100 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001101 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001102 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001103 return EOF;
1104 }
1105 }
jjako2c381332003-10-21 19:09:53 +00001106
Harald Weltebed35df2011-11-02 13:06:18 +01001107 if (pdp->version == 0) {
1108 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1109 sizeof(pdp->qos_req0), pdp->qos_req0);
1110 }
jjako52c24142002-12-16 13:33:51 +00001111
Harald Weltebed35df2011-11-02 13:06:18 +01001112 /* Section 7.7.2 */
1113 if (pdp->version == 1) {
1114 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1115 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1116 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1117 }
jjako52c24142002-12-16 13:33:51 +00001118
Harald Weltebed35df2011-11-02 13:06:18 +01001119 /* Section 7.7.3 Routing Area Information */
1120 if (pdp->rai_given == 1)
1121 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1122 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001123
Harald Weltebed35df2011-11-02 13:06:18 +01001124 /* Section 7.7.11 */
1125 if (pdp->norecovery_given == 0)
1126 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1127 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001128
Harald Weltebed35df2011-11-02 13:06:18 +01001129 /* Section 7.7.12 */
1130 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1131 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1132 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001133
Harald Weltebed35df2011-11-02 13:06:18 +01001134 if (pdp->version == 0) {
1135 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1136 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1137 }
jjako08d331d2003-10-13 20:33:30 +00001138
Harald Weltebed35df2011-11-02 13:06:18 +01001139 /* Section 7.7.13 */
1140 if (pdp->version == 1) {
1141 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1142 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001143
Harald Weltebed35df2011-11-02 13:06:18 +01001144 /* Section 7.7.14 */
1145 if (!pdp->teic_confirmed)
1146 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1147 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001148
Harald Weltebed35df2011-11-02 13:06:18 +01001149 /* Section 7.7.17 */
1150 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001151
Harald Weltebed35df2011-11-02 13:06:18 +01001152 /* Section 7.7.17 */
1153 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1154 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1155 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001156
Harald Weltebed35df2011-11-02 13:06:18 +01001157 /* Section 7.7.23 */
1158 if (pdp->cch_pdp) /* Only include charging if flags are set */
1159 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1160 pdp->cch_pdp);
1161 }
jjako9b4971d2004-05-27 20:30:19 +00001162
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001163 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001164 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1165 pdp->traceref);
1166 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1167 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001168
Harald Weltebed35df2011-11-02 13:06:18 +01001169 /* Section 7.7.27 */
1170 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1171 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1172 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001173
Harald Weltebed35df2011-11-02 13:06:18 +01001174 /* Section 7.7.30 */
1175 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1176 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1177 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001178
Harald Weltebed35df2011-11-02 13:06:18 +01001179 /* Section 7.7.31 */
1180 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1181 if (pdp->pco_req.l)
1182 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1183 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001184
Harald Weltebed35df2011-11-02 13:06:18 +01001185 /* Section 7.7.32 */
1186 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1187 pdp->gsnlc.l, pdp->gsnlc.v);
1188 /* Section 7.7.32 */
1189 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1190 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001191
Harald Weltebed35df2011-11-02 13:06:18 +01001192 /* Section 7.7.33 */
1193 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1194 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1195 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001196
Harald Weltebed35df2011-11-02 13:06:18 +01001197 /* Section 7.7.34 */
1198 if (pdp->version == 1)
1199 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1200 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001201
Harald Weltebed35df2011-11-02 13:06:18 +01001202 /* Section 7.7.36 */
1203 if ((pdp->version == 1) && pdp->tft.l)
1204 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1205 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001206
Harald Weltebed35df2011-11-02 13:06:18 +01001207 /* Section 7.7.41 */
1208 if ((pdp->version == 1) && pdp->triggerid.l)
1209 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1210 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001211
Harald Weltebed35df2011-11-02 13:06:18 +01001212 /* Section 7.7.42 */
1213 if ((pdp->version == 1) && pdp->omcid.l)
1214 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1215 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001216
Harald Weltebed35df2011-11-02 13:06:18 +01001217 /* new R7 fields */
1218 if (pdp->rattype_given == 1)
1219 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1220 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001221
Harald Weltebed35df2011-11-02 13:06:18 +01001222 if (pdp->userloc_given == 1)
1223 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1224 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001225
Harald Weltebed35df2011-11-02 13:06:18 +01001226 if (pdp->mstz_given == 1)
1227 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1228 pdp->mstz.l, pdp->mstz.v);
1229
1230 if (pdp->imeisv_given == 1)
1231 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1232 pdp->imeisv.l, pdp->imeisv.v);
1233
1234 /* TODO hisaddr0 */
1235 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1236
1237 return 0;
jjako52c24142002-12-16 13:33:51 +00001238}
1239
jjako08d331d2003-10-13 20:33:30 +00001240/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001241int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1242{
jjako08d331d2003-10-13 20:33:30 +00001243
Harald Weltebed35df2011-11-02 13:06:18 +01001244 /* Now send off a reply to the peer */
1245 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1246
1247 if (cause != GTPCAUSE_ACC_REQ) {
1248 pdp_freepdp(pdp);
1249 }
1250
1251 return 0;
jjako08d331d2003-10-13 20:33:30 +00001252}
1253
1254/* API: Register create context indication callback */
1255int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001256 int (*cb_create_context_ind) (struct pdp_t *
1257 pdp))
jjako52c24142002-12-16 13:33:51 +00001258{
Harald Weltebed35df2011-11-02 13:06:18 +01001259 gsn->cb_create_context_ind = cb_create_context_ind;
1260 return 0;
jjako08d331d2003-10-13 20:33:30 +00001261}
1262
jjako08d331d2003-10-13 20:33:30 +00001263/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001264int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1265 uint8_t cause)
1266{
1267 union gtp_packet packet;
1268 unsigned int length =
1269 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001270
Harald Weltebed35df2011-11-02 13:06:18 +01001271 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001272
Harald Weltebed35df2011-11-02 13:06:18 +01001273 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001274
Harald Weltebed35df2011-11-02 13:06:18 +01001275 if (version == 0)
1276 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1277 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001278
Harald Weltebed35df2011-11-02 13:06:18 +01001279 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1280 pdp->reorder);
1281 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1282 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001283
Harald Weltebed35df2011-11-02 13:06:18 +01001284 if (version == 0) {
1285 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1286 pdp->fllu);
1287 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1288 pdp->fllc);
1289 }
jjako08d331d2003-10-13 20:33:30 +00001290
Harald Weltebed35df2011-11-02 13:06:18 +01001291 if (version == 1) {
1292 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1293 pdp->teid_own);
1294 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1295 pdp->teic_own);
1296 }
jjako08d331d2003-10-13 20:33:30 +00001297
Harald Weltebed35df2011-11-02 13:06:18 +01001298 /* TODO: We use teic_own as charging ID */
1299 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1300 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001301
Harald Weltebed35df2011-11-02 13:06:18 +01001302 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1303 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001304
Harald Weltebed35df2011-11-02 13:06:18 +01001305 if (pdp->pco_neg.l) { /* Optional PCO */
1306 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1307 pdp->pco_neg.l, pdp->pco_neg.v);
1308 }
jjako52c24142002-12-16 13:33:51 +00001309
Harald Weltebed35df2011-11-02 13:06:18 +01001310 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1311 pdp->gsnlc.l, pdp->gsnlc.v);
1312 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1313 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001314
Harald Weltebed35df2011-11-02 13:06:18 +01001315 if (version == 1)
1316 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1317 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001318
Harald Weltebed35df2011-11-02 13:06:18 +01001319 /* TODO: Charging gateway address */
1320 }
jjako52c24142002-12-16 13:33:51 +00001321
Harald Weltebed35df2011-11-02 13:06:18 +01001322 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1323 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001324}
1325
1326/* Handle Create PDP Context Request */
1327int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001328 struct sockaddr_in *peer, int fd,
1329 void *pack, unsigned len)
1330{
1331 struct pdp_t *pdp, *pdp_old;
1332 struct pdp_t pdp_buf;
1333 union gtpie_member *ie[GTPIE_SIZE];
1334 uint8_t recovery;
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001335 bool recovery_recvd = false;
1336 int rc;
jjako52c24142002-12-16 13:33:51 +00001337
Harald Weltebed35df2011-11-02 13:06:18 +01001338 uint16_t seq = get_seq(pack);
1339 int hlen = get_hlen(pack);
1340 uint8_t linked_nsapi = 0;
1341 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001342
Harald Weltebed35df2011-11-02 13:06:18 +01001343 if (!gtp_dublicate(gsn, version, peer, seq))
1344 return 0;
jjako08d331d2003-10-13 20:33:30 +00001345
Harald Weltebed35df2011-11-02 13:06:18 +01001346 pdp = &pdp_buf;
1347 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001348
Harald Weltebed35df2011-11-02 13:06:18 +01001349 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001350 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1351
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001352 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001353 }
jjako52c24142002-12-16 13:33:51 +00001354
Harald Weltebed35df2011-11-02 13:06:18 +01001355 pdp->seq = seq;
1356 pdp->sa_peer = *peer;
1357 pdp->fd = fd;
1358 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001359
Harald Weltebed35df2011-11-02 13:06:18 +01001360 /* Decode information elements */
1361 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1362 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001363 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1364 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001365 if (0 == version)
1366 return EOF;
1367 else
1368 return gtp_create_pdp_resp(gsn, version, pdp,
1369 GTPCAUSE_INVALID_MESSAGE);
1370 }
jjako52c24142002-12-16 13:33:51 +00001371
Harald Weltebed35df2011-11-02 13:06:18 +01001372 if (version == 1) {
1373 /* Linked NSAPI (conditional) */
1374 /* If included this is the Secondary PDP Context Activation Procedure */
1375 /* In secondary activation IMSI is not included, so the context must be */
1376 /* identified by the tei */
1377 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001378
Harald Weltebed35df2011-11-02 13:06:18 +01001379 /* Find the primary PDP context */
1380 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1381 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001382 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001383 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001384 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001385 return gtp_create_pdp_resp(gsn, version, pdp,
1386 GTPCAUSE_OPT_IE_INCORRECT);
1387 }
jjako2c381332003-10-21 19:09:53 +00001388
Harald Weltebed35df2011-11-02 13:06:18 +01001389 /* Check that the primary PDP context matches linked nsapi */
1390 if (linked_pdp->nsapi != linked_nsapi) {
1391 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001392 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001393 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001394 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001395 return gtp_create_pdp_resp(gsn, version, pdp,
1396 GTPCAUSE_OPT_IE_INCORRECT);
1397 }
jjako52c24142002-12-16 13:33:51 +00001398
Harald Weltebed35df2011-11-02 13:06:18 +01001399 /* Copy parameters from primary context */
1400 pdp->selmode = linked_pdp->selmode;
1401 pdp->imsi = linked_pdp->imsi;
1402 pdp->msisdn = linked_pdp->msisdn;
1403 pdp->eua = linked_pdp->eua;
1404 pdp->pco_req = linked_pdp->pco_req;
1405 pdp->apn_req = linked_pdp->apn_req;
1406 pdp->teic_gn = linked_pdp->teic_gn;
1407 pdp->secondary = 1;
1408 }
1409 }
1410 /* if (version == 1) */
1411 if (version == 0) {
1412 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1413 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1414 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001415 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1416 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001417 return gtp_create_pdp_resp(gsn, version, pdp,
1418 GTPCAUSE_MAN_IE_MISSING);
1419 }
1420 }
jjako08d331d2003-10-13 20:33:30 +00001421
Harald Weltebed35df2011-11-02 13:06:18 +01001422 if ((version == 1) && (!linked_pdp)) {
1423 /* Not Secondary PDP Context Activation Procedure */
1424 /* IMSI (conditional) */
1425 if (gtpie_gettv0
1426 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1427 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001428 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1429 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001430 return gtp_create_pdp_resp(gsn, version, pdp,
1431 GTPCAUSE_MAN_IE_MISSING);
1432 }
1433 }
jjako52c24142002-12-16 13:33:51 +00001434
Harald Weltebed35df2011-11-02 13:06:18 +01001435 /* Recovery (optional) */
1436 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001437 /* we use recovery futher down after announcing new pdp ctx to user */
1438 recovery_recvd = true;
Harald Weltebed35df2011-11-02 13:06:18 +01001439 }
jjako52c24142002-12-16 13:33:51 +00001440
Harald Weltebed35df2011-11-02 13:06:18 +01001441 /* Selection mode (conditional) */
1442 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1443 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1444 &pdp->selmode, sizeof(pdp->selmode))) {
1445 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001446 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1447 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001448 return gtp_create_pdp_resp(gsn, version, pdp,
1449 GTPCAUSE_MAN_IE_MISSING);
1450 }
1451 }
jjako52c24142002-12-16 13:33:51 +00001452
Harald Weltebed35df2011-11-02 13:06:18 +01001453 if (version == 0) {
1454 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1455 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001456 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1457 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001458 return gtp_create_pdp_resp(gsn, version, pdp,
1459 GTPCAUSE_MAN_IE_MISSING);
1460 }
jjako52c24142002-12-16 13:33:51 +00001461
Harald Weltebed35df2011-11-02 13:06:18 +01001462 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1463 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001464 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1465 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001466 return gtp_create_pdp_resp(gsn, version, pdp,
1467 GTPCAUSE_MAN_IE_MISSING);
1468 }
1469 }
jjako08d331d2003-10-13 20:33:30 +00001470
Harald Weltebed35df2011-11-02 13:06:18 +01001471 if (version == 1) {
1472 /* TEID (mandatory) */
1473 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1474 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001475 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1476 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001477 return gtp_create_pdp_resp(gsn, version, pdp,
1478 GTPCAUSE_MAN_IE_MISSING);
1479 }
jjako2c381332003-10-21 19:09:53 +00001480
Harald Weltebed35df2011-11-02 13:06:18 +01001481 /* TEIC (conditional) */
1482 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1483 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1484 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001485 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001486 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001487 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001488 return gtp_create_pdp_resp(gsn, version, pdp,
1489 GTPCAUSE_MAN_IE_MISSING);
1490 }
1491 }
jjako08d331d2003-10-13 20:33:30 +00001492
Harald Weltebed35df2011-11-02 13:06:18 +01001493 /* NSAPI (mandatory) */
1494 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1495 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001496 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1497 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001498 return gtp_create_pdp_resp(gsn, version, pdp,
1499 GTPCAUSE_MAN_IE_MISSING);
1500 }
1501 }
jjako2e840a32003-01-28 16:05:18 +00001502
Harald Weltebed35df2011-11-02 13:06:18 +01001503 /* Charging Characteriatics (optional) */
1504 /* Trace reference (optional) */
1505 /* Trace type (optional) */
1506 /* Charging Characteriatics (optional) */
jjako52c24142002-12-16 13:33:51 +00001507
Harald Weltebed35df2011-11-02 13:06:18 +01001508 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1509 /* End User Address (conditional) */
1510 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1511 &pdp->eua.v, sizeof(pdp->eua.v))) {
1512 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001513 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1514 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001515 return gtp_create_pdp_resp(gsn, version, pdp,
1516 GTPCAUSE_MAN_IE_MISSING);
1517 }
jjako08d331d2003-10-13 20:33:30 +00001518
Harald Weltebed35df2011-11-02 13:06:18 +01001519 /* APN */
1520 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1521 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1522 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001523 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1524 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001525 return gtp_create_pdp_resp(gsn, version, pdp,
1526 GTPCAUSE_MAN_IE_MISSING);
1527 }
jjako2c381332003-10-21 19:09:53 +00001528
Harald Weltebed35df2011-11-02 13:06:18 +01001529 /* Extract protocol configuration options (optional) */
1530 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1531 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1532 }
1533 }
jjako2c381332003-10-21 19:09:53 +00001534
Harald Weltebed35df2011-11-02 13:06:18 +01001535 /* SGSN address for signalling (mandatory) */
1536 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1537 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1538 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001539 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1540 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001541 return gtp_create_pdp_resp(gsn, version, pdp,
1542 GTPCAUSE_MAN_IE_MISSING);
1543 }
jjako2e840a32003-01-28 16:05:18 +00001544
Harald Weltebed35df2011-11-02 13:06:18 +01001545 /* SGSN address for user traffic (mandatory) */
1546 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1547 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1548 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001549 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1550 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001551 return gtp_create_pdp_resp(gsn, version, pdp,
1552 GTPCAUSE_MAN_IE_MISSING);
1553 }
jjako52c24142002-12-16 13:33:51 +00001554
Harald Weltebed35df2011-11-02 13:06:18 +01001555 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1556 /* MSISDN (conditional) */
1557 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1558 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1559 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001560 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1561 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001562 return gtp_create_pdp_resp(gsn, version, pdp,
1563 GTPCAUSE_MAN_IE_MISSING);
1564 }
1565 }
jjako52c24142002-12-16 13:33:51 +00001566
Harald Weltebed35df2011-11-02 13:06:18 +01001567 if (version == 1) {
1568 /* QoS (mandatory) */
1569 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1570 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1571 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001572 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1573 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001574 return gtp_create_pdp_resp(gsn, version, pdp,
1575 GTPCAUSE_MAN_IE_MISSING);
1576 }
1577
1578 /* TFT (conditional) */
1579 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1580 &pdp->tft.v, sizeof(pdp->tft.v))) {
1581 }
1582
1583 /* Trigger ID */
1584 /* OMC identity */
1585 }
1586
1587 /* Initialize our own IP addresses */
1588 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1589 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1590
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001591 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001592
1593 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1594 /* Found old pdp with same tid. Now the voodoo begins! */
1595 /* 09.60 / 29.060 allows create on existing context to "steal" */
1596 /* the context which was allready established */
1597 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001598 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001599 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1600 &&
1601 (!memcmp
1602 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1603 && (pdp->selmode == pdp_old->selmode)
1604 && (pdp->msisdn.l == pdp_old->msisdn.l)
1605 &&
1606 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1607 {
1608 /* OK! We are dealing with the same APN. We will copy new
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001609 * parameters to the old pdp and send off confirmation
Harald Weltebed35df2011-11-02 13:06:18 +01001610 * We ignore the following information elements:
1611 * QoS: MS will get originally negotiated QoS.
1612 * End user address (EUA). MS will get old EUA anyway.
1613 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001614 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001615
1616 /* Copy remote flow label */
1617 pdp_old->flru = pdp->flru;
1618 pdp_old->flrc = pdp->flrc;
1619
1620 /* Copy remote tei */
1621 pdp_old->teid_gn = pdp->teid_gn;
1622 pdp_old->teic_gn = pdp->teic_gn;
1623
1624 /* Copy peer GSN address */
1625 pdp_old->gsnrc.l = pdp->gsnrc.l;
1626 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1627 pdp_old->gsnru.l = pdp->gsnru.l;
1628 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1629
1630 /* Copy request parameters */
1631 pdp_old->seq = pdp->seq;
1632 pdp_old->sa_peer = pdp->sa_peer;
1633 pdp_old->fd = pdp->fd = fd;
1634 pdp_old->version = pdp->version = version;
1635
1636 /* Switch to using the old pdp context */
1637 pdp = pdp_old;
1638
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001639 if (recovery_recvd)
1640 emit_cb_recovery(gsn, peer, pdp, recovery);
1641
Harald Weltebed35df2011-11-02 13:06:18 +01001642 /* Confirm to peer that things were "successful" */
1643 return gtp_create_pdp_resp(gsn, version, pdp,
1644 GTPCAUSE_ACC_REQ);
1645 } else { /* This is not the same PDP context. Delete the old one. */
1646
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001647 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001648
1649 if (gsn->cb_delete_context)
1650 gsn->cb_delete_context(pdp_old);
1651 pdp_freepdp(pdp_old);
1652
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001653 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001654 }
1655 }
1656
1657 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
Harald Weltee257be12017-08-12 14:55:09 +02001658 if (pdp)
1659 pdp->gsn = gsn;
Harald Weltebed35df2011-11-02 13:06:18 +01001660
1661 /* Callback function to validata login */
1662 if (gsn->cb_create_context_ind != 0)
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001663 rc = gsn->cb_create_context_ind(pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001664 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001665 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1666 "No create_context_ind callback defined\n");
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001667 rc = gtp_create_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001668 GTPCAUSE_NOT_SUPPORTED);
1669 }
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001670 if (recovery_recvd)
1671 emit_cb_recovery(gsn, peer, pdp, recovery);
1672 return rc;
jjako52c24142002-12-16 13:33:51 +00001673}
1674
jjako52c24142002-12-16 13:33:51 +00001675/* Handle Create PDP Context Response */
1676int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001677 struct sockaddr_in *peer, void *pack, unsigned len)
1678{
1679 struct pdp_t *pdp;
1680 union gtpie_member *ie[GTPIE_SIZE];
1681 uint8_t cause, recovery;
1682 void *cbp = NULL;
1683 uint8_t type = 0;
1684 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001685
Harald Weltebed35df2011-11-02 13:06:18 +01001686 /* Remove packet from queue */
1687 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1688 return EOF;
jjako52c24142002-12-16 13:33:51 +00001689
Harald Weltebed35df2011-11-02 13:06:18 +01001690 /* Find the context in question */
1691 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1692 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001693 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001694 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001695 if (gsn->cb_conf)
1696 gsn->cb_conf(type, EOF, NULL, cbp);
1697 return EOF;
1698 }
jjako2c381332003-10-21 19:09:53 +00001699
Harald Weltebed35df2011-11-02 13:06:18 +01001700 /* Register that we have received a valid teic from GGSN */
1701 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001702
Harald Weltebed35df2011-11-02 13:06:18 +01001703 /* Decode information elements */
1704 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1705 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001706 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1707 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001708 if (gsn->cb_conf)
1709 gsn->cb_conf(type, EOF, pdp, cbp);
1710 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1711 pdp_freepdp(pdp); */
1712 return EOF;
1713 }
jjako52c24142002-12-16 13:33:51 +00001714
Harald Weltebed35df2011-11-02 13:06:18 +01001715 /* Extract cause value (mandatory) */
1716 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1717 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001718 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1719 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001720 if (gsn->cb_conf)
1721 gsn->cb_conf(type, EOF, pdp, cbp);
1722 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1723 pdp_freepdp(pdp); */
1724 return EOF;
1725 }
jjako52c24142002-12-16 13:33:51 +00001726
Harald Weltebed35df2011-11-02 13:06:18 +01001727 /* Extract recovery (optional) */
1728 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001729 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001730 }
jjako52c24142002-12-16 13:33:51 +00001731
Harald Weltebed35df2011-11-02 13:06:18 +01001732 /* Extract protocol configuration options (optional) */
1733 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1734 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1735 }
jjako52c24142002-12-16 13:33:51 +00001736
Harald Weltebed35df2011-11-02 13:06:18 +01001737 /* Check all conditional information elements */
1738 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001739
Harald Weltebed35df2011-11-02 13:06:18 +01001740 if (version == 0) {
1741 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1742 &pdp->qos_neg0,
1743 sizeof(pdp->qos_neg0))) {
1744 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001745 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001746 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001747 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001748 if (gsn->cb_conf)
1749 gsn->cb_conf(type, EOF, pdp, cbp);
1750 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1751 pdp_freepdp(pdp); */
1752 return EOF;
1753 }
1754 }
jjako08d331d2003-10-13 20:33:30 +00001755
Harald Weltebed35df2011-11-02 13:06:18 +01001756 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1757 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001758 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001759 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001760 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001761 if (gsn->cb_conf)
1762 gsn->cb_conf(type, EOF, pdp, cbp);
1763 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1764 pdp_freepdp(pdp); */
1765 return EOF;
1766 }
jjako52c24142002-12-16 13:33:51 +00001767
Harald Weltebed35df2011-11-02 13:06:18 +01001768 if (version == 0) {
1769 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1770 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001771 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001772 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001773 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001774 if (gsn->cb_conf)
1775 gsn->cb_conf(type, EOF, pdp, cbp);
1776 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1777 pdp_freepdp(pdp); */
1778 return EOF;
1779 }
jjako52c24142002-12-16 13:33:51 +00001780
Harald Weltebed35df2011-11-02 13:06:18 +01001781 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1782 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001783 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001784 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001785 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001786 if (gsn->cb_conf)
1787 gsn->cb_conf(type, EOF, pdp, cbp);
1788 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1789 pdp_freepdp(pdp); */
1790 return EOF;
1791 }
1792 }
1793
1794 if (version == 1) {
1795 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1796 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001797 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001798 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001799 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001800 if (gsn->cb_conf)
1801 gsn->cb_conf(type, EOF, pdp, cbp);
1802 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1803 pdp_freepdp(pdp); */
1804 return EOF;
1805 }
1806
1807 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1808 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001809 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001810 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001811 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001812 if (gsn->cb_conf)
1813 gsn->cb_conf(type, EOF, pdp, cbp);
1814 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1815 pdp_freepdp(pdp); */
1816 return EOF;
1817 }
1818 }
1819
1820 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1821 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001822 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001823 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001824 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001825 if (gsn->cb_conf)
1826 gsn->cb_conf(type, EOF, pdp, cbp);
1827 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1828 pdp_freepdp(pdp); */
1829 }
1830
1831 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1832 &pdp->eua.v, sizeof(pdp->eua.v))) {
1833 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001834 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001835 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001836 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001837 if (gsn->cb_conf)
1838 gsn->cb_conf(type, EOF, pdp, cbp);
1839 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1840 pdp_freepdp(pdp); */
1841 return EOF;
1842 }
1843
1844 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1845 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1846 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001847 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001848 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001849 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001850 if (gsn->cb_conf)
1851 gsn->cb_conf(type, EOF, pdp, cbp);
1852 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1853 pdp_freepdp(pdp); */
1854 return EOF;
1855 }
1856
1857 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1858 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1859 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001860 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001861 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001862 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001863 if (gsn->cb_conf)
1864 gsn->cb_conf(type, EOF, pdp, cbp);
1865 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1866 pdp_freepdp(pdp); */
1867 return EOF;
1868 }
1869
1870 if (version == 1) {
1871 if (gtpie_gettlv
1872 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1873 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1874 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001875 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001876 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001877 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001878 if (gsn->cb_conf)
1879 gsn->cb_conf(type, EOF, pdp, cbp);
1880 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1881 pdp_freepdp(pdp); */
1882 return EOF;
1883 }
1884 }
1885
1886 }
1887
1888 if (gsn->cb_conf)
1889 gsn->cb_conf(type, cause, pdp, cbp);
1890
1891 return 0;
jjako52c24142002-12-16 13:33:51 +00001892}
1893
jjako08d331d2003-10-13 20:33:30 +00001894/* API: Send Update PDP Context Request */
1895int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001896 struct in_addr *inetaddr)
1897{
1898 union gtp_packet packet;
1899 unsigned int length =
1900 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001901
Harald Weltebed35df2011-11-02 13:06:18 +01001902 if (pdp->version == 0)
1903 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1904 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001905
Harald Weltebed35df2011-11-02 13:06:18 +01001906 /* Include IMSI if updating with unknown teic_gn */
1907 if ((pdp->version == 1) && (!pdp->teic_gn))
1908 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1909 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1910
1911 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1912 gsn->restart_counter);
1913
1914 if (pdp->version == 0) {
1915 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1916 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1917 }
1918
1919 if (pdp->version == 1) {
1920 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1921 pdp->teid_own);
1922
1923 if (!pdp->teic_confirmed)
1924 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1925 pdp->teic_own);
1926 }
1927
1928 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1929
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001930 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001931 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1932 pdp->traceref);
1933 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1934 pdp->tracetype); */
1935
1936 /* TODO if ggsn update message
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001937 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01001938 pdp->eua.l, pdp->eua.v);
1939 */
1940
1941 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1942 pdp->gsnlc.l, pdp->gsnlc.v);
1943 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1944 pdp->gsnlu.l, pdp->gsnlu.v);
1945
1946 if (pdp->version == 1)
1947 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1948 pdp->qos_req.l, pdp->qos_req.v);
1949
1950 if ((pdp->version == 1) && pdp->tft.l)
1951 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1952 pdp->tft.l, pdp->tft.v);
1953
1954 if ((pdp->version == 1) && pdp->triggerid.l)
1955 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1956 pdp->triggerid.l, pdp->triggerid.v);
1957
1958 if ((pdp->version == 1) && pdp->omcid.l)
1959 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1960 pdp->omcid.l, pdp->omcid.v);
1961
Daniel Willmann134a7752016-02-03 18:53:29 +01001962 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001963
1964 return 0;
jjako52c24142002-12-16 13:33:51 +00001965}
1966
jjako08d331d2003-10-13 20:33:30 +00001967/* Send Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001968static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01001969 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001970 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001971 struct pdp_t *pdp, uint8_t cause)
1972{
jjako08d331d2003-10-13 20:33:30 +00001973
Harald Weltebed35df2011-11-02 13:06:18 +01001974 union gtp_packet packet;
1975 unsigned int length =
1976 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001977
Harald Weltebed35df2011-11-02 13:06:18 +01001978 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001979
Harald Weltebed35df2011-11-02 13:06:18 +01001980 if (cause == GTPCAUSE_ACC_REQ) {
1981
1982 if (version == 0)
1983 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1984 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1985
1986 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1987 gsn->restart_counter);
1988
1989 if (version == 0) {
1990 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1991 pdp->fllu);
1992 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1993 pdp->fllc);
1994 }
1995
1996 if (version == 1) {
1997 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1998 pdp->teid_own);
1999
2000 if (!pdp->teic_confirmed)
2001 gtpie_tv4(&packet, &length, GTP_MAX,
2002 GTPIE_TEI_C, pdp->teic_own);
2003 }
2004
2005 /* TODO we use teid_own as charging ID address */
2006 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
2007 pdp->teid_own);
2008
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002009 /* If ggsn
2010 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01002011 pdp->eua.l, pdp->eua.v); */
2012
2013 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2014 pdp->gsnlc.l, pdp->gsnlc.v);
2015 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2016 pdp->gsnlu.l, pdp->gsnlu.v);
2017
2018 if (version == 1)
2019 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2020 pdp->qos_neg.l, pdp->qos_neg.v);
2021
2022 /* TODO: Charging gateway address */
2023 }
2024
2025 return gtp_resp(version, gsn, pdp, &packet, length, peer,
2026 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00002027}
2028
jjako52c24142002-12-16 13:33:51 +00002029/* Handle Update PDP Context Request */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002030static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002031 struct sockaddr_in *peer, int fd,
2032 void *pack, unsigned len)
2033{
2034 struct pdp_t *pdp;
2035 struct pdp_t pdp_backup;
2036 union gtpie_member *ie[GTPIE_SIZE];
2037 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002038
Harald Weltebed35df2011-11-02 13:06:18 +01002039 uint16_t seq = get_seq(pack);
2040 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002041
Harald Weltebed35df2011-11-02 13:06:18 +01002042 uint64_t imsi;
2043 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002044
Harald Weltebed35df2011-11-02 13:06:18 +01002045 /* Is this a dublicate ? */
2046 if (!gtp_dublicate(gsn, version, peer, seq)) {
2047 return 0; /* We allready send of response once */
2048 }
jjako08d331d2003-10-13 20:33:30 +00002049
Harald Weltebed35df2011-11-02 13:06:18 +01002050 /* Decode information elements */
2051 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2052 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002053 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2054 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002055 if (0 == version)
2056 return EOF;
2057 else
2058 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2059 len, NULL,
2060 GTPCAUSE_INVALID_MESSAGE);
2061 }
jjako08d331d2003-10-13 20:33:30 +00002062
Harald Weltebed35df2011-11-02 13:06:18 +01002063 /* Finding PDP: */
2064 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2065 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2066 /* we have to use the tunnel endpoint identifier */
2067 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002068 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
2069
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01002070 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00002071
Harald Weltebed35df2011-11-02 13:06:18 +01002072 /* Find the context in question */
2073 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2074 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002075 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2076 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002077 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2078 len, NULL,
2079 GTPCAUSE_NON_EXIST);
2080 }
2081 } else if (version == 1) {
2082 /* NSAPI (mandatory) */
2083 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2084 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002085 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2086 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002087 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2088 len, NULL,
2089 GTPCAUSE_MAN_IE_MISSING);
2090 }
jjako08d331d2003-10-13 20:33:30 +00002091
Harald Weltebed35df2011-11-02 13:06:18 +01002092 /* IMSI (conditional) */
2093 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2094 /* Find the context in question */
2095 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2096 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002097 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002098 pack, len, "Unknown PDP context: %u\n",
2099 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002100 return gtp_update_pdp_resp(gsn, version, peer,
2101 fd, pack, len, NULL,
2102 GTPCAUSE_NON_EXIST);
2103 }
2104 } else {
2105 /* Find the context in question */
2106 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2107 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002108 GTP_LOGPKG(LOGL_ERROR, peer,
2109 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002110 return gtp_update_pdp_resp(gsn, version, peer,
2111 fd, pack, len, NULL,
2112 GTPCAUSE_NON_EXIST);
2113 }
2114 }
2115 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002116 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002117 return EOF;
2118 }
jjako08d331d2003-10-13 20:33:30 +00002119
Harald Weltebed35df2011-11-02 13:06:18 +01002120 /* Make a backup copy in case anything is wrong */
2121 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002122
Harald Weltebed35df2011-11-02 13:06:18 +01002123 if (version == 0) {
2124 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2125 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2126 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002127 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2128 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002129 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2130 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2131 len, pdp,
2132 GTPCAUSE_MAN_IE_MISSING);
2133 }
2134 }
jjako52c24142002-12-16 13:33:51 +00002135
Harald Weltebed35df2011-11-02 13:06:18 +01002136 /* Recovery (optional) */
2137 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002138 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002139 }
jjako08d331d2003-10-13 20:33:30 +00002140
Harald Weltebed35df2011-11-02 13:06:18 +01002141 if (version == 0) {
2142 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2143 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002144 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2145 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002146 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2147 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2148 len, pdp,
2149 GTPCAUSE_MAN_IE_MISSING);
2150 }
jjako52c24142002-12-16 13:33:51 +00002151
Harald Weltebed35df2011-11-02 13:06:18 +01002152 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2153 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002154 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2155 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002156 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2157 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2158 len, pdp,
2159 GTPCAUSE_MAN_IE_MISSING);
2160 }
2161 }
jjako52c24142002-12-16 13:33:51 +00002162
Harald Weltebed35df2011-11-02 13:06:18 +01002163 if (version == 1) {
2164 /* TEID (mandatory) */
2165 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2166 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002167 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2168 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002169 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2170 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2171 len, pdp,
2172 GTPCAUSE_MAN_IE_MISSING);
2173 }
jjako52c24142002-12-16 13:33:51 +00002174
Harald Weltebed35df2011-11-02 13:06:18 +01002175 /* TEIC (conditional) */
2176 /* If TEIC is not included it means that we have allready received it */
2177 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2178 /* all updated contexts, or only for one of the linked contexts */
2179 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2180
2181 /* NSAPI (mandatory) */
2182 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2183 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002184 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2185 len, "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,
2188 len, pdp,
2189 GTPCAUSE_MAN_IE_MISSING);
2190 }
2191 }
2192
2193 /* Trace reference (optional) */
2194 /* Trace type (optional) */
2195
2196 /* End User Address (conditional) TODO: GGSN Initiated
2197 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2198 &pdp->eua.v, sizeof(pdp->eua.v))) {
2199 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002200 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002201 "Missing mandatory information field");
2202 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002203 return gtp_update_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01002204 GTPCAUSE_MAN_IE_MISSING);
2205 } */
2206
2207 /* SGSN address for signalling (mandatory) */
2208 /* It is weird that this is mandatory when TEIC is conditional */
2209 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2210 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2211 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002212 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2213 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002214 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2215 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2216 pdp, GTPCAUSE_MAN_IE_MISSING);
2217 }
2218
2219 /* SGSN address for user traffic (mandatory) */
2220 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2221 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2222 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002223 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2224 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002225 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2226 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2227 pdp, GTPCAUSE_MAN_IE_MISSING);
2228 }
2229
2230 if (version == 1) {
2231 /* QoS (mandatory) */
2232 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2233 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2234 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002235 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2236 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002237 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2238 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2239 len, pdp,
2240 GTPCAUSE_MAN_IE_MISSING);
2241 }
2242
2243 /* TFT (conditional) */
2244 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2245 &pdp->tft.v, sizeof(pdp->tft.v))) {
2246 }
2247
2248 /* OMC identity */
2249 }
2250
2251 /* Confirm to peer that things were "successful" */
2252 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2253 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002254}
2255
jjako52c24142002-12-16 13:33:51 +00002256/* Handle Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002257static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002258 struct sockaddr_in *peer, void *pack, unsigned len)
2259{
2260 struct pdp_t *pdp;
2261 union gtpie_member *ie[GTPIE_SIZE];
2262 uint8_t cause, recovery;
2263 void *cbp = NULL;
2264 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002265 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002266
Harald Weltebed35df2011-11-02 13:06:18 +01002267 /* Remove packet from queue */
2268 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2269 return EOF;
jjako52c24142002-12-16 13:33:51 +00002270
Harald Weltebed35df2011-11-02 13:06:18 +01002271 /* Find the context in question */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002272 if (pdp_getgtp1(&pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002273 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002274 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002275 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002276 pdp = NULL;
2277 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002278 }
jjako2c381332003-10-21 19:09:53 +00002279
Harald Weltebed35df2011-11-02 13:06:18 +01002280 /* Register that we have received a valid teic from GGSN */
2281 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002282
Harald Weltebed35df2011-11-02 13:06:18 +01002283 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002284 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002285 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002286 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2287 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002288 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002289 }
jjako52c24142002-12-16 13:33:51 +00002290
Harald Weltebed35df2011-11-02 13:06:18 +01002291 /* Extract cause value (mandatory) */
2292 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002293 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002294 }
jjako52c24142002-12-16 13:33:51 +00002295
Harald Weltebed35df2011-11-02 13:06:18 +01002296 /* Extract recovery (optional) */
2297 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002298 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002299 }
2300
2301 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002302 /* TODO: This does not handle GGSN-initiated update responses */
2303 if (GTPCAUSE_ACC_REQ == cause) {
2304 if (version == 0) {
2305 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2306 &pdp->qos_neg0,
2307 sizeof(pdp->qos_neg0))) {
2308 goto err_missing;
2309 }
2310
2311 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2312 goto err_missing;
2313 }
2314
2315 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2316 goto err_missing;
2317 }
Harald Weltebed35df2011-11-02 13:06:18 +01002318 }
2319
Daniel Willmannd9975522016-02-04 15:38:12 +01002320 if (version == 1) {
2321 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2322 goto err_missing;
2323 }
Harald Weltebed35df2011-11-02 13:06:18 +01002324
Daniel Willmannd9975522016-02-04 15:38:12 +01002325 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2326 goto err_missing;
2327 }
2328 }
2329
2330 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2331 goto err_missing;
2332 }
2333
2334 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2335 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2336 goto err_missing;
2337 }
2338
2339 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2340 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2341 goto err_missing;
2342 }
2343
2344 if (version == 1) {
2345 if (gtpie_gettlv
2346 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2347 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2348 goto err_missing;
2349 }
2350 }
Harald Weltebed35df2011-11-02 13:06:18 +01002351 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002352
2353 if (gsn->cb_conf)
2354 gsn->cb_conf(type, cause, pdp, cbp);
2355 return 0; /* Succes */
2356
2357err_missing:
2358 gsn->missing++;
2359 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2360 "Missing information field\n");
2361err_out:
2362 if (gsn->cb_conf)
2363 gsn->cb_conf(type, EOF, pdp, cbp);
2364 return EOF;
jjako52c24142002-12-16 13:33:51 +00002365}
2366
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002367/* API: Deprecated. Send Delete PDP Context Request And free pdp ctx. */
jjako2c381332003-10-21 19:09:53 +00002368int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002369 int teardown)
2370{
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002371 struct pdp_t *linked_pdp;
2372 struct pdp_t *secondary_pdp;
2373 int n;
2374
2375 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
2376 LOGP(DLGTP, LOGL_ERROR,
2377 "Unknown linked PDP context: %u\n", pdp->teic_own);
2378 return EOF;
2379 }
2380
2381 if (gtp_delete_context_req2(gsn, pdp, cbp, teardown) == EOF)
2382 return EOF;
2383
2384 if (teardown) { /* Remove all contexts */
2385 for (n = 0; n < PDP_MAXNSAPI; n++) {
2386 if (linked_pdp->secondary_tei[n]) {
2387 if (pdp_getgtp1
2388 (&secondary_pdp,
2389 linked_pdp->secondary_tei[n])) {
2390 LOGP(DLGTP, LOGL_ERROR,
2391 "Unknown secondary PDP context\n");
2392 return EOF;
2393 }
2394 if (linked_pdp != secondary_pdp) {
2395 if (gsn->cb_delete_context)
2396 gsn->cb_delete_context
2397 (secondary_pdp);
2398 pdp_freepdp(secondary_pdp);
2399 }
2400 }
2401 }
2402 if (gsn->cb_delete_context)
2403 gsn->cb_delete_context(linked_pdp);
2404 pdp_freepdp(linked_pdp);
2405 } else {
2406 if (gsn->cb_delete_context)
2407 gsn->cb_delete_context(pdp);
2408 if (pdp == linked_pdp) {
2409 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2410 linked_pdp->nodata = 1;
2411 } else
2412 pdp_freepdp(pdp);
2413 }
2414
2415 return 0;
2416}
2417
2418/* API: Send Delete PDP Context Request. PDP CTX shall be free'd by user at cb_conf(GTP_DELETE_PDP_RSP) */
2419int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2420 int teardown)
2421{
Harald Weltebed35df2011-11-02 13:06:18 +01002422 union gtp_packet packet;
2423 unsigned int length =
2424 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2425 struct in_addr addr;
2426 struct pdp_t *linked_pdp;
Harald Weltebed35df2011-11-02 13:06:18 +01002427 int n;
2428 int count = 0;
jjako2c381332003-10-21 19:09:53 +00002429
Harald Weltebed35df2011-11-02 13:06:18 +01002430 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2431 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002432 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002433 return EOF;
jjako2c381332003-10-21 19:09:53 +00002434 }
jjako2c381332003-10-21 19:09:53 +00002435
Harald Weltebed35df2011-11-02 13:06:18 +01002436 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002437 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002438 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002439 return EOF;
2440 }
2441
2442 if (!teardown) {
2443 for (n = 0; n < PDP_MAXNSAPI; n++)
2444 if (linked_pdp->secondary_tei[n])
2445 count++;
2446 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002447 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002448 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002449 return EOF;
2450 }
2451 }
2452
2453 if (pdp->version == 1) {
2454 if (teardown)
2455 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2456 0xff);
2457
2458 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2459 }
2460
2461 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2462
Harald Weltebed35df2011-11-02 13:06:18 +01002463 return 0;
jjako2c381332003-10-21 19:09:53 +00002464}
jjako08d331d2003-10-13 20:33:30 +00002465
jjako52c24142002-12-16 13:33:51 +00002466/* Send Delete PDP Context Response */
2467int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002468 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002469 void *pack, unsigned len,
2470 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002471 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002472{
Harald Weltebed35df2011-11-02 13:06:18 +01002473 union gtp_packet packet;
2474 struct pdp_t *secondary_pdp;
2475 unsigned int length =
2476 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2477 int n;
jjako52c24142002-12-16 13:33:51 +00002478
Harald Weltebed35df2011-11-02 13:06:18 +01002479 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002480
Harald Weltebed35df2011-11-02 13:06:18 +01002481 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2482 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002483
Harald Weltebed35df2011-11-02 13:06:18 +01002484 if (cause == GTPCAUSE_ACC_REQ) {
2485 if ((teardown) || (version == 0)) { /* Remove all contexts */
2486 for (n = 0; n < PDP_MAXNSAPI; n++) {
2487 if (linked_pdp->secondary_tei[n]) {
2488 if (pdp_getgtp1
2489 (&secondary_pdp,
2490 linked_pdp->secondary_tei[n])) {
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002491 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002492 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002493 return EOF;
2494 }
2495 if (linked_pdp != secondary_pdp) {
2496 if (gsn->cb_delete_context)
2497 gsn->cb_delete_context
2498 (secondary_pdp);
2499 pdp_freepdp(secondary_pdp);
2500 }
2501 }
2502 }
2503 if (gsn->cb_delete_context)
2504 gsn->cb_delete_context(linked_pdp);
2505 pdp_freepdp(linked_pdp);
2506 } else { /* Remove only current context */
2507 if (gsn->cb_delete_context)
2508 gsn->cb_delete_context(pdp);
2509 if (pdp == linked_pdp) {
2510 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2511 0;
2512 linked_pdp->nodata = 1;
2513 } else
2514 pdp_freepdp(pdp);
2515 }
jjako2c381332003-10-21 19:09:53 +00002516 }
Harald Weltebed35df2011-11-02 13:06:18 +01002517 /* if (cause == GTPCAUSE_ACC_REQ) */
2518 return 0;
jjako52c24142002-12-16 13:33:51 +00002519}
2520
2521/* Handle Delete PDP Context Request */
2522int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002523 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002524 void *pack, unsigned len)
2525{
2526 struct pdp_t *pdp = NULL;
2527 struct pdp_t *linked_pdp = NULL;
2528 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002529
Harald Weltebed35df2011-11-02 13:06:18 +01002530 uint16_t seq = get_seq(pack);
2531 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002532
Harald Weltebed35df2011-11-02 13:06:18 +01002533 uint8_t nsapi;
2534 uint8_t teardown = 0;
2535 int n;
2536 int count = 0;
jjako52c24142002-12-16 13:33:51 +00002537
Harald Weltebed35df2011-11-02 13:06:18 +01002538 /* Is this a dublicate ? */
2539 if (!gtp_dublicate(gsn, version, peer, seq)) {
2540 return 0; /* We allready send off response once */
2541 }
jjako2c381332003-10-21 19:09:53 +00002542
Harald Weltebed35df2011-11-02 13:06:18 +01002543 /* Find the linked context in question */
2544 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2545 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002546 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002547 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002548 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2549 NULL, NULL, GTPCAUSE_NON_EXIST,
2550 teardown);
2551 }
jjako2c381332003-10-21 19:09:53 +00002552
Harald Weltebed35df2011-11-02 13:06:18 +01002553 /* If version 0 this is also the secondary context */
2554 if (version == 0)
2555 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002556
Harald Weltebed35df2011-11-02 13:06:18 +01002557 /* Decode information elements */
2558 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2559 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002560 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2561 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002562 if (0 == version)
2563 return EOF;
2564 else
2565 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2566 len, NULL, NULL,
2567 GTPCAUSE_INVALID_MESSAGE,
2568 teardown);
2569 }
2570
2571 if (version == 1) {
2572 /* NSAPI (mandatory) */
2573 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2574 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002575 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2576 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002577 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2578 len, NULL, NULL,
2579 GTPCAUSE_MAN_IE_MISSING,
2580 teardown);
2581 }
2582
2583 /* Find the context in question */
2584 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2585 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002586 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2587 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002588 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2589 len, NULL, NULL,
2590 GTPCAUSE_NON_EXIST,
2591 teardown);
2592 }
2593
2594 /* Teardown (conditional) */
2595 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2596
2597 if (!teardown) {
2598 for (n = 0; n < PDP_MAXNSAPI; n++)
2599 if (linked_pdp->secondary_tei[n])
2600 count++;
2601 if (count <= 1) {
Pau Espin Pedrold1bd6fc2018-07-13 19:11:45 +02002602 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2603 "Ignoring CTX DEL without teardown and count=%d\n",
2604 count);
Harald Weltebed35df2011-11-02 13:06:18 +01002605 return 0; /* 29.060 7.3.5 Ignore message */
2606 }
2607 }
2608 }
2609
2610 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2611 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002612}
2613
jjako52c24142002-12-16 13:33:51 +00002614/* Handle Delete PDP Context Response */
2615int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002616 struct sockaddr_in *peer, void *pack, unsigned len)
2617{
2618 union gtpie_member *ie[GTPIE_SIZE];
2619 uint8_t cause;
2620 void *cbp = NULL;
2621 uint8_t type = 0;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002622 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002623 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002624
Harald Weltebed35df2011-11-02 13:06:18 +01002625 /* Remove packet from queue */
2626 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2627 return EOF;
jjako52c24142002-12-16 13:33:51 +00002628
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002629 /* Find the context in question. It may not be available if gtp_delete_context_req
2630 * was used and as a result the PDP ctx was already freed */
2631 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2632 gsn->err_unknownpdp++;
2633 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2634 "Unknown PDP context: %u (expected if gtp_delete_context_req is used)\n",
2635 get_tei(pack));
2636 if (gsn->cb_conf)
2637 gsn->cb_conf(type, EOF, NULL, cbp);
2638 return EOF;
2639 }
2640
Harald Weltebed35df2011-11-02 13:06:18 +01002641 /* Decode information elements */
2642 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2643 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002644 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2645 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002646 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002647 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002648 return EOF;
2649 }
2650
2651 /* Extract cause value (mandatory) */
2652 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2653 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002654 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2655 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002656 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002657 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002658 return EOF;
2659 }
2660
2661 /* Check the cause value (again) */
2662 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2663 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002664 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2665 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002666 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002667 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002668 return EOF;
2669 }
2670
2671 /* Callback function to notify application */
2672 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002673 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002674
2675 return 0;
jjako52c24142002-12-16 13:33:51 +00002676}
2677
Harald Welte54d082e2017-08-12 22:43:21 +02002678/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002679static int gtp_error_ind_resp(struct gsn_t *gsn, uint8_t version,
jjako08d331d2003-10-13 20:33:30 +00002680 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002681 void *pack, unsigned len)
2682{
Harald Weltebed35df2011-11-02 13:06:18 +01002683 union gtp_packet packet;
2684 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2685
Harald Welte54d082e2017-08-12 22:43:21 +02002686 if (version == 1) {
2687 /* Mandatory 7.7.13 TEI Data I */
2688 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2689 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2690
2691 /* Mandatory 7.7.32 GSN Address */
2692 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2693 sizeof(gsn->gsnu), &gsn->gsnu);
2694 }
2695
Harald Weltebed35df2011-11-02 13:06:18 +01002696 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2697 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002698}
2699
2700/* Handle Error Indication */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002701static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002702 struct sockaddr_in *peer, void *pack, unsigned len)
2703{
Harald Welte37d5b152017-08-12 23:58:29 +02002704 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002705 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002706
Harald Weltebed35df2011-11-02 13:06:18 +01002707 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002708 if (version == 0) {
2709 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
2710 gsn->err_unknownpdp++;
2711 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2712 "Unknown PDP context\n");
2713 return EOF;
2714 }
2715 } else if (version == 1) {
2716 /* we have to look-up based on the *peer* TEID */
2717 int hlen = get_hlen(pack);
2718 uint32_t teid_gn;
2719
2720 /* Decode information elements */
2721 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2722 gsn->invalid++;
2723 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2724 "Invalid message format\n");
2725 return EOF;
2726 }
2727
2728 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2729 gsn->missing++;
2730 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2731 "Missing mandatory information field\n");
2732 return EOF;
2733 }
2734
2735 if (pdp_getgtp1_peer_d(&pdp, peer, teid_gn)) {
2736 gsn->err_unknownpdp++;
2737 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2738 return EOF;
2739 }
Harald Weltebed35df2011-11-02 13:06:18 +01002740 }
jjako52c24142002-12-16 13:33:51 +00002741
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002742 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2743 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002744
Harald Weltebd228242017-11-06 03:16:49 +09002745 /* This is obvious from above code, given the semantics of the
2746 * functions above, but Coverity doesn't figure this out, so
2747 * let's make it clear. It's good style anyway in case above
2748 * code should ever change. */
2749 OSMO_ASSERT(pdp);
2750
Harald Weltebed35df2011-11-02 13:06:18 +01002751 if (gsn->cb_delete_context)
2752 gsn->cb_delete_context(pdp);
2753 pdp_freepdp(pdp);
2754 return 0;
jjako52c24142002-12-16 13:33:51 +00002755}
2756
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002757static int gtp_gpdu_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002758 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2759{
jjako08d331d2003-10-13 20:33:30 +00002760
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002761 int hlen;
jjako52c24142002-12-16 13:33:51 +00002762
Harald Weltebed35df2011-11-02 13:06:18 +01002763 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002764
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002765 switch (version) {
2766 case 0:
Harald Weltebed35df2011-11-02 13:06:18 +01002767 if (pdp_getgtp0
2768 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2769 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002770 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002771 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002772 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2773 len);
2774 }
2775 hlen = GTP0_HEADER_SIZE;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002776 break;
2777 case 1:
Harald Weltebed35df2011-11-02 13:06:18 +01002778 if (pdp_getgtp1
2779 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2780 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002781 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002782 len, "Unknown PDP context, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002783 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2784 len);
2785 }
jjako08d331d2003-10-13 20:33:30 +00002786
Harald Weltebed35df2011-11-02 13:06:18 +01002787 /* Is this a long or a short header ? */
2788 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2789 hlen = GTP1_HEADER_SIZE_LONG;
2790 else
2791 hlen = GTP1_HEADER_SIZE_SHORT;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002792 break;
2793 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002794 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002795 "Unknown version: %d\n", version);
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002796 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002797 }
jjako08d331d2003-10-13 20:33:30 +00002798
Harald Weltebed35df2011-11-02 13:06:18 +01002799 /* If the GPDU was not from the peer GSN tell him to delete context */
2800 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2801 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002802 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002803 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2804 }
jjako52c24142002-12-16 13:33:51 +00002805
Harald Weltebed35df2011-11-02 13:06:18 +01002806 /* Callback function */
2807 if (gsn->cb_data_ind != 0)
2808 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2809
2810 return 0;
jjako52c24142002-12-16 13:33:51 +00002811}
2812
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002813/* Receives GTP packet and sends off for further processing
jjako52c24142002-12-16 13:33:51 +00002814 * Function will check the validity of the header. If the header
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002815 * is not valid the packet is either dropped or a version not
2816 * supported is returned to the peer.
jjako52c24142002-12-16 13:33:51 +00002817 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002818int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002819{
Harald Weltebed35df2011-11-02 13:06:18 +01002820 unsigned char buffer[PACKET_MAX];
2821 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002822 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002823 int status;
2824 struct gtp0_header *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002825 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002826 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002827
Harald Weltebed35df2011-11-02 13:06:18 +01002828 /* TODO: Need strategy of userspace buffering and blocking */
2829 /* Currently read is non-blocking and send is blocking. */
2830 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002831
Harald Weltebed35df2011-11-02 13:06:18 +01002832 while (1) { /* Loop until no more to read */
2833 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002834 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002835 return -1;
2836 }
2837 peerlen = sizeof(peer);
2838 if ((status =
2839 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2840 (struct sockaddr *)&peer, &peerlen)) < 0) {
2841 if (errno == EAGAIN)
2842 return 0;
2843 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002844 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002845 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002846 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2847 status, status ? strerror(errno) : "No error");
2848 return -1;
2849 }
jjako1db1c812003-07-06 20:53:57 +00002850
Harald Weltebed35df2011-11-02 13:06:18 +01002851 /* Need at least 1 byte in order to check version */
2852 if (status < (1)) {
2853 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002854 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2855 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002856 continue;
2857 }
jjako08d331d2003-10-13 20:33:30 +00002858
Harald Weltebed35df2011-11-02 13:06:18 +01002859 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002860
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002861 version = GTPHDR_F_GET_VER(pheader->flags);
2862
Harald Weltebed35df2011-11-02 13:06:18 +01002863 /* Version should be gtp0 (or earlier) */
2864 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2865 /* GTP 0 messages. If other version message is received we reply that we */
2866 /* only support version 0, implying that this is the only version */
2867 /* supported on this port */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002868 if (version > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002869 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01002870 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2871 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002872 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2873 continue;
2874 }
2875
2876 /* Check length of gtp0 packet */
2877 if (status < GTP0_HEADER_SIZE) {
2878 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002879 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2880 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002881 continue; /* Silently discard 29.60: 11.1.2 */
2882 }
2883
2884 /* Check packet length field versus length of packet */
2885 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2886 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002887 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002888 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002889 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002890 continue; /* Silently discard */
2891 }
2892
2893 if ((gsn->mode == GTP_MODE_GGSN) &&
2894 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002895 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002896 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002897 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002898 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002899 "Unexpected GTPv0 Signalling Message '%s'\n",
2900 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002901 continue; /* Silently discard 29.60: 11.1.4 */
2902 }
2903
2904 if ((gsn->mode == GTP_MODE_SGSN) &&
2905 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002906 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002907 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002908 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002909 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002910 "Unexpected GTPv0 Signalling Message '%s'\n",
2911 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002912 continue; /* Silently discard 29.60: 11.1.4 */
2913 }
2914
2915 switch (pheader->type) {
2916 case GTP_ECHO_REQ:
2917 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2918 break;
2919 case GTP_ECHO_RSP:
2920 gtp_echo_conf(gsn, version, &peer, buffer, status);
2921 break;
2922 case GTP_NOT_SUPPORTED:
2923 gtp_unsup_ind(gsn, &peer, buffer, status);
2924 break;
2925 case GTP_CREATE_PDP_REQ:
2926 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2927 status);
2928 break;
2929 case GTP_CREATE_PDP_RSP:
2930 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2931 status);
2932 break;
2933 case GTP_UPDATE_PDP_REQ:
2934 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2935 status);
2936 break;
2937 case GTP_UPDATE_PDP_RSP:
2938 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2939 status);
2940 break;
2941 case GTP_DELETE_PDP_REQ:
2942 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2943 status);
2944 break;
2945 case GTP_DELETE_PDP_RSP:
2946 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2947 status);
2948 break;
2949 case GTP_ERROR:
2950 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2951 break;
2952 case GTP_GPDU:
2953 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2954 break;
2955 default:
2956 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002957 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2958 "Unknown GTP message type received: %d\n",
2959 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002960 break;
2961 }
2962 }
jjako08d331d2003-10-13 20:33:30 +00002963}
2964
jjako08d331d2003-10-13 20:33:30 +00002965int gtp_decaps1c(struct gsn_t *gsn)
2966{
Harald Weltebed35df2011-11-02 13:06:18 +01002967 unsigned char buffer[PACKET_MAX];
2968 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002969 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002970 int status;
2971 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002972 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002973 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002974
Harald Weltebed35df2011-11-02 13:06:18 +01002975 /* TODO: Need strategy of userspace buffering and blocking */
2976 /* Currently read is non-blocking and send is blocking. */
2977 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002978
Harald Weltebed35df2011-11-02 13:06:18 +01002979 while (1) { /* Loop until no more to read */
2980 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002981 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002982 return -1;
2983 }
2984 peerlen = sizeof(peer);
2985 if ((status =
2986 recvfrom(fd, buffer, sizeof(buffer), 0,
2987 (struct sockaddr *)&peer, &peerlen)) < 0) {
2988 if (errno == EAGAIN)
2989 return 0;
2990 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002991 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002992 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002993 fd, (unsigned long)buffer, sizeof(buffer),
2994 status, status ? strerror(errno) : "No error");
2995 return -1;
2996 }
jjako08d331d2003-10-13 20:33:30 +00002997
Harald Weltebed35df2011-11-02 13:06:18 +01002998 /* Need at least 1 byte in order to check version */
2999 if (status < (1)) {
3000 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003001 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3002 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003003 continue;
3004 }
jjako08d331d2003-10-13 20:33:30 +00003005
Harald Weltebed35df2011-11-02 13:06:18 +01003006 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003007
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003008 version = GTPHDR_F_GET_VER(pheader->flags);
3009
Harald Weltebed35df2011-11-02 13:06:18 +01003010 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003011 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003012 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003013 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3014 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003015 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
3016 /*29.60: 11.1.1 */
3017 continue;
3018 }
jjako08d331d2003-10-13 20:33:30 +00003019
Harald Weltebed35df2011-11-02 13:06:18 +01003020 /* Version must be at least GTP 1 */
3021 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3022 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3023 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003024 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003025 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003026 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3027 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003028 continue;
3029 }
jjako08d331d2003-10-13 20:33:30 +00003030
Harald Weltebed35df2011-11-02 13:06:18 +01003031 /* Check packet flag field */
3032 if (((pheader->flags & 0xf7) != 0x32)) {
3033 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003034 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003035 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003036 continue;
3037 }
jjako2c381332003-10-21 19:09:53 +00003038
Harald Weltebed35df2011-11-02 13:06:18 +01003039 /* Check length of packet */
3040 if (status < GTP1_HEADER_SIZE_LONG) {
3041 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003042 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3043 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003044 continue; /* Silently discard 29.60: 11.1.2 */
3045 }
jjako2c381332003-10-21 19:09:53 +00003046
Harald Weltebed35df2011-11-02 13:06:18 +01003047 /* Check packet length field versus length of packet */
3048 if (status !=
3049 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3050 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003051 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003052 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003053 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003054 continue; /* Silently discard */
3055 }
jjako1db1c812003-07-06 20:53:57 +00003056
Harald Weltebed35df2011-11-02 13:06:18 +01003057 /* Check for extension headers */
3058 /* TODO: We really should cycle through the headers and determine */
3059 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003060 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003061 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003062 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3063 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003064 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3065 status);
jjako1db1c812003-07-06 20:53:57 +00003066
Harald Weltebed35df2011-11-02 13:06:18 +01003067 continue;
3068 }
3069
3070 if ((gsn->mode == GTP_MODE_GGSN) &&
3071 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003072 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003073 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003074 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003075 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003076 "Unexpected GTPv1 Signalling Message '%s'\n",
3077 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003078 continue; /* Silently discard 29.60: 11.1.4 */
3079 }
3080
3081 if ((gsn->mode == GTP_MODE_SGSN) &&
3082 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003083 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003084 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003085 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003086 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003087 "Unexpected GTPv1 Signalling Message '%s'\n",
3088 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003089 continue; /* Silently discard 29.60: 11.1.4 */
3090 }
3091
3092 switch (pheader->type) {
3093 case GTP_ECHO_REQ:
3094 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3095 break;
3096 case GTP_ECHO_RSP:
3097 gtp_echo_conf(gsn, version, &peer, buffer, status);
3098 break;
3099 case GTP_NOT_SUPPORTED:
3100 gtp_unsup_ind(gsn, &peer, buffer, status);
3101 break;
3102 case GTP_SUPP_EXT_HEADER:
3103 gtp_extheader_ind(gsn, &peer, buffer, status);
3104 break;
3105 case GTP_CREATE_PDP_REQ:
3106 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3107 status);
3108 break;
3109 case GTP_CREATE_PDP_RSP:
3110 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3111 status);
3112 break;
3113 case GTP_UPDATE_PDP_REQ:
3114 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3115 status);
3116 break;
3117 case GTP_UPDATE_PDP_RSP:
3118 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3119 status);
3120 break;
3121 case GTP_DELETE_PDP_REQ:
3122 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3123 status);
3124 break;
3125 case GTP_DELETE_PDP_RSP:
3126 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3127 status);
3128 break;
3129 case GTP_ERROR:
3130 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3131 break;
3132 default:
3133 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003134 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3135 "Unknown GTP message type received: %u\n",
3136 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003137 break;
3138 }
3139 }
jjako52c24142002-12-16 13:33:51 +00003140}
3141
jjako08d331d2003-10-13 20:33:30 +00003142int gtp_decaps1u(struct gsn_t *gsn)
3143{
Harald Weltebed35df2011-11-02 13:06:18 +01003144 unsigned char buffer[PACKET_MAX];
3145 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003146 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003147 int status;
3148 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003149 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003150 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003151
Harald Weltebed35df2011-11-02 13:06:18 +01003152 /* TODO: Need strategy of userspace buffering and blocking */
3153 /* Currently read is non-blocking and send is blocking. */
3154 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003155
Harald Weltebed35df2011-11-02 13:06:18 +01003156 while (1) { /* Loop until no more to read */
3157 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003158 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003159 return -1;
3160 }
3161 peerlen = sizeof(peer);
3162 if ((status =
3163 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3164 (struct sockaddr *)&peer, &peerlen)) < 0) {
3165 if (errno == EAGAIN)
3166 return 0;
3167 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003168 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003169 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003170 gsn->fd1u, (unsigned long)buffer,
3171 sizeof(buffer), status,
3172 status ? strerror(errno) : "No error");
3173 return -1;
3174 }
jjako08d331d2003-10-13 20:33:30 +00003175
Harald Weltebed35df2011-11-02 13:06:18 +01003176 /* Need at least 1 byte in order to check version */
3177 if (status < (1)) {
3178 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003179 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3180 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003181 continue;
3182 }
jjako08d331d2003-10-13 20:33:30 +00003183
Harald Weltebed35df2011-11-02 13:06:18 +01003184 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003185
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003186 version = GTPHDR_F_GET_VER(pheader->flags);
3187
Harald Weltebed35df2011-11-02 13:06:18 +01003188 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003189 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003190 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003191 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3192 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003193 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3194 continue;
3195 }
jjako08d331d2003-10-13 20:33:30 +00003196
Harald Weltebed35df2011-11-02 13:06:18 +01003197 /* Version must be at least GTP 1 */
3198 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3199 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3200 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003201 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003202 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003203 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3204 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003205 continue;
3206 }
jjako2c381332003-10-21 19:09:53 +00003207
Harald Weltebed35df2011-11-02 13:06:18 +01003208 /* Check packet flag field (allow both with and without sequence number) */
3209 if (((pheader->flags & 0xf5) != 0x30)) {
3210 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003211 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003212 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003213 continue;
3214 }
jjako2c381332003-10-21 19:09:53 +00003215
Harald Weltebed35df2011-11-02 13:06:18 +01003216 /* Check length of packet */
3217 if (status < GTP1_HEADER_SIZE_SHORT) {
3218 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003219 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3220 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003221 continue; /* Silently discard 29.60: 11.1.2 */
3222 }
3223
3224 /* Check packet length field versus length of packet */
3225 if (status !=
3226 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3227 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003228 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003229 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003230 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003231 continue; /* Silently discard */
3232 }
3233
3234 /* Check for extension headers */
3235 /* TODO: We really should cycle through the headers and determine */
3236 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003237 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003238 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003239 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3240 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003241 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3242 status);
3243
3244 continue;
3245 }
3246
3247 switch (pheader->type) {
3248 case GTP_ECHO_REQ:
3249 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3250 break;
3251 case GTP_ECHO_RSP:
3252 gtp_echo_conf(gsn, version, &peer, buffer, status);
3253 break;
3254 case GTP_SUPP_EXT_HEADER:
3255 gtp_extheader_ind(gsn, &peer, buffer, status);
3256 break;
3257 case GTP_ERROR:
3258 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3259 break;
3260 /* Supported header extensions */
3261 case GTP_GPDU:
3262 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3263 break;
3264 default:
3265 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003266 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3267 "Unknown GTP message type received: %u\n",
3268 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003269 break;
3270 }
3271 }
jjako08d331d2003-10-13 20:33:30 +00003272}
3273
Harald Weltebed35df2011-11-02 13:06:18 +01003274int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003275{
Harald Weltebed35df2011-11-02 13:06:18 +01003276 union gtp_packet packet;
3277 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003278 struct msghdr msgh;
3279 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003280 int fd;
jjako52c24142002-12-16 13:33:51 +00003281
Harald Welte471e3492017-09-24 16:12:39 +08003282 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003283 memset(&addr, 0, sizeof(addr));
3284 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003285#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003286 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003287#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003288 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003289
Harald Welte471e3492017-09-24 16:12:39 +08003290 /* prepare msghdr */
3291 memset(&msgh, 0, sizeof(msgh));
3292 msgh.msg_name = &addr;
3293 msgh.msg_namelen = sizeof(addr);
3294 msgh.msg_iov = iov;
3295 msgh.msg_iovlen = ARRAY_SIZE(iov);
3296
3297 /* prepare iovectors */
3298 iov[0].iov_base = &packet;
3299 /* iov[0].iov_len is not known here yet */
3300 iov[1].iov_base = pack;
3301 iov[1].iov_len = len;
3302
Harald Weltebed35df2011-11-02 13:06:18 +01003303 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003304
Harald Welte471e3492017-09-24 16:12:39 +08003305 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003306 addr.sin_port = htons(GTP0_PORT);
3307 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003308
Harald Weltebed35df2011-11-02 13:06:18 +01003309 get_default_gtp(0, GTP_GPDU, &packet);
3310 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003311 if (pdp->tx_gpdu_seq)
3312 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3313 else
3314 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003315 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003316 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003317 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003318
Harald Weltebed35df2011-11-02 13:06:18 +01003319 addr.sin_port = htons(GTP1U_PORT);
3320 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003321
Harald Weltebed35df2011-11-02 13:06:18 +01003322 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003323 if (pdp->tx_gpdu_seq) {
3324 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3325 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3326 GTP1_HEADER_SIZE_LONG);
3327 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3328 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3329 } else {
3330 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3331 packet.gtp1s.h.length = hton16(len);
3332 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3333 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3334 }
Harald Weltebed35df2011-11-02 13:06:18 +01003335 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003336 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003337 return EOF;
3338 }
3339
3340 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003341 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003342 return -1;
3343 }
3344
Harald Welte471e3492017-09-24 16:12:39 +08003345 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003346 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003347 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003348 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003349 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3350 strerror(errno));
3351 return EOF;
3352 }
3353 return 0;
jjako52c24142002-12-16 13:33:51 +00003354}
3355
jjako52c24142002-12-16 13:33:51 +00003356/* ***********************************************************
3357 * Conversion functions
3358 *************************************************************/
3359
jjako52c24142002-12-16 13:33:51 +00003360/* ***********************************************************
3361 * IP address conversion functions
3362 * There exist several types of address representations:
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01003363 * - eua: End User Address. (29.060, 7.7.27, message type 128)
jjako52c24142002-12-16 13:33:51 +00003364 * Used for signalling address to mobile station. Supports IPv4
3365 * IPv6 x.25 etc. etc.
3366 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3367 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3368 * - in_addr: IPv4 address struct.
3369 * - sockaddr_in: Socket API representation of IP address and
3370 * port number.
3371 *************************************************************/
3372
Harald Weltebed35df2011-11-02 13:06:18 +01003373int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3374{
Harald Weltecee75462017-09-24 17:45:05 +08003375 eua->v[0] = PDP_EUA_ORG_IETF;
3376 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003377 if (src) {
3378 eua->l = 6;
3379 memcpy(&eua->v[2], src, 4);
3380 } else {
3381 eua->l = 2;
3382 }
3383 return 0;
jjako52c24142002-12-16 13:33:51 +00003384}
3385
Harald Weltebed35df2011-11-02 13:06:18 +01003386int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3387{
Harald Weltecee75462017-09-24 17:45:05 +08003388 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 +01003389 return -1; /* Not IPv4 address */
3390 memcpy(dst, &eua->v[2], 4);
3391 return 0;
jjako52c24142002-12-16 13:33:51 +00003392}
3393
Harald Weltebed35df2011-11-02 13:06:18 +01003394int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3395{
3396 memset(dst, 0, sizeof(struct in_addr));
3397 if (gsna->l != 4)
3398 return EOF; /* Return if not IPv4 */
3399 memcpy(dst, gsna->v, gsna->l);
3400 return 0;
jjako52c24142002-12-16 13:33:51 +00003401}
3402
Harald Weltebed35df2011-11-02 13:06:18 +01003403int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3404{
3405 memset(gsna, 0, sizeof(struct ul16_t));
3406 gsna->l = 4;
3407 memcpy(gsna->v, src, gsna->l);
3408 return 0;
jjako52c24142002-12-16 13:33:51 +00003409}
Harald Welteb10ee082017-08-12 19:29:16 +02003410
3411/* TS 29.060 has yet again a different encoding for IMSIs than
3412 * what we have in other places, so we cannot use the gsm48
3413 * decoding functions. Also, libgtp uses an uint64_t in
3414 * _network byte order_ to contain BCD digits ?!? */
3415const char *imsi_gtp2str(const uint64_t *imsi)
3416{
Harald Weltea06120d2017-11-06 03:12:54 +09003417 static char buf[sizeof(*imsi)*2+1];
Harald Welteb10ee082017-08-12 19:29:16 +02003418 const uint8_t *imsi8 = (const uint8_t *) imsi;
3419 unsigned int i, j = 0;
3420
3421 for (i = 0; i < sizeof(*imsi); i++) {
3422 uint8_t nibble;
3423
3424 nibble = imsi8[i] & 0xf;
3425 if (nibble == 0xf)
3426 break;
3427 buf[j++] = osmo_bcd2char(nibble);
3428
3429 nibble = imsi8[i] >> 4;
3430 if (nibble == 0xf)
3431 break;
3432 buf[j++] = osmo_bcd2char(nibble);
3433 }
3434
3435 buf[j++] = '\0';
3436 return buf;
3437}