blob: e41e692752b197d8a227c25b5d4dc78709a83614 [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));
195 gtp1_default->flags = 0x32; /* No extension, enable sequence, no N-PDU */
196 gtp1_default->type = hton8(type);
197 return GTP1_HEADER_SIZE_LONG;
198 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100199 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100200 "Unknown GTP packet version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +0100201 return 0;
202 }
jjako52c24142002-12-16 13:33:51 +0000203}
204
jjako08d331d2003-10-13 20:33:30 +0000205/**
206 * get_seq()
207 * Get sequence number of a packet.
208 * Returns 0 on error
209 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100210static uint16_t get_seq(void *pack)
211{
212 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000213
Harald Weltebed35df2011-11-02 13:06:18 +0100214 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
215 return ntoh16(packet->gtp0.h.seq);
216 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
217 return ntoh16(packet->gtp1l.h.seq);
218 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100219 return 0;
220 }
jjako08d331d2003-10-13 20:33:30 +0000221}
222
223/**
224 * get_tid()
225 * Get tunnel identifier of a packet.
226 * Returns 0 on error
227 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100228static uint64_t get_tid(void *pack)
229{
230 union gtp_packet *packet = (union gtp_packet *)pack;
231
232 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100233 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100234 }
235 return 0;
jjako08d331d2003-10-13 20:33:30 +0000236}
237
238/**
239 * get_hlen()
240 * Get the header length of a packet.
241 * Returns 0 on error
242 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100243static uint16_t get_hlen(void *pack)
244{
245 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000246
Harald Weltebed35df2011-11-02 13:06:18 +0100247 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
248 return GTP0_HEADER_SIZE;
249 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
250 return GTP1_HEADER_SIZE_LONG;
251 } else if ((packet->flags & 0xe7) == 0x20) { /* Short version 1 */
252 return GTP1_HEADER_SIZE_SHORT;
253 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100254 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100255 return 0;
256 }
jjako08d331d2003-10-13 20:33:30 +0000257}
258
259/**
260 * get_tei()
261 * Get the tunnel endpoint identifier (flow label) of a packet.
262 * Returns 0xffffffff on error.
263 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100264static uint32_t get_tei(void *pack)
265{
266 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000267
Harald Weltebed35df2011-11-02 13:06:18 +0100268 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
269 return ntoh16(packet->gtp0.h.flow);
270 } else if ((packet->flags & 0xe0) == 0x20) { /* Version 1 */
271 return ntoh32(packet->gtp1l.h.tei);
272 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100273 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100274 return 0xffffffff;
275 }
jjako08d331d2003-10-13 20:33:30 +0000276}
jjakoa7cd2492003-04-11 09:40:12 +0000277
jjako52c24142002-12-16 13:33:51 +0000278/* ***********************************************************
279 * Reliable delivery of signalling messages
280 *
281 * Sequence numbers are used for both signalling messages and
282 * data messages.
283 *
284 * For data messages each tunnel maintains a sequence counter,
285 * which is incremented by one each time a new data message
286 * is sent. The sequence number starts at (0) zero at tunnel
287 * establishment, and wraps around at 65535 (29.060 9.3.1.1
288 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
289 * or can be used to check the validity of the message in the
290 * receiver, or for reordering af packets.
291 *
292 * For signalling messages the sequence number is used by
293 * signalling messages for which a response is defined. A response
294 * message should copy the sequence from the corresponding request
295 * message. The sequence number "unambiguously" identifies a request
296 * message within a given path, with a path being defined as a set of
297 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
298 * messages shall be responded to, and all response messages associated
299 * with a certain request shall always include the same information"
300 *
301 * We take this to mean that the GSN transmitting a request is free to
302 * choose the sequence number, as long as it is unique within a given path.
303 * It means that we are allowed to count backwards, or roll over at 17
304 * if we prefer that. It also means that we can use the same counter for
305 * all paths. This has the advantage that the transmitted request sequence
306 * numbers are unique within each GSN, and also we dont have to mess around
307 * with path setup and teardown.
308 *
309 * If a response message is lost, the request will be retransmitted, and
310 * the receiving GSN will receive a "duplicated" request. The standard
311 * requires the receiving GSN to send a response, with the same information
312 * as in the original response. For most messages this happens automatically:
313 *
314 * Echo: Automatically dublicates the original response
315 * Create pdp context: The SGSN may send create context request even if
316 * a context allready exist (imsi+nsapi?). This means that the reply will
317 automatically dublicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000318 * side effects in the application which is asked twice to validate
319 * the login.
jjako52c24142002-12-16 13:33:51 +0000320 * Update pdp context: Automatically dublicates the original response???
321 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
322 * a nonexist reply message.
323 *
324 * The correct solution will be to make a queue containing response messages.
325 * This queue should be checked whenever a request is received. If the
326 * response is allready in the queue that response should be transmitted.
327 * It should be possible to find messages in this queue on the basis of
328 * the sequence number and peer GSN IP address (The sequense number is unique
329 * within each path). This need to be implemented by a hash table. Furthermore
330 * it should be possibly to delete messages based on a timeout. This can be
331 * achieved by means of a linked list. The timeout value need to be larger
332 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
333 * set in the peer GSN, so there is no way to know these parameters. On the
334 * other hand the timeout value need to be so small that we do not receive
335 * wraparound sequence numbere before the message is deleted. 60 seconds is
336 * probably not a bad choise.
337 *
338 * This queue however is first really needed from gtp1.
339 *
340 * gtp_req:
341 * Send off a signalling message with appropiate sequence
342 * number. Store packet in queue.
343 * gtp_conf:
344 * Remove an incoming confirmation from the queue
345 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000346 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000347 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000348 * gtp_notification:
349 * Send off a notification message. This is neither a request nor
350 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000351 * gtp_retrans:
352 * Retransmit any outstanding packets which have exceeded
353 * a predefined timeout.
354 *************************************************************/
355
jjako08d331d2003-10-13 20:33:30 +0000356int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100357 union gtp_packet *packet, int len,
358 struct in_addr *inetaddr, void *cbp)
359{
360 struct sockaddr_in addr;
361 struct qmsg_t *qmsg;
362 int fd;
jjako08d331d2003-10-13 20:33:30 +0000363
Harald Weltebed35df2011-11-02 13:06:18 +0100364 memset(&addr, 0, sizeof(addr));
365 addr.sin_family = AF_INET;
366 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000367#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100368 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000369#endif
jjako52c24142002-12-16 13:33:51 +0000370
Harald Weltebed35df2011-11-02 13:06:18 +0100371 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
372 addr.sin_port = htons(GTP0_PORT);
373 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
374 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100375 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100376 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100377 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100378 }
Harald Weltebed35df2011-11-02 13:06:18 +0100379 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
380 || (packet->gtp0.h.type == GTP_ERROR)))
381 packet->gtp0.h.flow = hton16(pdp->flru);
382 else if (pdp)
383 packet->gtp0.h.flow = hton16(pdp->flrc);
384 fd = gsn->fd0;
385 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
386 addr.sin_port = htons(GTP1C_PORT);
387 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
388 packet->gtp1l.h.seq = hton16(gsn->seq_next);
389 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
390 (packet->gtp1l.h.type == GTP_ERROR)))
391 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
392 else if (pdp)
393 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
394 fd = gsn->fd1c;
395 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100396 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100397 return -1;
398 }
jjako52c24142002-12-16 13:33:51 +0000399
Harald Weltebed35df2011-11-02 13:06:18 +0100400 if (sendto(fd, packet, len, 0,
401 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
402 gsn->err_sendto++;
Max14b1b632017-08-21 20:14:59 +0200403 LOGP(DLGTP, LOGL_ERROR, "Sendto(fd=%d, msg=%lx, len=%d, dst=%s) failed: Error = %s\n", fd,
404 (unsigned long)&packet, len, inet_ntoa(addr.sin_addr), strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100405 return -1;
406 }
407
408 /* Use new queue structure */
409 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
410 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100411 LOGP(DLGTP, LOGL_ERROR,
412 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100413 } else {
414 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
415 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100416 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100417 qmsg->retrans = 0; /* No retransmissions so far */
418 qmsg->cbp = cbp;
419 qmsg->type = ntoh8(packet->gtp0.h.type);
420 qmsg->fd = fd;
421 }
422 gsn->seq_next++; /* Count up this time */
423 return 0;
jjako52c24142002-12-16 13:33:51 +0000424}
425
426/* gtp_conf
427 * Remove signalling packet from retransmission queue.
428 * return 0 on success, EOF if packet was not found */
429
430int gtp_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100431 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
432{
jjako52c24142002-12-16 13:33:51 +0000433
Harald Weltebed35df2011-11-02 13:06:18 +0100434 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000435
Harald Weltebed35df2011-11-02 13:06:18 +0100436 if ((packet->gtp0.h.flags & 0xe0) == 0x00)
437 seq = ntoh16(packet->gtp0.h.seq);
438 else if ((packet->gtp1l.h.flags & 0xe2) == 0x22)
439 seq = ntoh16(packet->gtp1l.h.seq);
440 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100441 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
442 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100443 return EOF;
444 }
jjako08d331d2003-10-13 20:33:30 +0000445
Harald Weltebed35df2011-11-02 13:06:18 +0100446 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
447 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100448 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
449 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100450 return EOF;
451 }
jjako52c24142002-12-16 13:33:51 +0000452
Harald Weltebed35df2011-11-02 13:06:18 +0100453 return 0;
jjako52c24142002-12-16 13:33:51 +0000454}
455
Harald Weltebed35df2011-11-02 13:06:18 +0100456int gtp_retrans(struct gsn_t *gsn)
457{
458 /* Retransmit any outstanding packets */
459 /* Remove from queue if maxretrans exceeded */
460 time_t now;
461 struct qmsg_t *qmsg;
462 now = time(NULL);
463 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000464
Harald Welte95848ba2011-11-02 18:17:50 +0100465 /* get first element in queue, as long as the timeout of that
466 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100467 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
468 (qmsg->timeout <= now)) {
469 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100470 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100471 if (gsn->cb_conf)
472 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
473 queue_freemsg(gsn->queue_req, qmsg);
474 } else {
475 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
476 (struct sockaddr *)&qmsg->peer,
477 sizeof(struct sockaddr_in)) < 0) {
478 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100479 LOGP(DLGTP, LOGL_ERROR,
480 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100481 gsn->fd0, (unsigned long)&qmsg->p,
482 qmsg->l, strerror(errno));
483 }
484 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100485 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100486 qmsg->retrans++;
487 }
488 }
jjako52c24142002-12-16 13:33:51 +0000489
Harald Weltebed35df2011-11-02 13:06:18 +0100490 /* Also clean up reply timeouts */
491 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
492 (qmsg->timeout < now)) {
493 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
494 queue_freemsg(gsn->queue_resp, qmsg);
495 }
jjako52c24142002-12-16 13:33:51 +0000496
Harald Weltebed35df2011-11-02 13:06:18 +0100497 return 0;
jjako52c24142002-12-16 13:33:51 +0000498}
499
Harald Weltebed35df2011-11-02 13:06:18 +0100500int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
501{
502 time_t now, later;
503 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000504
Harald Weltebed35df2011-11-02 13:06:18 +0100505 if (queue_getfirst(gsn->queue_req, &qmsg)) {
506 timeout->tv_sec = 10;
507 timeout->tv_usec = 0;
508 } else {
509 now = time(NULL);
510 later = qmsg->timeout;
511 timeout->tv_sec = later - now;
512 timeout->tv_usec = 0;
513 if (timeout->tv_sec < 0)
514 timeout->tv_sec = 0; /* No negative allowed */
515 if (timeout->tv_sec > 10)
516 timeout->tv_sec = 10; /* Max sleep for 10 sec */
517 }
518 return 0;
jjako52c24142002-12-16 13:33:51 +0000519}
520
Harald Weltebed35df2011-11-02 13:06:18 +0100521int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000522 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100523 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
524{
525 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000526
Harald Weltebed35df2011-11-02 13:06:18 +0100527 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
528 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
529 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100530 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100531 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
532 (packet->gtp0.h.type == GTP_ERROR)))
533 packet->gtp0.h.flow = hton16(pdp->flru);
534 else if (pdp)
535 packet->gtp0.h.flow = hton16(pdp->flrc);
536 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
537 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
538 packet->gtp1l.h.seq = hton16(seq);
539 if (pdp && (fd == gsn->fd1u))
540 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
541 else if (pdp)
542 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
543 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100544 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100545 return -1;
546 }
jjako08d331d2003-10-13 20:33:30 +0000547
Harald Weltebed35df2011-11-02 13:06:18 +0100548 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100549 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100550 return -1;
551 }
jjako52c24142002-12-16 13:33:51 +0000552
Harald Weltebed35df2011-11-02 13:06:18 +0100553 if (sendto(fd, packet, len, 0,
554 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
555 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100556 LOGP(DLGTP, LOGL_ERROR,
557 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100558 (unsigned long)&packet, len, strerror(errno));
559 return -1;
560 }
561
562 /* Use new queue structure */
563 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
564 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100565 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100566 } else {
567 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
568 qmsg->l = len;
569 qmsg->timeout = time(NULL) + 60; /* When to timeout */
570 qmsg->retrans = 0; /* No retransmissions so far */
571 qmsg->cbp = NULL;
572 qmsg->type = 0;
573 qmsg->fd = fd;
574 }
575 return 0;
jjako52c24142002-12-16 13:33:51 +0000576}
577
jjako2c381332003-10-21 19:09:53 +0000578int gtp_notification(struct gsn_t *gsn, int version,
579 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100580 struct sockaddr_in *peer, int fd, uint16_t seq)
581{
jjako2c381332003-10-21 19:09:53 +0000582
Harald Weltebed35df2011-11-02 13:06:18 +0100583 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000584
Harald Weltebed35df2011-11-02 13:06:18 +0100585 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000586
Harald Weltebed35df2011-11-02 13:06:18 +0100587 /* In GTP0 notifications are treated as replies. In GTP1 they
588 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000589
Harald Weltebed35df2011-11-02 13:06:18 +0100590 if (fd == gsn->fd1c)
591 addr.sin_port = htons(GTP1C_PORT);
592 else if (fd == gsn->fd1u)
593 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000594
Harald Weltebed35df2011-11-02 13:06:18 +0100595 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
596 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
597 packet->gtp0.h.seq = hton16(seq);
598 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
599 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
600 packet->gtp1l.h.seq = hton16(seq);
601 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100602 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100603 return -1;
604 }
605
606 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100607 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100608 return -1;
609 }
610
611 if (sendto(fd, packet, len, 0,
612 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
613 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100614 LOGP(DLGTP, LOGL_ERROR,
615 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100616 (unsigned long)&packet, len, strerror(errno));
617 return -1;
618 }
619 return 0;
jjako2c381332003-10-21 19:09:53 +0000620}
621
Harald Weltebed35df2011-11-02 13:06:18 +0100622int gtp_dublicate(struct gsn_t *gsn, int version,
623 struct sockaddr_in *peer, uint16_t seq)
624{
625 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000626
Harald Weltebed35df2011-11-02 13:06:18 +0100627 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
628 return EOF; /* Notfound */
629 }
jjakoa7cd2492003-04-11 09:40:12 +0000630
Harald Weltebed35df2011-11-02 13:06:18 +0100631 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100632 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100633 return -1;
634 }
635
636 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
637 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
638 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100639 LOGP(DLGTP, LOGL_ERROR,
640 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100641 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
642 strerror(errno));
643 }
644 return 0;
jjako52c24142002-12-16 13:33:51 +0000645}
646
jjako52c24142002-12-16 13:33:51 +0000647/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100648static void log_restart(struct gsn_t *gsn)
649{
jjako52c24142002-12-16 13:33:51 +0000650 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200651 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000652 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200653 char *filename;
jjako52c24142002-12-16 13:33:51 +0000654
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200655 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
656 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000657
658 /* We try to open file. On failure we will later try to create file */
659 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100660 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100661 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100662 filename);
663 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100664 rc = fscanf(f, "%d", &counter);
665 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100666 LOGP(DLGTP, LOGL_ERROR,
667 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100668 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100669 }
670 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100671 LOGP(DLGTP, LOGL_ERROR,
672 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100673 }
jjako52c24142002-12-16 13:33:51 +0000674 }
Harald Weltebed35df2011-11-02 13:06:18 +0100675
676 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000677 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100678
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200679 /* Keep the umask closely wrapped around our fopen() call in case the
680 * log outputs cause file creation. */
681 i = umask(022);
682 f = fopen(filename, "w");
683 umask(i);
684 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100685 LOGP(DLGTP, LOGL_ERROR,
686 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100687 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200688 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000689 }
690
jjako52c24142002-12-16 13:33:51 +0000691 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100692close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200693 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100694 LOGP(DLGTP, LOGL_ERROR,
695 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200696free_filename:
697 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000698}
699
jjako1db1c812003-07-06 20:53:57 +0000700int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100701 int mode)
jjako52c24142002-12-16 13:33:51 +0000702{
Harald Weltebed35df2011-11-02 13:06:18 +0100703 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000704
Max14b1b632017-08-21 20:14:59 +0200705 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
jjako52c24142002-12-16 13:33:51 +0000706
Harald Weltebed35df2011-11-02 13:06:18 +0100707 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000708
Harald Weltebed35df2011-11-02 13:06:18 +0100709 (*gsn)->statedir = statedir;
710 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000711
Harald Weltebed35df2011-11-02 13:06:18 +0100712 /* Initialise sequence number */
713 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000714
Harald Weltebed35df2011-11-02 13:06:18 +0100715 /* Initialise request retransmit queue */
716 queue_new(&(*gsn)->queue_req);
717 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000718
Harald Weltebed35df2011-11-02 13:06:18 +0100719 /* Initialise pdp table */
720 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000721
Harald Weltebed35df2011-11-02 13:06:18 +0100722 /* Initialise call back functions */
723 (*gsn)->cb_create_context_ind = 0;
724 (*gsn)->cb_delete_context = 0;
725 (*gsn)->cb_unsup_ind = 0;
726 (*gsn)->cb_conf = 0;
727 (*gsn)->cb_data_ind = 0;
728
729 /* Store function parameters */
730 (*gsn)->gsnc = *listen;
731 (*gsn)->gsnu = *listen;
732 (*gsn)->mode = mode;
733
734 /* Create GTP version 0 socket */
735 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
736 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100737 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200738 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100739 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200740 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100741 }
742
743 memset(&addr, 0, sizeof(addr));
744 addr.sin_family = AF_INET;
745 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
746 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000747#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100748 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000749#endif
jjako08d331d2003-10-13 20:33:30 +0000750
Harald Weltebed35df2011-11-02 13:06:18 +0100751 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
752 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200753 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
754 "bind(fd0=%d) failed: Error = %s\n",
755 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200756 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100757 }
jjako08d331d2003-10-13 20:33:30 +0000758
Harald Weltebed35df2011-11-02 13:06:18 +0100759 /* Create GTP version 1 control plane socket */
760 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
761 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100762 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200763 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100764 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200765 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100766 }
767
768 memset(&addr, 0, sizeof(addr));
769 addr.sin_family = AF_INET;
770 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
771 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000772#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100773 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000774#endif
jjako08d331d2003-10-13 20:33:30 +0000775
Harald Weltebed35df2011-11-02 13:06:18 +0100776 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
777 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200778 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
779 "bind(fd1c=%d) failed: Error = %s\n",
780 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200781 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100782 }
jjako08d331d2003-10-13 20:33:30 +0000783
Harald Weltebed35df2011-11-02 13:06:18 +0100784 /* Create GTP version 1 user plane socket */
785 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
786 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100787 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200788 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100789 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200790 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100791 }
792
793 memset(&addr, 0, sizeof(addr));
794 addr.sin_family = AF_INET;
795 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
796 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000797#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100798 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000799#endif
jjako52c24142002-12-16 13:33:51 +0000800
Harald Weltebed35df2011-11-02 13:06:18 +0100801 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
802 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200803 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +0200804 "bind(fd1u=%d) failed: Error = %s\n",
805 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +0200806 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100807 }
808
809 return 0;
jjako52c24142002-12-16 13:33:51 +0000810}
811
Harald Weltebed35df2011-11-02 13:06:18 +0100812int gtp_free(struct gsn_t *gsn)
813{
jjako52c24142002-12-16 13:33:51 +0000814
Harald Weltebed35df2011-11-02 13:06:18 +0100815 /* Clean up retransmit queues */
816 queue_free(gsn->queue_req);
817 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000818
Harald Weltebed35df2011-11-02 13:06:18 +0100819 close(gsn->fd0);
820 close(gsn->fd1c);
821 close(gsn->fd1u);
822
823 free(gsn);
824 return 0;
jjako52c24142002-12-16 13:33:51 +0000825}
826
827/* ***********************************************************
828 * Path management messages
829 * Messages: echo and version not supported.
830 * A path is connection between two UDP/IP endpoints
831 *
832 * A path is either using GTP0 or GTP1. A path can be
833 * established by any kind of GTP message??
834
835 * Which source port to use?
836 * GTP-C request destination port is 2123/3386
837 * GTP-U request destination port is 2152/3386
838 * T-PDU destination port is 2152/3386.
839 * For the above messages the source port is locally allocated.
840 * For response messages src=rx-dst and dst=rx-src.
841 * For simplicity we should probably use 2123+2152/3386 as
842 * src port even for the cases where src can be locally
843 * allocated. This also means that we have to listen only to
844 * the same ports.
845 * For response messages we need to be able to respond to
846 * the relevant src port even if it is locally allocated by
847 * the peer.
848 *
849 * The need for path management!
850 * We might need to keep a list of active paths. This might
851 * be in the form of remote IP address + UDP port numbers.
852 * (We will consider a path astablished if we have a context
853 * with the node in question)
854 *************************************************************/
855
856/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000857int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
858 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000859{
Harald Weltebed35df2011-11-02 13:06:18 +0100860 union gtp_packet packet;
861 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
862 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000863}
864
jjako08d331d2003-10-13 20:33:30 +0000865/* Send off an echo reply */
866int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100867 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000868{
Harald Weltebed35df2011-11-02 13:06:18 +0100869 union gtp_packet packet;
870 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
871 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
872 gsn->restart_counter);
873 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
874 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000875}
876
jjako52c24142002-12-16 13:33:51 +0000877/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +0100878int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
879 int fd, void *pack, unsigned len)
880{
jjako52c24142002-12-16 13:33:51 +0000881
Harald Weltebed35df2011-11-02 13:06:18 +0100882 /* Check if it was a dublicate request */
883 if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
884 return 0;
jjako52c24142002-12-16 13:33:51 +0000885
Harald Weltebed35df2011-11-02 13:06:18 +0100886 /* Send off reply to request */
887 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000888}
889
890/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000891int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100892 void *pack, unsigned len)
893{
894 union gtpie_member *ie[GTPIE_SIZE];
895 unsigned char recovery;
896 void *cbp = NULL;
897 uint8_t type = 0;
898 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000899
Harald Weltebed35df2011-11-02 13:06:18 +0100900 /* Remove packet from queue */
901 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
902 return EOF;
jjako52c24142002-12-16 13:33:51 +0000903
Harald Weltebed35df2011-11-02 13:06:18 +0100904 /* Extract information elements into a pointer array */
905 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
906 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100907 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
908 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100909 if (gsn->cb_conf)
910 gsn->cb_conf(type, EOF, NULL, cbp);
911 return EOF;
912 }
jjako52c24142002-12-16 13:33:51 +0000913
Harald Weltebed35df2011-11-02 13:06:18 +0100914 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
915 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100916 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
917 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100918 if (gsn->cb_conf)
919 gsn->cb_conf(type, EOF, NULL, cbp);
920 return EOF;
921 }
jjako52c24142002-12-16 13:33:51 +0000922
Harald Weltebed35df2011-11-02 13:06:18 +0100923 /* Echo reply packages does not have a cause information element */
924 /* Instead we return the recovery number in the callback function */
925 if (gsn->cb_conf)
926 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +0100927
Harald Weltebed35df2011-11-02 13:06:18 +0100928 if (gsn->cb_recovery)
929 gsn->cb_recovery(peer, recovery);
930
931 return 0;
jjako52c24142002-12-16 13:33:51 +0000932}
933
934/* Send off a Version Not Supported message */
935/* This message is somewhat special in that it actually is a
936 * response to some other message with unsupported GTP version
937 * For this reason it has parameters like a response, and does
938 * its own message transmission. No signalling queue is used
939 * The reply is sent to the peer IP and peer UDP. This means that
940 * the peer will be receiving a GTP0 message on a GTP1 port!
941 * In practice however this will never happen as a GTP0 GSN will
942 * only listen to the GTP0 port, and therefore will never receive
943 * anything else than GTP0 */
944
jjako08d331d2003-10-13 20:33:30 +0000945int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
946 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000947{
Harald Weltebed35df2011-11-02 13:06:18 +0100948 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +0000949
Harald Weltebed35df2011-11-02 13:06:18 +0100950 /* GTP 1 is the highest supported protocol */
951 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
952 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +0000953}
954
955/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +0100956int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
957 void *pack, unsigned len)
958{
jjako52c24142002-12-16 13:33:51 +0000959
Harald Weltebed35df2011-11-02 13:06:18 +0100960 if (gsn->cb_unsup_ind)
961 gsn->cb_unsup_ind(peer);
962
963 return 0;
jjako52c24142002-12-16 13:33:51 +0000964}
965
jjako2c381332003-10-21 19:09:53 +0000966/* Send off an Supported Extension Headers Notification */
967int gtp_extheader_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
968 int fd, void *pack, unsigned len)
969{
Harald Weltebed35df2011-11-02 13:06:18 +0100970 union gtp_packet packet;
971 unsigned int length =
972 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +0000973
Harald Weltebed35df2011-11-02 13:06:18 +0100974 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +0000975
Harald Weltebed35df2011-11-02 13:06:18 +0100976 if (version < 1)
977 return 0;
jjako2c381332003-10-21 19:09:53 +0000978
Harald Weltebed35df2011-11-02 13:06:18 +0100979 /* We report back that we support only PDCP PDU headers */
980 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
981 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +0000982
Harald Weltebed35df2011-11-02 13:06:18 +0100983 return gtp_notification(gsn, version, &packet, length,
984 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +0000985}
986
987/* Handle a Supported Extension Headers Notification */
Harald Weltebed35df2011-11-02 13:06:18 +0100988int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
989 void *pack, unsigned len)
990{
jjako2c381332003-10-21 19:09:53 +0000991
Harald Weltebed35df2011-11-02 13:06:18 +0100992 if (gsn->cb_extheader_ind)
993 gsn->cb_extheader_ind(peer);
994
995 return 0;
jjako2c381332003-10-21 19:09:53 +0000996}
997
jjako52c24142002-12-16 13:33:51 +0000998/* ***********************************************************
999 * Session management messages
1000 * Messages: create, update and delete PDP context
1001 *
1002 * Information storage
1003 * Information storage for each PDP context is defined in
1004 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1005 * PDP-address (IP address), sequence numbers, charging ID.
1006 * For the SGSN it also includes radio related mobility
1007 * information.
1008 *************************************************************/
1009
Harald Welte7b3347b2010-05-15 12:18:46 +02001010/* API: Send Create PDP Context Request (7.3.1) */
Harald Weltebed35df2011-11-02 13:06:18 +01001011extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
1012 void *cbp)
1013{
1014 union gtp_packet packet;
1015 unsigned int length =
1016 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1017 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001018
Harald Weltebed35df2011-11-02 13:06:18 +01001019 /* TODO: Secondary PDP Context Activation Procedure */
1020 /* In secondary activation procedure the PDP context is identified
1021 by tei in the header. The following fields are omitted: Selection
1022 mode, IMSI, MSISDN, End User Address, Access Point Name and
1023 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001024
Harald Weltebed35df2011-11-02 13:06:18 +01001025 if (pdp->secondary) {
1026 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001027 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001028 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001029 return EOF;
1030 }
1031 }
jjako2c381332003-10-21 19:09:53 +00001032
Harald Weltebed35df2011-11-02 13:06:18 +01001033 if (pdp->version == 0) {
1034 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1035 sizeof(pdp->qos_req0), pdp->qos_req0);
1036 }
jjako52c24142002-12-16 13:33:51 +00001037
Harald Weltebed35df2011-11-02 13:06:18 +01001038 /* Section 7.7.2 */
1039 if (pdp->version == 1) {
1040 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1041 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1042 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1043 }
jjako52c24142002-12-16 13:33:51 +00001044
Harald Weltebed35df2011-11-02 13:06:18 +01001045 /* Section 7.7.3 Routing Area Information */
1046 if (pdp->rai_given == 1)
1047 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1048 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001049
Harald Weltebed35df2011-11-02 13:06:18 +01001050 /* Section 7.7.11 */
1051 if (pdp->norecovery_given == 0)
1052 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1053 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001054
Harald Weltebed35df2011-11-02 13:06:18 +01001055 /* Section 7.7.12 */
1056 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1057 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1058 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001059
Harald Weltebed35df2011-11-02 13:06:18 +01001060 if (pdp->version == 0) {
1061 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1062 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1063 }
jjako08d331d2003-10-13 20:33:30 +00001064
Harald Weltebed35df2011-11-02 13:06:18 +01001065 /* Section 7.7.13 */
1066 if (pdp->version == 1) {
1067 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1068 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001069
Harald Weltebed35df2011-11-02 13:06:18 +01001070 /* Section 7.7.14 */
1071 if (!pdp->teic_confirmed)
1072 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1073 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001074
Harald Weltebed35df2011-11-02 13:06:18 +01001075 /* Section 7.7.17 */
1076 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001077
Harald Weltebed35df2011-11-02 13:06:18 +01001078 /* Section 7.7.17 */
1079 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1080 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1081 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001082
Harald Weltebed35df2011-11-02 13:06:18 +01001083 /* Section 7.7.23 */
1084 if (pdp->cch_pdp) /* Only include charging if flags are set */
1085 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1086 pdp->cch_pdp);
1087 }
jjako9b4971d2004-05-27 20:30:19 +00001088
Harald Weltebed35df2011-11-02 13:06:18 +01001089 /* TODO
1090 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1091 pdp->traceref);
1092 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1093 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001094
Harald Weltebed35df2011-11-02 13:06:18 +01001095 /* Section 7.7.27 */
1096 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1097 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1098 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001099
Harald Weltebed35df2011-11-02 13:06:18 +01001100 /* Section 7.7.30 */
1101 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1102 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1103 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001104
Harald Weltebed35df2011-11-02 13:06:18 +01001105 /* Section 7.7.31 */
1106 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1107 if (pdp->pco_req.l)
1108 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1109 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001110
Harald Weltebed35df2011-11-02 13:06:18 +01001111 /* Section 7.7.32 */
1112 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1113 pdp->gsnlc.l, pdp->gsnlc.v);
1114 /* Section 7.7.32 */
1115 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1116 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001117
Harald Weltebed35df2011-11-02 13:06:18 +01001118 /* Section 7.7.33 */
1119 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1120 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1121 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001122
Harald Weltebed35df2011-11-02 13:06:18 +01001123 /* Section 7.7.34 */
1124 if (pdp->version == 1)
1125 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1126 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001127
Harald Weltebed35df2011-11-02 13:06:18 +01001128 /* Section 7.7.36 */
1129 if ((pdp->version == 1) && pdp->tft.l)
1130 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1131 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001132
Harald Weltebed35df2011-11-02 13:06:18 +01001133 /* Section 7.7.41 */
1134 if ((pdp->version == 1) && pdp->triggerid.l)
1135 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1136 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001137
Harald Weltebed35df2011-11-02 13:06:18 +01001138 /* Section 7.7.42 */
1139 if ((pdp->version == 1) && pdp->omcid.l)
1140 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1141 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001142
Harald Weltebed35df2011-11-02 13:06:18 +01001143 /* new R7 fields */
1144 if (pdp->rattype_given == 1)
1145 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1146 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001147
Harald Weltebed35df2011-11-02 13:06:18 +01001148 if (pdp->userloc_given == 1)
1149 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1150 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001151
Harald Weltebed35df2011-11-02 13:06:18 +01001152 if (pdp->mstz_given == 1)
1153 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1154 pdp->mstz.l, pdp->mstz.v);
1155
1156 if (pdp->imeisv_given == 1)
1157 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1158 pdp->imeisv.l, pdp->imeisv.v);
1159
1160 /* TODO hisaddr0 */
1161 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1162
1163 return 0;
jjako52c24142002-12-16 13:33:51 +00001164}
1165
jjako08d331d2003-10-13 20:33:30 +00001166/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001167int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1168{
jjako08d331d2003-10-13 20:33:30 +00001169
Harald Weltebed35df2011-11-02 13:06:18 +01001170 /* Now send off a reply to the peer */
1171 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1172
1173 if (cause != GTPCAUSE_ACC_REQ) {
1174 pdp_freepdp(pdp);
1175 }
1176
1177 return 0;
jjako08d331d2003-10-13 20:33:30 +00001178}
1179
1180/* API: Register create context indication callback */
1181int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001182 int (*cb_create_context_ind) (struct pdp_t *
1183 pdp))
jjako52c24142002-12-16 13:33:51 +00001184{
Harald Weltebed35df2011-11-02 13:06:18 +01001185 gsn->cb_create_context_ind = cb_create_context_ind;
1186 return 0;
jjako08d331d2003-10-13 20:33:30 +00001187}
1188
jjako08d331d2003-10-13 20:33:30 +00001189/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001190int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1191 uint8_t cause)
1192{
1193 union gtp_packet packet;
1194 unsigned int length =
1195 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001196
Harald Weltebed35df2011-11-02 13:06:18 +01001197 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001198
Harald Weltebed35df2011-11-02 13:06:18 +01001199 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001200
Harald Weltebed35df2011-11-02 13:06:18 +01001201 if (version == 0)
1202 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1203 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001204
Harald Weltebed35df2011-11-02 13:06:18 +01001205 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1206 pdp->reorder);
1207 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1208 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001209
Harald Weltebed35df2011-11-02 13:06:18 +01001210 if (version == 0) {
1211 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1212 pdp->fllu);
1213 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1214 pdp->fllc);
1215 }
jjako08d331d2003-10-13 20:33:30 +00001216
Harald Weltebed35df2011-11-02 13:06:18 +01001217 if (version == 1) {
1218 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1219 pdp->teid_own);
1220 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1221 pdp->teic_own);
1222 }
jjako08d331d2003-10-13 20:33:30 +00001223
Harald Weltebed35df2011-11-02 13:06:18 +01001224 /* TODO: We use teic_own as charging ID */
1225 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1226 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001227
Harald Weltebed35df2011-11-02 13:06:18 +01001228 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1229 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001230
Harald Weltebed35df2011-11-02 13:06:18 +01001231 if (pdp->pco_neg.l) { /* Optional PCO */
1232 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1233 pdp->pco_neg.l, pdp->pco_neg.v);
1234 }
jjako52c24142002-12-16 13:33:51 +00001235
Harald Weltebed35df2011-11-02 13:06:18 +01001236 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1237 pdp->gsnlc.l, pdp->gsnlc.v);
1238 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1239 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001240
Harald Weltebed35df2011-11-02 13:06:18 +01001241 if (version == 1)
1242 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1243 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001244
Harald Weltebed35df2011-11-02 13:06:18 +01001245 /* TODO: Charging gateway address */
1246 }
jjako52c24142002-12-16 13:33:51 +00001247
Harald Weltebed35df2011-11-02 13:06:18 +01001248 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1249 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001250}
1251
1252/* Handle Create PDP Context Request */
1253int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001254 struct sockaddr_in *peer, int fd,
1255 void *pack, unsigned len)
1256{
1257 struct pdp_t *pdp, *pdp_old;
1258 struct pdp_t pdp_buf;
1259 union gtpie_member *ie[GTPIE_SIZE];
1260 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001261
Harald Weltebed35df2011-11-02 13:06:18 +01001262 uint16_t seq = get_seq(pack);
1263 int hlen = get_hlen(pack);
1264 uint8_t linked_nsapi = 0;
1265 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001266
Harald Weltebed35df2011-11-02 13:06:18 +01001267 if (!gtp_dublicate(gsn, version, peer, seq))
1268 return 0;
jjako08d331d2003-10-13 20:33:30 +00001269
Harald Weltebed35df2011-11-02 13:06:18 +01001270 pdp = &pdp_buf;
1271 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001272
Harald Weltebed35df2011-11-02 13:06:18 +01001273 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001274 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1275
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001276 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001277 }
jjako52c24142002-12-16 13:33:51 +00001278
Harald Weltebed35df2011-11-02 13:06:18 +01001279 pdp->seq = seq;
1280 pdp->sa_peer = *peer;
1281 pdp->fd = fd;
1282 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001283
Harald Weltebed35df2011-11-02 13:06:18 +01001284 /* Decode information elements */
1285 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1286 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001287 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1288 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001289 if (0 == version)
1290 return EOF;
1291 else
1292 return gtp_create_pdp_resp(gsn, version, pdp,
1293 GTPCAUSE_INVALID_MESSAGE);
1294 }
jjako52c24142002-12-16 13:33:51 +00001295
Harald Weltebed35df2011-11-02 13:06:18 +01001296 if (version == 1) {
1297 /* Linked NSAPI (conditional) */
1298 /* If included this is the Secondary PDP Context Activation Procedure */
1299 /* In secondary activation IMSI is not included, so the context must be */
1300 /* identified by the tei */
1301 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001302
Harald Weltebed35df2011-11-02 13:06:18 +01001303 /* Find the primary PDP context */
1304 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1305 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001306 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001307 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001308 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001309 return gtp_create_pdp_resp(gsn, version, pdp,
1310 GTPCAUSE_OPT_IE_INCORRECT);
1311 }
jjako2c381332003-10-21 19:09:53 +00001312
Harald Weltebed35df2011-11-02 13:06:18 +01001313 /* Check that the primary PDP context matches linked nsapi */
1314 if (linked_pdp->nsapi != linked_nsapi) {
1315 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001316 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001317 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001318 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001319 return gtp_create_pdp_resp(gsn, version, pdp,
1320 GTPCAUSE_OPT_IE_INCORRECT);
1321 }
jjako52c24142002-12-16 13:33:51 +00001322
Harald Weltebed35df2011-11-02 13:06:18 +01001323 /* Copy parameters from primary context */
1324 pdp->selmode = linked_pdp->selmode;
1325 pdp->imsi = linked_pdp->imsi;
1326 pdp->msisdn = linked_pdp->msisdn;
1327 pdp->eua = linked_pdp->eua;
1328 pdp->pco_req = linked_pdp->pco_req;
1329 pdp->apn_req = linked_pdp->apn_req;
1330 pdp->teic_gn = linked_pdp->teic_gn;
1331 pdp->secondary = 1;
1332 }
1333 }
1334 /* if (version == 1) */
1335 if (version == 0) {
1336 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1337 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1338 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001339 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1340 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001341 return gtp_create_pdp_resp(gsn, version, pdp,
1342 GTPCAUSE_MAN_IE_MISSING);
1343 }
1344 }
jjako08d331d2003-10-13 20:33:30 +00001345
Harald Weltebed35df2011-11-02 13:06:18 +01001346 if ((version == 1) && (!linked_pdp)) {
1347 /* Not Secondary PDP Context Activation Procedure */
1348 /* IMSI (conditional) */
1349 if (gtpie_gettv0
1350 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1351 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001352 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1353 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001354 return gtp_create_pdp_resp(gsn, version, pdp,
1355 GTPCAUSE_MAN_IE_MISSING);
1356 }
1357 }
jjako52c24142002-12-16 13:33:51 +00001358
Harald Weltebed35df2011-11-02 13:06:18 +01001359 /* Recovery (optional) */
1360 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1361 if (gsn->cb_recovery)
1362 gsn->cb_recovery(peer, recovery);
1363 }
jjako52c24142002-12-16 13:33:51 +00001364
Harald Weltebed35df2011-11-02 13:06:18 +01001365 /* Selection mode (conditional) */
1366 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1367 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1368 &pdp->selmode, sizeof(pdp->selmode))) {
1369 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001370 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1371 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001372 return gtp_create_pdp_resp(gsn, version, pdp,
1373 GTPCAUSE_MAN_IE_MISSING);
1374 }
1375 }
jjako52c24142002-12-16 13:33:51 +00001376
Harald Weltebed35df2011-11-02 13:06:18 +01001377 if (version == 0) {
1378 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1379 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001380 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1381 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001382 return gtp_create_pdp_resp(gsn, version, pdp,
1383 GTPCAUSE_MAN_IE_MISSING);
1384 }
jjako52c24142002-12-16 13:33:51 +00001385
Harald Weltebed35df2011-11-02 13:06:18 +01001386 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1387 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001388 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1389 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001390 return gtp_create_pdp_resp(gsn, version, pdp,
1391 GTPCAUSE_MAN_IE_MISSING);
1392 }
1393 }
jjako08d331d2003-10-13 20:33:30 +00001394
Harald Weltebed35df2011-11-02 13:06:18 +01001395 if (version == 1) {
1396 /* TEID (mandatory) */
1397 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1398 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001399 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1400 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001401 return gtp_create_pdp_resp(gsn, version, pdp,
1402 GTPCAUSE_MAN_IE_MISSING);
1403 }
jjako2c381332003-10-21 19:09:53 +00001404
Harald Weltebed35df2011-11-02 13:06:18 +01001405 /* TEIC (conditional) */
1406 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1407 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1408 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001409 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001410 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001411 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001412 return gtp_create_pdp_resp(gsn, version, pdp,
1413 GTPCAUSE_MAN_IE_MISSING);
1414 }
1415 }
jjako08d331d2003-10-13 20:33:30 +00001416
Harald Weltebed35df2011-11-02 13:06:18 +01001417 /* NSAPI (mandatory) */
1418 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1419 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001420 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1421 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001422 return gtp_create_pdp_resp(gsn, version, pdp,
1423 GTPCAUSE_MAN_IE_MISSING);
1424 }
1425 }
jjako2e840a32003-01-28 16:05:18 +00001426
Harald Weltebed35df2011-11-02 13:06:18 +01001427 /* Charging Characteriatics (optional) */
1428 /* Trace reference (optional) */
1429 /* Trace type (optional) */
1430 /* Charging Characteriatics (optional) */
jjako52c24142002-12-16 13:33:51 +00001431
Harald Weltebed35df2011-11-02 13:06:18 +01001432 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1433 /* End User Address (conditional) */
1434 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1435 &pdp->eua.v, sizeof(pdp->eua.v))) {
1436 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001437 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1438 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001439 return gtp_create_pdp_resp(gsn, version, pdp,
1440 GTPCAUSE_MAN_IE_MISSING);
1441 }
jjako08d331d2003-10-13 20:33:30 +00001442
Harald Weltebed35df2011-11-02 13:06:18 +01001443 /* APN */
1444 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1445 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1446 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001447 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1448 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001449 return gtp_create_pdp_resp(gsn, version, pdp,
1450 GTPCAUSE_MAN_IE_MISSING);
1451 }
jjako2c381332003-10-21 19:09:53 +00001452
Harald Weltebed35df2011-11-02 13:06:18 +01001453 /* Extract protocol configuration options (optional) */
1454 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1455 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1456 }
1457 }
jjako2c381332003-10-21 19:09:53 +00001458
Harald Weltebed35df2011-11-02 13:06:18 +01001459 /* SGSN address for signalling (mandatory) */
1460 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1461 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1462 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001463 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1464 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001465 return gtp_create_pdp_resp(gsn, version, pdp,
1466 GTPCAUSE_MAN_IE_MISSING);
1467 }
jjako2e840a32003-01-28 16:05:18 +00001468
Harald Weltebed35df2011-11-02 13:06:18 +01001469 /* SGSN address for user traffic (mandatory) */
1470 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1471 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1472 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001473 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1474 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001475 return gtp_create_pdp_resp(gsn, version, pdp,
1476 GTPCAUSE_MAN_IE_MISSING);
1477 }
jjako52c24142002-12-16 13:33:51 +00001478
Harald Weltebed35df2011-11-02 13:06:18 +01001479 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1480 /* MSISDN (conditional) */
1481 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1482 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1483 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001484 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1485 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001486 return gtp_create_pdp_resp(gsn, version, pdp,
1487 GTPCAUSE_MAN_IE_MISSING);
1488 }
1489 }
jjako52c24142002-12-16 13:33:51 +00001490
Harald Weltebed35df2011-11-02 13:06:18 +01001491 if (version == 1) {
1492 /* QoS (mandatory) */
1493 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1494 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1495 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001496 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1497 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001498 return gtp_create_pdp_resp(gsn, version, pdp,
1499 GTPCAUSE_MAN_IE_MISSING);
1500 }
1501
1502 /* TFT (conditional) */
1503 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1504 &pdp->tft.v, sizeof(pdp->tft.v))) {
1505 }
1506
1507 /* Trigger ID */
1508 /* OMC identity */
1509 }
1510
1511 /* Initialize our own IP addresses */
1512 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1513 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1514
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001515 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001516
1517 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1518 /* Found old pdp with same tid. Now the voodoo begins! */
1519 /* 09.60 / 29.060 allows create on existing context to "steal" */
1520 /* the context which was allready established */
1521 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001522 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001523 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1524 &&
1525 (!memcmp
1526 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1527 && (pdp->selmode == pdp_old->selmode)
1528 && (pdp->msisdn.l == pdp_old->msisdn.l)
1529 &&
1530 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1531 {
1532 /* OK! We are dealing with the same APN. We will copy new
1533 * parameters to the old pdp and send off confirmation
1534 * We ignore the following information elements:
1535 * QoS: MS will get originally negotiated QoS.
1536 * End user address (EUA). MS will get old EUA anyway.
1537 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001538 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001539
1540 /* Copy remote flow label */
1541 pdp_old->flru = pdp->flru;
1542 pdp_old->flrc = pdp->flrc;
1543
1544 /* Copy remote tei */
1545 pdp_old->teid_gn = pdp->teid_gn;
1546 pdp_old->teic_gn = pdp->teic_gn;
1547
1548 /* Copy peer GSN address */
1549 pdp_old->gsnrc.l = pdp->gsnrc.l;
1550 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1551 pdp_old->gsnru.l = pdp->gsnru.l;
1552 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1553
1554 /* Copy request parameters */
1555 pdp_old->seq = pdp->seq;
1556 pdp_old->sa_peer = pdp->sa_peer;
1557 pdp_old->fd = pdp->fd = fd;
1558 pdp_old->version = pdp->version = version;
1559
1560 /* Switch to using the old pdp context */
1561 pdp = pdp_old;
1562
1563 /* Confirm to peer that things were "successful" */
1564 return gtp_create_pdp_resp(gsn, version, pdp,
1565 GTPCAUSE_ACC_REQ);
1566 } else { /* This is not the same PDP context. Delete the old one. */
1567
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001568 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001569
1570 if (gsn->cb_delete_context)
1571 gsn->cb_delete_context(pdp_old);
1572 pdp_freepdp(pdp_old);
1573
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001574 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001575 }
1576 }
1577
1578 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
Harald Weltee257be12017-08-12 14:55:09 +02001579 if (pdp)
1580 pdp->gsn = gsn;
Harald Weltebed35df2011-11-02 13:06:18 +01001581
1582 /* Callback function to validata login */
1583 if (gsn->cb_create_context_ind != 0)
1584 return gsn->cb_create_context_ind(pdp);
1585 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001586 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1587 "No create_context_ind callback defined\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001588 return gtp_create_pdp_resp(gsn, version, pdp,
1589 GTPCAUSE_NOT_SUPPORTED);
1590 }
jjako52c24142002-12-16 13:33:51 +00001591}
1592
jjako52c24142002-12-16 13:33:51 +00001593/* Handle Create PDP Context Response */
1594int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001595 struct sockaddr_in *peer, void *pack, unsigned len)
1596{
1597 struct pdp_t *pdp;
1598 union gtpie_member *ie[GTPIE_SIZE];
1599 uint8_t cause, recovery;
1600 void *cbp = NULL;
1601 uint8_t type = 0;
1602 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001603
Harald Weltebed35df2011-11-02 13:06:18 +01001604 /* Remove packet from queue */
1605 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1606 return EOF;
jjako52c24142002-12-16 13:33:51 +00001607
Harald Weltebed35df2011-11-02 13:06:18 +01001608 /* Find the context in question */
1609 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1610 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001611 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001612 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001613 if (gsn->cb_conf)
1614 gsn->cb_conf(type, EOF, NULL, cbp);
1615 return EOF;
1616 }
jjako2c381332003-10-21 19:09:53 +00001617
Harald Weltebed35df2011-11-02 13:06:18 +01001618 /* Register that we have received a valid teic from GGSN */
1619 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001620
Harald Weltebed35df2011-11-02 13:06:18 +01001621 /* Decode information elements */
1622 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1623 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001624 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1625 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001626 if (gsn->cb_conf)
1627 gsn->cb_conf(type, EOF, pdp, cbp);
1628 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1629 pdp_freepdp(pdp); */
1630 return EOF;
1631 }
jjako52c24142002-12-16 13:33:51 +00001632
Harald Weltebed35df2011-11-02 13:06:18 +01001633 /* Extract cause value (mandatory) */
1634 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1635 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001636 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1637 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001638 if (gsn->cb_conf)
1639 gsn->cb_conf(type, EOF, pdp, cbp);
1640 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1641 pdp_freepdp(pdp); */
1642 return EOF;
1643 }
jjako52c24142002-12-16 13:33:51 +00001644
Harald Weltebed35df2011-11-02 13:06:18 +01001645 /* Extract recovery (optional) */
1646 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1647 if (gsn->cb_recovery)
1648 gsn->cb_recovery(peer, recovery);
1649 }
jjako52c24142002-12-16 13:33:51 +00001650
Harald Weltebed35df2011-11-02 13:06:18 +01001651 /* Extract protocol configuration options (optional) */
1652 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1653 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1654 }
jjako52c24142002-12-16 13:33:51 +00001655
Harald Weltebed35df2011-11-02 13:06:18 +01001656 /* Check all conditional information elements */
1657 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001658
Harald Weltebed35df2011-11-02 13:06:18 +01001659 if (version == 0) {
1660 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1661 &pdp->qos_neg0,
1662 sizeof(pdp->qos_neg0))) {
1663 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001664 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001665 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001666 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001667 if (gsn->cb_conf)
1668 gsn->cb_conf(type, EOF, pdp, cbp);
1669 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1670 pdp_freepdp(pdp); */
1671 return EOF;
1672 }
1673 }
jjako08d331d2003-10-13 20:33:30 +00001674
Harald Weltebed35df2011-11-02 13:06:18 +01001675 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1676 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001677 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001678 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001679 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001680 if (gsn->cb_conf)
1681 gsn->cb_conf(type, EOF, pdp, cbp);
1682 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1683 pdp_freepdp(pdp); */
1684 return EOF;
1685 }
jjako52c24142002-12-16 13:33:51 +00001686
Harald Weltebed35df2011-11-02 13:06:18 +01001687 if (version == 0) {
1688 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1689 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001690 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001691 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001692 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001693 if (gsn->cb_conf)
1694 gsn->cb_conf(type, EOF, pdp, cbp);
1695 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1696 pdp_freepdp(pdp); */
1697 return EOF;
1698 }
jjako52c24142002-12-16 13:33:51 +00001699
Harald Weltebed35df2011-11-02 13:06:18 +01001700 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1701 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001702 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001703 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001704 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001705 if (gsn->cb_conf)
1706 gsn->cb_conf(type, EOF, pdp, cbp);
1707 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1708 pdp_freepdp(pdp); */
1709 return EOF;
1710 }
1711 }
1712
1713 if (version == 1) {
1714 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1715 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001716 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001717 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001718 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001719 if (gsn->cb_conf)
1720 gsn->cb_conf(type, EOF, pdp, cbp);
1721 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1722 pdp_freepdp(pdp); */
1723 return EOF;
1724 }
1725
1726 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1727 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001728 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001729 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001730 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001731 if (gsn->cb_conf)
1732 gsn->cb_conf(type, EOF, pdp, cbp);
1733 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1734 pdp_freepdp(pdp); */
1735 return EOF;
1736 }
1737 }
1738
1739 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1740 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001741 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001742 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001743 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001744 if (gsn->cb_conf)
1745 gsn->cb_conf(type, EOF, pdp, cbp);
1746 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1747 pdp_freepdp(pdp); */
1748 }
1749
1750 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1751 &pdp->eua.v, sizeof(pdp->eua.v))) {
1752 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001753 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001754 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001755 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001756 if (gsn->cb_conf)
1757 gsn->cb_conf(type, EOF, pdp, cbp);
1758 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1759 pdp_freepdp(pdp); */
1760 return EOF;
1761 }
1762
1763 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1764 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1765 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001766 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001767 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001768 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001769 if (gsn->cb_conf)
1770 gsn->cb_conf(type, EOF, pdp, cbp);
1771 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1772 pdp_freepdp(pdp); */
1773 return EOF;
1774 }
1775
1776 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1777 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1778 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001779 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001780 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001781 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001782 if (gsn->cb_conf)
1783 gsn->cb_conf(type, EOF, pdp, cbp);
1784 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1785 pdp_freepdp(pdp); */
1786 return EOF;
1787 }
1788
1789 if (version == 1) {
1790 if (gtpie_gettlv
1791 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1792 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1793 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001794 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001795 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001796 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001797 if (gsn->cb_conf)
1798 gsn->cb_conf(type, EOF, pdp, cbp);
1799 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1800 pdp_freepdp(pdp); */
1801 return EOF;
1802 }
1803 }
1804
1805 }
1806
1807 if (gsn->cb_conf)
1808 gsn->cb_conf(type, cause, pdp, cbp);
1809
1810 return 0;
jjako52c24142002-12-16 13:33:51 +00001811}
1812
jjako08d331d2003-10-13 20:33:30 +00001813/* API: Send Update PDP Context Request */
1814int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001815 struct in_addr *inetaddr)
1816{
1817 union gtp_packet packet;
1818 unsigned int length =
1819 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001820
Harald Weltebed35df2011-11-02 13:06:18 +01001821 if (pdp->version == 0)
1822 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1823 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001824
Harald Weltebed35df2011-11-02 13:06:18 +01001825 /* Include IMSI if updating with unknown teic_gn */
1826 if ((pdp->version == 1) && (!pdp->teic_gn))
1827 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1828 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1829
1830 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1831 gsn->restart_counter);
1832
1833 if (pdp->version == 0) {
1834 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1835 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1836 }
1837
1838 if (pdp->version == 1) {
1839 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1840 pdp->teid_own);
1841
1842 if (!pdp->teic_confirmed)
1843 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1844 pdp->teic_own);
1845 }
1846
1847 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1848
1849 /* TODO
1850 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1851 pdp->traceref);
1852 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1853 pdp->tracetype); */
1854
1855 /* TODO if ggsn update message
1856 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1857 pdp->eua.l, pdp->eua.v);
1858 */
1859
1860 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1861 pdp->gsnlc.l, pdp->gsnlc.v);
1862 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1863 pdp->gsnlu.l, pdp->gsnlu.v);
1864
1865 if (pdp->version == 1)
1866 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1867 pdp->qos_req.l, pdp->qos_req.v);
1868
1869 if ((pdp->version == 1) && pdp->tft.l)
1870 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1871 pdp->tft.l, pdp->tft.v);
1872
1873 if ((pdp->version == 1) && pdp->triggerid.l)
1874 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1875 pdp->triggerid.l, pdp->triggerid.v);
1876
1877 if ((pdp->version == 1) && pdp->omcid.l)
1878 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1879 pdp->omcid.l, pdp->omcid.v);
1880
Daniel Willmann134a7752016-02-03 18:53:29 +01001881 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001882
1883 return 0;
jjako52c24142002-12-16 13:33:51 +00001884}
1885
jjako08d331d2003-10-13 20:33:30 +00001886/* Send Update PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001887int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
1888 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001889 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001890 struct pdp_t *pdp, uint8_t cause)
1891{
jjako08d331d2003-10-13 20:33:30 +00001892
Harald Weltebed35df2011-11-02 13:06:18 +01001893 union gtp_packet packet;
1894 unsigned int length =
1895 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001896
Harald Weltebed35df2011-11-02 13:06:18 +01001897 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001898
Harald Weltebed35df2011-11-02 13:06:18 +01001899 if (cause == GTPCAUSE_ACC_REQ) {
1900
1901 if (version == 0)
1902 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1903 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1904
1905 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1906 gsn->restart_counter);
1907
1908 if (version == 0) {
1909 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1910 pdp->fllu);
1911 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1912 pdp->fllc);
1913 }
1914
1915 if (version == 1) {
1916 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1917 pdp->teid_own);
1918
1919 if (!pdp->teic_confirmed)
1920 gtpie_tv4(&packet, &length, GTP_MAX,
1921 GTPIE_TEI_C, pdp->teic_own);
1922 }
1923
1924 /* TODO we use teid_own as charging ID address */
1925 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1926 pdp->teid_own);
1927
1928 /* If ggsn
1929 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1930 pdp->eua.l, pdp->eua.v); */
1931
1932 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1933 pdp->gsnlc.l, pdp->gsnlc.v);
1934 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1935 pdp->gsnlu.l, pdp->gsnlu.v);
1936
1937 if (version == 1)
1938 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1939 pdp->qos_neg.l, pdp->qos_neg.v);
1940
1941 /* TODO: Charging gateway address */
1942 }
1943
1944 return gtp_resp(version, gsn, pdp, &packet, length, peer,
1945 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00001946}
1947
jjako52c24142002-12-16 13:33:51 +00001948/* Handle Update PDP Context Request */
1949int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001950 struct sockaddr_in *peer, int fd,
1951 void *pack, unsigned len)
1952{
1953 struct pdp_t *pdp;
1954 struct pdp_t pdp_backup;
1955 union gtpie_member *ie[GTPIE_SIZE];
1956 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001957
Harald Weltebed35df2011-11-02 13:06:18 +01001958 uint16_t seq = get_seq(pack);
1959 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001960
Harald Weltebed35df2011-11-02 13:06:18 +01001961 uint64_t imsi;
1962 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00001963
Harald Weltebed35df2011-11-02 13:06:18 +01001964 /* Is this a dublicate ? */
1965 if (!gtp_dublicate(gsn, version, peer, seq)) {
1966 return 0; /* We allready send of response once */
1967 }
jjako08d331d2003-10-13 20:33:30 +00001968
Harald Weltebed35df2011-11-02 13:06:18 +01001969 /* Decode information elements */
1970 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1971 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001972 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1973 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001974 if (0 == version)
1975 return EOF;
1976 else
1977 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
1978 len, NULL,
1979 GTPCAUSE_INVALID_MESSAGE);
1980 }
jjako08d331d2003-10-13 20:33:30 +00001981
Harald Weltebed35df2011-11-02 13:06:18 +01001982 /* Finding PDP: */
1983 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
1984 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
1985 /* we have to use the tunnel endpoint identifier */
1986 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001987 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1988
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001989 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00001990
Harald Weltebed35df2011-11-02 13:06:18 +01001991 /* Find the context in question */
1992 if (pdp_getimsi(&pdp, imsi, nsapi)) {
1993 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001994 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1995 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001996 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
1997 len, NULL,
1998 GTPCAUSE_NON_EXIST);
1999 }
2000 } else if (version == 1) {
2001 /* NSAPI (mandatory) */
2002 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2003 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002004 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2005 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002006 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2007 len, NULL,
2008 GTPCAUSE_MAN_IE_MISSING);
2009 }
jjako08d331d2003-10-13 20:33:30 +00002010
Harald Weltebed35df2011-11-02 13:06:18 +01002011 /* IMSI (conditional) */
2012 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2013 /* Find the context in question */
2014 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2015 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002016 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002017 pack, len, "Unknown PDP context: %u\n",
2018 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002019 return gtp_update_pdp_resp(gsn, version, peer,
2020 fd, pack, len, NULL,
2021 GTPCAUSE_NON_EXIST);
2022 }
2023 } else {
2024 /* Find the context in question */
2025 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2026 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002027 GTP_LOGPKG(LOGL_ERROR, peer,
2028 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002029 return gtp_update_pdp_resp(gsn, version, peer,
2030 fd, pack, len, NULL,
2031 GTPCAUSE_NON_EXIST);
2032 }
2033 }
2034 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002035 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002036 return EOF;
2037 }
jjako08d331d2003-10-13 20:33:30 +00002038
Harald Weltebed35df2011-11-02 13:06:18 +01002039 /* Make a backup copy in case anything is wrong */
2040 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002041
Harald Weltebed35df2011-11-02 13:06:18 +01002042 if (version == 0) {
2043 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2044 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2045 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002046 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2047 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002048 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2049 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2050 len, pdp,
2051 GTPCAUSE_MAN_IE_MISSING);
2052 }
2053 }
jjako52c24142002-12-16 13:33:51 +00002054
Harald Weltebed35df2011-11-02 13:06:18 +01002055 /* Recovery (optional) */
2056 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2057 if (gsn->cb_recovery)
2058 gsn->cb_recovery(peer, recovery);
2059 }
jjako08d331d2003-10-13 20:33:30 +00002060
Harald Weltebed35df2011-11-02 13:06:18 +01002061 if (version == 0) {
2062 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2063 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002064 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2065 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002066 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2067 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2068 len, pdp,
2069 GTPCAUSE_MAN_IE_MISSING);
2070 }
jjako52c24142002-12-16 13:33:51 +00002071
Harald Weltebed35df2011-11-02 13:06:18 +01002072 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2073 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002074 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2075 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002076 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2077 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2078 len, pdp,
2079 GTPCAUSE_MAN_IE_MISSING);
2080 }
2081 }
jjako52c24142002-12-16 13:33:51 +00002082
Harald Weltebed35df2011-11-02 13:06:18 +01002083 if (version == 1) {
2084 /* TEID (mandatory) */
2085 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2086 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002087 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2088 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002089 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2090 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2091 len, pdp,
2092 GTPCAUSE_MAN_IE_MISSING);
2093 }
jjako52c24142002-12-16 13:33:51 +00002094
Harald Weltebed35df2011-11-02 13:06:18 +01002095 /* TEIC (conditional) */
2096 /* If TEIC is not included it means that we have allready received it */
2097 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2098 /* all updated contexts, or only for one of the linked contexts */
2099 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2100
2101 /* NSAPI (mandatory) */
2102 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2103 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002104 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2105 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002106 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2107 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2108 len, pdp,
2109 GTPCAUSE_MAN_IE_MISSING);
2110 }
2111 }
2112
2113 /* Trace reference (optional) */
2114 /* Trace type (optional) */
2115
2116 /* End User Address (conditional) TODO: GGSN Initiated
2117 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2118 &pdp->eua.v, sizeof(pdp->eua.v))) {
2119 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002120 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002121 "Missing mandatory information field");
2122 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2123 return gtp_update_pdp_resp(gsn, version, pdp,
2124 GTPCAUSE_MAN_IE_MISSING);
2125 } */
2126
2127 /* SGSN address for signalling (mandatory) */
2128 /* It is weird that this is mandatory when TEIC is conditional */
2129 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2130 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2131 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002132 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2133 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002134 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2135 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2136 pdp, GTPCAUSE_MAN_IE_MISSING);
2137 }
2138
2139 /* SGSN address for user traffic (mandatory) */
2140 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2141 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2142 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002143 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2144 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002145 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2146 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2147 pdp, GTPCAUSE_MAN_IE_MISSING);
2148 }
2149
2150 if (version == 1) {
2151 /* QoS (mandatory) */
2152 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2153 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2154 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002155 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2156 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002157 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2158 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2159 len, pdp,
2160 GTPCAUSE_MAN_IE_MISSING);
2161 }
2162
2163 /* TFT (conditional) */
2164 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2165 &pdp->tft.v, sizeof(pdp->tft.v))) {
2166 }
2167
2168 /* OMC identity */
2169 }
2170
2171 /* Confirm to peer that things were "successful" */
2172 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2173 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002174}
2175
jjako52c24142002-12-16 13:33:51 +00002176/* Handle Update PDP Context Response */
2177int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002178 struct sockaddr_in *peer, void *pack, unsigned len)
2179{
2180 struct pdp_t *pdp;
2181 union gtpie_member *ie[GTPIE_SIZE];
2182 uint8_t cause, recovery;
2183 void *cbp = NULL;
2184 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002185 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002186
Harald Weltebed35df2011-11-02 13:06:18 +01002187 /* Remove packet from queue */
2188 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2189 return EOF;
jjako52c24142002-12-16 13:33:51 +00002190
Harald Weltebed35df2011-11-02 13:06:18 +01002191 /* Find the context in question */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002192 if (pdp_getgtp1(&pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002193 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002194 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002195 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002196 pdp = NULL;
2197 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002198 }
jjako2c381332003-10-21 19:09:53 +00002199
Harald Weltebed35df2011-11-02 13:06:18 +01002200 /* Register that we have received a valid teic from GGSN */
2201 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002202
Harald Weltebed35df2011-11-02 13:06:18 +01002203 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002204 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002205 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002206 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2207 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002208 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002209 }
jjako52c24142002-12-16 13:33:51 +00002210
Harald Weltebed35df2011-11-02 13:06:18 +01002211 /* Extract cause value (mandatory) */
2212 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002213 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002214 }
jjako52c24142002-12-16 13:33:51 +00002215
Harald Weltebed35df2011-11-02 13:06:18 +01002216 /* Extract recovery (optional) */
2217 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2218 if (gsn->cb_recovery)
2219 gsn->cb_recovery(peer, recovery);
2220 }
2221
2222 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002223 /* TODO: This does not handle GGSN-initiated update responses */
2224 if (GTPCAUSE_ACC_REQ == cause) {
2225 if (version == 0) {
2226 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2227 &pdp->qos_neg0,
2228 sizeof(pdp->qos_neg0))) {
2229 goto err_missing;
2230 }
2231
2232 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2233 goto err_missing;
2234 }
2235
2236 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2237 goto err_missing;
2238 }
Harald Weltebed35df2011-11-02 13:06:18 +01002239 }
2240
Daniel Willmannd9975522016-02-04 15:38:12 +01002241 if (version == 1) {
2242 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2243 goto err_missing;
2244 }
Harald Weltebed35df2011-11-02 13:06:18 +01002245
Daniel Willmannd9975522016-02-04 15:38:12 +01002246 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2247 goto err_missing;
2248 }
2249 }
2250
2251 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2252 goto err_missing;
2253 }
2254
2255 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2256 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2257 goto err_missing;
2258 }
2259
2260 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2261 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2262 goto err_missing;
2263 }
2264
2265 if (version == 1) {
2266 if (gtpie_gettlv
2267 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2268 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2269 goto err_missing;
2270 }
2271 }
Harald Weltebed35df2011-11-02 13:06:18 +01002272 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002273
2274 if (gsn->cb_conf)
2275 gsn->cb_conf(type, cause, pdp, cbp);
2276 return 0; /* Succes */
2277
2278err_missing:
2279 gsn->missing++;
2280 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2281 "Missing information field\n");
2282err_out:
2283 if (gsn->cb_conf)
2284 gsn->cb_conf(type, EOF, pdp, cbp);
2285 return EOF;
jjako52c24142002-12-16 13:33:51 +00002286}
2287
jjako08d331d2003-10-13 20:33:30 +00002288/* API: Send Delete PDP Context Request */
jjako2c381332003-10-21 19:09:53 +00002289int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002290 int teardown)
2291{
2292 union gtp_packet packet;
2293 unsigned int length =
2294 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2295 struct in_addr addr;
2296 struct pdp_t *linked_pdp;
2297 struct pdp_t *secondary_pdp;
2298 int n;
2299 int count = 0;
jjako2c381332003-10-21 19:09:53 +00002300
Harald Weltebed35df2011-11-02 13:06:18 +01002301 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2302 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002303 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002304 return EOF;
jjako2c381332003-10-21 19:09:53 +00002305 }
jjako2c381332003-10-21 19:09:53 +00002306
Harald Weltebed35df2011-11-02 13:06:18 +01002307 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002308 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002309 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002310 return EOF;
2311 }
2312
2313 if (!teardown) {
2314 for (n = 0; n < PDP_MAXNSAPI; n++)
2315 if (linked_pdp->secondary_tei[n])
2316 count++;
2317 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002318 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002319 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002320 return EOF;
2321 }
2322 }
2323
2324 if (pdp->version == 1) {
2325 if (teardown)
2326 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2327 0xff);
2328
2329 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2330 }
2331
2332 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2333
2334 if (teardown) { /* Remove all contexts */
2335 for (n = 0; n < PDP_MAXNSAPI; n++) {
2336 if (linked_pdp->secondary_tei[n]) {
2337 if (pdp_getgtp1
2338 (&secondary_pdp,
2339 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002340 LOGP(DLGTP, LOGL_ERROR,
2341 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002342 return EOF;
2343 }
2344 if (linked_pdp != secondary_pdp) {
2345 if (gsn->cb_delete_context)
2346 gsn->cb_delete_context
2347 (secondary_pdp);
2348 pdp_freepdp(secondary_pdp);
2349 }
2350 }
2351 }
2352 if (gsn->cb_delete_context)
2353 gsn->cb_delete_context(linked_pdp);
2354 pdp_freepdp(linked_pdp);
2355 } else {
2356 if (gsn->cb_delete_context)
2357 gsn->cb_delete_context(pdp);
2358 if (pdp == linked_pdp) {
2359 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2360 linked_pdp->nodata = 1;
2361 } else
2362 pdp_freepdp(pdp);
2363 }
2364
2365 return 0;
jjako2c381332003-10-21 19:09:53 +00002366}
jjako08d331d2003-10-13 20:33:30 +00002367
jjako52c24142002-12-16 13:33:51 +00002368/* Send Delete PDP Context Response */
2369int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002370 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002371 void *pack, unsigned len,
2372 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002373 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002374{
Harald Weltebed35df2011-11-02 13:06:18 +01002375 union gtp_packet packet;
2376 struct pdp_t *secondary_pdp;
2377 unsigned int length =
2378 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2379 int n;
jjako52c24142002-12-16 13:33:51 +00002380
Harald Weltebed35df2011-11-02 13:06:18 +01002381 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002382
Harald Weltebed35df2011-11-02 13:06:18 +01002383 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2384 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002385
Harald Weltebed35df2011-11-02 13:06:18 +01002386 if (cause == GTPCAUSE_ACC_REQ) {
2387 if ((teardown) || (version == 0)) { /* Remove all contexts */
2388 for (n = 0; n < PDP_MAXNSAPI; n++) {
2389 if (linked_pdp->secondary_tei[n]) {
2390 if (pdp_getgtp1
2391 (&secondary_pdp,
2392 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002393 LOGP(DLGTP, LOGL_ERROR,
2394 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002395 return EOF;
2396 }
2397 if (linked_pdp != secondary_pdp) {
2398 if (gsn->cb_delete_context)
2399 gsn->cb_delete_context
2400 (secondary_pdp);
2401 pdp_freepdp(secondary_pdp);
2402 }
2403 }
2404 }
2405 if (gsn->cb_delete_context)
2406 gsn->cb_delete_context(linked_pdp);
2407 pdp_freepdp(linked_pdp);
2408 } else { /* Remove only current context */
2409 if (gsn->cb_delete_context)
2410 gsn->cb_delete_context(pdp);
2411 if (pdp == linked_pdp) {
2412 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2413 0;
2414 linked_pdp->nodata = 1;
2415 } else
2416 pdp_freepdp(pdp);
2417 }
jjako2c381332003-10-21 19:09:53 +00002418 }
Harald Weltebed35df2011-11-02 13:06:18 +01002419 /* if (cause == GTPCAUSE_ACC_REQ) */
2420 return 0;
jjako52c24142002-12-16 13:33:51 +00002421}
2422
2423/* Handle Delete PDP Context Request */
2424int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002425 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002426 void *pack, unsigned len)
2427{
2428 struct pdp_t *pdp = NULL;
2429 struct pdp_t *linked_pdp = NULL;
2430 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002431
Harald Weltebed35df2011-11-02 13:06:18 +01002432 uint16_t seq = get_seq(pack);
2433 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002434
Harald Weltebed35df2011-11-02 13:06:18 +01002435 uint8_t nsapi;
2436 uint8_t teardown = 0;
2437 int n;
2438 int count = 0;
jjako52c24142002-12-16 13:33:51 +00002439
Harald Weltebed35df2011-11-02 13:06:18 +01002440 /* Is this a dublicate ? */
2441 if (!gtp_dublicate(gsn, version, peer, seq)) {
2442 return 0; /* We allready send off response once */
2443 }
jjako2c381332003-10-21 19:09:53 +00002444
Harald Weltebed35df2011-11-02 13:06:18 +01002445 /* Find the linked context in question */
2446 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2447 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002448 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002449 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002450 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2451 NULL, NULL, GTPCAUSE_NON_EXIST,
2452 teardown);
2453 }
jjako2c381332003-10-21 19:09:53 +00002454
Harald Weltebed35df2011-11-02 13:06:18 +01002455 /* If version 0 this is also the secondary context */
2456 if (version == 0)
2457 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002458
Harald Weltebed35df2011-11-02 13:06:18 +01002459 /* Decode information elements */
2460 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2461 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002462 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2463 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002464 if (0 == version)
2465 return EOF;
2466 else
2467 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2468 len, NULL, NULL,
2469 GTPCAUSE_INVALID_MESSAGE,
2470 teardown);
2471 }
2472
2473 if (version == 1) {
2474 /* NSAPI (mandatory) */
2475 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2476 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002477 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2478 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002479 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2480 len, NULL, NULL,
2481 GTPCAUSE_MAN_IE_MISSING,
2482 teardown);
2483 }
2484
2485 /* Find the context in question */
2486 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2487 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002488 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2489 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002490 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2491 len, NULL, NULL,
2492 GTPCAUSE_NON_EXIST,
2493 teardown);
2494 }
2495
2496 /* Teardown (conditional) */
2497 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2498
2499 if (!teardown) {
2500 for (n = 0; n < PDP_MAXNSAPI; n++)
2501 if (linked_pdp->secondary_tei[n])
2502 count++;
2503 if (count <= 1) {
2504 return 0; /* 29.060 7.3.5 Ignore message */
2505 }
2506 }
2507 }
2508
2509 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2510 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002511}
2512
jjako52c24142002-12-16 13:33:51 +00002513/* Handle Delete PDP Context Response */
2514int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002515 struct sockaddr_in *peer, void *pack, unsigned len)
2516{
2517 union gtpie_member *ie[GTPIE_SIZE];
2518 uint8_t cause;
2519 void *cbp = NULL;
2520 uint8_t type = 0;
2521 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002522
Harald Weltebed35df2011-11-02 13:06:18 +01002523 /* Remove packet from queue */
2524 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2525 return EOF;
jjako52c24142002-12-16 13:33:51 +00002526
Harald Weltebed35df2011-11-02 13:06:18 +01002527 /* Decode information elements */
2528 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2529 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002530 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2531 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002532 if (gsn->cb_conf)
2533 gsn->cb_conf(type, EOF, NULL, cbp);
2534 return EOF;
2535 }
2536
2537 /* Extract cause value (mandatory) */
2538 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2539 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002540 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2541 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002542 if (gsn->cb_conf)
2543 gsn->cb_conf(type, EOF, NULL, cbp);
2544 return EOF;
2545 }
2546
2547 /* Check the cause value (again) */
2548 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2549 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002550 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2551 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002552 if (gsn->cb_conf)
2553 gsn->cb_conf(type, cause, NULL, cbp);
2554 return EOF;
2555 }
2556
2557 /* Callback function to notify application */
2558 if (gsn->cb_conf)
2559 gsn->cb_conf(type, cause, NULL, cbp);
2560
2561 return 0;
jjako52c24142002-12-16 13:33:51 +00002562}
2563
Harald Welte54d082e2017-08-12 22:43:21 +02002564/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
jjako52c24142002-12-16 13:33:51 +00002565int gtp_error_ind_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002566 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002567 void *pack, unsigned len)
2568{
Harald Weltebed35df2011-11-02 13:06:18 +01002569 union gtp_packet packet;
2570 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2571
Harald Welte54d082e2017-08-12 22:43:21 +02002572 if (version == 1) {
2573 /* Mandatory 7.7.13 TEI Data I */
2574 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2575 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2576
2577 /* Mandatory 7.7.32 GSN Address */
2578 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2579 sizeof(gsn->gsnu), &gsn->gsnu);
2580 }
2581
Harald Weltebed35df2011-11-02 13:06:18 +01002582 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2583 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002584}
2585
2586/* Handle Error Indication */
2587int gtp_error_ind_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002588 struct sockaddr_in *peer, void *pack, unsigned len)
2589{
Harald Welte37d5b152017-08-12 23:58:29 +02002590 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002591 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002592
Harald Weltebed35df2011-11-02 13:06:18 +01002593 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002594 if (version == 0) {
2595 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
2596 gsn->err_unknownpdp++;
2597 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2598 "Unknown PDP context\n");
2599 return EOF;
2600 }
2601 } else if (version == 1) {
2602 /* we have to look-up based on the *peer* TEID */
2603 int hlen = get_hlen(pack);
2604 uint32_t teid_gn;
2605
2606 /* Decode information elements */
2607 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2608 gsn->invalid++;
2609 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2610 "Invalid message format\n");
2611 return EOF;
2612 }
2613
2614 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2615 gsn->missing++;
2616 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2617 "Missing mandatory information field\n");
2618 return EOF;
2619 }
2620
2621 if (pdp_getgtp1_peer_d(&pdp, peer, teid_gn)) {
2622 gsn->err_unknownpdp++;
2623 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2624 return EOF;
2625 }
Harald Weltebed35df2011-11-02 13:06:18 +01002626 }
jjako52c24142002-12-16 13:33:51 +00002627
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002628 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2629 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002630
2631 if (gsn->cb_delete_context)
2632 gsn->cb_delete_context(pdp);
2633 pdp_freepdp(pdp);
2634 return 0;
jjako52c24142002-12-16 13:33:51 +00002635}
2636
2637int gtp_gpdu_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002638 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2639{
jjako08d331d2003-10-13 20:33:30 +00002640
Harald Weltebed35df2011-11-02 13:06:18 +01002641 int hlen = GTP1_HEADER_SIZE_SHORT;
jjako52c24142002-12-16 13:33:51 +00002642
Harald Weltebed35df2011-11-02 13:06:18 +01002643 /* Need to include code to verify packet src and dest addresses */
2644 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002645
Harald Weltebed35df2011-11-02 13:06:18 +01002646 if (version == 0) {
2647 if (pdp_getgtp0
2648 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2649 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002650 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002651 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002652 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2653 len);
2654 }
2655 hlen = GTP0_HEADER_SIZE;
2656 } else if (version == 1) {
2657 if (pdp_getgtp1
2658 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2659 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002660 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002661 len, "Unknown PDP context, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002662 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2663 len);
2664 }
jjako08d331d2003-10-13 20:33:30 +00002665
Harald Weltebed35df2011-11-02 13:06:18 +01002666 /* Is this a long or a short header ? */
2667 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2668 hlen = GTP1_HEADER_SIZE_LONG;
2669 else
2670 hlen = GTP1_HEADER_SIZE_SHORT;
2671 } else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002672 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002673 "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002674 }
jjako08d331d2003-10-13 20:33:30 +00002675
Harald Weltebed35df2011-11-02 13:06:18 +01002676 /* If the GPDU was not from the peer GSN tell him to delete context */
2677 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2678 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002679 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002680 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2681 }
jjako52c24142002-12-16 13:33:51 +00002682
Harald Weltebed35df2011-11-02 13:06:18 +01002683 /* Callback function */
2684 if (gsn->cb_data_ind != 0)
2685 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2686
2687 return 0;
jjako52c24142002-12-16 13:33:51 +00002688}
2689
jjako52c24142002-12-16 13:33:51 +00002690/* Receives GTP packet and sends off for further processing
2691 * Function will check the validity of the header. If the header
2692 * is not valid the packet is either dropped or a version not
2693 * supported is returned to the peer.
2694 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002695int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002696{
Harald Weltebed35df2011-11-02 13:06:18 +01002697 unsigned char buffer[PACKET_MAX];
2698 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002699 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002700 int status;
2701 struct gtp0_header *pheader;
2702 int version = 0; /* GTP version should be determined from header! */
2703 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002704
Harald Weltebed35df2011-11-02 13:06:18 +01002705 /* TODO: Need strategy of userspace buffering and blocking */
2706 /* Currently read is non-blocking and send is blocking. */
2707 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002708
Harald Weltebed35df2011-11-02 13:06:18 +01002709 while (1) { /* Loop until no more to read */
2710 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002711 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002712 return -1;
2713 }
2714 peerlen = sizeof(peer);
2715 if ((status =
2716 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2717 (struct sockaddr *)&peer, &peerlen)) < 0) {
2718 if (errno == EAGAIN)
2719 return 0;
2720 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002721 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002722 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002723 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2724 status, status ? strerror(errno) : "No error");
2725 return -1;
2726 }
jjako1db1c812003-07-06 20:53:57 +00002727
Harald Weltebed35df2011-11-02 13:06:18 +01002728 /* Need at least 1 byte in order to check version */
2729 if (status < (1)) {
2730 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002731 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2732 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002733 continue;
2734 }
jjako08d331d2003-10-13 20:33:30 +00002735
Harald Weltebed35df2011-11-02 13:06:18 +01002736 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002737
Harald Weltebed35df2011-11-02 13:06:18 +01002738 /* Version should be gtp0 (or earlier) */
2739 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2740 /* GTP 0 messages. If other version message is received we reply that we */
2741 /* only support version 0, implying that this is the only version */
2742 /* supported on this port */
2743 if (((pheader->flags & 0xe0) > 0x00)) {
2744 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002745 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2746 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002747 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2748 continue;
2749 }
2750
2751 /* Check length of gtp0 packet */
2752 if (status < GTP0_HEADER_SIZE) {
2753 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002754 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2755 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002756 continue; /* Silently discard 29.60: 11.1.2 */
2757 }
2758
2759 /* Check packet length field versus length of packet */
2760 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2761 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002762 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002763 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002764 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002765 continue; /* Silently discard */
2766 }
2767
2768 if ((gsn->mode == GTP_MODE_GGSN) &&
2769 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2770 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2771 (pheader->type == GTP_DELETE_PDP_RSP))) {
2772 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002773 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002774 status,
Max28318872017-05-16 17:03:02 +02002775 "Unexpected GTPv0 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002776 continue; /* Silently discard 29.60: 11.1.4 */
2777 }
2778
2779 if ((gsn->mode == GTP_MODE_SGSN) &&
2780 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2781 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2782 (pheader->type == GTP_DELETE_PDP_REQ))) {
2783 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002784 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002785 status,
Max28318872017-05-16 17:03:02 +02002786 "Unexpected GTPv0 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002787 continue; /* Silently discard 29.60: 11.1.4 */
2788 }
2789
2790 switch (pheader->type) {
2791 case GTP_ECHO_REQ:
2792 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2793 break;
2794 case GTP_ECHO_RSP:
2795 gtp_echo_conf(gsn, version, &peer, buffer, status);
2796 break;
2797 case GTP_NOT_SUPPORTED:
2798 gtp_unsup_ind(gsn, &peer, buffer, status);
2799 break;
2800 case GTP_CREATE_PDP_REQ:
2801 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2802 status);
2803 break;
2804 case GTP_CREATE_PDP_RSP:
2805 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2806 status);
2807 break;
2808 case GTP_UPDATE_PDP_REQ:
2809 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2810 status);
2811 break;
2812 case GTP_UPDATE_PDP_RSP:
2813 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2814 status);
2815 break;
2816 case GTP_DELETE_PDP_REQ:
2817 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2818 status);
2819 break;
2820 case GTP_DELETE_PDP_RSP:
2821 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2822 status);
2823 break;
2824 case GTP_ERROR:
2825 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2826 break;
2827 case GTP_GPDU:
2828 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2829 break;
2830 default:
2831 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002832 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2833 "Unknown GTP message type received: %d\n",
2834 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002835 break;
2836 }
2837 }
jjako08d331d2003-10-13 20:33:30 +00002838}
2839
jjako08d331d2003-10-13 20:33:30 +00002840int gtp_decaps1c(struct gsn_t *gsn)
2841{
Harald Weltebed35df2011-11-02 13:06:18 +01002842 unsigned char buffer[PACKET_MAX];
2843 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002844 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002845 int status;
2846 struct gtp1_header_short *pheader;
2847 int version = 1; /* TODO GTP version should be determined from header! */
2848 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002849
Harald Weltebed35df2011-11-02 13:06:18 +01002850 /* TODO: Need strategy of userspace buffering and blocking */
2851 /* Currently read is non-blocking and send is blocking. */
2852 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002853
Harald Weltebed35df2011-11-02 13:06:18 +01002854 while (1) { /* Loop until no more to read */
2855 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002856 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002857 return -1;
2858 }
2859 peerlen = sizeof(peer);
2860 if ((status =
2861 recvfrom(fd, buffer, sizeof(buffer), 0,
2862 (struct sockaddr *)&peer, &peerlen)) < 0) {
2863 if (errno == EAGAIN)
2864 return 0;
2865 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002866 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002867 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002868 fd, (unsigned long)buffer, sizeof(buffer),
2869 status, status ? strerror(errno) : "No error");
2870 return -1;
2871 }
jjako08d331d2003-10-13 20:33:30 +00002872
Harald Weltebed35df2011-11-02 13:06:18 +01002873 /* Need at least 1 byte in order to check version */
2874 if (status < (1)) {
2875 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002876 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2877 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002878 continue;
2879 }
jjako08d331d2003-10-13 20:33:30 +00002880
Harald Weltebed35df2011-11-02 13:06:18 +01002881 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002882
Harald Weltebed35df2011-11-02 13:06:18 +01002883 /* Version must be no larger than GTP 1 */
2884 if (((pheader->flags & 0xe0) > 0x20)) {
2885 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002886 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2887 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002888 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2889 /*29.60: 11.1.1 */
2890 continue;
2891 }
jjako08d331d2003-10-13 20:33:30 +00002892
Harald Weltebed35df2011-11-02 13:06:18 +01002893 /* Version must be at least GTP 1 */
2894 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2895 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2896 /* the message */
2897 if (((pheader->flags & 0xe0) < 0x20)) {
2898 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002899 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2900 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002901 continue;
2902 }
jjako08d331d2003-10-13 20:33:30 +00002903
Harald Weltebed35df2011-11-02 13:06:18 +01002904 /* Check packet flag field */
2905 if (((pheader->flags & 0xf7) != 0x32)) {
2906 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002907 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01002908 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01002909 continue;
2910 }
jjako2c381332003-10-21 19:09:53 +00002911
Harald Weltebed35df2011-11-02 13:06:18 +01002912 /* Check length of packet */
2913 if (status < GTP1_HEADER_SIZE_LONG) {
2914 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002915 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2916 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002917 continue; /* Silently discard 29.60: 11.1.2 */
2918 }
jjako2c381332003-10-21 19:09:53 +00002919
Harald Weltebed35df2011-11-02 13:06:18 +01002920 /* Check packet length field versus length of packet */
2921 if (status !=
2922 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2923 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002924 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002925 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002926 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002927 continue; /* Silently discard */
2928 }
jjako1db1c812003-07-06 20:53:57 +00002929
Harald Weltebed35df2011-11-02 13:06:18 +01002930 /* Check for extension headers */
2931 /* TODO: We really should cycle through the headers and determine */
2932 /* if any have the comprehension required flag set */
2933 if (((pheader->flags & 0x04) != 0x00)) {
2934 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002935 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2936 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002937 gtp_extheader_req(gsn, version, &peer, fd, buffer,
2938 status);
jjako1db1c812003-07-06 20:53:57 +00002939
Harald Weltebed35df2011-11-02 13:06:18 +01002940 continue;
2941 }
2942
2943 if ((gsn->mode == GTP_MODE_GGSN) &&
2944 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2945 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2946 (pheader->type == GTP_DELETE_PDP_RSP))) {
2947 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002948 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002949 status,
Max28318872017-05-16 17:03:02 +02002950 "Unexpected GTPv1 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002951 continue; /* Silently discard 29.60: 11.1.4 */
2952 }
2953
2954 if ((gsn->mode == GTP_MODE_SGSN) &&
2955 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2956 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2957 (pheader->type == GTP_DELETE_PDP_REQ))) {
2958 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002959 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002960 status,
Max28318872017-05-16 17:03:02 +02002961 "Unexpected GTPv1 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002962 continue; /* Silently discard 29.60: 11.1.4 */
2963 }
2964
2965 switch (pheader->type) {
2966 case GTP_ECHO_REQ:
2967 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2968 break;
2969 case GTP_ECHO_RSP:
2970 gtp_echo_conf(gsn, version, &peer, buffer, status);
2971 break;
2972 case GTP_NOT_SUPPORTED:
2973 gtp_unsup_ind(gsn, &peer, buffer, status);
2974 break;
2975 case GTP_SUPP_EXT_HEADER:
2976 gtp_extheader_ind(gsn, &peer, buffer, status);
2977 break;
2978 case GTP_CREATE_PDP_REQ:
2979 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2980 status);
2981 break;
2982 case GTP_CREATE_PDP_RSP:
2983 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2984 status);
2985 break;
2986 case GTP_UPDATE_PDP_REQ:
2987 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2988 status);
2989 break;
2990 case GTP_UPDATE_PDP_RSP:
2991 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2992 status);
2993 break;
2994 case GTP_DELETE_PDP_REQ:
2995 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2996 status);
2997 break;
2998 case GTP_DELETE_PDP_RSP:
2999 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3000 status);
3001 break;
3002 case GTP_ERROR:
3003 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3004 break;
3005 default:
3006 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003007 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3008 "Unknown GTP message type received: %u\n",
3009 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003010 break;
3011 }
3012 }
jjako52c24142002-12-16 13:33:51 +00003013}
3014
jjako08d331d2003-10-13 20:33:30 +00003015int gtp_decaps1u(struct gsn_t *gsn)
3016{
Harald Weltebed35df2011-11-02 13:06:18 +01003017 unsigned char buffer[PACKET_MAX];
3018 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003019 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003020 int status;
3021 struct gtp1_header_short *pheader;
3022 int version = 1; /* GTP version should be determined from header! */
3023 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003024
Harald Weltebed35df2011-11-02 13:06:18 +01003025 /* TODO: Need strategy of userspace buffering and blocking */
3026 /* Currently read is non-blocking and send is blocking. */
3027 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003028
Harald Weltebed35df2011-11-02 13:06:18 +01003029 while (1) { /* Loop until no more to read */
3030 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003031 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003032 return -1;
3033 }
3034 peerlen = sizeof(peer);
3035 if ((status =
3036 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3037 (struct sockaddr *)&peer, &peerlen)) < 0) {
3038 if (errno == EAGAIN)
3039 return 0;
3040 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003041 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003042 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003043 gsn->fd1u, (unsigned long)buffer,
3044 sizeof(buffer), status,
3045 status ? strerror(errno) : "No error");
3046 return -1;
3047 }
jjako08d331d2003-10-13 20:33:30 +00003048
Harald Weltebed35df2011-11-02 13:06:18 +01003049 /* Need at least 1 byte in order to check version */
3050 if (status < (1)) {
3051 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003052 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3053 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003054 continue;
3055 }
jjako08d331d2003-10-13 20:33:30 +00003056
Harald Weltebed35df2011-11-02 13:06:18 +01003057 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003058
Harald Weltebed35df2011-11-02 13:06:18 +01003059 /* Version must be no larger than GTP 1 */
3060 if (((pheader->flags & 0xe0) > 0x20)) {
3061 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003062 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3063 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003064 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3065 continue;
3066 }
jjako08d331d2003-10-13 20:33:30 +00003067
Harald Weltebed35df2011-11-02 13:06:18 +01003068 /* Version must be at least GTP 1 */
3069 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3070 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3071 /* the message */
3072 if (((pheader->flags & 0xe0) < 0x20)) {
3073 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003074 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3075 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003076 continue;
3077 }
jjako2c381332003-10-21 19:09:53 +00003078
Harald Weltebed35df2011-11-02 13:06:18 +01003079 /* Check packet flag field (allow both with and without sequence number) */
3080 if (((pheader->flags & 0xf5) != 0x30)) {
3081 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003082 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003083 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003084 continue;
3085 }
jjako2c381332003-10-21 19:09:53 +00003086
Harald Weltebed35df2011-11-02 13:06:18 +01003087 /* Check length of packet */
3088 if (status < GTP1_HEADER_SIZE_SHORT) {
3089 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003090 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3091 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003092 continue; /* Silently discard 29.60: 11.1.2 */
3093 }
3094
3095 /* Check packet length field versus length of packet */
3096 if (status !=
3097 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3098 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003099 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003100 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003101 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003102 continue; /* Silently discard */
3103 }
3104
3105 /* Check for extension headers */
3106 /* TODO: We really should cycle through the headers and determine */
3107 /* if any have the comprehension required flag set */
3108 if (((pheader->flags & 0x04) != 0x00)) {
3109 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003110 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3111 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003112 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3113 status);
3114
3115 continue;
3116 }
3117
3118 switch (pheader->type) {
3119 case GTP_ECHO_REQ:
3120 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3121 break;
3122 case GTP_ECHO_RSP:
3123 gtp_echo_conf(gsn, version, &peer, buffer, status);
3124 break;
3125 case GTP_SUPP_EXT_HEADER:
3126 gtp_extheader_ind(gsn, &peer, buffer, status);
3127 break;
3128 case GTP_ERROR:
3129 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3130 break;
3131 /* Supported header extensions */
3132 case GTP_GPDU:
3133 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3134 break;
3135 default:
3136 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003137 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3138 "Unknown GTP message type received: %u\n",
3139 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003140 break;
3141 }
3142 }
jjako08d331d2003-10-13 20:33:30 +00003143}
3144
Harald Weltebed35df2011-11-02 13:06:18 +01003145int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003146{
Harald Weltebed35df2011-11-02 13:06:18 +01003147 union gtp_packet packet;
3148 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003149 struct msghdr msgh;
3150 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003151 int fd;
jjako52c24142002-12-16 13:33:51 +00003152
Harald Welte471e3492017-09-24 16:12:39 +08003153 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003154 memset(&addr, 0, sizeof(addr));
3155 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003156#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003157 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003158#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003159 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003160
Harald Welte471e3492017-09-24 16:12:39 +08003161 /* prepare msghdr */
3162 memset(&msgh, 0, sizeof(msgh));
3163 msgh.msg_name = &addr;
3164 msgh.msg_namelen = sizeof(addr);
3165 msgh.msg_iov = iov;
3166 msgh.msg_iovlen = ARRAY_SIZE(iov);
3167
3168 /* prepare iovectors */
3169 iov[0].iov_base = &packet;
3170 /* iov[0].iov_len is not known here yet */
3171 iov[1].iov_base = pack;
3172 iov[1].iov_len = len;
3173
Harald Weltebed35df2011-11-02 13:06:18 +01003174 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003175
Harald Welte471e3492017-09-24 16:12:39 +08003176 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003177 addr.sin_port = htons(GTP0_PORT);
3178 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003179
Harald Weltebed35df2011-11-02 13:06:18 +01003180 get_default_gtp(0, GTP_GPDU, &packet);
3181 packet.gtp0.h.length = hton16(len);
3182 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3183 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003184 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003185 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003186
Harald Welte471e3492017-09-24 16:12:39 +08003187 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
Harald Weltebed35df2011-11-02 13:06:18 +01003188 addr.sin_port = htons(GTP1U_PORT);
3189 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003190
Harald Weltebed35df2011-11-02 13:06:18 +01003191 get_default_gtp(1, GTP_GPDU, &packet);
3192 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3193 GTP1_HEADER_SIZE_LONG);
3194 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3195 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
Harald Weltebed35df2011-11-02 13:06:18 +01003196 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003197 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003198 return EOF;
3199 }
3200
3201 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003202 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003203 return -1;
3204 }
3205
Harald Welte471e3492017-09-24 16:12:39 +08003206 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003207 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003208 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003209 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003210 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3211 strerror(errno));
3212 return EOF;
3213 }
3214 return 0;
jjako52c24142002-12-16 13:33:51 +00003215}
3216
jjako52c24142002-12-16 13:33:51 +00003217/* ***********************************************************
3218 * Conversion functions
3219 *************************************************************/
3220
Harald Weltebed35df2011-11-02 13:06:18 +01003221int char2ul_t(char *src, struct ul_t dst)
3222{
3223 dst.l = strlen(src) + 1;
3224 dst.v = malloc(dst.l);
3225 dst.v[0] = dst.l - 1;
3226 memcpy(&dst.v[1], src, dst.v[0]);
3227 return 0;
jjako52c24142002-12-16 13:33:51 +00003228}
3229
3230/* ***********************************************************
3231 * IP address conversion functions
3232 * There exist several types of address representations:
3233 * - eua: End User Address. (29.060, 7.7.27, message type 128)
3234 * Used for signalling address to mobile station. Supports IPv4
3235 * IPv6 x.25 etc. etc.
3236 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3237 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3238 * - in_addr: IPv4 address struct.
3239 * - sockaddr_in: Socket API representation of IP address and
3240 * port number.
3241 *************************************************************/
3242
Harald Weltebed35df2011-11-02 13:06:18 +01003243int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3244{
3245 eua->v[0] = 0xf1; /* IETF */
3246 eua->v[1] = 0x21; /* IPv4 */
3247 if (src) {
3248 eua->l = 6;
3249 memcpy(&eua->v[2], src, 4);
3250 } else {
3251 eua->l = 2;
3252 }
3253 return 0;
jjako52c24142002-12-16 13:33:51 +00003254}
3255
Harald Weltebed35df2011-11-02 13:06:18 +01003256int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3257{
3258 if ((eua->l != 6) || (eua->v[0] != 0xf1) || (eua->v[1] = 0x21))
3259 return -1; /* Not IPv4 address */
3260 memcpy(dst, &eua->v[2], 4);
3261 return 0;
jjako52c24142002-12-16 13:33:51 +00003262}
3263
Harald Weltebed35df2011-11-02 13:06:18 +01003264int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3265{
3266 memset(dst, 0, sizeof(struct in_addr));
3267 if (gsna->l != 4)
3268 return EOF; /* Return if not IPv4 */
3269 memcpy(dst, gsna->v, gsna->l);
3270 return 0;
jjako52c24142002-12-16 13:33:51 +00003271}
3272
Harald Weltebed35df2011-11-02 13:06:18 +01003273int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3274{
3275 memset(gsna, 0, sizeof(struct ul16_t));
3276 gsna->l = 4;
3277 memcpy(gsna->v, src, gsna->l);
3278 return 0;
jjako52c24142002-12-16 13:33:51 +00003279}
Harald Welteb10ee082017-08-12 19:29:16 +02003280
3281/* TS 29.060 has yet again a different encoding for IMSIs than
3282 * what we have in other places, so we cannot use the gsm48
3283 * decoding functions. Also, libgtp uses an uint64_t in
3284 * _network byte order_ to contain BCD digits ?!? */
3285const char *imsi_gtp2str(const uint64_t *imsi)
3286{
3287 static char buf[sizeof(*imsi)+1];
3288 const uint8_t *imsi8 = (const uint8_t *) imsi;
3289 unsigned int i, j = 0;
3290
3291 for (i = 0; i < sizeof(*imsi); i++) {
3292 uint8_t nibble;
3293
3294 nibble = imsi8[i] & 0xf;
3295 if (nibble == 0xf)
3296 break;
3297 buf[j++] = osmo_bcd2char(nibble);
3298
3299 nibble = imsi8[i] >> 4;
3300 if (nibble == 0xf)
3301 break;
3302 buf[j++] = osmo_bcd2char(nibble);
3303 }
3304
3305 buf[j++] = '\0';
3306 return buf;
3307}