blob: 430eeb4d527c0778f83a2e1586e9fc063ebd9696 [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
Alexander Couzense1412d92018-09-16 05:10:03 +0200499
500/**
501 * @brief clear the request and response queue. Useful for debugging to reset "some" state.
502 * @param gsn The GGSN instance
503 */
504void gtp_clear_queues(struct gsn_t *gsn)
505{
506 struct qmsg_t *qmsg;
507
508 while (!queue_getfirst(gsn->queue_req, &qmsg)) {
509 queue_freemsg(gsn->queue_req, qmsg);
510 }
511
512 while (!queue_getfirst(gsn->queue_resp, &qmsg)) {
513 queue_freemsg(gsn->queue_resp, qmsg);
514 }
515}
516
jjako52c24142002-12-16 13:33:51 +0000517/* gtp_conf
518 * Remove signalling packet from retransmission queue.
519 * return 0 on success, EOF if packet was not found */
520
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100521static int gtp_conf(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100522 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
523{
Harald Weltefed598f2017-09-24 16:39:22 +0800524 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100525 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000526
Harald Weltefed598f2017-09-24 16:39:22 +0800527 if (ver == 0)
Harald Weltebed35df2011-11-02 13:06:18 +0100528 seq = ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800529 else if (ver == 1 && (packet->gtp1l.h.flags & GTP1HDR_F_SEQ))
Harald Weltebed35df2011-11-02 13:06:18 +0100530 seq = ntoh16(packet->gtp1l.h.seq);
531 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100532 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
533 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100534 return EOF;
535 }
jjako08d331d2003-10-13 20:33:30 +0000536
Harald Weltebed35df2011-11-02 13:06:18 +0100537 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
538 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100539 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
540 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100541 return EOF;
542 }
jjako52c24142002-12-16 13:33:51 +0000543
Harald Weltebed35df2011-11-02 13:06:18 +0100544 return 0;
jjako52c24142002-12-16 13:33:51 +0000545}
546
Harald Weltebed35df2011-11-02 13:06:18 +0100547int gtp_retrans(struct gsn_t *gsn)
548{
549 /* Retransmit any outstanding packets */
550 /* Remove from queue if maxretrans exceeded */
551 time_t now;
552 struct qmsg_t *qmsg;
553 now = time(NULL);
554 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000555
Harald Welte95848ba2011-11-02 18:17:50 +0100556 /* get first element in queue, as long as the timeout of that
557 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100558 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
559 (qmsg->timeout <= now)) {
560 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100561 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100562 if (gsn->cb_conf)
563 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
564 queue_freemsg(gsn->queue_req, qmsg);
565 } else {
566 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
567 (struct sockaddr *)&qmsg->peer,
568 sizeof(struct sockaddr_in)) < 0) {
569 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100570 LOGP(DLGTP, LOGL_ERROR,
571 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100572 gsn->fd0, (unsigned long)&qmsg->p,
573 qmsg->l, strerror(errno));
574 }
575 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100576 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100577 qmsg->retrans++;
578 }
579 }
jjako52c24142002-12-16 13:33:51 +0000580
Harald Weltebed35df2011-11-02 13:06:18 +0100581 /* Also clean up reply timeouts */
582 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
583 (qmsg->timeout < now)) {
584 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
585 queue_freemsg(gsn->queue_resp, qmsg);
586 }
jjako52c24142002-12-16 13:33:51 +0000587
Harald Weltebed35df2011-11-02 13:06:18 +0100588 return 0;
jjako52c24142002-12-16 13:33:51 +0000589}
590
Harald Weltebed35df2011-11-02 13:06:18 +0100591int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
592{
593 time_t now, later;
594 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000595
Harald Weltebed35df2011-11-02 13:06:18 +0100596 if (queue_getfirst(gsn->queue_req, &qmsg)) {
597 timeout->tv_sec = 10;
598 timeout->tv_usec = 0;
599 } else {
600 now = time(NULL);
601 later = qmsg->timeout;
602 timeout->tv_sec = later - now;
603 timeout->tv_usec = 0;
604 if (timeout->tv_sec < 0)
605 timeout->tv_sec = 0; /* No negative allowed */
606 if (timeout->tv_sec > 10)
607 timeout->tv_sec = 10; /* Max sleep for 10 sec */
608 }
609 return 0;
jjako52c24142002-12-16 13:33:51 +0000610}
611
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100612static int gtp_resp(uint8_t version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000613 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100614 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
615{
Harald Weltefed598f2017-09-24 16:39:22 +0800616 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100617 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000618
Harald Weltefed598f2017-09-24 16:39:22 +0800619 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100620 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
621 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100622 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100623 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
624 (packet->gtp0.h.type == GTP_ERROR)))
625 packet->gtp0.h.flow = hton16(pdp->flru);
626 else if (pdp)
627 packet->gtp0.h.flow = hton16(pdp->flrc);
Harald Weltefed598f2017-09-24 16:39:22 +0800628 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100629 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
630 packet->gtp1l.h.seq = hton16(seq);
631 if (pdp && (fd == gsn->fd1u))
632 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
633 else if (pdp)
634 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
635 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100636 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100637 return -1;
638 }
jjako08d331d2003-10-13 20:33:30 +0000639
Harald Weltebed35df2011-11-02 13:06:18 +0100640 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100641 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100642 return -1;
643 }
jjako52c24142002-12-16 13:33:51 +0000644
Harald Weltebed35df2011-11-02 13:06:18 +0100645 if (sendto(fd, packet, len, 0,
646 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
647 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100648 LOGP(DLGTP, LOGL_ERROR,
649 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100650 (unsigned long)&packet, len, strerror(errno));
651 return -1;
652 }
653
654 /* Use new queue structure */
655 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
656 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100657 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100658 } else {
659 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
660 qmsg->l = len;
661 qmsg->timeout = time(NULL) + 60; /* When to timeout */
662 qmsg->retrans = 0; /* No retransmissions so far */
663 qmsg->cbp = NULL;
664 qmsg->type = 0;
665 qmsg->fd = fd;
666 }
667 return 0;
jjako52c24142002-12-16 13:33:51 +0000668}
669
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100670static int gtp_notification(struct gsn_t *gsn, uint8_t version,
jjako2c381332003-10-21 19:09:53 +0000671 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100672 struct sockaddr_in *peer, int fd, uint16_t seq)
673{
jjako2c381332003-10-21 19:09:53 +0000674
Harald Weltefed598f2017-09-24 16:39:22 +0800675 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100676 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000677
Harald Weltebed35df2011-11-02 13:06:18 +0100678 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000679
Harald Weltebed35df2011-11-02 13:06:18 +0100680 /* In GTP0 notifications are treated as replies. In GTP1 they
681 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000682
Harald Weltebed35df2011-11-02 13:06:18 +0100683 if (fd == gsn->fd1c)
684 addr.sin_port = htons(GTP1C_PORT);
685 else if (fd == gsn->fd1u)
686 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000687
Harald Weltefed598f2017-09-24 16:39:22 +0800688 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100689 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
690 packet->gtp0.h.seq = hton16(seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800691 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100692 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
693 packet->gtp1l.h.seq = hton16(seq);
694 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100695 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100696 return -1;
697 }
698
699 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100700 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100701 return -1;
702 }
703
704 if (sendto(fd, packet, len, 0,
705 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
706 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100707 LOGP(DLGTP, LOGL_ERROR,
708 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100709 (unsigned long)&packet, len, strerror(errno));
710 return -1;
711 }
712 return 0;
jjako2c381332003-10-21 19:09:53 +0000713}
714
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +0100715static int gtp_dublicate(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +0100716 struct sockaddr_in *peer, uint16_t seq)
717{
718 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000719
Harald Weltebed35df2011-11-02 13:06:18 +0100720 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
721 return EOF; /* Notfound */
722 }
jjakoa7cd2492003-04-11 09:40:12 +0000723
Harald Weltebed35df2011-11-02 13:06:18 +0100724 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100725 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100726 return -1;
727 }
728
729 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
730 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
731 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100732 LOGP(DLGTP, LOGL_ERROR,
733 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100734 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
735 strerror(errno));
736 }
737 return 0;
jjako52c24142002-12-16 13:33:51 +0000738}
739
jjako52c24142002-12-16 13:33:51 +0000740/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100741static void log_restart(struct gsn_t *gsn)
742{
jjako52c24142002-12-16 13:33:51 +0000743 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200744 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000745 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200746 char *filename;
jjako52c24142002-12-16 13:33:51 +0000747
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200748 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
749 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000750
751 /* We try to open file. On failure we will later try to create file */
752 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100753 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100754 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100755 filename);
756 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100757 rc = fscanf(f, "%d", &counter);
758 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100759 LOGP(DLGTP, LOGL_ERROR,
760 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100761 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100762 }
763 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100764 LOGP(DLGTP, LOGL_ERROR,
765 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100766 }
jjako52c24142002-12-16 13:33:51 +0000767 }
Harald Weltebed35df2011-11-02 13:06:18 +0100768
769 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000770 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100771
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200772 /* Keep the umask closely wrapped around our fopen() call in case the
773 * log outputs cause file creation. */
774 i = umask(022);
775 f = fopen(filename, "w");
776 umask(i);
777 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100778 LOGP(DLGTP, LOGL_ERROR,
779 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100780 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200781 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000782 }
783
jjako52c24142002-12-16 13:33:51 +0000784 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100785close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200786 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100787 LOGP(DLGTP, LOGL_ERROR,
788 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200789free_filename:
790 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000791}
792
jjako1db1c812003-07-06 20:53:57 +0000793int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100794 int mode)
jjako52c24142002-12-16 13:33:51 +0000795{
Harald Weltebed35df2011-11-02 13:06:18 +0100796 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000797
Max14b1b632017-08-21 20:14:59 +0200798 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
jjako52c24142002-12-16 13:33:51 +0000799
Harald Weltebed35df2011-11-02 13:06:18 +0100800 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000801
Harald Weltebed35df2011-11-02 13:06:18 +0100802 (*gsn)->statedir = statedir;
803 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000804
Harald Weltebed35df2011-11-02 13:06:18 +0100805 /* Initialise sequence number */
806 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000807
Harald Weltebed35df2011-11-02 13:06:18 +0100808 /* Initialise request retransmit queue */
809 queue_new(&(*gsn)->queue_req);
810 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000811
Harald Weltebed35df2011-11-02 13:06:18 +0100812 /* Initialise pdp table */
813 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000814
Harald Weltebed35df2011-11-02 13:06:18 +0100815 /* Initialise call back functions */
816 (*gsn)->cb_create_context_ind = 0;
817 (*gsn)->cb_delete_context = 0;
818 (*gsn)->cb_unsup_ind = 0;
819 (*gsn)->cb_conf = 0;
820 (*gsn)->cb_data_ind = 0;
821
822 /* Store function parameters */
823 (*gsn)->gsnc = *listen;
824 (*gsn)->gsnu = *listen;
825 (*gsn)->mode = mode;
826
827 /* Create GTP version 0 socket */
828 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
829 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100830 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200831 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100832 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200833 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100834 }
835
836 memset(&addr, 0, sizeof(addr));
837 addr.sin_family = AF_INET;
838 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
839 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000840#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100841 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000842#endif
jjako08d331d2003-10-13 20:33:30 +0000843
Harald Weltebed35df2011-11-02 13:06:18 +0100844 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
845 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200846 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
847 "bind(fd0=%d) failed: Error = %s\n",
848 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200849 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100850 }
jjako08d331d2003-10-13 20:33:30 +0000851
Harald Weltebed35df2011-11-02 13:06:18 +0100852 /* Create GTP version 1 control plane socket */
853 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
854 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100855 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200856 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100857 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200858 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100859 }
860
861 memset(&addr, 0, sizeof(addr));
862 addr.sin_family = AF_INET;
863 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
864 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000865#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100866 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000867#endif
jjako08d331d2003-10-13 20:33:30 +0000868
Harald Weltebed35df2011-11-02 13:06:18 +0100869 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
870 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200871 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
872 "bind(fd1c=%d) failed: Error = %s\n",
873 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200874 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100875 }
jjako08d331d2003-10-13 20:33:30 +0000876
Harald Weltebed35df2011-11-02 13:06:18 +0100877 /* Create GTP version 1 user plane socket */
878 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
879 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100880 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200881 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100882 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200883 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100884 }
885
886 memset(&addr, 0, sizeof(addr));
887 addr.sin_family = AF_INET;
888 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
889 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000890#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100891 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000892#endif
jjako52c24142002-12-16 13:33:51 +0000893
Harald Weltebed35df2011-11-02 13:06:18 +0100894 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
895 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200896 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +0200897 "bind(fd1u=%d) failed: Error = %s\n",
898 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +0200899 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100900 }
901
902 return 0;
jjako52c24142002-12-16 13:33:51 +0000903}
904
Harald Weltebed35df2011-11-02 13:06:18 +0100905int gtp_free(struct gsn_t *gsn)
906{
jjako52c24142002-12-16 13:33:51 +0000907
Harald Weltebed35df2011-11-02 13:06:18 +0100908 /* Clean up retransmit queues */
909 queue_free(gsn->queue_req);
910 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000911
Harald Weltebed35df2011-11-02 13:06:18 +0100912 close(gsn->fd0);
913 close(gsn->fd1c);
914 close(gsn->fd1u);
915
916 free(gsn);
917 return 0;
jjako52c24142002-12-16 13:33:51 +0000918}
919
920/* ***********************************************************
921 * Path management messages
922 * Messages: echo and version not supported.
923 * A path is connection between two UDP/IP endpoints
924 *
925 * A path is either using GTP0 or GTP1. A path can be
926 * established by any kind of GTP message??
927
928 * Which source port to use?
929 * GTP-C request destination port is 2123/3386
930 * GTP-U request destination port is 2152/3386
931 * T-PDU destination port is 2152/3386.
932 * For the above messages the source port is locally allocated.
933 * For response messages src=rx-dst and dst=rx-src.
934 * For simplicity we should probably use 2123+2152/3386 as
935 * src port even for the cases where src can be locally
936 * allocated. This also means that we have to listen only to
937 * the same ports.
938 * For response messages we need to be able to respond to
939 * the relevant src port even if it is locally allocated by
940 * the peer.
Pau Espin Pedrol732131d2018-01-25 17:23:09 +0100941 *
jjako52c24142002-12-16 13:33:51 +0000942 * The need for path management!
943 * We might need to keep a list of active paths. This might
944 * be in the form of remote IP address + UDP port numbers.
945 * (We will consider a path astablished if we have a context
946 * with the node in question)
947 *************************************************************/
948
949/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000950int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
951 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000952{
Harald Weltebed35df2011-11-02 13:06:18 +0100953 union gtp_packet packet;
954 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
955 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000956}
957
jjako08d331d2003-10-13 20:33:30 +0000958/* Send off an echo reply */
959int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100960 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000961{
Harald Weltebed35df2011-11-02 13:06:18 +0100962 union gtp_packet packet;
963 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
964 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
965 gsn->restart_counter);
966 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
967 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000968}
969
jjako52c24142002-12-16 13:33:51 +0000970/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +0100971int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
972 int fd, void *pack, unsigned len)
973{
jjako52c24142002-12-16 13:33:51 +0000974
Harald Weltebed35df2011-11-02 13:06:18 +0100975 /* Check if it was a dublicate request */
976 if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
977 return 0;
jjako52c24142002-12-16 13:33:51 +0000978
Harald Weltebed35df2011-11-02 13:06:18 +0100979 /* Send off reply to request */
980 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000981}
982
983/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000984int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100985 void *pack, unsigned len)
986{
987 union gtpie_member *ie[GTPIE_SIZE];
988 unsigned char recovery;
989 void *cbp = NULL;
990 uint8_t type = 0;
991 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000992
Harald Weltebed35df2011-11-02 13:06:18 +0100993 /* Remove packet from queue */
994 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
995 return EOF;
jjako52c24142002-12-16 13:33:51 +0000996
Harald Weltebed35df2011-11-02 13:06:18 +0100997 /* Extract information elements into a pointer array */
998 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
999 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001000 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1001 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001002 if (gsn->cb_conf)
1003 gsn->cb_conf(type, EOF, NULL, cbp);
1004 return EOF;
1005 }
jjako52c24142002-12-16 13:33:51 +00001006
Harald Weltebed35df2011-11-02 13:06:18 +01001007 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1008 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001009 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1010 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001011 if (gsn->cb_conf)
1012 gsn->cb_conf(type, EOF, NULL, cbp);
1013 return EOF;
1014 }
jjako52c24142002-12-16 13:33:51 +00001015
Harald Weltebed35df2011-11-02 13:06:18 +01001016 /* Echo reply packages does not have a cause information element */
1017 /* Instead we return the recovery number in the callback function */
1018 if (gsn->cb_conf)
1019 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +01001020
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001021 emit_cb_recovery(gsn, peer, NULL, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001022
1023 return 0;
jjako52c24142002-12-16 13:33:51 +00001024}
1025
1026/* Send off a Version Not Supported message */
1027/* This message is somewhat special in that it actually is a
1028 * response to some other message with unsupported GTP version
1029 * For this reason it has parameters like a response, and does
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001030 * its own message transmission. No signalling queue is used
jjako52c24142002-12-16 13:33:51 +00001031 * The reply is sent to the peer IP and peer UDP. This means that
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001032 * the peer will be receiving a GTP0 message on a GTP1 port!
jjako52c24142002-12-16 13:33:51 +00001033 * In practice however this will never happen as a GTP0 GSN will
1034 * only listen to the GTP0 port, and therefore will never receive
1035 * anything else than GTP0 */
1036
jjako08d331d2003-10-13 20:33:30 +00001037int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1038 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001039{
Harald Weltebed35df2011-11-02 13:06:18 +01001040 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +00001041
Harald Weltebed35df2011-11-02 13:06:18 +01001042 /* GTP 1 is the highest supported protocol */
1043 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
1044 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +00001045}
1046
1047/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +01001048int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1049 void *pack, unsigned len)
1050{
jjako52c24142002-12-16 13:33:51 +00001051
Harald Weltebed35df2011-11-02 13:06:18 +01001052 if (gsn->cb_unsup_ind)
1053 gsn->cb_unsup_ind(peer);
1054
1055 return 0;
jjako52c24142002-12-16 13:33:51 +00001056}
1057
jjako2c381332003-10-21 19:09:53 +00001058/* Send off an Supported Extension Headers Notification */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001059static int gtp_extheader_req(struct gsn_t *gsn, uint8_t version, struct sockaddr_in *peer,
jjako2c381332003-10-21 19:09:53 +00001060 int fd, void *pack, unsigned len)
1061{
Harald Weltebed35df2011-11-02 13:06:18 +01001062 union gtp_packet packet;
1063 unsigned int length =
1064 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +00001065
Harald Weltebed35df2011-11-02 13:06:18 +01001066 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +00001067
Harald Weltebed35df2011-11-02 13:06:18 +01001068 if (version < 1)
1069 return 0;
jjako2c381332003-10-21 19:09:53 +00001070
Harald Weltebed35df2011-11-02 13:06:18 +01001071 /* We report back that we support only PDCP PDU headers */
1072 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
1073 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +00001074
Harald Weltebed35df2011-11-02 13:06:18 +01001075 return gtp_notification(gsn, version, &packet, length,
1076 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +00001077}
1078
1079/* Handle a Supported Extension Headers Notification */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001080static int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001081 void *pack, unsigned len)
1082{
jjako2c381332003-10-21 19:09:53 +00001083
Harald Weltebed35df2011-11-02 13:06:18 +01001084 if (gsn->cb_extheader_ind)
1085 gsn->cb_extheader_ind(peer);
1086
1087 return 0;
jjako2c381332003-10-21 19:09:53 +00001088}
1089
jjako52c24142002-12-16 13:33:51 +00001090/* ***********************************************************
1091 * Session management messages
1092 * Messages: create, update and delete PDP context
1093 *
1094 * Information storage
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001095 * Information storage for each PDP context is defined in
jjako52c24142002-12-16 13:33:51 +00001096 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1097 * PDP-address (IP address), sequence numbers, charging ID.
1098 * For the SGSN it also includes radio related mobility
1099 * information.
1100 *************************************************************/
1101
Harald Welte7b3347b2010-05-15 12:18:46 +02001102/* API: Send Create PDP Context Request (7.3.1) */
Pau Espin Pedrol7b38af52018-01-25 18:35:33 +01001103int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001104 void *cbp)
1105{
1106 union gtp_packet packet;
1107 unsigned int length =
1108 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1109 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001110
Harald Weltebed35df2011-11-02 13:06:18 +01001111 /* TODO: Secondary PDP Context Activation Procedure */
1112 /* In secondary activation procedure the PDP context is identified
1113 by tei in the header. The following fields are omitted: Selection
1114 mode, IMSI, MSISDN, End User Address, Access Point Name and
1115 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001116
Harald Weltebed35df2011-11-02 13:06:18 +01001117 if (pdp->secondary) {
1118 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001119 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001120 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001121 return EOF;
1122 }
1123 }
jjako2c381332003-10-21 19:09:53 +00001124
Harald Weltebed35df2011-11-02 13:06:18 +01001125 if (pdp->version == 0) {
1126 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1127 sizeof(pdp->qos_req0), pdp->qos_req0);
1128 }
jjako52c24142002-12-16 13:33:51 +00001129
Harald Weltebed35df2011-11-02 13:06:18 +01001130 /* Section 7.7.2 */
1131 if (pdp->version == 1) {
1132 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1133 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1134 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1135 }
jjako52c24142002-12-16 13:33:51 +00001136
Harald Weltebed35df2011-11-02 13:06:18 +01001137 /* Section 7.7.3 Routing Area Information */
1138 if (pdp->rai_given == 1)
1139 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1140 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001141
Harald Weltebed35df2011-11-02 13:06:18 +01001142 /* Section 7.7.11 */
1143 if (pdp->norecovery_given == 0)
1144 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1145 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001146
Harald Weltebed35df2011-11-02 13:06:18 +01001147 /* Section 7.7.12 */
1148 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1149 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1150 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001151
Harald Weltebed35df2011-11-02 13:06:18 +01001152 if (pdp->version == 0) {
1153 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1154 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1155 }
jjako08d331d2003-10-13 20:33:30 +00001156
Harald Weltebed35df2011-11-02 13:06:18 +01001157 /* Section 7.7.13 */
1158 if (pdp->version == 1) {
1159 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1160 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001161
Harald Weltebed35df2011-11-02 13:06:18 +01001162 /* Section 7.7.14 */
1163 if (!pdp->teic_confirmed)
1164 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1165 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001166
Harald Weltebed35df2011-11-02 13:06:18 +01001167 /* Section 7.7.17 */
1168 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001169
Harald Weltebed35df2011-11-02 13:06:18 +01001170 /* Section 7.7.17 */
1171 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1172 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1173 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001174
Harald Weltebed35df2011-11-02 13:06:18 +01001175 /* Section 7.7.23 */
1176 if (pdp->cch_pdp) /* Only include charging if flags are set */
1177 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1178 pdp->cch_pdp);
1179 }
jjako9b4971d2004-05-27 20:30:19 +00001180
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001181 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001182 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1183 pdp->traceref);
1184 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1185 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001186
Harald Weltebed35df2011-11-02 13:06:18 +01001187 /* Section 7.7.27 */
1188 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1189 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1190 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001191
Harald Weltebed35df2011-11-02 13:06:18 +01001192 /* Section 7.7.30 */
1193 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1194 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1195 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001196
Harald Weltebed35df2011-11-02 13:06:18 +01001197 /* Section 7.7.31 */
1198 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1199 if (pdp->pco_req.l)
1200 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1201 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001202
Harald Weltebed35df2011-11-02 13:06:18 +01001203 /* Section 7.7.32 */
1204 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1205 pdp->gsnlc.l, pdp->gsnlc.v);
1206 /* Section 7.7.32 */
1207 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1208 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001209
Harald Weltebed35df2011-11-02 13:06:18 +01001210 /* Section 7.7.33 */
1211 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1212 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1213 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001214
Harald Weltebed35df2011-11-02 13:06:18 +01001215 /* Section 7.7.34 */
1216 if (pdp->version == 1)
1217 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1218 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001219
Harald Weltebed35df2011-11-02 13:06:18 +01001220 /* Section 7.7.36 */
1221 if ((pdp->version == 1) && pdp->tft.l)
1222 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1223 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001224
Harald Weltebed35df2011-11-02 13:06:18 +01001225 /* Section 7.7.41 */
1226 if ((pdp->version == 1) && pdp->triggerid.l)
1227 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1228 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001229
Harald Weltebed35df2011-11-02 13:06:18 +01001230 /* Section 7.7.42 */
1231 if ((pdp->version == 1) && pdp->omcid.l)
1232 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1233 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001234
Harald Weltebed35df2011-11-02 13:06:18 +01001235 /* new R7 fields */
1236 if (pdp->rattype_given == 1)
1237 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1238 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001239
Harald Weltebed35df2011-11-02 13:06:18 +01001240 if (pdp->userloc_given == 1)
1241 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1242 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001243
Harald Weltebed35df2011-11-02 13:06:18 +01001244 if (pdp->mstz_given == 1)
1245 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1246 pdp->mstz.l, pdp->mstz.v);
1247
1248 if (pdp->imeisv_given == 1)
1249 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1250 pdp->imeisv.l, pdp->imeisv.v);
1251
1252 /* TODO hisaddr0 */
1253 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1254
1255 return 0;
jjako52c24142002-12-16 13:33:51 +00001256}
1257
jjako08d331d2003-10-13 20:33:30 +00001258/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001259int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1260{
jjako08d331d2003-10-13 20:33:30 +00001261
Harald Weltebed35df2011-11-02 13:06:18 +01001262 /* Now send off a reply to the peer */
1263 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1264
1265 if (cause != GTPCAUSE_ACC_REQ) {
1266 pdp_freepdp(pdp);
1267 }
1268
1269 return 0;
jjako08d331d2003-10-13 20:33:30 +00001270}
1271
1272/* API: Register create context indication callback */
1273int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001274 int (*cb_create_context_ind) (struct pdp_t *
1275 pdp))
jjako52c24142002-12-16 13:33:51 +00001276{
Harald Weltebed35df2011-11-02 13:06:18 +01001277 gsn->cb_create_context_ind = cb_create_context_ind;
1278 return 0;
jjako08d331d2003-10-13 20:33:30 +00001279}
1280
jjako08d331d2003-10-13 20:33:30 +00001281/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001282int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1283 uint8_t cause)
1284{
1285 union gtp_packet packet;
1286 unsigned int length =
1287 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001288
Harald Weltebed35df2011-11-02 13:06:18 +01001289 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001290
Harald Weltebed35df2011-11-02 13:06:18 +01001291 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001292
Harald Weltebed35df2011-11-02 13:06:18 +01001293 if (version == 0)
1294 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1295 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001296
Harald Weltebed35df2011-11-02 13:06:18 +01001297 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1298 pdp->reorder);
1299 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1300 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001301
Harald Weltebed35df2011-11-02 13:06:18 +01001302 if (version == 0) {
1303 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1304 pdp->fllu);
1305 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1306 pdp->fllc);
1307 }
jjako08d331d2003-10-13 20:33:30 +00001308
Harald Weltebed35df2011-11-02 13:06:18 +01001309 if (version == 1) {
1310 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1311 pdp->teid_own);
1312 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1313 pdp->teic_own);
1314 }
jjako08d331d2003-10-13 20:33:30 +00001315
Harald Weltebed35df2011-11-02 13:06:18 +01001316 /* TODO: We use teic_own as charging ID */
1317 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1318 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001319
Harald Weltebed35df2011-11-02 13:06:18 +01001320 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1321 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001322
Harald Weltebed35df2011-11-02 13:06:18 +01001323 if (pdp->pco_neg.l) { /* Optional PCO */
1324 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1325 pdp->pco_neg.l, pdp->pco_neg.v);
1326 }
jjako52c24142002-12-16 13:33:51 +00001327
Harald Weltebed35df2011-11-02 13:06:18 +01001328 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1329 pdp->gsnlc.l, pdp->gsnlc.v);
1330 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1331 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001332
Harald Weltebed35df2011-11-02 13:06:18 +01001333 if (version == 1)
1334 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1335 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001336
Harald Weltebed35df2011-11-02 13:06:18 +01001337 /* TODO: Charging gateway address */
1338 }
jjako52c24142002-12-16 13:33:51 +00001339
Harald Weltebed35df2011-11-02 13:06:18 +01001340 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1341 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001342}
1343
1344/* Handle Create PDP Context Request */
1345int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001346 struct sockaddr_in *peer, int fd,
1347 void *pack, unsigned len)
1348{
1349 struct pdp_t *pdp, *pdp_old;
1350 struct pdp_t pdp_buf;
1351 union gtpie_member *ie[GTPIE_SIZE];
1352 uint8_t recovery;
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001353 bool recovery_recvd = false;
1354 int rc;
jjako52c24142002-12-16 13:33:51 +00001355
Harald Weltebed35df2011-11-02 13:06:18 +01001356 uint16_t seq = get_seq(pack);
1357 int hlen = get_hlen(pack);
1358 uint8_t linked_nsapi = 0;
1359 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001360
Harald Weltebed35df2011-11-02 13:06:18 +01001361 if (!gtp_dublicate(gsn, version, peer, seq))
1362 return 0;
jjako08d331d2003-10-13 20:33:30 +00001363
Harald Weltebed35df2011-11-02 13:06:18 +01001364 pdp = &pdp_buf;
1365 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001366
Harald Weltebed35df2011-11-02 13:06:18 +01001367 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001368 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1369
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001370 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001371 }
jjako52c24142002-12-16 13:33:51 +00001372
Harald Weltebed35df2011-11-02 13:06:18 +01001373 pdp->seq = seq;
1374 pdp->sa_peer = *peer;
1375 pdp->fd = fd;
1376 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001377
Harald Weltebed35df2011-11-02 13:06:18 +01001378 /* Decode information elements */
1379 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1380 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001381 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1382 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001383 if (0 == version)
1384 return EOF;
1385 else
1386 return gtp_create_pdp_resp(gsn, version, pdp,
1387 GTPCAUSE_INVALID_MESSAGE);
1388 }
jjako52c24142002-12-16 13:33:51 +00001389
Harald Weltebed35df2011-11-02 13:06:18 +01001390 if (version == 1) {
1391 /* Linked NSAPI (conditional) */
1392 /* If included this is the Secondary PDP Context Activation Procedure */
1393 /* In secondary activation IMSI is not included, so the context must be */
1394 /* identified by the tei */
1395 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001396
Harald Weltebed35df2011-11-02 13:06:18 +01001397 /* Find the primary PDP context */
1398 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1399 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001400 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001401 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001402 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001403 return gtp_create_pdp_resp(gsn, version, pdp,
1404 GTPCAUSE_OPT_IE_INCORRECT);
1405 }
jjako2c381332003-10-21 19:09:53 +00001406
Harald Weltebed35df2011-11-02 13:06:18 +01001407 /* Check that the primary PDP context matches linked nsapi */
1408 if (linked_pdp->nsapi != linked_nsapi) {
1409 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001410 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001411 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001412 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001413 return gtp_create_pdp_resp(gsn, version, pdp,
1414 GTPCAUSE_OPT_IE_INCORRECT);
1415 }
jjako52c24142002-12-16 13:33:51 +00001416
Harald Weltebed35df2011-11-02 13:06:18 +01001417 /* Copy parameters from primary context */
1418 pdp->selmode = linked_pdp->selmode;
1419 pdp->imsi = linked_pdp->imsi;
1420 pdp->msisdn = linked_pdp->msisdn;
1421 pdp->eua = linked_pdp->eua;
1422 pdp->pco_req = linked_pdp->pco_req;
1423 pdp->apn_req = linked_pdp->apn_req;
1424 pdp->teic_gn = linked_pdp->teic_gn;
1425 pdp->secondary = 1;
1426 }
1427 }
1428 /* if (version == 1) */
1429 if (version == 0) {
1430 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1431 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1432 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001433 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1434 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001435 return gtp_create_pdp_resp(gsn, version, pdp,
1436 GTPCAUSE_MAN_IE_MISSING);
1437 }
1438 }
jjako08d331d2003-10-13 20:33:30 +00001439
Harald Weltebed35df2011-11-02 13:06:18 +01001440 if ((version == 1) && (!linked_pdp)) {
1441 /* Not Secondary PDP Context Activation Procedure */
1442 /* IMSI (conditional) */
1443 if (gtpie_gettv0
1444 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
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 /* Recovery (optional) */
1454 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001455 /* we use recovery futher down after announcing new pdp ctx to user */
1456 recovery_recvd = true;
Harald Weltebed35df2011-11-02 13:06:18 +01001457 }
jjako52c24142002-12-16 13:33:51 +00001458
Harald Weltebed35df2011-11-02 13:06:18 +01001459 /* Selection mode (conditional) */
1460 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1461 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1462 &pdp->selmode, sizeof(pdp->selmode))) {
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 }
jjako52c24142002-12-16 13:33:51 +00001470
Harald Weltebed35df2011-11-02 13:06:18 +01001471 if (version == 0) {
1472 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1473 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001474 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1475 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001476 return gtp_create_pdp_resp(gsn, version, pdp,
1477 GTPCAUSE_MAN_IE_MISSING);
1478 }
jjako52c24142002-12-16 13:33:51 +00001479
Harald Weltebed35df2011-11-02 13:06:18 +01001480 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1481 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001482 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1483 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001484 return gtp_create_pdp_resp(gsn, version, pdp,
1485 GTPCAUSE_MAN_IE_MISSING);
1486 }
1487 }
jjako08d331d2003-10-13 20:33:30 +00001488
Harald Weltebed35df2011-11-02 13:06:18 +01001489 if (version == 1) {
1490 /* TEID (mandatory) */
1491 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1492 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001493 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1494 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001495 return gtp_create_pdp_resp(gsn, version, pdp,
1496 GTPCAUSE_MAN_IE_MISSING);
1497 }
jjako2c381332003-10-21 19:09:53 +00001498
Harald Weltebed35df2011-11-02 13:06:18 +01001499 /* TEIC (conditional) */
1500 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1501 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1502 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001503 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001504 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001505 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001506 return gtp_create_pdp_resp(gsn, version, pdp,
1507 GTPCAUSE_MAN_IE_MISSING);
1508 }
1509 }
jjako08d331d2003-10-13 20:33:30 +00001510
Harald Weltebed35df2011-11-02 13:06:18 +01001511 /* NSAPI (mandatory) */
1512 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1513 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001514 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1515 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001516 return gtp_create_pdp_resp(gsn, version, pdp,
1517 GTPCAUSE_MAN_IE_MISSING);
1518 }
1519 }
jjako2e840a32003-01-28 16:05:18 +00001520
Harald Weltebed35df2011-11-02 13:06:18 +01001521 /* Charging Characteriatics (optional) */
1522 /* Trace reference (optional) */
1523 /* Trace type (optional) */
1524 /* Charging Characteriatics (optional) */
jjako52c24142002-12-16 13:33:51 +00001525
Harald Weltebed35df2011-11-02 13:06:18 +01001526 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1527 /* End User Address (conditional) */
1528 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1529 &pdp->eua.v, sizeof(pdp->eua.v))) {
1530 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001531 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1532 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001533 return gtp_create_pdp_resp(gsn, version, pdp,
1534 GTPCAUSE_MAN_IE_MISSING);
1535 }
jjako08d331d2003-10-13 20:33:30 +00001536
Harald Weltebed35df2011-11-02 13:06:18 +01001537 /* APN */
1538 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1539 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1540 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001541 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1542 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001543 return gtp_create_pdp_resp(gsn, version, pdp,
1544 GTPCAUSE_MAN_IE_MISSING);
1545 }
jjako2c381332003-10-21 19:09:53 +00001546
Harald Weltebed35df2011-11-02 13:06:18 +01001547 /* Extract protocol configuration options (optional) */
1548 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1549 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1550 }
1551 }
jjako2c381332003-10-21 19:09:53 +00001552
Harald Weltebed35df2011-11-02 13:06:18 +01001553 /* SGSN address for signalling (mandatory) */
1554 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1555 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1556 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001557 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1558 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001559 return gtp_create_pdp_resp(gsn, version, pdp,
1560 GTPCAUSE_MAN_IE_MISSING);
1561 }
jjako2e840a32003-01-28 16:05:18 +00001562
Harald Weltebed35df2011-11-02 13:06:18 +01001563 /* SGSN address for user traffic (mandatory) */
1564 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1565 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1566 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001567 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1568 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001569 return gtp_create_pdp_resp(gsn, version, pdp,
1570 GTPCAUSE_MAN_IE_MISSING);
1571 }
jjako52c24142002-12-16 13:33:51 +00001572
Harald Weltebed35df2011-11-02 13:06:18 +01001573 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1574 /* MSISDN (conditional) */
1575 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1576 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1577 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001578 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1579 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001580 return gtp_create_pdp_resp(gsn, version, pdp,
1581 GTPCAUSE_MAN_IE_MISSING);
1582 }
1583 }
jjako52c24142002-12-16 13:33:51 +00001584
Harald Weltebed35df2011-11-02 13:06:18 +01001585 if (version == 1) {
1586 /* QoS (mandatory) */
1587 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1588 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1589 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001590 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1591 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001592 return gtp_create_pdp_resp(gsn, version, pdp,
1593 GTPCAUSE_MAN_IE_MISSING);
1594 }
1595
1596 /* TFT (conditional) */
1597 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1598 &pdp->tft.v, sizeof(pdp->tft.v))) {
1599 }
1600
1601 /* Trigger ID */
1602 /* OMC identity */
1603 }
1604
1605 /* Initialize our own IP addresses */
1606 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1607 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1608
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001609 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001610
1611 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1612 /* Found old pdp with same tid. Now the voodoo begins! */
1613 /* 09.60 / 29.060 allows create on existing context to "steal" */
1614 /* the context which was allready established */
1615 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001616 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001617 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1618 &&
1619 (!memcmp
1620 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1621 && (pdp->selmode == pdp_old->selmode)
1622 && (pdp->msisdn.l == pdp_old->msisdn.l)
1623 &&
1624 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1625 {
1626 /* OK! We are dealing with the same APN. We will copy new
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001627 * parameters to the old pdp and send off confirmation
Harald Weltebed35df2011-11-02 13:06:18 +01001628 * We ignore the following information elements:
1629 * QoS: MS will get originally negotiated QoS.
1630 * End user address (EUA). MS will get old EUA anyway.
1631 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001632 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001633
1634 /* Copy remote flow label */
1635 pdp_old->flru = pdp->flru;
1636 pdp_old->flrc = pdp->flrc;
1637
1638 /* Copy remote tei */
1639 pdp_old->teid_gn = pdp->teid_gn;
1640 pdp_old->teic_gn = pdp->teic_gn;
1641
1642 /* Copy peer GSN address */
1643 pdp_old->gsnrc.l = pdp->gsnrc.l;
1644 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1645 pdp_old->gsnru.l = pdp->gsnru.l;
1646 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1647
1648 /* Copy request parameters */
1649 pdp_old->seq = pdp->seq;
1650 pdp_old->sa_peer = pdp->sa_peer;
1651 pdp_old->fd = pdp->fd = fd;
1652 pdp_old->version = pdp->version = version;
1653
1654 /* Switch to using the old pdp context */
1655 pdp = pdp_old;
1656
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001657 if (recovery_recvd)
1658 emit_cb_recovery(gsn, peer, pdp, recovery);
1659
Harald Weltebed35df2011-11-02 13:06:18 +01001660 /* Confirm to peer that things were "successful" */
1661 return gtp_create_pdp_resp(gsn, version, pdp,
1662 GTPCAUSE_ACC_REQ);
1663 } else { /* This is not the same PDP context. Delete the old one. */
1664
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001665 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001666
1667 if (gsn->cb_delete_context)
1668 gsn->cb_delete_context(pdp_old);
1669 pdp_freepdp(pdp_old);
1670
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001671 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001672 }
1673 }
1674
1675 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
Harald Weltee257be12017-08-12 14:55:09 +02001676 if (pdp)
1677 pdp->gsn = gsn;
Harald Weltebed35df2011-11-02 13:06:18 +01001678
1679 /* Callback function to validata login */
1680 if (gsn->cb_create_context_ind != 0)
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001681 rc = gsn->cb_create_context_ind(pdp);
Harald Weltebed35df2011-11-02 13:06:18 +01001682 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001683 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1684 "No create_context_ind callback defined\n");
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001685 rc = gtp_create_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01001686 GTPCAUSE_NOT_SUPPORTED);
1687 }
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001688 if (recovery_recvd)
1689 emit_cb_recovery(gsn, peer, pdp, recovery);
1690 return rc;
jjako52c24142002-12-16 13:33:51 +00001691}
1692
jjako52c24142002-12-16 13:33:51 +00001693/* Handle Create PDP Context Response */
1694int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001695 struct sockaddr_in *peer, void *pack, unsigned len)
1696{
1697 struct pdp_t *pdp;
1698 union gtpie_member *ie[GTPIE_SIZE];
1699 uint8_t cause, recovery;
1700 void *cbp = NULL;
1701 uint8_t type = 0;
1702 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001703
Harald Weltebed35df2011-11-02 13:06:18 +01001704 /* Remove packet from queue */
1705 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1706 return EOF;
jjako52c24142002-12-16 13:33:51 +00001707
Harald Weltebed35df2011-11-02 13:06:18 +01001708 /* Find the context in question */
1709 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1710 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001711 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001712 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001713 if (gsn->cb_conf)
1714 gsn->cb_conf(type, EOF, NULL, cbp);
1715 return EOF;
1716 }
jjako2c381332003-10-21 19:09:53 +00001717
Harald Weltebed35df2011-11-02 13:06:18 +01001718 /* Register that we have received a valid teic from GGSN */
1719 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001720
Harald Weltebed35df2011-11-02 13:06:18 +01001721 /* Decode information elements */
1722 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1723 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001724 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1725 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001726 if (gsn->cb_conf)
1727 gsn->cb_conf(type, EOF, pdp, cbp);
1728 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1729 pdp_freepdp(pdp); */
1730 return EOF;
1731 }
jjako52c24142002-12-16 13:33:51 +00001732
Harald Weltebed35df2011-11-02 13:06:18 +01001733 /* Extract cause value (mandatory) */
1734 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1735 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001736 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1737 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001738 if (gsn->cb_conf)
1739 gsn->cb_conf(type, EOF, pdp, cbp);
1740 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1741 pdp_freepdp(pdp); */
1742 return EOF;
1743 }
jjako52c24142002-12-16 13:33:51 +00001744
Harald Weltebed35df2011-11-02 13:06:18 +01001745 /* Extract recovery (optional) */
1746 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02001747 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01001748 }
jjako52c24142002-12-16 13:33:51 +00001749
Harald Weltebed35df2011-11-02 13:06:18 +01001750 /* Extract protocol configuration options (optional) */
1751 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1752 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1753 }
jjako52c24142002-12-16 13:33:51 +00001754
Harald Weltebed35df2011-11-02 13:06:18 +01001755 /* Check all conditional information elements */
1756 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001757
Harald Weltebed35df2011-11-02 13:06:18 +01001758 if (version == 0) {
1759 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1760 &pdp->qos_neg0,
1761 sizeof(pdp->qos_neg0))) {
1762 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001763 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001764 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001765 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001766 if (gsn->cb_conf)
1767 gsn->cb_conf(type, EOF, pdp, cbp);
1768 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1769 pdp_freepdp(pdp); */
1770 return EOF;
1771 }
1772 }
jjako08d331d2003-10-13 20:33:30 +00001773
Harald Weltebed35df2011-11-02 13:06:18 +01001774 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1775 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001776 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001777 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001778 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001779 if (gsn->cb_conf)
1780 gsn->cb_conf(type, EOF, pdp, cbp);
1781 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1782 pdp_freepdp(pdp); */
1783 return EOF;
1784 }
jjako52c24142002-12-16 13:33:51 +00001785
Harald Weltebed35df2011-11-02 13:06:18 +01001786 if (version == 0) {
1787 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1788 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001789 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001790 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001791 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001792 if (gsn->cb_conf)
1793 gsn->cb_conf(type, EOF, pdp, cbp);
1794 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1795 pdp_freepdp(pdp); */
1796 return EOF;
1797 }
jjako52c24142002-12-16 13:33:51 +00001798
Harald Weltebed35df2011-11-02 13:06:18 +01001799 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1800 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001801 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001802 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001803 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001804 if (gsn->cb_conf)
1805 gsn->cb_conf(type, EOF, pdp, cbp);
1806 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1807 pdp_freepdp(pdp); */
1808 return EOF;
1809 }
1810 }
1811
1812 if (version == 1) {
1813 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1814 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001815 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001816 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001817 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001818 if (gsn->cb_conf)
1819 gsn->cb_conf(type, EOF, pdp, cbp);
1820 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1821 pdp_freepdp(pdp); */
1822 return EOF;
1823 }
1824
1825 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1826 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001827 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001828 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001829 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001830 if (gsn->cb_conf)
1831 gsn->cb_conf(type, EOF, pdp, cbp);
1832 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1833 pdp_freepdp(pdp); */
1834 return EOF;
1835 }
1836 }
1837
1838 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1839 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001840 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001841 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001842 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001843 if (gsn->cb_conf)
1844 gsn->cb_conf(type, EOF, pdp, cbp);
1845 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1846 pdp_freepdp(pdp); */
1847 }
1848
1849 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1850 &pdp->eua.v, sizeof(pdp->eua.v))) {
1851 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001852 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001853 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001854 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001855 if (gsn->cb_conf)
1856 gsn->cb_conf(type, EOF, pdp, cbp);
1857 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1858 pdp_freepdp(pdp); */
1859 return EOF;
1860 }
1861
1862 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1863 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1864 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001865 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001866 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001867 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001868 if (gsn->cb_conf)
1869 gsn->cb_conf(type, EOF, pdp, cbp);
1870 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1871 pdp_freepdp(pdp); */
1872 return EOF;
1873 }
1874
1875 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1876 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1877 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001878 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001879 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001880 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001881 if (gsn->cb_conf)
1882 gsn->cb_conf(type, EOF, pdp, cbp);
1883 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1884 pdp_freepdp(pdp); */
1885 return EOF;
1886 }
1887
1888 if (version == 1) {
1889 if (gtpie_gettlv
1890 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1891 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1892 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001893 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001894 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001895 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001896 if (gsn->cb_conf)
1897 gsn->cb_conf(type, EOF, pdp, cbp);
1898 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1899 pdp_freepdp(pdp); */
1900 return EOF;
1901 }
1902 }
1903
1904 }
1905
1906 if (gsn->cb_conf)
1907 gsn->cb_conf(type, cause, pdp, cbp);
1908
1909 return 0;
jjako52c24142002-12-16 13:33:51 +00001910}
1911
jjako08d331d2003-10-13 20:33:30 +00001912/* API: Send Update PDP Context Request */
1913int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001914 struct in_addr *inetaddr)
1915{
1916 union gtp_packet packet;
1917 unsigned int length =
1918 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001919
Harald Weltebed35df2011-11-02 13:06:18 +01001920 if (pdp->version == 0)
1921 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1922 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001923
Harald Weltebed35df2011-11-02 13:06:18 +01001924 /* Include IMSI if updating with unknown teic_gn */
1925 if ((pdp->version == 1) && (!pdp->teic_gn))
1926 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1927 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1928
1929 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1930 gsn->restart_counter);
1931
1932 if (pdp->version == 0) {
1933 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1934 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1935 }
1936
1937 if (pdp->version == 1) {
1938 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1939 pdp->teid_own);
1940
1941 if (!pdp->teic_confirmed)
1942 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1943 pdp->teic_own);
1944 }
1945
1946 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1947
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001948 /* TODO
Harald Weltebed35df2011-11-02 13:06:18 +01001949 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1950 pdp->traceref);
1951 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1952 pdp->tracetype); */
1953
1954 /* TODO if ggsn update message
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01001955 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01001956 pdp->eua.l, pdp->eua.v);
1957 */
1958
1959 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1960 pdp->gsnlc.l, pdp->gsnlc.v);
1961 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1962 pdp->gsnlu.l, pdp->gsnlu.v);
1963
1964 if (pdp->version == 1)
1965 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1966 pdp->qos_req.l, pdp->qos_req.v);
1967
1968 if ((pdp->version == 1) && pdp->tft.l)
1969 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1970 pdp->tft.l, pdp->tft.v);
1971
1972 if ((pdp->version == 1) && pdp->triggerid.l)
1973 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1974 pdp->triggerid.l, pdp->triggerid.v);
1975
1976 if ((pdp->version == 1) && pdp->omcid.l)
1977 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1978 pdp->omcid.l, pdp->omcid.v);
1979
Daniel Willmann134a7752016-02-03 18:53:29 +01001980 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001981
1982 return 0;
jjako52c24142002-12-16 13:33:51 +00001983}
1984
jjako08d331d2003-10-13 20:33:30 +00001985/* Send Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01001986static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01001987 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001988 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001989 struct pdp_t *pdp, uint8_t cause)
1990{
jjako08d331d2003-10-13 20:33:30 +00001991
Harald Weltebed35df2011-11-02 13:06:18 +01001992 union gtp_packet packet;
1993 unsigned int length =
1994 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001995
Harald Weltebed35df2011-11-02 13:06:18 +01001996 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001997
Harald Weltebed35df2011-11-02 13:06:18 +01001998 if (cause == GTPCAUSE_ACC_REQ) {
1999
2000 if (version == 0)
2001 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
2002 sizeof(pdp->qos_neg0), pdp->qos_neg0);
2003
2004 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
2005 gsn->restart_counter);
2006
2007 if (version == 0) {
2008 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
2009 pdp->fllu);
2010 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
2011 pdp->fllc);
2012 }
2013
2014 if (version == 1) {
2015 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2016 pdp->teid_own);
2017
2018 if (!pdp->teic_confirmed)
2019 gtpie_tv4(&packet, &length, GTP_MAX,
2020 GTPIE_TEI_C, pdp->teic_own);
2021 }
2022
2023 /* TODO we use teid_own as charging ID address */
2024 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
2025 pdp->teid_own);
2026
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002027 /* If ggsn
2028 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
Harald Weltebed35df2011-11-02 13:06:18 +01002029 pdp->eua.l, pdp->eua.v); */
2030
2031 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2032 pdp->gsnlc.l, pdp->gsnlc.v);
2033 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2034 pdp->gsnlu.l, pdp->gsnlu.v);
2035
2036 if (version == 1)
2037 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2038 pdp->qos_neg.l, pdp->qos_neg.v);
2039
2040 /* TODO: Charging gateway address */
2041 }
2042
2043 return gtp_resp(version, gsn, pdp, &packet, length, peer,
2044 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00002045}
2046
jjako52c24142002-12-16 13:33:51 +00002047/* Handle Update PDP Context Request */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002048static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002049 struct sockaddr_in *peer, int fd,
2050 void *pack, unsigned len)
2051{
2052 struct pdp_t *pdp;
2053 struct pdp_t pdp_backup;
2054 union gtpie_member *ie[GTPIE_SIZE];
2055 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002056
Harald Weltebed35df2011-11-02 13:06:18 +01002057 uint16_t seq = get_seq(pack);
2058 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002059
Harald Weltebed35df2011-11-02 13:06:18 +01002060 uint64_t imsi;
2061 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002062
Harald Weltebed35df2011-11-02 13:06:18 +01002063 /* Is this a dublicate ? */
2064 if (!gtp_dublicate(gsn, version, peer, seq)) {
2065 return 0; /* We allready send of response once */
2066 }
jjako08d331d2003-10-13 20:33:30 +00002067
Harald Weltebed35df2011-11-02 13:06:18 +01002068 /* Decode information elements */
2069 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2070 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002071 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2072 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002073 if (0 == version)
2074 return EOF;
2075 else
2076 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2077 len, NULL,
2078 GTPCAUSE_INVALID_MESSAGE);
2079 }
jjako08d331d2003-10-13 20:33:30 +00002080
Harald Weltebed35df2011-11-02 13:06:18 +01002081 /* Finding PDP: */
2082 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2083 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2084 /* we have to use the tunnel endpoint identifier */
2085 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002086 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
2087
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01002088 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00002089
Harald Weltebed35df2011-11-02 13:06:18 +01002090 /* Find the context in question */
2091 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2092 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002093 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2094 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002095 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2096 len, NULL,
2097 GTPCAUSE_NON_EXIST);
2098 }
2099 } else if (version == 1) {
2100 /* NSAPI (mandatory) */
2101 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2102 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002103 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2104 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002105 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2106 len, NULL,
2107 GTPCAUSE_MAN_IE_MISSING);
2108 }
jjako08d331d2003-10-13 20:33:30 +00002109
Harald Weltebed35df2011-11-02 13:06:18 +01002110 /* IMSI (conditional) */
2111 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2112 /* Find the context in question */
2113 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2114 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002115 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002116 pack, len, "Unknown PDP context: %u\n",
2117 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002118 return gtp_update_pdp_resp(gsn, version, peer,
2119 fd, pack, len, NULL,
2120 GTPCAUSE_NON_EXIST);
2121 }
2122 } else {
2123 /* Find the context in question */
2124 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2125 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002126 GTP_LOGPKG(LOGL_ERROR, peer,
2127 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002128 return gtp_update_pdp_resp(gsn, version, peer,
2129 fd, pack, len, NULL,
2130 GTPCAUSE_NON_EXIST);
2131 }
2132 }
2133 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002134 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002135 return EOF;
2136 }
jjako08d331d2003-10-13 20:33:30 +00002137
Harald Weltebed35df2011-11-02 13:06:18 +01002138 /* Make a backup copy in case anything is wrong */
2139 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002140
Harald Weltebed35df2011-11-02 13:06:18 +01002141 if (version == 0) {
2142 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2143 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2144 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002145 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2146 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002147 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2148 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2149 len, pdp,
2150 GTPCAUSE_MAN_IE_MISSING);
2151 }
2152 }
jjako52c24142002-12-16 13:33:51 +00002153
Harald Weltebed35df2011-11-02 13:06:18 +01002154 /* Recovery (optional) */
2155 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002156 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002157 }
jjako08d331d2003-10-13 20:33:30 +00002158
Harald Weltebed35df2011-11-02 13:06:18 +01002159 if (version == 0) {
2160 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2161 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002162 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2163 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002164 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2165 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2166 len, pdp,
2167 GTPCAUSE_MAN_IE_MISSING);
2168 }
jjako52c24142002-12-16 13:33:51 +00002169
Harald Weltebed35df2011-11-02 13:06:18 +01002170 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2171 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002172 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2173 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002174 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2175 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2176 len, pdp,
2177 GTPCAUSE_MAN_IE_MISSING);
2178 }
2179 }
jjako52c24142002-12-16 13:33:51 +00002180
Harald Weltebed35df2011-11-02 13:06:18 +01002181 if (version == 1) {
2182 /* TEID (mandatory) */
2183 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2184 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002185 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2186 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002187 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2188 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2189 len, pdp,
2190 GTPCAUSE_MAN_IE_MISSING);
2191 }
jjako52c24142002-12-16 13:33:51 +00002192
Harald Weltebed35df2011-11-02 13:06:18 +01002193 /* TEIC (conditional) */
2194 /* If TEIC is not included it means that we have allready received it */
2195 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2196 /* all updated contexts, or only for one of the linked contexts */
2197 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2198
2199 /* NSAPI (mandatory) */
2200 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2201 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002202 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2203 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002204 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2205 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2206 len, pdp,
2207 GTPCAUSE_MAN_IE_MISSING);
2208 }
2209 }
2210
2211 /* Trace reference (optional) */
2212 /* Trace type (optional) */
2213
2214 /* End User Address (conditional) TODO: GGSN Initiated
2215 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2216 &pdp->eua.v, sizeof(pdp->eua.v))) {
2217 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002218 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002219 "Missing mandatory information field");
2220 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002221 return gtp_update_pdp_resp(gsn, version, pdp,
Harald Weltebed35df2011-11-02 13:06:18 +01002222 GTPCAUSE_MAN_IE_MISSING);
2223 } */
2224
2225 /* SGSN address for signalling (mandatory) */
2226 /* It is weird that this is mandatory when TEIC is conditional */
2227 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2228 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2229 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002230 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2231 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002232 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2233 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2234 pdp, GTPCAUSE_MAN_IE_MISSING);
2235 }
2236
2237 /* SGSN address for user traffic (mandatory) */
2238 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2239 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2240 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002241 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2242 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002243 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2244 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2245 pdp, GTPCAUSE_MAN_IE_MISSING);
2246 }
2247
2248 if (version == 1) {
2249 /* QoS (mandatory) */
2250 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2251 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2252 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002253 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2254 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002255 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2256 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2257 len, pdp,
2258 GTPCAUSE_MAN_IE_MISSING);
2259 }
2260
2261 /* TFT (conditional) */
2262 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2263 &pdp->tft.v, sizeof(pdp->tft.v))) {
2264 }
2265
2266 /* OMC identity */
2267 }
2268
2269 /* Confirm to peer that things were "successful" */
2270 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2271 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002272}
2273
jjako52c24142002-12-16 13:33:51 +00002274/* Handle Update PDP Context Response */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002275static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002276 struct sockaddr_in *peer, void *pack, unsigned len)
2277{
2278 struct pdp_t *pdp;
2279 union gtpie_member *ie[GTPIE_SIZE];
2280 uint8_t cause, recovery;
2281 void *cbp = NULL;
2282 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002283 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002284
Harald Weltebed35df2011-11-02 13:06:18 +01002285 /* Remove packet from queue */
2286 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2287 return EOF;
jjako52c24142002-12-16 13:33:51 +00002288
Harald Weltebed35df2011-11-02 13:06:18 +01002289 /* Find the context in question */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002290 if (pdp_getgtp1(&pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002291 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002292 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002293 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002294 pdp = NULL;
2295 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002296 }
jjako2c381332003-10-21 19:09:53 +00002297
Harald Weltebed35df2011-11-02 13:06:18 +01002298 /* Register that we have received a valid teic from GGSN */
2299 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002300
Harald Weltebed35df2011-11-02 13:06:18 +01002301 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002302 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002303 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002304 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2305 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002306 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002307 }
jjako52c24142002-12-16 13:33:51 +00002308
Harald Weltebed35df2011-11-02 13:06:18 +01002309 /* Extract cause value (mandatory) */
2310 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002311 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002312 }
jjako52c24142002-12-16 13:33:51 +00002313
Harald Weltebed35df2011-11-02 13:06:18 +01002314 /* Extract recovery (optional) */
2315 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
Pau Espin Pedrolb5f93342018-07-23 11:24:07 +02002316 emit_cb_recovery(gsn, peer, pdp, recovery);
Harald Weltebed35df2011-11-02 13:06:18 +01002317 }
2318
2319 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002320 /* TODO: This does not handle GGSN-initiated update responses */
2321 if (GTPCAUSE_ACC_REQ == cause) {
2322 if (version == 0) {
2323 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2324 &pdp->qos_neg0,
2325 sizeof(pdp->qos_neg0))) {
2326 goto err_missing;
2327 }
2328
2329 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2330 goto err_missing;
2331 }
2332
2333 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2334 goto err_missing;
2335 }
Harald Weltebed35df2011-11-02 13:06:18 +01002336 }
2337
Daniel Willmannd9975522016-02-04 15:38:12 +01002338 if (version == 1) {
2339 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2340 goto err_missing;
2341 }
Harald Weltebed35df2011-11-02 13:06:18 +01002342
Daniel Willmannd9975522016-02-04 15:38:12 +01002343 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2344 goto err_missing;
2345 }
2346 }
2347
2348 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2349 goto err_missing;
2350 }
2351
2352 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2353 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2354 goto err_missing;
2355 }
2356
2357 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2358 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2359 goto err_missing;
2360 }
2361
2362 if (version == 1) {
2363 if (gtpie_gettlv
2364 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2365 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2366 goto err_missing;
2367 }
2368 }
Harald Weltebed35df2011-11-02 13:06:18 +01002369 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002370
2371 if (gsn->cb_conf)
2372 gsn->cb_conf(type, cause, pdp, cbp);
2373 return 0; /* Succes */
2374
2375err_missing:
2376 gsn->missing++;
2377 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2378 "Missing information field\n");
2379err_out:
2380 if (gsn->cb_conf)
2381 gsn->cb_conf(type, EOF, pdp, cbp);
2382 return EOF;
jjako52c24142002-12-16 13:33:51 +00002383}
2384
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002385/* API: Deprecated. Send Delete PDP Context Request And free pdp ctx. */
jjako2c381332003-10-21 19:09:53 +00002386int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002387 int teardown)
2388{
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002389 struct pdp_t *linked_pdp;
2390 struct pdp_t *secondary_pdp;
2391 int n;
2392
2393 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
2394 LOGP(DLGTP, LOGL_ERROR,
2395 "Unknown linked PDP context: %u\n", pdp->teic_own);
2396 return EOF;
2397 }
2398
2399 if (gtp_delete_context_req2(gsn, pdp, cbp, teardown) == EOF)
2400 return EOF;
2401
2402 if (teardown) { /* Remove all contexts */
2403 for (n = 0; n < PDP_MAXNSAPI; n++) {
2404 if (linked_pdp->secondary_tei[n]) {
2405 if (pdp_getgtp1
2406 (&secondary_pdp,
2407 linked_pdp->secondary_tei[n])) {
2408 LOGP(DLGTP, LOGL_ERROR,
2409 "Unknown secondary PDP context\n");
2410 return EOF;
2411 }
2412 if (linked_pdp != secondary_pdp) {
2413 if (gsn->cb_delete_context)
2414 gsn->cb_delete_context
2415 (secondary_pdp);
2416 pdp_freepdp(secondary_pdp);
2417 }
2418 }
2419 }
2420 if (gsn->cb_delete_context)
2421 gsn->cb_delete_context(linked_pdp);
2422 pdp_freepdp(linked_pdp);
2423 } else {
2424 if (gsn->cb_delete_context)
2425 gsn->cb_delete_context(pdp);
2426 if (pdp == linked_pdp) {
2427 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2428 linked_pdp->nodata = 1;
2429 } else
2430 pdp_freepdp(pdp);
2431 }
2432
2433 return 0;
2434}
2435
2436/* API: Send Delete PDP Context Request. PDP CTX shall be free'd by user at cb_conf(GTP_DELETE_PDP_RSP) */
2437int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2438 int teardown)
2439{
Harald Weltebed35df2011-11-02 13:06:18 +01002440 union gtp_packet packet;
2441 unsigned int length =
2442 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2443 struct in_addr addr;
2444 struct pdp_t *linked_pdp;
Harald Weltebed35df2011-11-02 13:06:18 +01002445 int n;
2446 int count = 0;
jjako2c381332003-10-21 19:09:53 +00002447
Harald Weltebed35df2011-11-02 13:06:18 +01002448 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2449 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002450 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002451 return EOF;
jjako2c381332003-10-21 19:09:53 +00002452 }
jjako2c381332003-10-21 19:09:53 +00002453
Harald Weltebed35df2011-11-02 13:06:18 +01002454 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002455 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002456 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002457 return EOF;
2458 }
2459
2460 if (!teardown) {
2461 for (n = 0; n < PDP_MAXNSAPI; n++)
2462 if (linked_pdp->secondary_tei[n])
2463 count++;
2464 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002465 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002466 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002467 return EOF;
2468 }
2469 }
2470
2471 if (pdp->version == 1) {
2472 if (teardown)
2473 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2474 0xff);
2475
2476 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2477 }
2478
2479 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2480
Harald Weltebed35df2011-11-02 13:06:18 +01002481 return 0;
jjako2c381332003-10-21 19:09:53 +00002482}
jjako08d331d2003-10-13 20:33:30 +00002483
jjako52c24142002-12-16 13:33:51 +00002484/* Send Delete PDP Context Response */
2485int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002486 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002487 void *pack, unsigned len,
2488 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002489 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002490{
Harald Weltebed35df2011-11-02 13:06:18 +01002491 union gtp_packet packet;
2492 struct pdp_t *secondary_pdp;
2493 unsigned int length =
2494 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2495 int n;
jjako52c24142002-12-16 13:33:51 +00002496
Harald Weltebed35df2011-11-02 13:06:18 +01002497 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002498
Harald Weltebed35df2011-11-02 13:06:18 +01002499 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2500 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002501
Harald Weltebed35df2011-11-02 13:06:18 +01002502 if (cause == GTPCAUSE_ACC_REQ) {
2503 if ((teardown) || (version == 0)) { /* Remove all contexts */
2504 for (n = 0; n < PDP_MAXNSAPI; n++) {
2505 if (linked_pdp->secondary_tei[n]) {
2506 if (pdp_getgtp1
2507 (&secondary_pdp,
2508 linked_pdp->secondary_tei[n])) {
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002509 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002510 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002511 return EOF;
2512 }
2513 if (linked_pdp != secondary_pdp) {
2514 if (gsn->cb_delete_context)
2515 gsn->cb_delete_context
2516 (secondary_pdp);
2517 pdp_freepdp(secondary_pdp);
2518 }
2519 }
2520 }
2521 if (gsn->cb_delete_context)
2522 gsn->cb_delete_context(linked_pdp);
2523 pdp_freepdp(linked_pdp);
2524 } else { /* Remove only current context */
2525 if (gsn->cb_delete_context)
2526 gsn->cb_delete_context(pdp);
2527 if (pdp == linked_pdp) {
2528 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2529 0;
2530 linked_pdp->nodata = 1;
2531 } else
2532 pdp_freepdp(pdp);
2533 }
jjako2c381332003-10-21 19:09:53 +00002534 }
Harald Weltebed35df2011-11-02 13:06:18 +01002535 /* if (cause == GTPCAUSE_ACC_REQ) */
2536 return 0;
jjako52c24142002-12-16 13:33:51 +00002537}
2538
2539/* Handle Delete PDP Context Request */
2540int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002541 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002542 void *pack, unsigned len)
2543{
2544 struct pdp_t *pdp = NULL;
2545 struct pdp_t *linked_pdp = NULL;
2546 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002547
Harald Weltebed35df2011-11-02 13:06:18 +01002548 uint16_t seq = get_seq(pack);
2549 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002550
Harald Weltebed35df2011-11-02 13:06:18 +01002551 uint8_t nsapi;
2552 uint8_t teardown = 0;
2553 int n;
2554 int count = 0;
jjako52c24142002-12-16 13:33:51 +00002555
Harald Weltebed35df2011-11-02 13:06:18 +01002556 /* Is this a dublicate ? */
2557 if (!gtp_dublicate(gsn, version, peer, seq)) {
2558 return 0; /* We allready send off response once */
2559 }
jjako2c381332003-10-21 19:09:53 +00002560
Harald Weltebed35df2011-11-02 13:06:18 +01002561 /* Find the linked context in question */
2562 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2563 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002564 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002565 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002566 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2567 NULL, NULL, GTPCAUSE_NON_EXIST,
2568 teardown);
2569 }
jjako2c381332003-10-21 19:09:53 +00002570
Harald Weltebed35df2011-11-02 13:06:18 +01002571 /* If version 0 this is also the secondary context */
2572 if (version == 0)
2573 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002574
Harald Weltebed35df2011-11-02 13:06:18 +01002575 /* Decode information elements */
2576 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2577 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002578 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2579 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002580 if (0 == version)
2581 return EOF;
2582 else
2583 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2584 len, NULL, NULL,
2585 GTPCAUSE_INVALID_MESSAGE,
2586 teardown);
2587 }
2588
2589 if (version == 1) {
2590 /* NSAPI (mandatory) */
2591 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2592 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002593 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2594 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002595 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2596 len, NULL, NULL,
2597 GTPCAUSE_MAN_IE_MISSING,
2598 teardown);
2599 }
2600
2601 /* Find the context in question */
2602 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2603 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002604 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2605 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002606 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2607 len, NULL, NULL,
2608 GTPCAUSE_NON_EXIST,
2609 teardown);
2610 }
2611
2612 /* Teardown (conditional) */
2613 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2614
2615 if (!teardown) {
Pau Espin Pedrol742a6b52019-05-30 13:36:10 +02002616 /* TS 29.060 section 7.3.5: If a GSN receives a Delete PDP context
2617 * without a Teardown Indicator or with a Teardown Indicator with
2618 * value set to "0" and only that PDP context is active for a PDN
2619 * connection, then the GSN shall ignore the message. (Note:
2620 * This is symptom of a race condition. The reliable delivery of
2621 * signalling messages will eventually lead to a consistent
2622 * situation, allowing the teardown of the PDP context.)
2623 */
Harald Weltebed35df2011-11-02 13:06:18 +01002624 for (n = 0; n < PDP_MAXNSAPI; n++)
2625 if (linked_pdp->secondary_tei[n])
2626 count++;
2627 if (count <= 1) {
Pau Espin Pedrold1bd6fc2018-07-13 19:11:45 +02002628 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2629 "Ignoring CTX DEL without teardown and count=%d\n",
2630 count);
Harald Weltebed35df2011-11-02 13:06:18 +01002631 return 0; /* 29.060 7.3.5 Ignore message */
2632 }
2633 }
2634 }
2635
2636 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2637 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002638}
2639
jjako52c24142002-12-16 13:33:51 +00002640/* Handle Delete PDP Context Response */
2641int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002642 struct sockaddr_in *peer, void *pack, unsigned len)
2643{
2644 union gtpie_member *ie[GTPIE_SIZE];
2645 uint8_t cause;
2646 void *cbp = NULL;
2647 uint8_t type = 0;
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002648 struct pdp_t *pdp = NULL;
Harald Weltebed35df2011-11-02 13:06:18 +01002649 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002650
Harald Weltebed35df2011-11-02 13:06:18 +01002651 /* Remove packet from queue */
2652 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2653 return EOF;
jjako52c24142002-12-16 13:33:51 +00002654
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002655 /* Find the context in question. It may not be available if gtp_delete_context_req
2656 * was used and as a result the PDP ctx was already freed */
2657 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2658 gsn->err_unknownpdp++;
2659 GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
2660 "Unknown PDP context: %u (expected if gtp_delete_context_req is used)\n",
2661 get_tei(pack));
2662 if (gsn->cb_conf)
2663 gsn->cb_conf(type, EOF, NULL, cbp);
2664 return EOF;
2665 }
2666
Harald Weltebed35df2011-11-02 13:06:18 +01002667 /* Decode information elements */
2668 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2669 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002670 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2671 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002672 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002673 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002674 return EOF;
2675 }
2676
2677 /* Extract cause value (mandatory) */
2678 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2679 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002680 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2681 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002682 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002683 gsn->cb_conf(type, EOF, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002684 return EOF;
2685 }
2686
2687 /* Check the cause value (again) */
2688 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2689 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002690 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2691 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002692 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002693 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002694 return EOF;
2695 }
2696
2697 /* Callback function to notify application */
2698 if (gsn->cb_conf)
Pau Espin Pedrol8e8c7ef2018-07-16 16:47:12 +02002699 gsn->cb_conf(type, cause, pdp, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01002700
2701 return 0;
jjako52c24142002-12-16 13:33:51 +00002702}
2703
Harald Welte54d082e2017-08-12 22:43:21 +02002704/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002705static int gtp_error_ind_resp(struct gsn_t *gsn, uint8_t version,
jjako08d331d2003-10-13 20:33:30 +00002706 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002707 void *pack, unsigned len)
2708{
Harald Weltebed35df2011-11-02 13:06:18 +01002709 union gtp_packet packet;
2710 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2711
Harald Welte54d082e2017-08-12 22:43:21 +02002712 if (version == 1) {
2713 /* Mandatory 7.7.13 TEI Data I */
2714 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2715 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2716
2717 /* Mandatory 7.7.32 GSN Address */
2718 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2719 sizeof(gsn->gsnu), &gsn->gsnu);
2720 }
2721
Harald Weltebed35df2011-11-02 13:06:18 +01002722 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2723 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002724}
2725
2726/* Handle Error Indication */
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002727static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002728 struct sockaddr_in *peer, void *pack, unsigned len)
2729{
Harald Welte37d5b152017-08-12 23:58:29 +02002730 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002731 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002732
Harald Weltebed35df2011-11-02 13:06:18 +01002733 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002734 if (version == 0) {
2735 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
2736 gsn->err_unknownpdp++;
2737 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2738 "Unknown PDP context\n");
2739 return EOF;
2740 }
2741 } else if (version == 1) {
2742 /* we have to look-up based on the *peer* TEID */
2743 int hlen = get_hlen(pack);
2744 uint32_t teid_gn;
2745
2746 /* Decode information elements */
2747 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2748 gsn->invalid++;
2749 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2750 "Invalid message format\n");
2751 return EOF;
2752 }
2753
2754 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2755 gsn->missing++;
2756 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2757 "Missing mandatory information field\n");
2758 return EOF;
2759 }
2760
2761 if (pdp_getgtp1_peer_d(&pdp, peer, teid_gn)) {
2762 gsn->err_unknownpdp++;
2763 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2764 return EOF;
2765 }
Harald Weltebed35df2011-11-02 13:06:18 +01002766 }
jjako52c24142002-12-16 13:33:51 +00002767
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002768 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2769 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002770
Harald Weltebd228242017-11-06 03:16:49 +09002771 /* This is obvious from above code, given the semantics of the
2772 * functions above, but Coverity doesn't figure this out, so
2773 * let's make it clear. It's good style anyway in case above
2774 * code should ever change. */
2775 OSMO_ASSERT(pdp);
2776
Harald Weltebed35df2011-11-02 13:06:18 +01002777 if (gsn->cb_delete_context)
2778 gsn->cb_delete_context(pdp);
2779 pdp_freepdp(pdp);
2780 return 0;
jjako52c24142002-12-16 13:33:51 +00002781}
2782
Pau Espin Pedrol07730bb2018-01-25 18:43:38 +01002783static int gtp_gpdu_ind(struct gsn_t *gsn, uint8_t version,
Harald Weltebed35df2011-11-02 13:06:18 +01002784 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2785{
jjako08d331d2003-10-13 20:33:30 +00002786
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002787 int hlen;
jjako52c24142002-12-16 13:33:51 +00002788
Harald Weltebed35df2011-11-02 13:06:18 +01002789 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002790
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002791 switch (version) {
2792 case 0:
Harald Weltebed35df2011-11-02 13:06:18 +01002793 if (pdp_getgtp0
2794 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2795 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002796 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002797 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002798 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2799 len);
2800 }
2801 hlen = GTP0_HEADER_SIZE;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002802 break;
2803 case 1:
Harald Weltebed35df2011-11-02 13:06:18 +01002804 if (pdp_getgtp1
2805 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2806 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002807 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002808 len, "Unknown PDP context, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002809 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2810 len);
2811 }
jjako08d331d2003-10-13 20:33:30 +00002812
Harald Weltebed35df2011-11-02 13:06:18 +01002813 /* Is this a long or a short header ? */
2814 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2815 hlen = GTP1_HEADER_SIZE_LONG;
2816 else
2817 hlen = GTP1_HEADER_SIZE_SHORT;
Pau Espin Pedrol42d32502018-01-25 18:17:17 +01002818 break;
2819 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002820 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002821 "Unknown version: %d\n", version);
Pau Espin Pedrol282d4e32018-01-25 18:20:51 +01002822 return EOF;
Harald Weltebed35df2011-11-02 13:06:18 +01002823 }
jjako08d331d2003-10-13 20:33:30 +00002824
Harald Weltebed35df2011-11-02 13:06:18 +01002825 /* If the GPDU was not from the peer GSN tell him to delete context */
2826 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2827 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002828 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002829 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2830 }
jjako52c24142002-12-16 13:33:51 +00002831
Harald Weltebed35df2011-11-02 13:06:18 +01002832 /* Callback function */
2833 if (gsn->cb_data_ind != 0)
2834 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2835
2836 return 0;
jjako52c24142002-12-16 13:33:51 +00002837}
2838
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002839/* Receives GTP packet and sends off for further processing
jjako52c24142002-12-16 13:33:51 +00002840 * Function will check the validity of the header. If the header
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01002841 * is not valid the packet is either dropped or a version not
2842 * supported is returned to the peer.
jjako52c24142002-12-16 13:33:51 +00002843 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002844int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002845{
Harald Weltebed35df2011-11-02 13:06:18 +01002846 unsigned char buffer[PACKET_MAX];
2847 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002848 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002849 int status;
2850 struct gtp0_header *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002851 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002852 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002853
Harald Weltebed35df2011-11-02 13:06:18 +01002854 /* TODO: Need strategy of userspace buffering and blocking */
2855 /* Currently read is non-blocking and send is blocking. */
2856 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002857
Harald Weltebed35df2011-11-02 13:06:18 +01002858 while (1) { /* Loop until no more to read */
2859 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002860 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002861 return -1;
2862 }
2863 peerlen = sizeof(peer);
2864 if ((status =
2865 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2866 (struct sockaddr *)&peer, &peerlen)) < 0) {
2867 if (errno == EAGAIN)
2868 return 0;
2869 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002870 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002871 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002872 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2873 status, status ? strerror(errno) : "No error");
2874 return -1;
2875 }
jjako1db1c812003-07-06 20:53:57 +00002876
Harald Weltebed35df2011-11-02 13:06:18 +01002877 /* Need at least 1 byte in order to check version */
2878 if (status < (1)) {
2879 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002880 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2881 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002882 continue;
2883 }
jjako08d331d2003-10-13 20:33:30 +00002884
Harald Weltebed35df2011-11-02 13:06:18 +01002885 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002886
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002887 version = GTPHDR_F_GET_VER(pheader->flags);
2888
Harald Weltebed35df2011-11-02 13:06:18 +01002889 /* Version should be gtp0 (or earlier) */
2890 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2891 /* GTP 0 messages. If other version message is received we reply that we */
2892 /* only support version 0, implying that this is the only version */
2893 /* supported on this port */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002894 if (version > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002895 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01002896 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2897 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002898 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2899 continue;
2900 }
2901
2902 /* Check length of gtp0 packet */
2903 if (status < GTP0_HEADER_SIZE) {
2904 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002905 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2906 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002907 continue; /* Silently discard 29.60: 11.1.2 */
2908 }
2909
2910 /* Check packet length field versus length of packet */
2911 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2912 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002913 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002914 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002915 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002916 continue; /* Silently discard */
2917 }
2918
2919 if ((gsn->mode == GTP_MODE_GGSN) &&
2920 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002921 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002922 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002923 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002924 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002925 "Unexpected GTPv0 Signalling Message '%s'\n",
2926 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002927 continue; /* Silently discard 29.60: 11.1.4 */
2928 }
2929
2930 if ((gsn->mode == GTP_MODE_SGSN) &&
2931 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02002932 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002933 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002934 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002935 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02002936 "Unexpected GTPv0 Signalling Message '%s'\n",
2937 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01002938 continue; /* Silently discard 29.60: 11.1.4 */
2939 }
2940
2941 switch (pheader->type) {
2942 case GTP_ECHO_REQ:
2943 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2944 break;
2945 case GTP_ECHO_RSP:
2946 gtp_echo_conf(gsn, version, &peer, buffer, status);
2947 break;
2948 case GTP_NOT_SUPPORTED:
2949 gtp_unsup_ind(gsn, &peer, buffer, status);
2950 break;
2951 case GTP_CREATE_PDP_REQ:
2952 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2953 status);
2954 break;
2955 case GTP_CREATE_PDP_RSP:
2956 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2957 status);
2958 break;
2959 case GTP_UPDATE_PDP_REQ:
2960 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2961 status);
2962 break;
2963 case GTP_UPDATE_PDP_RSP:
2964 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2965 status);
2966 break;
2967 case GTP_DELETE_PDP_REQ:
2968 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2969 status);
2970 break;
2971 case GTP_DELETE_PDP_RSP:
2972 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2973 status);
2974 break;
2975 case GTP_ERROR:
2976 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2977 break;
2978 case GTP_GPDU:
2979 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2980 break;
2981 default:
2982 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002983 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2984 "Unknown GTP message type received: %d\n",
2985 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002986 break;
2987 }
2988 }
jjako08d331d2003-10-13 20:33:30 +00002989}
2990
jjako08d331d2003-10-13 20:33:30 +00002991int gtp_decaps1c(struct gsn_t *gsn)
2992{
Harald Weltebed35df2011-11-02 13:06:18 +01002993 unsigned char buffer[PACKET_MAX];
2994 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002995 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002996 int status;
2997 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01002998 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01002999 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00003000
Harald Weltebed35df2011-11-02 13:06:18 +01003001 /* TODO: Need strategy of userspace buffering and blocking */
3002 /* Currently read is non-blocking and send is blocking. */
3003 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003004
Harald Weltebed35df2011-11-02 13:06:18 +01003005 while (1) { /* Loop until no more to read */
3006 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003007 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003008 return -1;
3009 }
3010 peerlen = sizeof(peer);
3011 if ((status =
3012 recvfrom(fd, buffer, sizeof(buffer), 0,
3013 (struct sockaddr *)&peer, &peerlen)) < 0) {
3014 if (errno == EAGAIN)
3015 return 0;
3016 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003017 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003018 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003019 fd, (unsigned long)buffer, sizeof(buffer),
3020 status, status ? strerror(errno) : "No error");
3021 return -1;
3022 }
jjako08d331d2003-10-13 20:33:30 +00003023
Harald Weltebed35df2011-11-02 13:06:18 +01003024 /* Need at least 1 byte in order to check version */
3025 if (status < (1)) {
3026 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003027 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3028 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003029 continue;
3030 }
jjako08d331d2003-10-13 20:33:30 +00003031
Harald Weltebed35df2011-11-02 13:06:18 +01003032 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003033
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003034 version = GTPHDR_F_GET_VER(pheader->flags);
3035
Harald Weltebed35df2011-11-02 13:06:18 +01003036 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003037 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003038 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003039 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3040 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003041 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
3042 /*29.60: 11.1.1 */
3043 continue;
3044 }
jjako08d331d2003-10-13 20:33:30 +00003045
Harald Weltebed35df2011-11-02 13:06:18 +01003046 /* Version must be at least GTP 1 */
3047 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3048 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3049 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003050 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003051 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003052 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3053 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003054 continue;
3055 }
jjako08d331d2003-10-13 20:33:30 +00003056
Harald Weltebed35df2011-11-02 13:06:18 +01003057 /* Check packet flag field */
3058 if (((pheader->flags & 0xf7) != 0x32)) {
3059 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003060 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003061 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003062 continue;
3063 }
jjako2c381332003-10-21 19:09:53 +00003064
Harald Weltebed35df2011-11-02 13:06:18 +01003065 /* Check length of packet */
3066 if (status < GTP1_HEADER_SIZE_LONG) {
3067 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003068 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3069 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003070 continue; /* Silently discard 29.60: 11.1.2 */
3071 }
jjako2c381332003-10-21 19:09:53 +00003072
Harald Weltebed35df2011-11-02 13:06:18 +01003073 /* Check packet length field versus length of packet */
3074 if (status !=
3075 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3076 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003077 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003078 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003079 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003080 continue; /* Silently discard */
3081 }
jjako1db1c812003-07-06 20:53:57 +00003082
Harald Weltebed35df2011-11-02 13:06:18 +01003083 /* Check for extension headers */
3084 /* TODO: We really should cycle through the headers and determine */
3085 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003086 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003087 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003088 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3089 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003090 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3091 status);
jjako1db1c812003-07-06 20:53:57 +00003092
Harald Weltebed35df2011-11-02 13:06:18 +01003093 continue;
3094 }
3095
3096 if ((gsn->mode == GTP_MODE_GGSN) &&
3097 ((pheader->type == GTP_CREATE_PDP_RSP) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003098 (pheader->type == GTP_UPDATE_PDP_RSP))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003099 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003100 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003101 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003102 "Unexpected GTPv1 Signalling Message '%s'\n",
3103 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003104 continue; /* Silently discard 29.60: 11.1.4 */
3105 }
3106
3107 if ((gsn->mode == GTP_MODE_SGSN) &&
3108 ((pheader->type == GTP_CREATE_PDP_REQ) ||
Pau Espin Pedrola32e4c42018-07-13 19:05:00 +02003109 (pheader->type == GTP_UPDATE_PDP_REQ))) {
Harald Weltebed35df2011-11-02 13:06:18 +01003110 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003111 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003112 status,
Pau Espin Pedrol3b84e922018-07-13 18:32:35 +02003113 "Unexpected GTPv1 Signalling Message '%s'\n",
3114 get_value_string(gtp_type_names, pheader->type));
Harald Weltebed35df2011-11-02 13:06:18 +01003115 continue; /* Silently discard 29.60: 11.1.4 */
3116 }
3117
3118 switch (pheader->type) {
3119 case GTP_ECHO_REQ:
3120 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3121 break;
3122 case GTP_ECHO_RSP:
3123 gtp_echo_conf(gsn, version, &peer, buffer, status);
3124 break;
3125 case GTP_NOT_SUPPORTED:
3126 gtp_unsup_ind(gsn, &peer, buffer, status);
3127 break;
3128 case GTP_SUPP_EXT_HEADER:
3129 gtp_extheader_ind(gsn, &peer, buffer, status);
3130 break;
3131 case GTP_CREATE_PDP_REQ:
3132 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3133 status);
3134 break;
3135 case GTP_CREATE_PDP_RSP:
3136 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3137 status);
3138 break;
3139 case GTP_UPDATE_PDP_REQ:
3140 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3141 status);
3142 break;
3143 case GTP_UPDATE_PDP_RSP:
3144 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3145 status);
3146 break;
3147 case GTP_DELETE_PDP_REQ:
3148 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3149 status);
3150 break;
3151 case GTP_DELETE_PDP_RSP:
3152 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3153 status);
3154 break;
3155 case GTP_ERROR:
3156 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3157 break;
3158 default:
3159 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003160 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3161 "Unknown GTP message type received: %u\n",
3162 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003163 break;
3164 }
3165 }
jjako52c24142002-12-16 13:33:51 +00003166}
3167
jjako08d331d2003-10-13 20:33:30 +00003168int gtp_decaps1u(struct gsn_t *gsn)
3169{
Harald Weltebed35df2011-11-02 13:06:18 +01003170 unsigned char buffer[PACKET_MAX];
3171 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003172 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003173 int status;
3174 struct gtp1_header_short *pheader;
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003175 uint8_t version;
Harald Weltebed35df2011-11-02 13:06:18 +01003176 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003177
Harald Weltebed35df2011-11-02 13:06:18 +01003178 /* TODO: Need strategy of userspace buffering and blocking */
3179 /* Currently read is non-blocking and send is blocking. */
3180 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003181
Harald Weltebed35df2011-11-02 13:06:18 +01003182 while (1) { /* Loop until no more to read */
3183 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003184 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003185 return -1;
3186 }
3187 peerlen = sizeof(peer);
3188 if ((status =
3189 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3190 (struct sockaddr *)&peer, &peerlen)) < 0) {
3191 if (errno == EAGAIN)
3192 return 0;
3193 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003194 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003195 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003196 gsn->fd1u, (unsigned long)buffer,
3197 sizeof(buffer), status,
3198 status ? strerror(errno) : "No error");
3199 return -1;
3200 }
jjako08d331d2003-10-13 20:33:30 +00003201
Harald Weltebed35df2011-11-02 13:06:18 +01003202 /* Need at least 1 byte in order to check version */
3203 if (status < (1)) {
3204 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003205 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3206 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003207 continue;
3208 }
jjako08d331d2003-10-13 20:33:30 +00003209
Harald Weltebed35df2011-11-02 13:06:18 +01003210 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003211
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003212 version = GTPHDR_F_GET_VER(pheader->flags);
3213
Harald Weltebed35df2011-11-02 13:06:18 +01003214 /* Version must be no larger than GTP 1 */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003215 if (version > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003216 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003217 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3218 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003219 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3220 continue;
3221 }
jjako08d331d2003-10-13 20:33:30 +00003222
Harald Weltebed35df2011-11-02 13:06:18 +01003223 /* Version must be at least GTP 1 */
3224 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3225 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3226 /* the message */
Pau Espin Pedrola4aada02018-01-25 17:24:38 +01003227 if (version < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003228 gsn->unsup++;
Pau Espin Pedrola884a952018-01-25 17:28:11 +01003229 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3230 "Unsupported GTP version %"PRIu8"\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01003231 continue;
3232 }
jjako2c381332003-10-21 19:09:53 +00003233
Harald Weltebed35df2011-11-02 13:06:18 +01003234 /* Check packet flag field (allow both with and without sequence number) */
3235 if (((pheader->flags & 0xf5) != 0x30)) {
3236 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003237 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003238 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003239 continue;
3240 }
jjako2c381332003-10-21 19:09:53 +00003241
Harald Weltebed35df2011-11-02 13:06:18 +01003242 /* Check length of packet */
3243 if (status < GTP1_HEADER_SIZE_SHORT) {
3244 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003245 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3246 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003247 continue; /* Silently discard 29.60: 11.1.2 */
3248 }
3249
3250 /* Check packet length field versus length of packet */
3251 if (status !=
3252 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3253 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003254 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003255 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003256 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003257 continue; /* Silently discard */
3258 }
3259
3260 /* Check for extension headers */
3261 /* TODO: We really should cycle through the headers and determine */
3262 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003263 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003264 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003265 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3266 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003267 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3268 status);
3269
3270 continue;
3271 }
3272
3273 switch (pheader->type) {
3274 case GTP_ECHO_REQ:
3275 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3276 break;
3277 case GTP_ECHO_RSP:
3278 gtp_echo_conf(gsn, version, &peer, buffer, status);
3279 break;
3280 case GTP_SUPP_EXT_HEADER:
3281 gtp_extheader_ind(gsn, &peer, buffer, status);
3282 break;
3283 case GTP_ERROR:
3284 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3285 break;
3286 /* Supported header extensions */
3287 case GTP_GPDU:
3288 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3289 break;
3290 default:
3291 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003292 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3293 "Unknown GTP message type received: %u\n",
3294 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003295 break;
3296 }
3297 }
jjako08d331d2003-10-13 20:33:30 +00003298}
3299
Harald Weltebed35df2011-11-02 13:06:18 +01003300int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003301{
Harald Weltebed35df2011-11-02 13:06:18 +01003302 union gtp_packet packet;
3303 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003304 struct msghdr msgh;
3305 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003306 int fd;
jjako52c24142002-12-16 13:33:51 +00003307
Harald Welte471e3492017-09-24 16:12:39 +08003308 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003309 memset(&addr, 0, sizeof(addr));
3310 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003311#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003312 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003313#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003314 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003315
Harald Welte471e3492017-09-24 16:12:39 +08003316 /* prepare msghdr */
3317 memset(&msgh, 0, sizeof(msgh));
3318 msgh.msg_name = &addr;
3319 msgh.msg_namelen = sizeof(addr);
3320 msgh.msg_iov = iov;
3321 msgh.msg_iovlen = ARRAY_SIZE(iov);
3322
3323 /* prepare iovectors */
3324 iov[0].iov_base = &packet;
3325 /* iov[0].iov_len is not known here yet */
3326 iov[1].iov_base = pack;
3327 iov[1].iov_len = len;
3328
Harald Weltebed35df2011-11-02 13:06:18 +01003329 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003330
Harald Welte471e3492017-09-24 16:12:39 +08003331 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003332 addr.sin_port = htons(GTP0_PORT);
3333 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003334
Harald Weltebed35df2011-11-02 13:06:18 +01003335 get_default_gtp(0, GTP_GPDU, &packet);
3336 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003337 if (pdp->tx_gpdu_seq)
3338 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3339 else
3340 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003341 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003342 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003343 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003344
Harald Weltebed35df2011-11-02 13:06:18 +01003345 addr.sin_port = htons(GTP1U_PORT);
3346 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003347
Harald Weltebed35df2011-11-02 13:06:18 +01003348 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003349 if (pdp->tx_gpdu_seq) {
3350 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3351 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3352 GTP1_HEADER_SIZE_LONG);
3353 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3354 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3355 } else {
3356 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3357 packet.gtp1s.h.length = hton16(len);
3358 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3359 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3360 }
Harald Weltebed35df2011-11-02 13:06:18 +01003361 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003362 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003363 return EOF;
3364 }
3365
3366 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003367 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003368 return -1;
3369 }
3370
Harald Welte471e3492017-09-24 16:12:39 +08003371 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003372 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003373 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003374 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003375 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3376 strerror(errno));
3377 return EOF;
3378 }
3379 return 0;
jjako52c24142002-12-16 13:33:51 +00003380}
3381
jjako52c24142002-12-16 13:33:51 +00003382/* ***********************************************************
3383 * Conversion functions
3384 *************************************************************/
3385
jjako52c24142002-12-16 13:33:51 +00003386/* ***********************************************************
3387 * IP address conversion functions
3388 * There exist several types of address representations:
Pau Espin Pedrol732131d2018-01-25 17:23:09 +01003389 * - eua: End User Address. (29.060, 7.7.27, message type 128)
jjako52c24142002-12-16 13:33:51 +00003390 * Used for signalling address to mobile station. Supports IPv4
3391 * IPv6 x.25 etc. etc.
3392 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3393 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3394 * - in_addr: IPv4 address struct.
3395 * - sockaddr_in: Socket API representation of IP address and
3396 * port number.
3397 *************************************************************/
3398
Harald Weltebed35df2011-11-02 13:06:18 +01003399int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3400{
Harald Weltecee75462017-09-24 17:45:05 +08003401 eua->v[0] = PDP_EUA_ORG_IETF;
3402 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003403 if (src) {
3404 eua->l = 6;
3405 memcpy(&eua->v[2], src, 4);
3406 } else {
3407 eua->l = 2;
3408 }
3409 return 0;
jjako52c24142002-12-16 13:33:51 +00003410}
3411
Harald Weltebed35df2011-11-02 13:06:18 +01003412int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3413{
Harald Weltecee75462017-09-24 17:45:05 +08003414 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 +01003415 return -1; /* Not IPv4 address */
3416 memcpy(dst, &eua->v[2], 4);
3417 return 0;
jjako52c24142002-12-16 13:33:51 +00003418}
3419
Harald Weltebed35df2011-11-02 13:06:18 +01003420int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3421{
3422 memset(dst, 0, sizeof(struct in_addr));
3423 if (gsna->l != 4)
3424 return EOF; /* Return if not IPv4 */
3425 memcpy(dst, gsna->v, gsna->l);
3426 return 0;
jjako52c24142002-12-16 13:33:51 +00003427}
3428
Harald Weltebed35df2011-11-02 13:06:18 +01003429int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3430{
3431 memset(gsna, 0, sizeof(struct ul16_t));
3432 gsna->l = 4;
3433 memcpy(gsna->v, src, gsna->l);
3434 return 0;
jjako52c24142002-12-16 13:33:51 +00003435}
Harald Welteb10ee082017-08-12 19:29:16 +02003436
3437/* TS 29.060 has yet again a different encoding for IMSIs than
3438 * what we have in other places, so we cannot use the gsm48
3439 * decoding functions. Also, libgtp uses an uint64_t in
3440 * _network byte order_ to contain BCD digits ?!? */
3441const char *imsi_gtp2str(const uint64_t *imsi)
3442{
Harald Weltea06120d2017-11-06 03:12:54 +09003443 static char buf[sizeof(*imsi)*2+1];
Harald Welteb10ee082017-08-12 19:29:16 +02003444 const uint8_t *imsi8 = (const uint8_t *) imsi;
3445 unsigned int i, j = 0;
3446
3447 for (i = 0; i < sizeof(*imsi); i++) {
3448 uint8_t nibble;
3449
3450 nibble = imsi8[i] & 0xf;
3451 if (nibble == 0xf)
3452 break;
3453 buf[j++] = osmo_bcd2char(nibble);
3454
3455 nibble = imsi8[i] >> 4;
3456 if (nibble == 0xf)
3457 break;
3458 buf[j++] = osmo_bcd2char(nibble);
3459 }
3460
3461 buf[j++] = '\0';
3462 return buf;
3463}