blob: 3051aaac6ae8c9ce043d87c095807afeede4dd54 [file] [log] [blame]
jjako52c24142002-12-16 13:33:51 +00001/*
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
jjako52c24142002-12-16 13:33:51 +00006 *
7 * 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.
11 *
jjako52c24142002-12-16 13:33:51 +000012 */
13
14/*
15 * gtp.c: Contains all GTP functionality. Should be able to handle multiple
16 * tunnels in the same program.
17 *
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
89/* gtp_new */
90/* gtp_free */
91
Harald Weltebed35df2011-11-02 13:06:18 +010092int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
93 uint64_t imsi, uint8_t nsapi)
94{
Harald Weltee257be12017-08-12 14:55:09 +020095 int rc;
96 rc = pdp_newpdp(pdp, imsi, nsapi, NULL);
97 if (!rc && *pdp)
98 (*pdp)->gsn = gsn;
99 return rc;
jjako52c24142002-12-16 13:33:51 +0000100}
101
Harald Weltebed35df2011-11-02 13:06:18 +0100102int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp)
103{
104 return pdp_freepdp(pdp);
jjako52c24142002-12-16 13:33:51 +0000105}
106
jjako52c24142002-12-16 13:33:51 +0000107/* gtp_gpdu */
108
Harald Weltebed35df2011-11-02 13:06:18 +0100109extern int gtp_fd(struct gsn_t *gsn)
110{
111 return gsn->fd0;
jjako52c24142002-12-16 13:33:51 +0000112}
113
114/* gtp_decaps */
115/* gtp_retrans */
116/* gtp_retranstimeout */
117
jjako08d331d2003-10-13 20:33:30 +0000118int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100119 int (*cb) (struct sockaddr_in * peer))
120{
121 gsn->cb_unsup_ind = cb;
122 return 0;
jjako08d331d2003-10-13 20:33:30 +0000123}
124
jjako2c381332003-10-21 19:09:53 +0000125int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100126 int (*cb) (struct sockaddr_in * peer))
127{
128 gsn->cb_extheader_ind = cb;
129 return 0;
jjako2c381332003-10-21 19:09:53 +0000130}
131
jjako08d331d2003-10-13 20:33:30 +0000132/* API: Initialise delete context callback */
133/* Called whenever a pdp context is deleted for any reason */
Harald Weltebed35df2011-11-02 13:06:18 +0100134int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
jjako52c24142002-12-16 13:33:51 +0000135{
Harald Weltebed35df2011-11-02 13:06:18 +0100136 gsn->cb_delete_context = cb;
137 return 0;
jjako52c24142002-12-16 13:33:51 +0000138}
139
jjako52c24142002-12-16 13:33:51 +0000140int gtp_set_cb_conf(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100141 int (*cb) (int type, int cause,
142 struct pdp_t * pdp, void *cbp))
143{
144 gsn->cb_conf = cb;
145 return 0;
jjako52c24142002-12-16 13:33:51 +0000146}
147
Harald Welte629e9862010-12-24 20:58:09 +0100148int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100149 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
150{
151 gsn->cb_recovery = cb;
152 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100153}
154
jjako08d331d2003-10-13 20:33:30 +0000155extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100156 int (*cb_data_ind) (struct pdp_t * pdp,
157 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000158{
Harald Weltebed35df2011-11-02 13:06:18 +0100159 gsn->cb_data_ind = cb_data_ind;
160 return 0;
jjako52c24142002-12-16 13:33:51 +0000161}
162
jjako08d331d2003-10-13 20:33:30 +0000163/**
164 * get_default_gtp()
165 * Generate a GPRS Tunneling Protocol signalling packet header, depending
166 * on GTP version and message type. pdp is used for teid/flow label.
167 * *packet must be allocated by the calling function, and be large enough
168 * to hold the packet header.
169 * returns the length of the header. 0 on error.
170 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100171static unsigned int get_default_gtp(int version, uint8_t type, void *packet)
172{
173 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
174 struct gtp1_header_long *gtp1_default =
175 (struct gtp1_header_long *)packet;
176 switch (version) {
177 case 0:
178 /* Initialise "standard" GTP0 header */
179 memset(gtp0_default, 0, sizeof(struct gtp0_header));
180 gtp0_default->flags = 0x1e;
181 gtp0_default->type = hton8(type);
182 gtp0_default->spare1 = 0xff;
183 gtp0_default->spare2 = 0xff;
184 gtp0_default->spare3 = 0xff;
185 gtp0_default->number = 0xff;
186 return GTP0_HEADER_SIZE;
187 case 1:
188 /* Initialise "standard" GTP1 header */
189 /* 29.060: 8.2: S=1 and PN=0 */
190 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
191 /* and Supported Extension Headers Notification, the S field shall be */
192 /* set to 1 */
193 /* Currently extension headers are not supported */
194 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
Harald Weltefed598f2017-09-24 16:39:22 +0800195 /* No extension, enable sequence, no N-PDU */
196 gtp1_default->flags = GTPHDR_F_VER(1) | GTP1HDR_F_GTP1 | GTP1HDR_F_SEQ;
Harald Weltebed35df2011-11-02 13:06:18 +0100197 gtp1_default->type = hton8(type);
198 return GTP1_HEADER_SIZE_LONG;
199 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100200 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100201 "Unknown GTP packet version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +0100202 return 0;
203 }
jjako52c24142002-12-16 13:33:51 +0000204}
205
jjako08d331d2003-10-13 20:33:30 +0000206/**
207 * get_seq()
208 * Get sequence number of a packet.
209 * Returns 0 on error
210 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100211static uint16_t get_seq(void *pack)
212{
213 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800214 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000215
Harald Weltefed598f2017-09-24 16:39:22 +0800216 if (ver == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +0100217 return ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800218 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100219 return ntoh16(packet->gtp1l.h.seq);
220 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100221 return 0;
222 }
jjako08d331d2003-10-13 20:33:30 +0000223}
224
225/**
226 * get_tid()
227 * Get tunnel identifier of a packet.
228 * Returns 0 on error
229 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100230static uint64_t get_tid(void *pack)
231{
232 union gtp_packet *packet = (union gtp_packet *)pack;
233
Harald Weltefed598f2017-09-24 16:39:22 +0800234 if (GTPHDR_F_GET_VER(packet->flags) == 0) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100235 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100236 }
237 return 0;
jjako08d331d2003-10-13 20:33:30 +0000238}
239
240/**
241 * get_hlen()
242 * Get the header length of a packet.
243 * Returns 0 on error
244 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100245static uint16_t get_hlen(void *pack)
246{
247 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800248 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000249
Harald Weltefed598f2017-09-24 16:39:22 +0800250 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100251 return GTP0_HEADER_SIZE;
Harald Weltefed598f2017-09-24 16:39:22 +0800252 } else if (ver == 1 && (packet->flags & 0x07) == 0) { /* Short version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100253 return GTP1_HEADER_SIZE_SHORT;
Harald Weltefed598f2017-09-24 16:39:22 +0800254 } else if (ver == 1) { /* Version 1 with seq/n-pdu/ext */
255 return GTP1_HEADER_SIZE_LONG;
Harald Weltebed35df2011-11-02 13:06:18 +0100256 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100257 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100258 return 0;
259 }
jjako08d331d2003-10-13 20:33:30 +0000260}
261
262/**
263 * get_tei()
264 * Get the tunnel endpoint identifier (flow label) of a packet.
265 * Returns 0xffffffff on error.
266 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100267static uint32_t get_tei(void *pack)
268{
269 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800270 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000271
Harald Weltefed598f2017-09-24 16:39:22 +0800272 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100273 return ntoh16(packet->gtp0.h.flow);
Harald Weltefed598f2017-09-24 16:39:22 +0800274 } else if (ver == 1) { /* Version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100275 return ntoh32(packet->gtp1l.h.tei);
276 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100277 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100278 return 0xffffffff;
279 }
jjako08d331d2003-10-13 20:33:30 +0000280}
jjakoa7cd2492003-04-11 09:40:12 +0000281
jjako52c24142002-12-16 13:33:51 +0000282/* ***********************************************************
283 * Reliable delivery of signalling messages
284 *
285 * Sequence numbers are used for both signalling messages and
286 * data messages.
287 *
288 * For data messages each tunnel maintains a sequence counter,
289 * which is incremented by one each time a new data message
290 * is sent. The sequence number starts at (0) zero at tunnel
291 * establishment, and wraps around at 65535 (29.060 9.3.1.1
292 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
293 * or can be used to check the validity of the message in the
294 * receiver, or for reordering af packets.
295 *
296 * For signalling messages the sequence number is used by
297 * signalling messages for which a response is defined. A response
298 * message should copy the sequence from the corresponding request
299 * message. The sequence number "unambiguously" identifies a request
300 * message within a given path, with a path being defined as a set of
301 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
302 * messages shall be responded to, and all response messages associated
303 * with a certain request shall always include the same information"
304 *
305 * We take this to mean that the GSN transmitting a request is free to
306 * choose the sequence number, as long as it is unique within a given path.
307 * It means that we are allowed to count backwards, or roll over at 17
308 * if we prefer that. It also means that we can use the same counter for
309 * all paths. This has the advantage that the transmitted request sequence
310 * numbers are unique within each GSN, and also we dont have to mess around
311 * with path setup and teardown.
312 *
313 * If a response message is lost, the request will be retransmitted, and
314 * the receiving GSN will receive a "duplicated" request. The standard
315 * requires the receiving GSN to send a response, with the same information
316 * as in the original response. For most messages this happens automatically:
317 *
318 * Echo: Automatically dublicates the original response
319 * Create pdp context: The SGSN may send create context request even if
320 * a context allready exist (imsi+nsapi?). This means that the reply will
321 automatically dublicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000322 * side effects in the application which is asked twice to validate
323 * the login.
jjako52c24142002-12-16 13:33:51 +0000324 * Update pdp context: Automatically dublicates the original response???
325 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
326 * a nonexist reply message.
327 *
328 * The correct solution will be to make a queue containing response messages.
329 * This queue should be checked whenever a request is received. If the
330 * response is allready in the queue that response should be transmitted.
331 * It should be possible to find messages in this queue on the basis of
332 * the sequence number and peer GSN IP address (The sequense number is unique
333 * within each path). This need to be implemented by a hash table. Furthermore
334 * it should be possibly to delete messages based on a timeout. This can be
335 * achieved by means of a linked list. The timeout value need to be larger
336 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
337 * set in the peer GSN, so there is no way to know these parameters. On the
338 * other hand the timeout value need to be so small that we do not receive
339 * wraparound sequence numbere before the message is deleted. 60 seconds is
340 * probably not a bad choise.
341 *
342 * This queue however is first really needed from gtp1.
343 *
344 * gtp_req:
345 * Send off a signalling message with appropiate sequence
346 * number. Store packet in queue.
347 * gtp_conf:
348 * Remove an incoming confirmation from the queue
349 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000350 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000351 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000352 * gtp_notification:
353 * Send off a notification message. This is neither a request nor
354 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000355 * gtp_retrans:
356 * Retransmit any outstanding packets which have exceeded
357 * a predefined timeout.
358 *************************************************************/
359
jjako08d331d2003-10-13 20:33:30 +0000360int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100361 union gtp_packet *packet, int len,
362 struct in_addr *inetaddr, void *cbp)
363{
Harald Weltefed598f2017-09-24 16:39:22 +0800364 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100365 struct sockaddr_in addr;
366 struct qmsg_t *qmsg;
367 int fd;
jjako08d331d2003-10-13 20:33:30 +0000368
Harald Weltebed35df2011-11-02 13:06:18 +0100369 memset(&addr, 0, sizeof(addr));
370 addr.sin_family = AF_INET;
371 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000372#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100373 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000374#endif
jjako52c24142002-12-16 13:33:51 +0000375
Harald Weltefed598f2017-09-24 16:39:22 +0800376 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100377 addr.sin_port = htons(GTP0_PORT);
378 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
379 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100380 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100381 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100382 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100383 }
Harald Weltebed35df2011-11-02 13:06:18 +0100384 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
385 || (packet->gtp0.h.type == GTP_ERROR)))
386 packet->gtp0.h.flow = hton16(pdp->flru);
387 else if (pdp)
388 packet->gtp0.h.flow = hton16(pdp->flrc);
389 fd = gsn->fd0;
Harald Weltefed598f2017-09-24 16:39:22 +0800390 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100391 addr.sin_port = htons(GTP1C_PORT);
392 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
393 packet->gtp1l.h.seq = hton16(gsn->seq_next);
394 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
395 (packet->gtp1l.h.type == GTP_ERROR)))
396 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
397 else if (pdp)
398 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
399 fd = gsn->fd1c;
400 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100401 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100402 return -1;
403 }
jjako52c24142002-12-16 13:33:51 +0000404
Harald Weltebed35df2011-11-02 13:06:18 +0100405 if (sendto(fd, packet, len, 0,
406 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
407 gsn->err_sendto++;
Max14b1b632017-08-21 20:14:59 +0200408 LOGP(DLGTP, LOGL_ERROR, "Sendto(fd=%d, msg=%lx, len=%d, dst=%s) failed: Error = %s\n", fd,
409 (unsigned long)&packet, len, inet_ntoa(addr.sin_addr), strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100410 return -1;
411 }
412
413 /* Use new queue structure */
414 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
415 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100416 LOGP(DLGTP, LOGL_ERROR,
417 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100418 } else {
419 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
420 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100421 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100422 qmsg->retrans = 0; /* No retransmissions so far */
423 qmsg->cbp = cbp;
424 qmsg->type = ntoh8(packet->gtp0.h.type);
425 qmsg->fd = fd;
426 }
427 gsn->seq_next++; /* Count up this time */
428 return 0;
jjako52c24142002-12-16 13:33:51 +0000429}
430
431/* gtp_conf
432 * Remove signalling packet from retransmission queue.
433 * return 0 on success, EOF if packet was not found */
434
435int gtp_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100436 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
437{
Harald Weltefed598f2017-09-24 16:39:22 +0800438 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100439 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000440
Harald Weltefed598f2017-09-24 16:39:22 +0800441 if (ver == 0)
Harald Weltebed35df2011-11-02 13:06:18 +0100442 seq = ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800443 else if (ver == 1 && (packet->gtp1l.h.flags & GTP1HDR_F_SEQ))
Harald Weltebed35df2011-11-02 13:06:18 +0100444 seq = ntoh16(packet->gtp1l.h.seq);
445 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100446 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
447 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100448 return EOF;
449 }
jjako08d331d2003-10-13 20:33:30 +0000450
Harald Weltebed35df2011-11-02 13:06:18 +0100451 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
452 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100453 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
454 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100455 return EOF;
456 }
jjako52c24142002-12-16 13:33:51 +0000457
Harald Weltebed35df2011-11-02 13:06:18 +0100458 return 0;
jjako52c24142002-12-16 13:33:51 +0000459}
460
Harald Weltebed35df2011-11-02 13:06:18 +0100461int gtp_retrans(struct gsn_t *gsn)
462{
463 /* Retransmit any outstanding packets */
464 /* Remove from queue if maxretrans exceeded */
465 time_t now;
466 struct qmsg_t *qmsg;
467 now = time(NULL);
468 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000469
Harald Welte95848ba2011-11-02 18:17:50 +0100470 /* get first element in queue, as long as the timeout of that
471 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100472 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
473 (qmsg->timeout <= now)) {
474 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100475 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100476 if (gsn->cb_conf)
477 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
478 queue_freemsg(gsn->queue_req, qmsg);
479 } else {
480 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
481 (struct sockaddr *)&qmsg->peer,
482 sizeof(struct sockaddr_in)) < 0) {
483 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100484 LOGP(DLGTP, LOGL_ERROR,
485 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100486 gsn->fd0, (unsigned long)&qmsg->p,
487 qmsg->l, strerror(errno));
488 }
489 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100490 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100491 qmsg->retrans++;
492 }
493 }
jjako52c24142002-12-16 13:33:51 +0000494
Harald Weltebed35df2011-11-02 13:06:18 +0100495 /* Also clean up reply timeouts */
496 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
497 (qmsg->timeout < now)) {
498 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
499 queue_freemsg(gsn->queue_resp, qmsg);
500 }
jjako52c24142002-12-16 13:33:51 +0000501
Harald Weltebed35df2011-11-02 13:06:18 +0100502 return 0;
jjako52c24142002-12-16 13:33:51 +0000503}
504
Harald Weltebed35df2011-11-02 13:06:18 +0100505int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
506{
507 time_t now, later;
508 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000509
Harald Weltebed35df2011-11-02 13:06:18 +0100510 if (queue_getfirst(gsn->queue_req, &qmsg)) {
511 timeout->tv_sec = 10;
512 timeout->tv_usec = 0;
513 } else {
514 now = time(NULL);
515 later = qmsg->timeout;
516 timeout->tv_sec = later - now;
517 timeout->tv_usec = 0;
518 if (timeout->tv_sec < 0)
519 timeout->tv_sec = 0; /* No negative allowed */
520 if (timeout->tv_sec > 10)
521 timeout->tv_sec = 10; /* Max sleep for 10 sec */
522 }
523 return 0;
jjako52c24142002-12-16 13:33:51 +0000524}
525
Harald Weltebed35df2011-11-02 13:06:18 +0100526int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000527 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100528 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
529{
Harald Weltefed598f2017-09-24 16:39:22 +0800530 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100531 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000532
Harald Weltefed598f2017-09-24 16:39:22 +0800533 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100534 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
535 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100536 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100537 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
538 (packet->gtp0.h.type == GTP_ERROR)))
539 packet->gtp0.h.flow = hton16(pdp->flru);
540 else if (pdp)
541 packet->gtp0.h.flow = hton16(pdp->flrc);
Harald Weltefed598f2017-09-24 16:39:22 +0800542 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100543 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
544 packet->gtp1l.h.seq = hton16(seq);
545 if (pdp && (fd == gsn->fd1u))
546 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
547 else if (pdp)
548 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
549 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100550 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100551 return -1;
552 }
jjako08d331d2003-10-13 20:33:30 +0000553
Harald Weltebed35df2011-11-02 13:06:18 +0100554 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100555 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100556 return -1;
557 }
jjako52c24142002-12-16 13:33:51 +0000558
Harald Weltebed35df2011-11-02 13:06:18 +0100559 if (sendto(fd, packet, len, 0,
560 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
561 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100562 LOGP(DLGTP, LOGL_ERROR,
563 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100564 (unsigned long)&packet, len, strerror(errno));
565 return -1;
566 }
567
568 /* Use new queue structure */
569 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
570 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100571 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100572 } else {
573 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
574 qmsg->l = len;
575 qmsg->timeout = time(NULL) + 60; /* When to timeout */
576 qmsg->retrans = 0; /* No retransmissions so far */
577 qmsg->cbp = NULL;
578 qmsg->type = 0;
579 qmsg->fd = fd;
580 }
581 return 0;
jjako52c24142002-12-16 13:33:51 +0000582}
583
jjako2c381332003-10-21 19:09:53 +0000584int gtp_notification(struct gsn_t *gsn, int version,
585 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100586 struct sockaddr_in *peer, int fd, uint16_t seq)
587{
jjako2c381332003-10-21 19:09:53 +0000588
Harald Weltefed598f2017-09-24 16:39:22 +0800589 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100590 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000591
Harald Weltebed35df2011-11-02 13:06:18 +0100592 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000593
Harald Weltebed35df2011-11-02 13:06:18 +0100594 /* In GTP0 notifications are treated as replies. In GTP1 they
595 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000596
Harald Weltebed35df2011-11-02 13:06:18 +0100597 if (fd == gsn->fd1c)
598 addr.sin_port = htons(GTP1C_PORT);
599 else if (fd == gsn->fd1u)
600 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000601
Harald Weltefed598f2017-09-24 16:39:22 +0800602 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100603 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
604 packet->gtp0.h.seq = hton16(seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800605 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100606 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
607 packet->gtp1l.h.seq = hton16(seq);
608 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100609 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100610 return -1;
611 }
612
613 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100614 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100615 return -1;
616 }
617
618 if (sendto(fd, packet, len, 0,
619 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
620 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100621 LOGP(DLGTP, LOGL_ERROR,
622 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100623 (unsigned long)&packet, len, strerror(errno));
624 return -1;
625 }
626 return 0;
jjako2c381332003-10-21 19:09:53 +0000627}
628
Harald Weltebed35df2011-11-02 13:06:18 +0100629int gtp_dublicate(struct gsn_t *gsn, int version,
630 struct sockaddr_in *peer, uint16_t seq)
631{
632 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000633
Harald Weltebed35df2011-11-02 13:06:18 +0100634 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
635 return EOF; /* Notfound */
636 }
jjakoa7cd2492003-04-11 09:40:12 +0000637
Harald Weltebed35df2011-11-02 13:06:18 +0100638 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100639 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100640 return -1;
641 }
642
643 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
644 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
645 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100646 LOGP(DLGTP, LOGL_ERROR,
647 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100648 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
649 strerror(errno));
650 }
651 return 0;
jjako52c24142002-12-16 13:33:51 +0000652}
653
jjako52c24142002-12-16 13:33:51 +0000654/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100655static void log_restart(struct gsn_t *gsn)
656{
jjako52c24142002-12-16 13:33:51 +0000657 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200658 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000659 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200660 char *filename;
jjako52c24142002-12-16 13:33:51 +0000661
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200662 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
663 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000664
665 /* We try to open file. On failure we will later try to create file */
666 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100667 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100668 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100669 filename);
670 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100671 rc = fscanf(f, "%d", &counter);
672 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100673 LOGP(DLGTP, LOGL_ERROR,
674 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100675 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100676 }
677 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100678 LOGP(DLGTP, LOGL_ERROR,
679 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100680 }
jjako52c24142002-12-16 13:33:51 +0000681 }
Harald Weltebed35df2011-11-02 13:06:18 +0100682
683 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000684 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100685
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200686 /* Keep the umask closely wrapped around our fopen() call in case the
687 * log outputs cause file creation. */
688 i = umask(022);
689 f = fopen(filename, "w");
690 umask(i);
691 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100692 LOGP(DLGTP, LOGL_ERROR,
693 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100694 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200695 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000696 }
697
jjako52c24142002-12-16 13:33:51 +0000698 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100699close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200700 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100701 LOGP(DLGTP, LOGL_ERROR,
702 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200703free_filename:
704 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000705}
706
jjako1db1c812003-07-06 20:53:57 +0000707int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100708 int mode)
jjako52c24142002-12-16 13:33:51 +0000709{
Harald Weltebed35df2011-11-02 13:06:18 +0100710 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000711
Max14b1b632017-08-21 20:14:59 +0200712 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
jjako52c24142002-12-16 13:33:51 +0000713
Harald Weltebed35df2011-11-02 13:06:18 +0100714 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000715
Harald Weltebed35df2011-11-02 13:06:18 +0100716 (*gsn)->statedir = statedir;
717 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000718
Harald Weltebed35df2011-11-02 13:06:18 +0100719 /* Initialise sequence number */
720 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000721
Harald Weltebed35df2011-11-02 13:06:18 +0100722 /* Initialise request retransmit queue */
723 queue_new(&(*gsn)->queue_req);
724 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000725
Harald Weltebed35df2011-11-02 13:06:18 +0100726 /* Initialise pdp table */
727 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000728
Harald Weltebed35df2011-11-02 13:06:18 +0100729 /* Initialise call back functions */
730 (*gsn)->cb_create_context_ind = 0;
731 (*gsn)->cb_delete_context = 0;
732 (*gsn)->cb_unsup_ind = 0;
733 (*gsn)->cb_conf = 0;
734 (*gsn)->cb_data_ind = 0;
735
736 /* Store function parameters */
737 (*gsn)->gsnc = *listen;
738 (*gsn)->gsnu = *listen;
739 (*gsn)->mode = mode;
740
741 /* Create GTP version 0 socket */
742 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
743 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100744 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200745 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100746 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200747 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100748 }
749
750 memset(&addr, 0, sizeof(addr));
751 addr.sin_family = AF_INET;
752 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
753 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000754#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100755 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000756#endif
jjako08d331d2003-10-13 20:33:30 +0000757
Harald Weltebed35df2011-11-02 13:06:18 +0100758 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
759 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200760 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
761 "bind(fd0=%d) failed: Error = %s\n",
762 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200763 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100764 }
jjako08d331d2003-10-13 20:33:30 +0000765
Harald Weltebed35df2011-11-02 13:06:18 +0100766 /* Create GTP version 1 control plane socket */
767 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
768 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100769 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200770 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100771 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200772 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100773 }
774
775 memset(&addr, 0, sizeof(addr));
776 addr.sin_family = AF_INET;
777 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
778 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000779#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100780 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000781#endif
jjako08d331d2003-10-13 20:33:30 +0000782
Harald Weltebed35df2011-11-02 13:06:18 +0100783 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
784 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200785 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
786 "bind(fd1c=%d) failed: Error = %s\n",
787 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200788 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100789 }
jjako08d331d2003-10-13 20:33:30 +0000790
Harald Weltebed35df2011-11-02 13:06:18 +0100791 /* Create GTP version 1 user plane socket */
792 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
793 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100794 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200795 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100796 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200797 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100798 }
799
800 memset(&addr, 0, sizeof(addr));
801 addr.sin_family = AF_INET;
802 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
803 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000804#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100805 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000806#endif
jjako52c24142002-12-16 13:33:51 +0000807
Harald Weltebed35df2011-11-02 13:06:18 +0100808 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
809 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200810 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +0200811 "bind(fd1u=%d) failed: Error = %s\n",
812 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +0200813 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100814 }
815
816 return 0;
jjako52c24142002-12-16 13:33:51 +0000817}
818
Harald Weltebed35df2011-11-02 13:06:18 +0100819int gtp_free(struct gsn_t *gsn)
820{
jjako52c24142002-12-16 13:33:51 +0000821
Harald Weltebed35df2011-11-02 13:06:18 +0100822 /* Clean up retransmit queues */
823 queue_free(gsn->queue_req);
824 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000825
Harald Weltebed35df2011-11-02 13:06:18 +0100826 close(gsn->fd0);
827 close(gsn->fd1c);
828 close(gsn->fd1u);
829
830 free(gsn);
831 return 0;
jjako52c24142002-12-16 13:33:51 +0000832}
833
834/* ***********************************************************
835 * Path management messages
836 * Messages: echo and version not supported.
837 * A path is connection between two UDP/IP endpoints
838 *
839 * A path is either using GTP0 or GTP1. A path can be
840 * established by any kind of GTP message??
841
842 * Which source port to use?
843 * GTP-C request destination port is 2123/3386
844 * GTP-U request destination port is 2152/3386
845 * T-PDU destination port is 2152/3386.
846 * For the above messages the source port is locally allocated.
847 * For response messages src=rx-dst and dst=rx-src.
848 * For simplicity we should probably use 2123+2152/3386 as
849 * src port even for the cases where src can be locally
850 * allocated. This also means that we have to listen only to
851 * the same ports.
852 * For response messages we need to be able to respond to
853 * the relevant src port even if it is locally allocated by
854 * the peer.
855 *
856 * The need for path management!
857 * We might need to keep a list of active paths. This might
858 * be in the form of remote IP address + UDP port numbers.
859 * (We will consider a path astablished if we have a context
860 * with the node in question)
861 *************************************************************/
862
863/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000864int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
865 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000866{
Harald Weltebed35df2011-11-02 13:06:18 +0100867 union gtp_packet packet;
868 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
869 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000870}
871
jjako08d331d2003-10-13 20:33:30 +0000872/* Send off an echo reply */
873int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100874 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000875{
Harald Weltebed35df2011-11-02 13:06:18 +0100876 union gtp_packet packet;
877 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
878 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
879 gsn->restart_counter);
880 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
881 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000882}
883
jjako52c24142002-12-16 13:33:51 +0000884/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +0100885int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
886 int fd, void *pack, unsigned len)
887{
jjako52c24142002-12-16 13:33:51 +0000888
Harald Weltebed35df2011-11-02 13:06:18 +0100889 /* Check if it was a dublicate request */
890 if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
891 return 0;
jjako52c24142002-12-16 13:33:51 +0000892
Harald Weltebed35df2011-11-02 13:06:18 +0100893 /* Send off reply to request */
894 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000895}
896
897/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000898int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100899 void *pack, unsigned len)
900{
901 union gtpie_member *ie[GTPIE_SIZE];
902 unsigned char recovery;
903 void *cbp = NULL;
904 uint8_t type = 0;
905 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000906
Harald Weltebed35df2011-11-02 13:06:18 +0100907 /* Remove packet from queue */
908 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
909 return EOF;
jjako52c24142002-12-16 13:33:51 +0000910
Harald Weltebed35df2011-11-02 13:06:18 +0100911 /* Extract information elements into a pointer array */
912 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
913 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100914 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
915 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100916 if (gsn->cb_conf)
917 gsn->cb_conf(type, EOF, NULL, cbp);
918 return EOF;
919 }
jjako52c24142002-12-16 13:33:51 +0000920
Harald Weltebed35df2011-11-02 13:06:18 +0100921 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
922 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100923 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
924 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100925 if (gsn->cb_conf)
926 gsn->cb_conf(type, EOF, NULL, cbp);
927 return EOF;
928 }
jjako52c24142002-12-16 13:33:51 +0000929
Harald Weltebed35df2011-11-02 13:06:18 +0100930 /* Echo reply packages does not have a cause information element */
931 /* Instead we return the recovery number in the callback function */
932 if (gsn->cb_conf)
933 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +0100934
Harald Weltebed35df2011-11-02 13:06:18 +0100935 if (gsn->cb_recovery)
936 gsn->cb_recovery(peer, recovery);
937
938 return 0;
jjako52c24142002-12-16 13:33:51 +0000939}
940
941/* Send off a Version Not Supported message */
942/* This message is somewhat special in that it actually is a
943 * response to some other message with unsupported GTP version
944 * For this reason it has parameters like a response, and does
945 * its own message transmission. No signalling queue is used
946 * The reply is sent to the peer IP and peer UDP. This means that
947 * the peer will be receiving a GTP0 message on a GTP1 port!
948 * In practice however this will never happen as a GTP0 GSN will
949 * only listen to the GTP0 port, and therefore will never receive
950 * anything else than GTP0 */
951
jjako08d331d2003-10-13 20:33:30 +0000952int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
953 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000954{
Harald Weltebed35df2011-11-02 13:06:18 +0100955 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +0000956
Harald Weltebed35df2011-11-02 13:06:18 +0100957 /* GTP 1 is the highest supported protocol */
958 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
959 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +0000960}
961
962/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +0100963int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
964 void *pack, unsigned len)
965{
jjako52c24142002-12-16 13:33:51 +0000966
Harald Weltebed35df2011-11-02 13:06:18 +0100967 if (gsn->cb_unsup_ind)
968 gsn->cb_unsup_ind(peer);
969
970 return 0;
jjako52c24142002-12-16 13:33:51 +0000971}
972
jjako2c381332003-10-21 19:09:53 +0000973/* Send off an Supported Extension Headers Notification */
974int gtp_extheader_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
975 int fd, void *pack, unsigned len)
976{
Harald Weltebed35df2011-11-02 13:06:18 +0100977 union gtp_packet packet;
978 unsigned int length =
979 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +0000980
Harald Weltebed35df2011-11-02 13:06:18 +0100981 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +0000982
Harald Weltebed35df2011-11-02 13:06:18 +0100983 if (version < 1)
984 return 0;
jjako2c381332003-10-21 19:09:53 +0000985
Harald Weltebed35df2011-11-02 13:06:18 +0100986 /* We report back that we support only PDCP PDU headers */
987 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
988 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +0000989
Harald Weltebed35df2011-11-02 13:06:18 +0100990 return gtp_notification(gsn, version, &packet, length,
991 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +0000992}
993
994/* Handle a Supported Extension Headers Notification */
Harald Weltebed35df2011-11-02 13:06:18 +0100995int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
996 void *pack, unsigned len)
997{
jjako2c381332003-10-21 19:09:53 +0000998
Harald Weltebed35df2011-11-02 13:06:18 +0100999 if (gsn->cb_extheader_ind)
1000 gsn->cb_extheader_ind(peer);
1001
1002 return 0;
jjako2c381332003-10-21 19:09:53 +00001003}
1004
jjako52c24142002-12-16 13:33:51 +00001005/* ***********************************************************
1006 * Session management messages
1007 * Messages: create, update and delete PDP context
1008 *
1009 * Information storage
1010 * Information storage for each PDP context is defined in
1011 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1012 * PDP-address (IP address), sequence numbers, charging ID.
1013 * For the SGSN it also includes radio related mobility
1014 * information.
1015 *************************************************************/
1016
Harald Welte7b3347b2010-05-15 12:18:46 +02001017/* API: Send Create PDP Context Request (7.3.1) */
Harald Weltebed35df2011-11-02 13:06:18 +01001018extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
1019 void *cbp)
1020{
1021 union gtp_packet packet;
1022 unsigned int length =
1023 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1024 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001025
Harald Weltebed35df2011-11-02 13:06:18 +01001026 /* TODO: Secondary PDP Context Activation Procedure */
1027 /* In secondary activation procedure the PDP context is identified
1028 by tei in the header. The following fields are omitted: Selection
1029 mode, IMSI, MSISDN, End User Address, Access Point Name and
1030 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001031
Harald Weltebed35df2011-11-02 13:06:18 +01001032 if (pdp->secondary) {
1033 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001034 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001035 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001036 return EOF;
1037 }
1038 }
jjako2c381332003-10-21 19:09:53 +00001039
Harald Weltebed35df2011-11-02 13:06:18 +01001040 if (pdp->version == 0) {
1041 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1042 sizeof(pdp->qos_req0), pdp->qos_req0);
1043 }
jjako52c24142002-12-16 13:33:51 +00001044
Harald Weltebed35df2011-11-02 13:06:18 +01001045 /* Section 7.7.2 */
1046 if (pdp->version == 1) {
1047 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1048 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1049 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1050 }
jjako52c24142002-12-16 13:33:51 +00001051
Harald Weltebed35df2011-11-02 13:06:18 +01001052 /* Section 7.7.3 Routing Area Information */
1053 if (pdp->rai_given == 1)
1054 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1055 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001056
Harald Weltebed35df2011-11-02 13:06:18 +01001057 /* Section 7.7.11 */
1058 if (pdp->norecovery_given == 0)
1059 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1060 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001061
Harald Weltebed35df2011-11-02 13:06:18 +01001062 /* Section 7.7.12 */
1063 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1064 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1065 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001066
Harald Weltebed35df2011-11-02 13:06:18 +01001067 if (pdp->version == 0) {
1068 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1069 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1070 }
jjako08d331d2003-10-13 20:33:30 +00001071
Harald Weltebed35df2011-11-02 13:06:18 +01001072 /* Section 7.7.13 */
1073 if (pdp->version == 1) {
1074 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1075 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001076
Harald Weltebed35df2011-11-02 13:06:18 +01001077 /* Section 7.7.14 */
1078 if (!pdp->teic_confirmed)
1079 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1080 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001081
Harald Weltebed35df2011-11-02 13:06:18 +01001082 /* Section 7.7.17 */
1083 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001084
Harald Weltebed35df2011-11-02 13:06:18 +01001085 /* Section 7.7.17 */
1086 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1087 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1088 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001089
Harald Weltebed35df2011-11-02 13:06:18 +01001090 /* Section 7.7.23 */
1091 if (pdp->cch_pdp) /* Only include charging if flags are set */
1092 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1093 pdp->cch_pdp);
1094 }
jjako9b4971d2004-05-27 20:30:19 +00001095
Harald Weltebed35df2011-11-02 13:06:18 +01001096 /* TODO
1097 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1098 pdp->traceref);
1099 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1100 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001101
Harald Weltebed35df2011-11-02 13:06:18 +01001102 /* Section 7.7.27 */
1103 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1104 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1105 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001106
Harald Weltebed35df2011-11-02 13:06:18 +01001107 /* Section 7.7.30 */
1108 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1109 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1110 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001111
Harald Weltebed35df2011-11-02 13:06:18 +01001112 /* Section 7.7.31 */
1113 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1114 if (pdp->pco_req.l)
1115 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1116 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001117
Harald Weltebed35df2011-11-02 13:06:18 +01001118 /* Section 7.7.32 */
1119 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1120 pdp->gsnlc.l, pdp->gsnlc.v);
1121 /* Section 7.7.32 */
1122 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1123 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001124
Harald Weltebed35df2011-11-02 13:06:18 +01001125 /* Section 7.7.33 */
1126 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1127 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1128 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001129
Harald Weltebed35df2011-11-02 13:06:18 +01001130 /* Section 7.7.34 */
1131 if (pdp->version == 1)
1132 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1133 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001134
Harald Weltebed35df2011-11-02 13:06:18 +01001135 /* Section 7.7.36 */
1136 if ((pdp->version == 1) && pdp->tft.l)
1137 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1138 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001139
Harald Weltebed35df2011-11-02 13:06:18 +01001140 /* Section 7.7.41 */
1141 if ((pdp->version == 1) && pdp->triggerid.l)
1142 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1143 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001144
Harald Weltebed35df2011-11-02 13:06:18 +01001145 /* Section 7.7.42 */
1146 if ((pdp->version == 1) && pdp->omcid.l)
1147 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1148 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001149
Harald Weltebed35df2011-11-02 13:06:18 +01001150 /* new R7 fields */
1151 if (pdp->rattype_given == 1)
1152 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1153 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001154
Harald Weltebed35df2011-11-02 13:06:18 +01001155 if (pdp->userloc_given == 1)
1156 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1157 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001158
Harald Weltebed35df2011-11-02 13:06:18 +01001159 if (pdp->mstz_given == 1)
1160 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1161 pdp->mstz.l, pdp->mstz.v);
1162
1163 if (pdp->imeisv_given == 1)
1164 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1165 pdp->imeisv.l, pdp->imeisv.v);
1166
1167 /* TODO hisaddr0 */
1168 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1169
1170 return 0;
jjako52c24142002-12-16 13:33:51 +00001171}
1172
jjako08d331d2003-10-13 20:33:30 +00001173/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001174int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1175{
jjako08d331d2003-10-13 20:33:30 +00001176
Harald Weltebed35df2011-11-02 13:06:18 +01001177 /* Now send off a reply to the peer */
1178 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1179
1180 if (cause != GTPCAUSE_ACC_REQ) {
1181 pdp_freepdp(pdp);
1182 }
1183
1184 return 0;
jjako08d331d2003-10-13 20:33:30 +00001185}
1186
1187/* API: Register create context indication callback */
1188int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001189 int (*cb_create_context_ind) (struct pdp_t *
1190 pdp))
jjako52c24142002-12-16 13:33:51 +00001191{
Harald Weltebed35df2011-11-02 13:06:18 +01001192 gsn->cb_create_context_ind = cb_create_context_ind;
1193 return 0;
jjako08d331d2003-10-13 20:33:30 +00001194}
1195
jjako08d331d2003-10-13 20:33:30 +00001196/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001197int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1198 uint8_t cause)
1199{
1200 union gtp_packet packet;
1201 unsigned int length =
1202 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001203
Harald Weltebed35df2011-11-02 13:06:18 +01001204 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001205
Harald Weltebed35df2011-11-02 13:06:18 +01001206 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001207
Harald Weltebed35df2011-11-02 13:06:18 +01001208 if (version == 0)
1209 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1210 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001211
Harald Weltebed35df2011-11-02 13:06:18 +01001212 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1213 pdp->reorder);
1214 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1215 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001216
Harald Weltebed35df2011-11-02 13:06:18 +01001217 if (version == 0) {
1218 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1219 pdp->fllu);
1220 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1221 pdp->fllc);
1222 }
jjako08d331d2003-10-13 20:33:30 +00001223
Harald Weltebed35df2011-11-02 13:06:18 +01001224 if (version == 1) {
1225 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1226 pdp->teid_own);
1227 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1228 pdp->teic_own);
1229 }
jjako08d331d2003-10-13 20:33:30 +00001230
Harald Weltebed35df2011-11-02 13:06:18 +01001231 /* TODO: We use teic_own as charging ID */
1232 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1233 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001234
Harald Weltebed35df2011-11-02 13:06:18 +01001235 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1236 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001237
Harald Weltebed35df2011-11-02 13:06:18 +01001238 if (pdp->pco_neg.l) { /* Optional PCO */
1239 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1240 pdp->pco_neg.l, pdp->pco_neg.v);
1241 }
jjako52c24142002-12-16 13:33:51 +00001242
Harald Weltebed35df2011-11-02 13:06:18 +01001243 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1244 pdp->gsnlc.l, pdp->gsnlc.v);
1245 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1246 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001247
Harald Weltebed35df2011-11-02 13:06:18 +01001248 if (version == 1)
1249 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1250 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001251
Harald Weltebed35df2011-11-02 13:06:18 +01001252 /* TODO: Charging gateway address */
1253 }
jjako52c24142002-12-16 13:33:51 +00001254
Harald Weltebed35df2011-11-02 13:06:18 +01001255 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1256 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001257}
1258
1259/* Handle Create PDP Context Request */
1260int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001261 struct sockaddr_in *peer, int fd,
1262 void *pack, unsigned len)
1263{
1264 struct pdp_t *pdp, *pdp_old;
1265 struct pdp_t pdp_buf;
1266 union gtpie_member *ie[GTPIE_SIZE];
1267 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001268
Harald Weltebed35df2011-11-02 13:06:18 +01001269 uint16_t seq = get_seq(pack);
1270 int hlen = get_hlen(pack);
1271 uint8_t linked_nsapi = 0;
1272 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001273
Harald Weltebed35df2011-11-02 13:06:18 +01001274 if (!gtp_dublicate(gsn, version, peer, seq))
1275 return 0;
jjako08d331d2003-10-13 20:33:30 +00001276
Harald Weltebed35df2011-11-02 13:06:18 +01001277 pdp = &pdp_buf;
1278 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001279
Harald Weltebed35df2011-11-02 13:06:18 +01001280 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001281 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1282
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001283 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001284 }
jjako52c24142002-12-16 13:33:51 +00001285
Harald Weltebed35df2011-11-02 13:06:18 +01001286 pdp->seq = seq;
1287 pdp->sa_peer = *peer;
1288 pdp->fd = fd;
1289 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001290
Harald Weltebed35df2011-11-02 13:06:18 +01001291 /* Decode information elements */
1292 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1293 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001294 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1295 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001296 if (0 == version)
1297 return EOF;
1298 else
1299 return gtp_create_pdp_resp(gsn, version, pdp,
1300 GTPCAUSE_INVALID_MESSAGE);
1301 }
jjako52c24142002-12-16 13:33:51 +00001302
Harald Weltebed35df2011-11-02 13:06:18 +01001303 if (version == 1) {
1304 /* Linked NSAPI (conditional) */
1305 /* If included this is the Secondary PDP Context Activation Procedure */
1306 /* In secondary activation IMSI is not included, so the context must be */
1307 /* identified by the tei */
1308 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001309
Harald Weltebed35df2011-11-02 13:06:18 +01001310 /* Find the primary PDP context */
1311 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1312 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001313 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001314 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001315 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001316 return gtp_create_pdp_resp(gsn, version, pdp,
1317 GTPCAUSE_OPT_IE_INCORRECT);
1318 }
jjako2c381332003-10-21 19:09:53 +00001319
Harald Weltebed35df2011-11-02 13:06:18 +01001320 /* Check that the primary PDP context matches linked nsapi */
1321 if (linked_pdp->nsapi != linked_nsapi) {
1322 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001323 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001324 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001325 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001326 return gtp_create_pdp_resp(gsn, version, pdp,
1327 GTPCAUSE_OPT_IE_INCORRECT);
1328 }
jjako52c24142002-12-16 13:33:51 +00001329
Harald Weltebed35df2011-11-02 13:06:18 +01001330 /* Copy parameters from primary context */
1331 pdp->selmode = linked_pdp->selmode;
1332 pdp->imsi = linked_pdp->imsi;
1333 pdp->msisdn = linked_pdp->msisdn;
1334 pdp->eua = linked_pdp->eua;
1335 pdp->pco_req = linked_pdp->pco_req;
1336 pdp->apn_req = linked_pdp->apn_req;
1337 pdp->teic_gn = linked_pdp->teic_gn;
1338 pdp->secondary = 1;
1339 }
1340 }
1341 /* if (version == 1) */
1342 if (version == 0) {
1343 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1344 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1345 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001346 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1347 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001348 return gtp_create_pdp_resp(gsn, version, pdp,
1349 GTPCAUSE_MAN_IE_MISSING);
1350 }
1351 }
jjako08d331d2003-10-13 20:33:30 +00001352
Harald Weltebed35df2011-11-02 13:06:18 +01001353 if ((version == 1) && (!linked_pdp)) {
1354 /* Not Secondary PDP Context Activation Procedure */
1355 /* IMSI (conditional) */
1356 if (gtpie_gettv0
1357 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1358 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001359 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1360 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001361 return gtp_create_pdp_resp(gsn, version, pdp,
1362 GTPCAUSE_MAN_IE_MISSING);
1363 }
1364 }
jjako52c24142002-12-16 13:33:51 +00001365
Harald Weltebed35df2011-11-02 13:06:18 +01001366 /* Recovery (optional) */
1367 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1368 if (gsn->cb_recovery)
1369 gsn->cb_recovery(peer, recovery);
1370 }
jjako52c24142002-12-16 13:33:51 +00001371
Harald Weltebed35df2011-11-02 13:06:18 +01001372 /* Selection mode (conditional) */
1373 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1374 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1375 &pdp->selmode, sizeof(pdp->selmode))) {
1376 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001377 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1378 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001379 return gtp_create_pdp_resp(gsn, version, pdp,
1380 GTPCAUSE_MAN_IE_MISSING);
1381 }
1382 }
jjako52c24142002-12-16 13:33:51 +00001383
Harald Weltebed35df2011-11-02 13:06:18 +01001384 if (version == 0) {
1385 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1386 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001387 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1388 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001389 return gtp_create_pdp_resp(gsn, version, pdp,
1390 GTPCAUSE_MAN_IE_MISSING);
1391 }
jjako52c24142002-12-16 13:33:51 +00001392
Harald Weltebed35df2011-11-02 13:06:18 +01001393 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1394 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001395 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1396 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001397 return gtp_create_pdp_resp(gsn, version, pdp,
1398 GTPCAUSE_MAN_IE_MISSING);
1399 }
1400 }
jjako08d331d2003-10-13 20:33:30 +00001401
Harald Weltebed35df2011-11-02 13:06:18 +01001402 if (version == 1) {
1403 /* TEID (mandatory) */
1404 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1405 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001406 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1407 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001408 return gtp_create_pdp_resp(gsn, version, pdp,
1409 GTPCAUSE_MAN_IE_MISSING);
1410 }
jjako2c381332003-10-21 19:09:53 +00001411
Harald Weltebed35df2011-11-02 13:06:18 +01001412 /* TEIC (conditional) */
1413 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1414 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1415 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001416 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001417 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001418 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001419 return gtp_create_pdp_resp(gsn, version, pdp,
1420 GTPCAUSE_MAN_IE_MISSING);
1421 }
1422 }
jjako08d331d2003-10-13 20:33:30 +00001423
Harald Weltebed35df2011-11-02 13:06:18 +01001424 /* NSAPI (mandatory) */
1425 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1426 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001427 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1428 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001429 return gtp_create_pdp_resp(gsn, version, pdp,
1430 GTPCAUSE_MAN_IE_MISSING);
1431 }
1432 }
jjako2e840a32003-01-28 16:05:18 +00001433
Harald Weltebed35df2011-11-02 13:06:18 +01001434 /* Charging Characteriatics (optional) */
1435 /* Trace reference (optional) */
1436 /* Trace type (optional) */
1437 /* Charging Characteriatics (optional) */
jjako52c24142002-12-16 13:33:51 +00001438
Harald Weltebed35df2011-11-02 13:06:18 +01001439 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1440 /* End User Address (conditional) */
1441 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1442 &pdp->eua.v, sizeof(pdp->eua.v))) {
1443 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001444 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1445 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001446 return gtp_create_pdp_resp(gsn, version, pdp,
1447 GTPCAUSE_MAN_IE_MISSING);
1448 }
jjako08d331d2003-10-13 20:33:30 +00001449
Harald Weltebed35df2011-11-02 13:06:18 +01001450 /* APN */
1451 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1452 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1453 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001454 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1455 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001456 return gtp_create_pdp_resp(gsn, version, pdp,
1457 GTPCAUSE_MAN_IE_MISSING);
1458 }
jjako2c381332003-10-21 19:09:53 +00001459
Harald Weltebed35df2011-11-02 13:06:18 +01001460 /* Extract protocol configuration options (optional) */
1461 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1462 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1463 }
1464 }
jjako2c381332003-10-21 19:09:53 +00001465
Harald Weltebed35df2011-11-02 13:06:18 +01001466 /* SGSN address for signalling (mandatory) */
1467 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1468 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1469 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001470 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1471 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001472 return gtp_create_pdp_resp(gsn, version, pdp,
1473 GTPCAUSE_MAN_IE_MISSING);
1474 }
jjako2e840a32003-01-28 16:05:18 +00001475
Harald Weltebed35df2011-11-02 13:06:18 +01001476 /* SGSN address for user traffic (mandatory) */
1477 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1478 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1479 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001480 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1481 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001482 return gtp_create_pdp_resp(gsn, version, pdp,
1483 GTPCAUSE_MAN_IE_MISSING);
1484 }
jjako52c24142002-12-16 13:33:51 +00001485
Harald Weltebed35df2011-11-02 13:06:18 +01001486 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1487 /* MSISDN (conditional) */
1488 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1489 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1490 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001491 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1492 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001493 return gtp_create_pdp_resp(gsn, version, pdp,
1494 GTPCAUSE_MAN_IE_MISSING);
1495 }
1496 }
jjako52c24142002-12-16 13:33:51 +00001497
Harald Weltebed35df2011-11-02 13:06:18 +01001498 if (version == 1) {
1499 /* QoS (mandatory) */
1500 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1501 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1502 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001503 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1504 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001505 return gtp_create_pdp_resp(gsn, version, pdp,
1506 GTPCAUSE_MAN_IE_MISSING);
1507 }
1508
1509 /* TFT (conditional) */
1510 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1511 &pdp->tft.v, sizeof(pdp->tft.v))) {
1512 }
1513
1514 /* Trigger ID */
1515 /* OMC identity */
1516 }
1517
1518 /* Initialize our own IP addresses */
1519 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1520 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1521
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001522 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001523
1524 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1525 /* Found old pdp with same tid. Now the voodoo begins! */
1526 /* 09.60 / 29.060 allows create on existing context to "steal" */
1527 /* the context which was allready established */
1528 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001529 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001530 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1531 &&
1532 (!memcmp
1533 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1534 && (pdp->selmode == pdp_old->selmode)
1535 && (pdp->msisdn.l == pdp_old->msisdn.l)
1536 &&
1537 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1538 {
1539 /* OK! We are dealing with the same APN. We will copy new
1540 * parameters to the old pdp and send off confirmation
1541 * We ignore the following information elements:
1542 * QoS: MS will get originally negotiated QoS.
1543 * End user address (EUA). MS will get old EUA anyway.
1544 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001545 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001546
1547 /* Copy remote flow label */
1548 pdp_old->flru = pdp->flru;
1549 pdp_old->flrc = pdp->flrc;
1550
1551 /* Copy remote tei */
1552 pdp_old->teid_gn = pdp->teid_gn;
1553 pdp_old->teic_gn = pdp->teic_gn;
1554
1555 /* Copy peer GSN address */
1556 pdp_old->gsnrc.l = pdp->gsnrc.l;
1557 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1558 pdp_old->gsnru.l = pdp->gsnru.l;
1559 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1560
1561 /* Copy request parameters */
1562 pdp_old->seq = pdp->seq;
1563 pdp_old->sa_peer = pdp->sa_peer;
1564 pdp_old->fd = pdp->fd = fd;
1565 pdp_old->version = pdp->version = version;
1566
1567 /* Switch to using the old pdp context */
1568 pdp = pdp_old;
1569
1570 /* Confirm to peer that things were "successful" */
1571 return gtp_create_pdp_resp(gsn, version, pdp,
1572 GTPCAUSE_ACC_REQ);
1573 } else { /* This is not the same PDP context. Delete the old one. */
1574
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001575 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001576
1577 if (gsn->cb_delete_context)
1578 gsn->cb_delete_context(pdp_old);
1579 pdp_freepdp(pdp_old);
1580
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001581 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001582 }
1583 }
1584
1585 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
Harald Weltee257be12017-08-12 14:55:09 +02001586 if (pdp)
1587 pdp->gsn = gsn;
Harald Weltebed35df2011-11-02 13:06:18 +01001588
1589 /* Callback function to validata login */
1590 if (gsn->cb_create_context_ind != 0)
1591 return gsn->cb_create_context_ind(pdp);
1592 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001593 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1594 "No create_context_ind callback defined\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001595 return gtp_create_pdp_resp(gsn, version, pdp,
1596 GTPCAUSE_NOT_SUPPORTED);
1597 }
jjako52c24142002-12-16 13:33:51 +00001598}
1599
jjako52c24142002-12-16 13:33:51 +00001600/* Handle Create PDP Context Response */
1601int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001602 struct sockaddr_in *peer, void *pack, unsigned len)
1603{
1604 struct pdp_t *pdp;
1605 union gtpie_member *ie[GTPIE_SIZE];
1606 uint8_t cause, recovery;
1607 void *cbp = NULL;
1608 uint8_t type = 0;
1609 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001610
Harald Weltebed35df2011-11-02 13:06:18 +01001611 /* Remove packet from queue */
1612 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1613 return EOF;
jjako52c24142002-12-16 13:33:51 +00001614
Harald Weltebed35df2011-11-02 13:06:18 +01001615 /* Find the context in question */
1616 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1617 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001618 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001619 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001620 if (gsn->cb_conf)
1621 gsn->cb_conf(type, EOF, NULL, cbp);
1622 return EOF;
1623 }
jjako2c381332003-10-21 19:09:53 +00001624
Harald Weltebed35df2011-11-02 13:06:18 +01001625 /* Register that we have received a valid teic from GGSN */
1626 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001627
Harald Weltebed35df2011-11-02 13:06:18 +01001628 /* Decode information elements */
1629 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1630 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001631 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1632 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001633 if (gsn->cb_conf)
1634 gsn->cb_conf(type, EOF, pdp, cbp);
1635 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1636 pdp_freepdp(pdp); */
1637 return EOF;
1638 }
jjako52c24142002-12-16 13:33:51 +00001639
Harald Weltebed35df2011-11-02 13:06:18 +01001640 /* Extract cause value (mandatory) */
1641 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1642 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001643 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1644 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001645 if (gsn->cb_conf)
1646 gsn->cb_conf(type, EOF, pdp, cbp);
1647 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1648 pdp_freepdp(pdp); */
1649 return EOF;
1650 }
jjako52c24142002-12-16 13:33:51 +00001651
Harald Weltebed35df2011-11-02 13:06:18 +01001652 /* Extract recovery (optional) */
1653 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1654 if (gsn->cb_recovery)
1655 gsn->cb_recovery(peer, recovery);
1656 }
jjako52c24142002-12-16 13:33:51 +00001657
Harald Weltebed35df2011-11-02 13:06:18 +01001658 /* Extract protocol configuration options (optional) */
1659 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1660 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1661 }
jjako52c24142002-12-16 13:33:51 +00001662
Harald Weltebed35df2011-11-02 13:06:18 +01001663 /* Check all conditional information elements */
1664 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001665
Harald Weltebed35df2011-11-02 13:06:18 +01001666 if (version == 0) {
1667 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1668 &pdp->qos_neg0,
1669 sizeof(pdp->qos_neg0))) {
1670 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001671 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001672 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001673 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001674 if (gsn->cb_conf)
1675 gsn->cb_conf(type, EOF, pdp, cbp);
1676 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1677 pdp_freepdp(pdp); */
1678 return EOF;
1679 }
1680 }
jjako08d331d2003-10-13 20:33:30 +00001681
Harald Weltebed35df2011-11-02 13:06:18 +01001682 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1683 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001684 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001685 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001686 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001687 if (gsn->cb_conf)
1688 gsn->cb_conf(type, EOF, pdp, cbp);
1689 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1690 pdp_freepdp(pdp); */
1691 return EOF;
1692 }
jjako52c24142002-12-16 13:33:51 +00001693
Harald Weltebed35df2011-11-02 13:06:18 +01001694 if (version == 0) {
1695 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1696 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001697 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001698 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001699 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001700 if (gsn->cb_conf)
1701 gsn->cb_conf(type, EOF, pdp, cbp);
1702 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1703 pdp_freepdp(pdp); */
1704 return EOF;
1705 }
jjako52c24142002-12-16 13:33:51 +00001706
Harald Weltebed35df2011-11-02 13:06:18 +01001707 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1708 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001709 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001710 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001711 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001712 if (gsn->cb_conf)
1713 gsn->cb_conf(type, EOF, pdp, cbp);
1714 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1715 pdp_freepdp(pdp); */
1716 return EOF;
1717 }
1718 }
1719
1720 if (version == 1) {
1721 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1722 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001723 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001724 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001725 "Missing conditional information field\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 }
1732
1733 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1734 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001735 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001736 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001737 "Missing conditional 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 }
1744 }
1745
1746 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1747 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001748 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001749 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001750 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001751 if (gsn->cb_conf)
1752 gsn->cb_conf(type, EOF, pdp, cbp);
1753 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1754 pdp_freepdp(pdp); */
1755 }
1756
1757 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1758 &pdp->eua.v, sizeof(pdp->eua.v))) {
1759 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001760 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001761 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001762 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001763 if (gsn->cb_conf)
1764 gsn->cb_conf(type, EOF, pdp, cbp);
1765 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1766 pdp_freepdp(pdp); */
1767 return EOF;
1768 }
1769
1770 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1771 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1772 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001773 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001774 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001775 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001776 if (gsn->cb_conf)
1777 gsn->cb_conf(type, EOF, pdp, cbp);
1778 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1779 pdp_freepdp(pdp); */
1780 return EOF;
1781 }
1782
1783 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1784 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1785 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001786 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001787 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001788 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001789 if (gsn->cb_conf)
1790 gsn->cb_conf(type, EOF, pdp, cbp);
1791 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1792 pdp_freepdp(pdp); */
1793 return EOF;
1794 }
1795
1796 if (version == 1) {
1797 if (gtpie_gettlv
1798 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1799 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
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 }
1813
1814 if (gsn->cb_conf)
1815 gsn->cb_conf(type, cause, pdp, cbp);
1816
1817 return 0;
jjako52c24142002-12-16 13:33:51 +00001818}
1819
jjako08d331d2003-10-13 20:33:30 +00001820/* API: Send Update PDP Context Request */
1821int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001822 struct in_addr *inetaddr)
1823{
1824 union gtp_packet packet;
1825 unsigned int length =
1826 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001827
Harald Weltebed35df2011-11-02 13:06:18 +01001828 if (pdp->version == 0)
1829 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1830 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001831
Harald Weltebed35df2011-11-02 13:06:18 +01001832 /* Include IMSI if updating with unknown teic_gn */
1833 if ((pdp->version == 1) && (!pdp->teic_gn))
1834 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1835 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1836
1837 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1838 gsn->restart_counter);
1839
1840 if (pdp->version == 0) {
1841 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1842 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1843 }
1844
1845 if (pdp->version == 1) {
1846 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1847 pdp->teid_own);
1848
1849 if (!pdp->teic_confirmed)
1850 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1851 pdp->teic_own);
1852 }
1853
1854 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1855
1856 /* TODO
1857 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1858 pdp->traceref);
1859 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1860 pdp->tracetype); */
1861
1862 /* TODO if ggsn update message
1863 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1864 pdp->eua.l, pdp->eua.v);
1865 */
1866
1867 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1868 pdp->gsnlc.l, pdp->gsnlc.v);
1869 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1870 pdp->gsnlu.l, pdp->gsnlu.v);
1871
1872 if (pdp->version == 1)
1873 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1874 pdp->qos_req.l, pdp->qos_req.v);
1875
1876 if ((pdp->version == 1) && pdp->tft.l)
1877 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1878 pdp->tft.l, pdp->tft.v);
1879
1880 if ((pdp->version == 1) && pdp->triggerid.l)
1881 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1882 pdp->triggerid.l, pdp->triggerid.v);
1883
1884 if ((pdp->version == 1) && pdp->omcid.l)
1885 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1886 pdp->omcid.l, pdp->omcid.v);
1887
Daniel Willmann134a7752016-02-03 18:53:29 +01001888 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001889
1890 return 0;
jjako52c24142002-12-16 13:33:51 +00001891}
1892
jjako08d331d2003-10-13 20:33:30 +00001893/* Send Update PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001894int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
1895 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001896 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001897 struct pdp_t *pdp, uint8_t cause)
1898{
jjako08d331d2003-10-13 20:33:30 +00001899
Harald Weltebed35df2011-11-02 13:06:18 +01001900 union gtp_packet packet;
1901 unsigned int length =
1902 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001903
Harald Weltebed35df2011-11-02 13:06:18 +01001904 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001905
Harald Weltebed35df2011-11-02 13:06:18 +01001906 if (cause == GTPCAUSE_ACC_REQ) {
1907
1908 if (version == 0)
1909 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1910 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1911
1912 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1913 gsn->restart_counter);
1914
1915 if (version == 0) {
1916 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1917 pdp->fllu);
1918 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1919 pdp->fllc);
1920 }
1921
1922 if (version == 1) {
1923 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1924 pdp->teid_own);
1925
1926 if (!pdp->teic_confirmed)
1927 gtpie_tv4(&packet, &length, GTP_MAX,
1928 GTPIE_TEI_C, pdp->teic_own);
1929 }
1930
1931 /* TODO we use teid_own as charging ID address */
1932 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1933 pdp->teid_own);
1934
1935 /* If ggsn
1936 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1937 pdp->eua.l, pdp->eua.v); */
1938
1939 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1940 pdp->gsnlc.l, pdp->gsnlc.v);
1941 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1942 pdp->gsnlu.l, pdp->gsnlu.v);
1943
1944 if (version == 1)
1945 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1946 pdp->qos_neg.l, pdp->qos_neg.v);
1947
1948 /* TODO: Charging gateway address */
1949 }
1950
1951 return gtp_resp(version, gsn, pdp, &packet, length, peer,
1952 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00001953}
1954
jjako52c24142002-12-16 13:33:51 +00001955/* Handle Update PDP Context Request */
1956int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001957 struct sockaddr_in *peer, int fd,
1958 void *pack, unsigned len)
1959{
1960 struct pdp_t *pdp;
1961 struct pdp_t pdp_backup;
1962 union gtpie_member *ie[GTPIE_SIZE];
1963 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001964
Harald Weltebed35df2011-11-02 13:06:18 +01001965 uint16_t seq = get_seq(pack);
1966 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001967
Harald Weltebed35df2011-11-02 13:06:18 +01001968 uint64_t imsi;
1969 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00001970
Harald Weltebed35df2011-11-02 13:06:18 +01001971 /* Is this a dublicate ? */
1972 if (!gtp_dublicate(gsn, version, peer, seq)) {
1973 return 0; /* We allready send of response once */
1974 }
jjako08d331d2003-10-13 20:33:30 +00001975
Harald Weltebed35df2011-11-02 13:06:18 +01001976 /* Decode information elements */
1977 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1978 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001979 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1980 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001981 if (0 == version)
1982 return EOF;
1983 else
1984 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
1985 len, NULL,
1986 GTPCAUSE_INVALID_MESSAGE);
1987 }
jjako08d331d2003-10-13 20:33:30 +00001988
Harald Weltebed35df2011-11-02 13:06:18 +01001989 /* Finding PDP: */
1990 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
1991 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
1992 /* we have to use the tunnel endpoint identifier */
1993 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001994 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1995
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001996 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00001997
Harald Weltebed35df2011-11-02 13:06:18 +01001998 /* Find the context in question */
1999 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2000 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002001 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2002 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002003 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2004 len, NULL,
2005 GTPCAUSE_NON_EXIST);
2006 }
2007 } else if (version == 1) {
2008 /* NSAPI (mandatory) */
2009 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2010 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002011 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2012 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002013 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2014 len, NULL,
2015 GTPCAUSE_MAN_IE_MISSING);
2016 }
jjako08d331d2003-10-13 20:33:30 +00002017
Harald Weltebed35df2011-11-02 13:06:18 +01002018 /* IMSI (conditional) */
2019 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2020 /* Find the context in question */
2021 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2022 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002023 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002024 pack, len, "Unknown PDP context: %u\n",
2025 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002026 return gtp_update_pdp_resp(gsn, version, peer,
2027 fd, pack, len, NULL,
2028 GTPCAUSE_NON_EXIST);
2029 }
2030 } else {
2031 /* Find the context in question */
2032 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2033 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002034 GTP_LOGPKG(LOGL_ERROR, peer,
2035 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002036 return gtp_update_pdp_resp(gsn, version, peer,
2037 fd, pack, len, NULL,
2038 GTPCAUSE_NON_EXIST);
2039 }
2040 }
2041 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002042 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002043 return EOF;
2044 }
jjako08d331d2003-10-13 20:33:30 +00002045
Harald Weltebed35df2011-11-02 13:06:18 +01002046 /* Make a backup copy in case anything is wrong */
2047 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002048
Harald Weltebed35df2011-11-02 13:06:18 +01002049 if (version == 0) {
2050 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2051 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2052 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002053 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2054 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002055 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2056 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2057 len, pdp,
2058 GTPCAUSE_MAN_IE_MISSING);
2059 }
2060 }
jjako52c24142002-12-16 13:33:51 +00002061
Harald Weltebed35df2011-11-02 13:06:18 +01002062 /* Recovery (optional) */
2063 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2064 if (gsn->cb_recovery)
2065 gsn->cb_recovery(peer, recovery);
2066 }
jjako08d331d2003-10-13 20:33:30 +00002067
Harald Weltebed35df2011-11-02 13:06:18 +01002068 if (version == 0) {
2069 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2070 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002071 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2072 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002073 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2074 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2075 len, pdp,
2076 GTPCAUSE_MAN_IE_MISSING);
2077 }
jjako52c24142002-12-16 13:33:51 +00002078
Harald Weltebed35df2011-11-02 13:06:18 +01002079 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2080 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002081 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2082 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002083 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2084 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2085 len, pdp,
2086 GTPCAUSE_MAN_IE_MISSING);
2087 }
2088 }
jjako52c24142002-12-16 13:33:51 +00002089
Harald Weltebed35df2011-11-02 13:06:18 +01002090 if (version == 1) {
2091 /* TEID (mandatory) */
2092 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2093 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002094 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2095 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002096 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2097 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2098 len, pdp,
2099 GTPCAUSE_MAN_IE_MISSING);
2100 }
jjako52c24142002-12-16 13:33:51 +00002101
Harald Weltebed35df2011-11-02 13:06:18 +01002102 /* TEIC (conditional) */
2103 /* If TEIC is not included it means that we have allready received it */
2104 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2105 /* all updated contexts, or only for one of the linked contexts */
2106 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2107
2108 /* NSAPI (mandatory) */
2109 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2110 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002111 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2112 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002113 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2114 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2115 len, pdp,
2116 GTPCAUSE_MAN_IE_MISSING);
2117 }
2118 }
2119
2120 /* Trace reference (optional) */
2121 /* Trace type (optional) */
2122
2123 /* End User Address (conditional) TODO: GGSN Initiated
2124 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2125 &pdp->eua.v, sizeof(pdp->eua.v))) {
2126 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002127 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002128 "Missing mandatory information field");
2129 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2130 return gtp_update_pdp_resp(gsn, version, pdp,
2131 GTPCAUSE_MAN_IE_MISSING);
2132 } */
2133
2134 /* SGSN address for signalling (mandatory) */
2135 /* It is weird that this is mandatory when TEIC is conditional */
2136 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2137 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2138 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002139 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2140 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002141 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2142 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2143 pdp, GTPCAUSE_MAN_IE_MISSING);
2144 }
2145
2146 /* SGSN address for user traffic (mandatory) */
2147 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2148 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2149 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002150 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2151 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002152 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2153 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2154 pdp, GTPCAUSE_MAN_IE_MISSING);
2155 }
2156
2157 if (version == 1) {
2158 /* QoS (mandatory) */
2159 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2160 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
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 }
2169
2170 /* TFT (conditional) */
2171 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2172 &pdp->tft.v, sizeof(pdp->tft.v))) {
2173 }
2174
2175 /* OMC identity */
2176 }
2177
2178 /* Confirm to peer that things were "successful" */
2179 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2180 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002181}
2182
jjako52c24142002-12-16 13:33:51 +00002183/* Handle Update PDP Context Response */
2184int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002185 struct sockaddr_in *peer, void *pack, unsigned len)
2186{
2187 struct pdp_t *pdp;
2188 union gtpie_member *ie[GTPIE_SIZE];
2189 uint8_t cause, recovery;
2190 void *cbp = NULL;
2191 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002192 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002193
Harald Weltebed35df2011-11-02 13:06:18 +01002194 /* Remove packet from queue */
2195 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2196 return EOF;
jjako52c24142002-12-16 13:33:51 +00002197
Harald Weltebed35df2011-11-02 13:06:18 +01002198 /* Find the context in question */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002199 if (pdp_getgtp1(&pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002200 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002201 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002202 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002203 pdp = NULL;
2204 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002205 }
jjako2c381332003-10-21 19:09:53 +00002206
Harald Weltebed35df2011-11-02 13:06:18 +01002207 /* Register that we have received a valid teic from GGSN */
2208 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002209
Harald Weltebed35df2011-11-02 13:06:18 +01002210 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002211 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002212 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002213 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2214 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002215 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002216 }
jjako52c24142002-12-16 13:33:51 +00002217
Harald Weltebed35df2011-11-02 13:06:18 +01002218 /* Extract cause value (mandatory) */
2219 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002220 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002221 }
jjako52c24142002-12-16 13:33:51 +00002222
Harald Weltebed35df2011-11-02 13:06:18 +01002223 /* Extract recovery (optional) */
2224 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2225 if (gsn->cb_recovery)
2226 gsn->cb_recovery(peer, recovery);
2227 }
2228
2229 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002230 /* TODO: This does not handle GGSN-initiated update responses */
2231 if (GTPCAUSE_ACC_REQ == cause) {
2232 if (version == 0) {
2233 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2234 &pdp->qos_neg0,
2235 sizeof(pdp->qos_neg0))) {
2236 goto err_missing;
2237 }
2238
2239 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2240 goto err_missing;
2241 }
2242
2243 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2244 goto err_missing;
2245 }
Harald Weltebed35df2011-11-02 13:06:18 +01002246 }
2247
Daniel Willmannd9975522016-02-04 15:38:12 +01002248 if (version == 1) {
2249 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2250 goto err_missing;
2251 }
Harald Weltebed35df2011-11-02 13:06:18 +01002252
Daniel Willmannd9975522016-02-04 15:38:12 +01002253 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2254 goto err_missing;
2255 }
2256 }
2257
2258 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2259 goto err_missing;
2260 }
2261
2262 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2263 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2264 goto err_missing;
2265 }
2266
2267 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2268 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2269 goto err_missing;
2270 }
2271
2272 if (version == 1) {
2273 if (gtpie_gettlv
2274 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2275 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2276 goto err_missing;
2277 }
2278 }
Harald Weltebed35df2011-11-02 13:06:18 +01002279 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002280
2281 if (gsn->cb_conf)
2282 gsn->cb_conf(type, cause, pdp, cbp);
2283 return 0; /* Succes */
2284
2285err_missing:
2286 gsn->missing++;
2287 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2288 "Missing information field\n");
2289err_out:
2290 if (gsn->cb_conf)
2291 gsn->cb_conf(type, EOF, pdp, cbp);
2292 return EOF;
jjako52c24142002-12-16 13:33:51 +00002293}
2294
jjako08d331d2003-10-13 20:33:30 +00002295/* API: Send Delete PDP Context Request */
jjako2c381332003-10-21 19:09:53 +00002296int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002297 int teardown)
2298{
2299 union gtp_packet packet;
2300 unsigned int length =
2301 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2302 struct in_addr addr;
2303 struct pdp_t *linked_pdp;
2304 struct pdp_t *secondary_pdp;
2305 int n;
2306 int count = 0;
jjako2c381332003-10-21 19:09:53 +00002307
Harald Weltebed35df2011-11-02 13:06:18 +01002308 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2309 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002310 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002311 return EOF;
jjako2c381332003-10-21 19:09:53 +00002312 }
jjako2c381332003-10-21 19:09:53 +00002313
Harald Weltebed35df2011-11-02 13:06:18 +01002314 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002315 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002316 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002317 return EOF;
2318 }
2319
2320 if (!teardown) {
2321 for (n = 0; n < PDP_MAXNSAPI; n++)
2322 if (linked_pdp->secondary_tei[n])
2323 count++;
2324 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002325 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002326 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002327 return EOF;
2328 }
2329 }
2330
2331 if (pdp->version == 1) {
2332 if (teardown)
2333 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2334 0xff);
2335
2336 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2337 }
2338
2339 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2340
2341 if (teardown) { /* Remove all contexts */
2342 for (n = 0; n < PDP_MAXNSAPI; n++) {
2343 if (linked_pdp->secondary_tei[n]) {
2344 if (pdp_getgtp1
2345 (&secondary_pdp,
2346 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002347 LOGP(DLGTP, LOGL_ERROR,
2348 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002349 return EOF;
2350 }
2351 if (linked_pdp != secondary_pdp) {
2352 if (gsn->cb_delete_context)
2353 gsn->cb_delete_context
2354 (secondary_pdp);
2355 pdp_freepdp(secondary_pdp);
2356 }
2357 }
2358 }
2359 if (gsn->cb_delete_context)
2360 gsn->cb_delete_context(linked_pdp);
2361 pdp_freepdp(linked_pdp);
2362 } else {
2363 if (gsn->cb_delete_context)
2364 gsn->cb_delete_context(pdp);
2365 if (pdp == linked_pdp) {
2366 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2367 linked_pdp->nodata = 1;
2368 } else
2369 pdp_freepdp(pdp);
2370 }
2371
2372 return 0;
jjako2c381332003-10-21 19:09:53 +00002373}
jjako08d331d2003-10-13 20:33:30 +00002374
jjako52c24142002-12-16 13:33:51 +00002375/* Send Delete PDP Context Response */
2376int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002377 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002378 void *pack, unsigned len,
2379 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002380 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002381{
Harald Weltebed35df2011-11-02 13:06:18 +01002382 union gtp_packet packet;
2383 struct pdp_t *secondary_pdp;
2384 unsigned int length =
2385 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2386 int n;
jjako52c24142002-12-16 13:33:51 +00002387
Harald Weltebed35df2011-11-02 13:06:18 +01002388 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002389
Harald Weltebed35df2011-11-02 13:06:18 +01002390 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2391 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002392
Harald Weltebed35df2011-11-02 13:06:18 +01002393 if (cause == GTPCAUSE_ACC_REQ) {
2394 if ((teardown) || (version == 0)) { /* Remove all contexts */
2395 for (n = 0; n < PDP_MAXNSAPI; n++) {
2396 if (linked_pdp->secondary_tei[n]) {
2397 if (pdp_getgtp1
2398 (&secondary_pdp,
2399 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002400 LOGP(DLGTP, LOGL_ERROR,
2401 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002402 return EOF;
2403 }
2404 if (linked_pdp != secondary_pdp) {
2405 if (gsn->cb_delete_context)
2406 gsn->cb_delete_context
2407 (secondary_pdp);
2408 pdp_freepdp(secondary_pdp);
2409 }
2410 }
2411 }
2412 if (gsn->cb_delete_context)
2413 gsn->cb_delete_context(linked_pdp);
2414 pdp_freepdp(linked_pdp);
2415 } else { /* Remove only current context */
2416 if (gsn->cb_delete_context)
2417 gsn->cb_delete_context(pdp);
2418 if (pdp == linked_pdp) {
2419 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2420 0;
2421 linked_pdp->nodata = 1;
2422 } else
2423 pdp_freepdp(pdp);
2424 }
jjako2c381332003-10-21 19:09:53 +00002425 }
Harald Weltebed35df2011-11-02 13:06:18 +01002426 /* if (cause == GTPCAUSE_ACC_REQ) */
2427 return 0;
jjako52c24142002-12-16 13:33:51 +00002428}
2429
2430/* Handle Delete PDP Context Request */
2431int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002432 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002433 void *pack, unsigned len)
2434{
2435 struct pdp_t *pdp = NULL;
2436 struct pdp_t *linked_pdp = NULL;
2437 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002438
Harald Weltebed35df2011-11-02 13:06:18 +01002439 uint16_t seq = get_seq(pack);
2440 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002441
Harald Weltebed35df2011-11-02 13:06:18 +01002442 uint8_t nsapi;
2443 uint8_t teardown = 0;
2444 int n;
2445 int count = 0;
jjako52c24142002-12-16 13:33:51 +00002446
Harald Weltebed35df2011-11-02 13:06:18 +01002447 /* Is this a dublicate ? */
2448 if (!gtp_dublicate(gsn, version, peer, seq)) {
2449 return 0; /* We allready send off response once */
2450 }
jjako2c381332003-10-21 19:09:53 +00002451
Harald Weltebed35df2011-11-02 13:06:18 +01002452 /* Find the linked context in question */
2453 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2454 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002455 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002456 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002457 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2458 NULL, NULL, GTPCAUSE_NON_EXIST,
2459 teardown);
2460 }
jjako2c381332003-10-21 19:09:53 +00002461
Harald Weltebed35df2011-11-02 13:06:18 +01002462 /* If version 0 this is also the secondary context */
2463 if (version == 0)
2464 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002465
Harald Weltebed35df2011-11-02 13:06:18 +01002466 /* Decode information elements */
2467 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2468 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002469 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2470 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002471 if (0 == version)
2472 return EOF;
2473 else
2474 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2475 len, NULL, NULL,
2476 GTPCAUSE_INVALID_MESSAGE,
2477 teardown);
2478 }
2479
2480 if (version == 1) {
2481 /* NSAPI (mandatory) */
2482 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2483 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002484 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2485 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002486 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2487 len, NULL, NULL,
2488 GTPCAUSE_MAN_IE_MISSING,
2489 teardown);
2490 }
2491
2492 /* Find the context in question */
2493 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2494 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002495 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2496 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002497 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2498 len, NULL, NULL,
2499 GTPCAUSE_NON_EXIST,
2500 teardown);
2501 }
2502
2503 /* Teardown (conditional) */
2504 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2505
2506 if (!teardown) {
2507 for (n = 0; n < PDP_MAXNSAPI; n++)
2508 if (linked_pdp->secondary_tei[n])
2509 count++;
2510 if (count <= 1) {
2511 return 0; /* 29.060 7.3.5 Ignore message */
2512 }
2513 }
2514 }
2515
2516 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2517 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002518}
2519
jjako52c24142002-12-16 13:33:51 +00002520/* Handle Delete PDP Context Response */
2521int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002522 struct sockaddr_in *peer, void *pack, unsigned len)
2523{
2524 union gtpie_member *ie[GTPIE_SIZE];
2525 uint8_t cause;
2526 void *cbp = NULL;
2527 uint8_t type = 0;
2528 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002529
Harald Weltebed35df2011-11-02 13:06:18 +01002530 /* Remove packet from queue */
2531 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2532 return EOF;
jjako52c24142002-12-16 13:33:51 +00002533
Harald Weltebed35df2011-11-02 13:06:18 +01002534 /* Decode information elements */
2535 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2536 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002537 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2538 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002539 if (gsn->cb_conf)
2540 gsn->cb_conf(type, EOF, NULL, cbp);
2541 return EOF;
2542 }
2543
2544 /* Extract cause value (mandatory) */
2545 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2546 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002547 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2548 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002549 if (gsn->cb_conf)
2550 gsn->cb_conf(type, EOF, NULL, cbp);
2551 return EOF;
2552 }
2553
2554 /* Check the cause value (again) */
2555 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2556 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002557 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2558 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002559 if (gsn->cb_conf)
2560 gsn->cb_conf(type, cause, NULL, cbp);
2561 return EOF;
2562 }
2563
2564 /* Callback function to notify application */
2565 if (gsn->cb_conf)
2566 gsn->cb_conf(type, cause, NULL, cbp);
2567
2568 return 0;
jjako52c24142002-12-16 13:33:51 +00002569}
2570
Harald Welte54d082e2017-08-12 22:43:21 +02002571/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
jjako52c24142002-12-16 13:33:51 +00002572int gtp_error_ind_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002573 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002574 void *pack, unsigned len)
2575{
Harald Weltebed35df2011-11-02 13:06:18 +01002576 union gtp_packet packet;
2577 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2578
Harald Welte54d082e2017-08-12 22:43:21 +02002579 if (version == 1) {
2580 /* Mandatory 7.7.13 TEI Data I */
2581 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2582 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2583
2584 /* Mandatory 7.7.32 GSN Address */
2585 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2586 sizeof(gsn->gsnu), &gsn->gsnu);
2587 }
2588
Harald Weltebed35df2011-11-02 13:06:18 +01002589 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2590 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002591}
2592
2593/* Handle Error Indication */
2594int gtp_error_ind_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002595 struct sockaddr_in *peer, void *pack, unsigned len)
2596{
Harald Welte37d5b152017-08-12 23:58:29 +02002597 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002598 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002599
Harald Weltebed35df2011-11-02 13:06:18 +01002600 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002601 if (version == 0) {
2602 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
2603 gsn->err_unknownpdp++;
2604 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2605 "Unknown PDP context\n");
2606 return EOF;
2607 }
2608 } else if (version == 1) {
2609 /* we have to look-up based on the *peer* TEID */
2610 int hlen = get_hlen(pack);
2611 uint32_t teid_gn;
2612
2613 /* Decode information elements */
2614 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2615 gsn->invalid++;
2616 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2617 "Invalid message format\n");
2618 return EOF;
2619 }
2620
2621 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2622 gsn->missing++;
2623 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2624 "Missing mandatory information field\n");
2625 return EOF;
2626 }
2627
2628 if (pdp_getgtp1_peer_d(&pdp, peer, teid_gn)) {
2629 gsn->err_unknownpdp++;
2630 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2631 return EOF;
2632 }
Harald Weltebed35df2011-11-02 13:06:18 +01002633 }
jjako52c24142002-12-16 13:33:51 +00002634
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002635 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2636 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002637
2638 if (gsn->cb_delete_context)
2639 gsn->cb_delete_context(pdp);
2640 pdp_freepdp(pdp);
2641 return 0;
jjako52c24142002-12-16 13:33:51 +00002642}
2643
2644int gtp_gpdu_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002645 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2646{
jjako08d331d2003-10-13 20:33:30 +00002647
Harald Weltebed35df2011-11-02 13:06:18 +01002648 int hlen = GTP1_HEADER_SIZE_SHORT;
jjako52c24142002-12-16 13:33:51 +00002649
Harald Weltebed35df2011-11-02 13:06:18 +01002650 /* Need to include code to verify packet src and dest addresses */
2651 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002652
Harald Weltebed35df2011-11-02 13:06:18 +01002653 if (version == 0) {
2654 if (pdp_getgtp0
2655 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2656 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002657 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002658 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002659 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2660 len);
2661 }
2662 hlen = GTP0_HEADER_SIZE;
2663 } else if (version == 1) {
2664 if (pdp_getgtp1
2665 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2666 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002667 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002668 len, "Unknown PDP context, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002669 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2670 len);
2671 }
jjako08d331d2003-10-13 20:33:30 +00002672
Harald Weltebed35df2011-11-02 13:06:18 +01002673 /* Is this a long or a short header ? */
2674 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2675 hlen = GTP1_HEADER_SIZE_LONG;
2676 else
2677 hlen = GTP1_HEADER_SIZE_SHORT;
2678 } else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002679 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002680 "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002681 }
jjako08d331d2003-10-13 20:33:30 +00002682
Harald Weltebed35df2011-11-02 13:06:18 +01002683 /* If the GPDU was not from the peer GSN tell him to delete context */
2684 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2685 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002686 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002687 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2688 }
jjako52c24142002-12-16 13:33:51 +00002689
Harald Weltebed35df2011-11-02 13:06:18 +01002690 /* Callback function */
2691 if (gsn->cb_data_ind != 0)
2692 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2693
2694 return 0;
jjako52c24142002-12-16 13:33:51 +00002695}
2696
jjako52c24142002-12-16 13:33:51 +00002697/* Receives GTP packet and sends off for further processing
2698 * Function will check the validity of the header. If the header
2699 * is not valid the packet is either dropped or a version not
2700 * supported is returned to the peer.
2701 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002702int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002703{
Harald Weltebed35df2011-11-02 13:06:18 +01002704 unsigned char buffer[PACKET_MAX];
2705 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002706 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002707 int status;
2708 struct gtp0_header *pheader;
2709 int version = 0; /* GTP version should be determined from header! */
2710 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002711
Harald Weltebed35df2011-11-02 13:06:18 +01002712 /* TODO: Need strategy of userspace buffering and blocking */
2713 /* Currently read is non-blocking and send is blocking. */
2714 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002715
Harald Weltebed35df2011-11-02 13:06:18 +01002716 while (1) { /* Loop until no more to read */
2717 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002718 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002719 return -1;
2720 }
2721 peerlen = sizeof(peer);
2722 if ((status =
2723 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2724 (struct sockaddr *)&peer, &peerlen)) < 0) {
2725 if (errno == EAGAIN)
2726 return 0;
2727 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002728 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002729 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002730 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2731 status, status ? strerror(errno) : "No error");
2732 return -1;
2733 }
jjako1db1c812003-07-06 20:53:57 +00002734
Harald Weltebed35df2011-11-02 13:06:18 +01002735 /* Need at least 1 byte in order to check version */
2736 if (status < (1)) {
2737 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002738 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2739 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002740 continue;
2741 }
jjako08d331d2003-10-13 20:33:30 +00002742
Harald Weltebed35df2011-11-02 13:06:18 +01002743 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002744
Harald Weltebed35df2011-11-02 13:06:18 +01002745 /* Version should be gtp0 (or earlier) */
2746 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2747 /* GTP 0 messages. If other version message is received we reply that we */
2748 /* only support version 0, implying that this is the only version */
2749 /* supported on this port */
Harald Weltefed598f2017-09-24 16:39:22 +08002750 if (GTPHDR_F_GET_VER(pheader->flags) > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002751 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002752 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2753 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002754 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2755 continue;
2756 }
2757
2758 /* Check length of gtp0 packet */
2759 if (status < GTP0_HEADER_SIZE) {
2760 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002761 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2762 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002763 continue; /* Silently discard 29.60: 11.1.2 */
2764 }
2765
2766 /* Check packet length field versus length of packet */
2767 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2768 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002769 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002770 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002771 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002772 continue; /* Silently discard */
2773 }
2774
2775 if ((gsn->mode == GTP_MODE_GGSN) &&
2776 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2777 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2778 (pheader->type == GTP_DELETE_PDP_RSP))) {
2779 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002780 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002781 status,
Max28318872017-05-16 17:03:02 +02002782 "Unexpected GTPv0 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002783 continue; /* Silently discard 29.60: 11.1.4 */
2784 }
2785
2786 if ((gsn->mode == GTP_MODE_SGSN) &&
2787 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2788 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2789 (pheader->type == GTP_DELETE_PDP_REQ))) {
2790 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002791 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002792 status,
Max28318872017-05-16 17:03:02 +02002793 "Unexpected GTPv0 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002794 continue; /* Silently discard 29.60: 11.1.4 */
2795 }
2796
2797 switch (pheader->type) {
2798 case GTP_ECHO_REQ:
2799 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2800 break;
2801 case GTP_ECHO_RSP:
2802 gtp_echo_conf(gsn, version, &peer, buffer, status);
2803 break;
2804 case GTP_NOT_SUPPORTED:
2805 gtp_unsup_ind(gsn, &peer, buffer, status);
2806 break;
2807 case GTP_CREATE_PDP_REQ:
2808 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2809 status);
2810 break;
2811 case GTP_CREATE_PDP_RSP:
2812 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2813 status);
2814 break;
2815 case GTP_UPDATE_PDP_REQ:
2816 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2817 status);
2818 break;
2819 case GTP_UPDATE_PDP_RSP:
2820 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2821 status);
2822 break;
2823 case GTP_DELETE_PDP_REQ:
2824 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2825 status);
2826 break;
2827 case GTP_DELETE_PDP_RSP:
2828 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2829 status);
2830 break;
2831 case GTP_ERROR:
2832 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2833 break;
2834 case GTP_GPDU:
2835 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2836 break;
2837 default:
2838 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002839 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2840 "Unknown GTP message type received: %d\n",
2841 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002842 break;
2843 }
2844 }
jjako08d331d2003-10-13 20:33:30 +00002845}
2846
jjako08d331d2003-10-13 20:33:30 +00002847int gtp_decaps1c(struct gsn_t *gsn)
2848{
Harald Weltebed35df2011-11-02 13:06:18 +01002849 unsigned char buffer[PACKET_MAX];
2850 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002851 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002852 int status;
2853 struct gtp1_header_short *pheader;
2854 int version = 1; /* TODO GTP version should be determined from header! */
2855 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002856
Harald Weltebed35df2011-11-02 13:06:18 +01002857 /* TODO: Need strategy of userspace buffering and blocking */
2858 /* Currently read is non-blocking and send is blocking. */
2859 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002860
Harald Weltebed35df2011-11-02 13:06:18 +01002861 while (1) { /* Loop until no more to read */
2862 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002863 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002864 return -1;
2865 }
2866 peerlen = sizeof(peer);
2867 if ((status =
2868 recvfrom(fd, buffer, sizeof(buffer), 0,
2869 (struct sockaddr *)&peer, &peerlen)) < 0) {
2870 if (errno == EAGAIN)
2871 return 0;
2872 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002873 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002874 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002875 fd, (unsigned long)buffer, sizeof(buffer),
2876 status, status ? strerror(errno) : "No error");
2877 return -1;
2878 }
jjako08d331d2003-10-13 20:33:30 +00002879
Harald Weltebed35df2011-11-02 13:06:18 +01002880 /* Need at least 1 byte in order to check version */
2881 if (status < (1)) {
2882 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002883 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2884 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002885 continue;
2886 }
jjako08d331d2003-10-13 20:33:30 +00002887
Harald Weltebed35df2011-11-02 13:06:18 +01002888 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002889
Harald Weltebed35df2011-11-02 13:06:18 +01002890 /* Version must be no larger than GTP 1 */
Harald Weltefed598f2017-09-24 16:39:22 +08002891 if (GTPHDR_F_GET_VER(pheader->flags) > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01002892 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002893 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2894 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002895 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2896 /*29.60: 11.1.1 */
2897 continue;
2898 }
jjako08d331d2003-10-13 20:33:30 +00002899
Harald Weltebed35df2011-11-02 13:06:18 +01002900 /* Version must be at least GTP 1 */
2901 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2902 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2903 /* the message */
Harald Weltefed598f2017-09-24 16:39:22 +08002904 if (GTPHDR_F_GET_VER(pheader->flags) < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01002905 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002906 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2907 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002908 continue;
2909 }
jjako08d331d2003-10-13 20:33:30 +00002910
Harald Weltebed35df2011-11-02 13:06:18 +01002911 /* Check packet flag field */
2912 if (((pheader->flags & 0xf7) != 0x32)) {
2913 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002914 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01002915 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01002916 continue;
2917 }
jjako2c381332003-10-21 19:09:53 +00002918
Harald Weltebed35df2011-11-02 13:06:18 +01002919 /* Check length of packet */
2920 if (status < GTP1_HEADER_SIZE_LONG) {
2921 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002922 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2923 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002924 continue; /* Silently discard 29.60: 11.1.2 */
2925 }
jjako2c381332003-10-21 19:09:53 +00002926
Harald Weltebed35df2011-11-02 13:06:18 +01002927 /* Check packet length field versus length of packet */
2928 if (status !=
2929 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2930 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002931 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002932 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002933 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002934 continue; /* Silently discard */
2935 }
jjako1db1c812003-07-06 20:53:57 +00002936
Harald Weltebed35df2011-11-02 13:06:18 +01002937 /* Check for extension headers */
2938 /* TODO: We really should cycle through the headers and determine */
2939 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08002940 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002941 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002942 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2943 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002944 gtp_extheader_req(gsn, version, &peer, fd, buffer,
2945 status);
jjako1db1c812003-07-06 20:53:57 +00002946
Harald Weltebed35df2011-11-02 13:06:18 +01002947 continue;
2948 }
2949
2950 if ((gsn->mode == GTP_MODE_GGSN) &&
2951 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2952 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2953 (pheader->type == GTP_DELETE_PDP_RSP))) {
2954 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002955 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002956 status,
Max28318872017-05-16 17:03:02 +02002957 "Unexpected GTPv1 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002958 continue; /* Silently discard 29.60: 11.1.4 */
2959 }
2960
2961 if ((gsn->mode == GTP_MODE_SGSN) &&
2962 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2963 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2964 (pheader->type == GTP_DELETE_PDP_REQ))) {
2965 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002966 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002967 status,
Max28318872017-05-16 17:03:02 +02002968 "Unexpected GTPv1 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002969 continue; /* Silently discard 29.60: 11.1.4 */
2970 }
2971
2972 switch (pheader->type) {
2973 case GTP_ECHO_REQ:
2974 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2975 break;
2976 case GTP_ECHO_RSP:
2977 gtp_echo_conf(gsn, version, &peer, buffer, status);
2978 break;
2979 case GTP_NOT_SUPPORTED:
2980 gtp_unsup_ind(gsn, &peer, buffer, status);
2981 break;
2982 case GTP_SUPP_EXT_HEADER:
2983 gtp_extheader_ind(gsn, &peer, buffer, status);
2984 break;
2985 case GTP_CREATE_PDP_REQ:
2986 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2987 status);
2988 break;
2989 case GTP_CREATE_PDP_RSP:
2990 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2991 status);
2992 break;
2993 case GTP_UPDATE_PDP_REQ:
2994 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2995 status);
2996 break;
2997 case GTP_UPDATE_PDP_RSP:
2998 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2999 status);
3000 break;
3001 case GTP_DELETE_PDP_REQ:
3002 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3003 status);
3004 break;
3005 case GTP_DELETE_PDP_RSP:
3006 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3007 status);
3008 break;
3009 case GTP_ERROR:
3010 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3011 break;
3012 default:
3013 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003014 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3015 "Unknown GTP message type received: %u\n",
3016 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003017 break;
3018 }
3019 }
jjako52c24142002-12-16 13:33:51 +00003020}
3021
jjako08d331d2003-10-13 20:33:30 +00003022int gtp_decaps1u(struct gsn_t *gsn)
3023{
Harald Weltebed35df2011-11-02 13:06:18 +01003024 unsigned char buffer[PACKET_MAX];
3025 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003026 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003027 int status;
3028 struct gtp1_header_short *pheader;
3029 int version = 1; /* GTP version should be determined from header! */
3030 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003031
Harald Weltebed35df2011-11-02 13:06:18 +01003032 /* TODO: Need strategy of userspace buffering and blocking */
3033 /* Currently read is non-blocking and send is blocking. */
3034 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003035
Harald Weltebed35df2011-11-02 13:06:18 +01003036 while (1) { /* Loop until no more to read */
3037 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003038 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003039 return -1;
3040 }
3041 peerlen = sizeof(peer);
3042 if ((status =
3043 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3044 (struct sockaddr *)&peer, &peerlen)) < 0) {
3045 if (errno == EAGAIN)
3046 return 0;
3047 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003048 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003049 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003050 gsn->fd1u, (unsigned long)buffer,
3051 sizeof(buffer), status,
3052 status ? strerror(errno) : "No error");
3053 return -1;
3054 }
jjako08d331d2003-10-13 20:33:30 +00003055
Harald Weltebed35df2011-11-02 13:06:18 +01003056 /* Need at least 1 byte in order to check version */
3057 if (status < (1)) {
3058 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003059 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3060 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003061 continue;
3062 }
jjako08d331d2003-10-13 20:33:30 +00003063
Harald Weltebed35df2011-11-02 13:06:18 +01003064 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003065
Harald Weltebed35df2011-11-02 13:06:18 +01003066 /* Version must be no larger than GTP 1 */
Harald Weltefed598f2017-09-24 16:39:22 +08003067 if (GTPHDR_F_GET_VER(pheader->flags) > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003068 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003069 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3070 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003071 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3072 continue;
3073 }
jjako08d331d2003-10-13 20:33:30 +00003074
Harald Weltebed35df2011-11-02 13:06:18 +01003075 /* Version must be at least GTP 1 */
3076 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3077 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3078 /* the message */
Harald Weltefed598f2017-09-24 16:39:22 +08003079 if (GTPHDR_F_GET_VER(pheader->flags) < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003080 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003081 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3082 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003083 continue;
3084 }
jjako2c381332003-10-21 19:09:53 +00003085
Harald Weltebed35df2011-11-02 13:06:18 +01003086 /* Check packet flag field (allow both with and without sequence number) */
3087 if (((pheader->flags & 0xf5) != 0x30)) {
3088 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003089 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003090 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003091 continue;
3092 }
jjako2c381332003-10-21 19:09:53 +00003093
Harald Weltebed35df2011-11-02 13:06:18 +01003094 /* Check length of packet */
3095 if (status < GTP1_HEADER_SIZE_SHORT) {
3096 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003097 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3098 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003099 continue; /* Silently discard 29.60: 11.1.2 */
3100 }
3101
3102 /* Check packet length field versus length of packet */
3103 if (status !=
3104 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3105 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003106 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003107 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003108 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003109 continue; /* Silently discard */
3110 }
3111
3112 /* Check for extension headers */
3113 /* TODO: We really should cycle through the headers and determine */
3114 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003115 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003116 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003117 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3118 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003119 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3120 status);
3121
3122 continue;
3123 }
3124
3125 switch (pheader->type) {
3126 case GTP_ECHO_REQ:
3127 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3128 break;
3129 case GTP_ECHO_RSP:
3130 gtp_echo_conf(gsn, version, &peer, buffer, status);
3131 break;
3132 case GTP_SUPP_EXT_HEADER:
3133 gtp_extheader_ind(gsn, &peer, buffer, status);
3134 break;
3135 case GTP_ERROR:
3136 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3137 break;
3138 /* Supported header extensions */
3139 case GTP_GPDU:
3140 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3141 break;
3142 default:
3143 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003144 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3145 "Unknown GTP message type received: %u\n",
3146 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003147 break;
3148 }
3149 }
jjako08d331d2003-10-13 20:33:30 +00003150}
3151
Harald Weltebed35df2011-11-02 13:06:18 +01003152int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003153{
Harald Weltebed35df2011-11-02 13:06:18 +01003154 union gtp_packet packet;
3155 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003156 struct msghdr msgh;
3157 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003158 int fd;
jjako52c24142002-12-16 13:33:51 +00003159
Harald Welte471e3492017-09-24 16:12:39 +08003160 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003161 memset(&addr, 0, sizeof(addr));
3162 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003163#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003164 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003165#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003166 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003167
Harald Welte471e3492017-09-24 16:12:39 +08003168 /* prepare msghdr */
3169 memset(&msgh, 0, sizeof(msgh));
3170 msgh.msg_name = &addr;
3171 msgh.msg_namelen = sizeof(addr);
3172 msgh.msg_iov = iov;
3173 msgh.msg_iovlen = ARRAY_SIZE(iov);
3174
3175 /* prepare iovectors */
3176 iov[0].iov_base = &packet;
3177 /* iov[0].iov_len is not known here yet */
3178 iov[1].iov_base = pack;
3179 iov[1].iov_len = len;
3180
Harald Weltebed35df2011-11-02 13:06:18 +01003181 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003182
Harald Welte471e3492017-09-24 16:12:39 +08003183 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003184 addr.sin_port = htons(GTP0_PORT);
3185 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003186
Harald Weltebed35df2011-11-02 13:06:18 +01003187 get_default_gtp(0, GTP_GPDU, &packet);
3188 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003189 if (pdp->tx_gpdu_seq)
3190 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3191 else
3192 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003193 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003194 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003195 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003196
Harald Weltebed35df2011-11-02 13:06:18 +01003197 addr.sin_port = htons(GTP1U_PORT);
3198 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003199
Harald Weltebed35df2011-11-02 13:06:18 +01003200 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003201 if (pdp->tx_gpdu_seq) {
3202 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3203 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3204 GTP1_HEADER_SIZE_LONG);
3205 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3206 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3207 } else {
3208 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3209 packet.gtp1s.h.length = hton16(len);
3210 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3211 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3212 }
Harald Weltebed35df2011-11-02 13:06:18 +01003213 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003214 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003215 return EOF;
3216 }
3217
3218 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003219 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003220 return -1;
3221 }
3222
Harald Welte471e3492017-09-24 16:12:39 +08003223 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003224 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003225 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003226 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003227 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3228 strerror(errno));
3229 return EOF;
3230 }
3231 return 0;
jjako52c24142002-12-16 13:33:51 +00003232}
3233
jjako52c24142002-12-16 13:33:51 +00003234/* ***********************************************************
3235 * Conversion functions
3236 *************************************************************/
3237
Harald Weltebed35df2011-11-02 13:06:18 +01003238int char2ul_t(char *src, struct ul_t dst)
3239{
3240 dst.l = strlen(src) + 1;
3241 dst.v = malloc(dst.l);
3242 dst.v[0] = dst.l - 1;
3243 memcpy(&dst.v[1], src, dst.v[0]);
3244 return 0;
jjako52c24142002-12-16 13:33:51 +00003245}
3246
3247/* ***********************************************************
3248 * IP address conversion functions
3249 * There exist several types of address representations:
3250 * - eua: End User Address. (29.060, 7.7.27, message type 128)
3251 * Used for signalling address to mobile station. Supports IPv4
3252 * IPv6 x.25 etc. etc.
3253 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3254 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3255 * - in_addr: IPv4 address struct.
3256 * - sockaddr_in: Socket API representation of IP address and
3257 * port number.
3258 *************************************************************/
3259
Harald Weltebed35df2011-11-02 13:06:18 +01003260int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3261{
Harald Weltecee75462017-09-24 17:45:05 +08003262 eua->v[0] = PDP_EUA_ORG_IETF;
3263 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003264 if (src) {
3265 eua->l = 6;
3266 memcpy(&eua->v[2], src, 4);
3267 } else {
3268 eua->l = 2;
3269 }
3270 return 0;
jjako52c24142002-12-16 13:33:51 +00003271}
3272
Harald Weltebed35df2011-11-02 13:06:18 +01003273int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3274{
Harald Weltecee75462017-09-24 17:45:05 +08003275 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 +01003276 return -1; /* Not IPv4 address */
3277 memcpy(dst, &eua->v[2], 4);
3278 return 0;
jjako52c24142002-12-16 13:33:51 +00003279}
3280
Harald Weltebed35df2011-11-02 13:06:18 +01003281int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3282{
3283 memset(dst, 0, sizeof(struct in_addr));
3284 if (gsna->l != 4)
3285 return EOF; /* Return if not IPv4 */
3286 memcpy(dst, gsna->v, gsna->l);
3287 return 0;
jjako52c24142002-12-16 13:33:51 +00003288}
3289
Harald Weltebed35df2011-11-02 13:06:18 +01003290int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3291{
3292 memset(gsna, 0, sizeof(struct ul16_t));
3293 gsna->l = 4;
3294 memcpy(gsna->v, src, gsna->l);
3295 return 0;
jjako52c24142002-12-16 13:33:51 +00003296}
Harald Welteb10ee082017-08-12 19:29:16 +02003297
3298/* TS 29.060 has yet again a different encoding for IMSIs than
3299 * what we have in other places, so we cannot use the gsm48
3300 * decoding functions. Also, libgtp uses an uint64_t in
3301 * _network byte order_ to contain BCD digits ?!? */
3302const char *imsi_gtp2str(const uint64_t *imsi)
3303{
3304 static char buf[sizeof(*imsi)+1];
3305 const uint8_t *imsi8 = (const uint8_t *) imsi;
3306 unsigned int i, j = 0;
3307
3308 for (i = 0; i < sizeof(*imsi); i++) {
3309 uint8_t nibble;
3310
3311 nibble = imsi8[i] & 0xf;
3312 if (nibble == 0xf)
3313 break;
3314 buf[j++] = osmo_bcd2char(nibble);
3315
3316 nibble = imsi8[i] >> 4;
3317 if (nibble == 0xf)
3318 break;
3319 buf[j++] = osmo_bcd2char(nibble);
3320 }
3321
3322 buf[j++] = '\0';
3323 return buf;
3324}