blob: a3f6eb273d60bbca647e2f3773b9f2656ef5d369 [file] [log] [blame]
jjako52c24142002-12-16 13:33:51 +00001/*
2 * OpenGGSN - Gateway GPRS Support Node
jjako0fe0df02004-09-17 11:30:40 +00003 * Copyright (C) 2002, 2003, 2004 Mondru AB.
jjako52c24142002-12-16 13:33:51 +00004 *
5 * The contents of this file may be used under the terms of the GNU
6 * General Public License Version 2, provided that the above copyright
7 * notice and this permission notice is included in all copies or
8 * substantial portions of the software.
9 *
jjako52c24142002-12-16 13:33:51 +000010 */
11
12/*
13 * gtp.c: Contains all GTP functionality. Should be able to handle multiple
14 * tunnels in the same program.
15 *
16 * TODO:
17 * - Do we need to handle fragmentation?
18 */
19
jjako52c24142002-12-16 13:33:51 +000020#ifdef __linux__
21#define _GNU_SOURCE 1
22#endif
23
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +010024#include <osmocom/core/logging.h>
25#include <osmocom/core/utils.h>
26
Holger Hans Peter Freyther5816bcf2014-04-04 11:43:09 +020027#if defined(__FreeBSD__)
28#include <sys/endian.h>
29#endif
30
jjako0fe0df02004-09-17 11:30:40 +000031#include "../config.h"
32#ifdef HAVE_STDINT_H
33#include <stdint.h>
34#endif
jjako52c24142002-12-16 13:33:51 +000035
jjako52c24142002-12-16 13:33:51 +000036#include <stdio.h>
37#include <stdarg.h>
38#include <stdlib.h>
39#include <sys/time.h>
40#include <sys/types.h>
41#include <sys/socket.h>
42#include <netinet/in.h>
43#include <arpa/inet.h>
44#include <sys/stat.h>
45#include <time.h>
46#include <unistd.h>
47#include <string.h>
48#include <errno.h>
49#include <fcntl.h>
Alexander Huemerdb852a12015-11-06 20:59:01 +010050#include <inttypes.h>
jjako52c24142002-12-16 13:33:51 +000051
52#include <arpa/inet.h>
53
jjakobae2cd42004-01-09 12:04:39 +000054/* #include <stdint.h> ISO C99 types */
jjako52c24142002-12-16 13:33:51 +000055
56#include "pdp.h"
57#include "gtp.h"
58#include "gtpie.h"
59#include "queue.h"
60
Harald Welte95848ba2011-11-02 18:17:50 +010061/* According to section 14.2 of 3GPP TS 29.006 version 6.9.0 */
62#define N3_REQUESTS 5
63
64#define T3_REQUEST 3
65
jjako1db1c812003-07-06 20:53:57 +000066/* Error reporting functions */
67
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +010068#define GTP_LOGPKG(pri, peer, pack, len, fmt, args...) \
69 logp2(DLGTP, pri, __FILE__, __LINE__, 0, \
70 "Packet from %s:%u, length: %d content: %s: " fmt, \
71 inet_ntoa((peer)->sin_addr), htons((peer)->sin_port), \
72 len, osmo_hexdump((const uint8_t *) pack, len), \
73 ##args);
jjako1db1c812003-07-06 20:53:57 +000074
Neels Hofmeyr9b097382015-10-12 14:00:19 +020075#define LOGP_WITH_ADDR(ss, level, addr, fmt, args...) \
76 LOGP(ss, level, "addr(%s:%d) " fmt, \
77 inet_ntoa((addr).sin_addr), htons((addr).sin_port), \
78 ##args);
79
jjako52c24142002-12-16 13:33:51 +000080/* API Functions */
81
Harald Weltebed35df2011-11-02 13:06:18 +010082const char *gtp_version()
jjako52c24142002-12-16 13:33:51 +000083{
Harald Weltebed35df2011-11-02 13:06:18 +010084 return VERSION;
jjako52c24142002-12-16 13:33:51 +000085}
86
87/* gtp_new */
88/* gtp_free */
89
Harald Weltebed35df2011-11-02 13:06:18 +010090int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
91 uint64_t imsi, uint8_t nsapi)
92{
93 return pdp_newpdp(pdp, imsi, nsapi, NULL);
jjako52c24142002-12-16 13:33:51 +000094}
95
Harald Weltebed35df2011-11-02 13:06:18 +010096int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp)
97{
98 return pdp_freepdp(pdp);
jjako52c24142002-12-16 13:33:51 +000099}
100
jjako52c24142002-12-16 13:33:51 +0000101/* gtp_gpdu */
102
Harald Weltebed35df2011-11-02 13:06:18 +0100103extern int gtp_fd(struct gsn_t *gsn)
104{
105 return gsn->fd0;
jjako52c24142002-12-16 13:33:51 +0000106}
107
108/* gtp_decaps */
109/* gtp_retrans */
110/* gtp_retranstimeout */
111
jjako08d331d2003-10-13 20:33:30 +0000112int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100113 int (*cb) (struct sockaddr_in * peer))
114{
115 gsn->cb_unsup_ind = cb;
116 return 0;
jjako08d331d2003-10-13 20:33:30 +0000117}
118
jjako2c381332003-10-21 19:09:53 +0000119int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100120 int (*cb) (struct sockaddr_in * peer))
121{
122 gsn->cb_extheader_ind = cb;
123 return 0;
jjako2c381332003-10-21 19:09:53 +0000124}
125
jjako08d331d2003-10-13 20:33:30 +0000126/* API: Initialise delete context callback */
127/* Called whenever a pdp context is deleted for any reason */
Harald Weltebed35df2011-11-02 13:06:18 +0100128int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
jjako52c24142002-12-16 13:33:51 +0000129{
Harald Weltebed35df2011-11-02 13:06:18 +0100130 gsn->cb_delete_context = cb;
131 return 0;
jjako52c24142002-12-16 13:33:51 +0000132}
133
jjako52c24142002-12-16 13:33:51 +0000134int gtp_set_cb_conf(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100135 int (*cb) (int type, int cause,
136 struct pdp_t * pdp, void *cbp))
137{
138 gsn->cb_conf = cb;
139 return 0;
jjako52c24142002-12-16 13:33:51 +0000140}
141
Harald Welte629e9862010-12-24 20:58:09 +0100142int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100143 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
144{
145 gsn->cb_recovery = cb;
146 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100147}
148
jjako08d331d2003-10-13 20:33:30 +0000149extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100150 int (*cb_data_ind) (struct pdp_t * pdp,
151 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000152{
Harald Weltebed35df2011-11-02 13:06:18 +0100153 gsn->cb_data_ind = cb_data_ind;
154 return 0;
jjako52c24142002-12-16 13:33:51 +0000155}
156
jjako08d331d2003-10-13 20:33:30 +0000157/**
158 * get_default_gtp()
159 * Generate a GPRS Tunneling Protocol signalling packet header, depending
160 * on GTP version and message type. pdp is used for teid/flow label.
161 * *packet must be allocated by the calling function, and be large enough
162 * to hold the packet header.
163 * returns the length of the header. 0 on error.
164 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100165static unsigned int get_default_gtp(int version, uint8_t type, void *packet)
166{
167 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
168 struct gtp1_header_long *gtp1_default =
169 (struct gtp1_header_long *)packet;
170 switch (version) {
171 case 0:
172 /* Initialise "standard" GTP0 header */
173 memset(gtp0_default, 0, sizeof(struct gtp0_header));
174 gtp0_default->flags = 0x1e;
175 gtp0_default->type = hton8(type);
176 gtp0_default->spare1 = 0xff;
177 gtp0_default->spare2 = 0xff;
178 gtp0_default->spare3 = 0xff;
179 gtp0_default->number = 0xff;
180 return GTP0_HEADER_SIZE;
181 case 1:
182 /* Initialise "standard" GTP1 header */
183 /* 29.060: 8.2: S=1 and PN=0 */
184 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
185 /* and Supported Extension Headers Notification, the S field shall be */
186 /* set to 1 */
187 /* Currently extension headers are not supported */
188 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
189 gtp1_default->flags = 0x32; /* No extension, enable sequence, no N-PDU */
190 gtp1_default->type = hton8(type);
191 return GTP1_HEADER_SIZE_LONG;
192 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100193 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100194 "Unknown GTP packet version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +0100195 return 0;
196 }
jjako52c24142002-12-16 13:33:51 +0000197}
198
jjako08d331d2003-10-13 20:33:30 +0000199/**
200 * get_seq()
201 * Get sequence number of a packet.
202 * Returns 0 on error
203 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100204static uint16_t get_seq(void *pack)
205{
206 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000207
Harald Weltebed35df2011-11-02 13:06:18 +0100208 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
209 return ntoh16(packet->gtp0.h.seq);
210 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
211 return ntoh16(packet->gtp1l.h.seq);
212 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100213 return 0;
214 }
jjako08d331d2003-10-13 20:33:30 +0000215}
216
217/**
218 * get_tid()
219 * Get tunnel identifier of a packet.
220 * Returns 0 on error
221 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100222static uint64_t get_tid(void *pack)
223{
224 union gtp_packet *packet = (union gtp_packet *)pack;
225
226 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100227 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100228 }
229 return 0;
jjako08d331d2003-10-13 20:33:30 +0000230}
231
232/**
233 * get_hlen()
234 * Get the header length of a packet.
235 * Returns 0 on error
236 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100237static uint16_t get_hlen(void *pack)
238{
239 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000240
Harald Weltebed35df2011-11-02 13:06:18 +0100241 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
242 return GTP0_HEADER_SIZE;
243 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
244 return GTP1_HEADER_SIZE_LONG;
245 } else if ((packet->flags & 0xe7) == 0x20) { /* Short version 1 */
246 return GTP1_HEADER_SIZE_SHORT;
247 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100248 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100249 return 0;
250 }
jjako08d331d2003-10-13 20:33:30 +0000251}
252
253/**
254 * get_tei()
255 * Get the tunnel endpoint identifier (flow label) of a packet.
256 * Returns 0xffffffff on error.
257 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100258static uint32_t get_tei(void *pack)
259{
260 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000261
Harald Weltebed35df2011-11-02 13:06:18 +0100262 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
263 return ntoh16(packet->gtp0.h.flow);
264 } else if ((packet->flags & 0xe0) == 0x20) { /* Version 1 */
265 return ntoh32(packet->gtp1l.h.tei);
266 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100267 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100268 return 0xffffffff;
269 }
jjako08d331d2003-10-13 20:33:30 +0000270}
jjakoa7cd2492003-04-11 09:40:12 +0000271
jjako52c24142002-12-16 13:33:51 +0000272/* ***********************************************************
273 * Reliable delivery of signalling messages
274 *
275 * Sequence numbers are used for both signalling messages and
276 * data messages.
277 *
278 * For data messages each tunnel maintains a sequence counter,
279 * which is incremented by one each time a new data message
280 * is sent. The sequence number starts at (0) zero at tunnel
281 * establishment, and wraps around at 65535 (29.060 9.3.1.1
282 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
283 * or can be used to check the validity of the message in the
284 * receiver, or for reordering af packets.
285 *
286 * For signalling messages the sequence number is used by
287 * signalling messages for which a response is defined. A response
288 * message should copy the sequence from the corresponding request
289 * message. The sequence number "unambiguously" identifies a request
290 * message within a given path, with a path being defined as a set of
291 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
292 * messages shall be responded to, and all response messages associated
293 * with a certain request shall always include the same information"
294 *
295 * We take this to mean that the GSN transmitting a request is free to
296 * choose the sequence number, as long as it is unique within a given path.
297 * It means that we are allowed to count backwards, or roll over at 17
298 * if we prefer that. It also means that we can use the same counter for
299 * all paths. This has the advantage that the transmitted request sequence
300 * numbers are unique within each GSN, and also we dont have to mess around
301 * with path setup and teardown.
302 *
303 * If a response message is lost, the request will be retransmitted, and
304 * the receiving GSN will receive a "duplicated" request. The standard
305 * requires the receiving GSN to send a response, with the same information
306 * as in the original response. For most messages this happens automatically:
307 *
308 * Echo: Automatically dublicates the original response
309 * Create pdp context: The SGSN may send create context request even if
310 * a context allready exist (imsi+nsapi?). This means that the reply will
311 automatically dublicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000312 * side effects in the application which is asked twice to validate
313 * the login.
jjako52c24142002-12-16 13:33:51 +0000314 * Update pdp context: Automatically dublicates the original response???
315 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
316 * a nonexist reply message.
317 *
318 * The correct solution will be to make a queue containing response messages.
319 * This queue should be checked whenever a request is received. If the
320 * response is allready in the queue that response should be transmitted.
321 * It should be possible to find messages in this queue on the basis of
322 * the sequence number and peer GSN IP address (The sequense number is unique
323 * within each path). This need to be implemented by a hash table. Furthermore
324 * it should be possibly to delete messages based on a timeout. This can be
325 * achieved by means of a linked list. The timeout value need to be larger
326 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
327 * set in the peer GSN, so there is no way to know these parameters. On the
328 * other hand the timeout value need to be so small that we do not receive
329 * wraparound sequence numbere before the message is deleted. 60 seconds is
330 * probably not a bad choise.
331 *
332 * This queue however is first really needed from gtp1.
333 *
334 * gtp_req:
335 * Send off a signalling message with appropiate sequence
336 * number. Store packet in queue.
337 * gtp_conf:
338 * Remove an incoming confirmation from the queue
339 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000340 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000341 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000342 * gtp_notification:
343 * Send off a notification message. This is neither a request nor
344 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000345 * gtp_retrans:
346 * Retransmit any outstanding packets which have exceeded
347 * a predefined timeout.
348 *************************************************************/
349
jjako08d331d2003-10-13 20:33:30 +0000350int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100351 union gtp_packet *packet, int len,
352 struct in_addr *inetaddr, void *cbp)
353{
354 struct sockaddr_in addr;
355 struct qmsg_t *qmsg;
356 int fd;
jjako08d331d2003-10-13 20:33:30 +0000357
Harald Weltebed35df2011-11-02 13:06:18 +0100358 memset(&addr, 0, sizeof(addr));
359 addr.sin_family = AF_INET;
360 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000361#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100362 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000363#endif
jjako52c24142002-12-16 13:33:51 +0000364
Harald Weltebed35df2011-11-02 13:06:18 +0100365 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
366 addr.sin_port = htons(GTP0_PORT);
367 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
368 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100369 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100370 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100371 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100372 }
Harald Weltebed35df2011-11-02 13:06:18 +0100373 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
374 || (packet->gtp0.h.type == GTP_ERROR)))
375 packet->gtp0.h.flow = hton16(pdp->flru);
376 else if (pdp)
377 packet->gtp0.h.flow = hton16(pdp->flrc);
378 fd = gsn->fd0;
379 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
380 addr.sin_port = htons(GTP1C_PORT);
381 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
382 packet->gtp1l.h.seq = hton16(gsn->seq_next);
383 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
384 (packet->gtp1l.h.type == GTP_ERROR)))
385 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
386 else if (pdp)
387 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
388 fd = gsn->fd1c;
389 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100390 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100391 return -1;
392 }
jjako52c24142002-12-16 13:33:51 +0000393
Harald Weltebed35df2011-11-02 13:06:18 +0100394 if (sendto(fd, packet, len, 0,
395 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
396 gsn->err_sendto++;
Max14b1b632017-08-21 20:14:59 +0200397 LOGP(DLGTP, LOGL_ERROR, "Sendto(fd=%d, msg=%lx, len=%d, dst=%s) failed: Error = %s\n", fd,
398 (unsigned long)&packet, len, inet_ntoa(addr.sin_addr), strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100399 return -1;
400 }
401
402 /* Use new queue structure */
403 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
404 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100405 LOGP(DLGTP, LOGL_ERROR,
406 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100407 } else {
408 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
409 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100410 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100411 qmsg->retrans = 0; /* No retransmissions so far */
412 qmsg->cbp = cbp;
413 qmsg->type = ntoh8(packet->gtp0.h.type);
414 qmsg->fd = fd;
415 }
416 gsn->seq_next++; /* Count up this time */
417 return 0;
jjako52c24142002-12-16 13:33:51 +0000418}
419
420/* gtp_conf
421 * Remove signalling packet from retransmission queue.
422 * return 0 on success, EOF if packet was not found */
423
424int gtp_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100425 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
426{
jjako52c24142002-12-16 13:33:51 +0000427
Harald Weltebed35df2011-11-02 13:06:18 +0100428 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000429
Harald Weltebed35df2011-11-02 13:06:18 +0100430 if ((packet->gtp0.h.flags & 0xe0) == 0x00)
431 seq = ntoh16(packet->gtp0.h.seq);
432 else if ((packet->gtp1l.h.flags & 0xe2) == 0x22)
433 seq = ntoh16(packet->gtp1l.h.seq);
434 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100435 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
436 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100437 return EOF;
438 }
jjako08d331d2003-10-13 20:33:30 +0000439
Harald Weltebed35df2011-11-02 13:06:18 +0100440 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
441 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100442 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
443 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100444 return EOF;
445 }
jjako52c24142002-12-16 13:33:51 +0000446
Harald Weltebed35df2011-11-02 13:06:18 +0100447 return 0;
jjako52c24142002-12-16 13:33:51 +0000448}
449
Harald Weltebed35df2011-11-02 13:06:18 +0100450int gtp_retrans(struct gsn_t *gsn)
451{
452 /* Retransmit any outstanding packets */
453 /* Remove from queue if maxretrans exceeded */
454 time_t now;
455 struct qmsg_t *qmsg;
456 now = time(NULL);
457 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000458
Harald Welte95848ba2011-11-02 18:17:50 +0100459 /* get first element in queue, as long as the timeout of that
460 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100461 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
462 (qmsg->timeout <= now)) {
463 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100464 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100465 if (gsn->cb_conf)
466 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
467 queue_freemsg(gsn->queue_req, qmsg);
468 } else {
469 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
470 (struct sockaddr *)&qmsg->peer,
471 sizeof(struct sockaddr_in)) < 0) {
472 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100473 LOGP(DLGTP, LOGL_ERROR,
474 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100475 gsn->fd0, (unsigned long)&qmsg->p,
476 qmsg->l, strerror(errno));
477 }
478 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100479 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100480 qmsg->retrans++;
481 }
482 }
jjako52c24142002-12-16 13:33:51 +0000483
Harald Weltebed35df2011-11-02 13:06:18 +0100484 /* Also clean up reply timeouts */
485 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
486 (qmsg->timeout < now)) {
487 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
488 queue_freemsg(gsn->queue_resp, qmsg);
489 }
jjako52c24142002-12-16 13:33:51 +0000490
Harald Weltebed35df2011-11-02 13:06:18 +0100491 return 0;
jjako52c24142002-12-16 13:33:51 +0000492}
493
Harald Weltebed35df2011-11-02 13:06:18 +0100494int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
495{
496 time_t now, later;
497 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000498
Harald Weltebed35df2011-11-02 13:06:18 +0100499 if (queue_getfirst(gsn->queue_req, &qmsg)) {
500 timeout->tv_sec = 10;
501 timeout->tv_usec = 0;
502 } else {
503 now = time(NULL);
504 later = qmsg->timeout;
505 timeout->tv_sec = later - now;
506 timeout->tv_usec = 0;
507 if (timeout->tv_sec < 0)
508 timeout->tv_sec = 0; /* No negative allowed */
509 if (timeout->tv_sec > 10)
510 timeout->tv_sec = 10; /* Max sleep for 10 sec */
511 }
512 return 0;
jjako52c24142002-12-16 13:33:51 +0000513}
514
Harald Weltebed35df2011-11-02 13:06:18 +0100515int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000516 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100517 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
518{
519 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000520
Harald Weltebed35df2011-11-02 13:06:18 +0100521 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
522 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
523 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100524 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100525 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
526 (packet->gtp0.h.type == GTP_ERROR)))
527 packet->gtp0.h.flow = hton16(pdp->flru);
528 else if (pdp)
529 packet->gtp0.h.flow = hton16(pdp->flrc);
530 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
531 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
532 packet->gtp1l.h.seq = hton16(seq);
533 if (pdp && (fd == gsn->fd1u))
534 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
535 else if (pdp)
536 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
537 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100538 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100539 return -1;
540 }
jjako08d331d2003-10-13 20:33:30 +0000541
Harald Weltebed35df2011-11-02 13:06:18 +0100542 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100543 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100544 return -1;
545 }
jjako52c24142002-12-16 13:33:51 +0000546
Harald Weltebed35df2011-11-02 13:06:18 +0100547 if (sendto(fd, packet, len, 0,
548 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
549 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100550 LOGP(DLGTP, LOGL_ERROR,
551 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100552 (unsigned long)&packet, len, strerror(errno));
553 return -1;
554 }
555
556 /* Use new queue structure */
557 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
558 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100559 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100560 } else {
561 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
562 qmsg->l = len;
563 qmsg->timeout = time(NULL) + 60; /* When to timeout */
564 qmsg->retrans = 0; /* No retransmissions so far */
565 qmsg->cbp = NULL;
566 qmsg->type = 0;
567 qmsg->fd = fd;
568 }
569 return 0;
jjako52c24142002-12-16 13:33:51 +0000570}
571
jjako2c381332003-10-21 19:09:53 +0000572int gtp_notification(struct gsn_t *gsn, int version,
573 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100574 struct sockaddr_in *peer, int fd, uint16_t seq)
575{
jjako2c381332003-10-21 19:09:53 +0000576
Harald Weltebed35df2011-11-02 13:06:18 +0100577 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000578
Harald Weltebed35df2011-11-02 13:06:18 +0100579 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000580
Harald Weltebed35df2011-11-02 13:06:18 +0100581 /* In GTP0 notifications are treated as replies. In GTP1 they
582 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000583
Harald Weltebed35df2011-11-02 13:06:18 +0100584 if (fd == gsn->fd1c)
585 addr.sin_port = htons(GTP1C_PORT);
586 else if (fd == gsn->fd1u)
587 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000588
Harald Weltebed35df2011-11-02 13:06:18 +0100589 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
590 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
591 packet->gtp0.h.seq = hton16(seq);
592 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
593 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
594 packet->gtp1l.h.seq = hton16(seq);
595 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100596 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100597 return -1;
598 }
599
600 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100601 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100602 return -1;
603 }
604
605 if (sendto(fd, packet, len, 0,
606 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
607 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100608 LOGP(DLGTP, LOGL_ERROR,
609 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100610 (unsigned long)&packet, len, strerror(errno));
611 return -1;
612 }
613 return 0;
jjako2c381332003-10-21 19:09:53 +0000614}
615
Harald Weltebed35df2011-11-02 13:06:18 +0100616int gtp_dublicate(struct gsn_t *gsn, int version,
617 struct sockaddr_in *peer, uint16_t seq)
618{
619 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000620
Harald Weltebed35df2011-11-02 13:06:18 +0100621 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
622 return EOF; /* Notfound */
623 }
jjakoa7cd2492003-04-11 09:40:12 +0000624
Harald Weltebed35df2011-11-02 13:06:18 +0100625 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100626 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100627 return -1;
628 }
629
630 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
631 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
632 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100633 LOGP(DLGTP, LOGL_ERROR,
634 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100635 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
636 strerror(errno));
637 }
638 return 0;
jjako52c24142002-12-16 13:33:51 +0000639}
640
jjako52c24142002-12-16 13:33:51 +0000641/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100642static void log_restart(struct gsn_t *gsn)
643{
jjako52c24142002-12-16 13:33:51 +0000644 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200645 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000646 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200647 char *filename;
jjako52c24142002-12-16 13:33:51 +0000648
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200649 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
650 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000651
652 /* We try to open file. On failure we will later try to create file */
653 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100654 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100655 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100656 filename);
657 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100658 rc = fscanf(f, "%d", &counter);
659 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100660 LOGP(DLGTP, LOGL_ERROR,
661 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100662 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100663 }
664 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100665 LOGP(DLGTP, LOGL_ERROR,
666 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100667 }
jjako52c24142002-12-16 13:33:51 +0000668 }
Harald Weltebed35df2011-11-02 13:06:18 +0100669
670 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000671 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100672
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200673 /* Keep the umask closely wrapped around our fopen() call in case the
674 * log outputs cause file creation. */
675 i = umask(022);
676 f = fopen(filename, "w");
677 umask(i);
678 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100679 LOGP(DLGTP, LOGL_ERROR,
680 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100681 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200682 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000683 }
684
jjako52c24142002-12-16 13:33:51 +0000685 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100686close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200687 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100688 LOGP(DLGTP, LOGL_ERROR,
689 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200690free_filename:
691 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000692}
693
jjako1db1c812003-07-06 20:53:57 +0000694int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100695 int mode)
jjako52c24142002-12-16 13:33:51 +0000696{
Harald Weltebed35df2011-11-02 13:06:18 +0100697 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000698
Max14b1b632017-08-21 20:14:59 +0200699 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
jjako52c24142002-12-16 13:33:51 +0000700
Harald Weltebed35df2011-11-02 13:06:18 +0100701 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000702
Harald Weltebed35df2011-11-02 13:06:18 +0100703 (*gsn)->statedir = statedir;
704 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000705
Harald Weltebed35df2011-11-02 13:06:18 +0100706 /* Initialise sequence number */
707 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000708
Harald Weltebed35df2011-11-02 13:06:18 +0100709 /* Initialise request retransmit queue */
710 queue_new(&(*gsn)->queue_req);
711 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000712
Harald Weltebed35df2011-11-02 13:06:18 +0100713 /* Initialise pdp table */
714 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000715
Harald Weltebed35df2011-11-02 13:06:18 +0100716 /* Initialise call back functions */
717 (*gsn)->cb_create_context_ind = 0;
718 (*gsn)->cb_delete_context = 0;
719 (*gsn)->cb_unsup_ind = 0;
720 (*gsn)->cb_conf = 0;
721 (*gsn)->cb_data_ind = 0;
722
723 /* Store function parameters */
724 (*gsn)->gsnc = *listen;
725 (*gsn)->gsnu = *listen;
726 (*gsn)->mode = mode;
727
728 /* Create GTP version 0 socket */
729 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
730 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100731 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200732 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100733 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200734 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100735 }
736
737 memset(&addr, 0, sizeof(addr));
738 addr.sin_family = AF_INET;
739 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
740 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000741#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100742 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000743#endif
jjako08d331d2003-10-13 20:33:30 +0000744
Harald Weltebed35df2011-11-02 13:06:18 +0100745 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
746 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200747 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
748 "bind(fd0=%d) failed: Error = %s\n",
749 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200750 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100751 }
jjako08d331d2003-10-13 20:33:30 +0000752
Harald Weltebed35df2011-11-02 13:06:18 +0100753 /* Create GTP version 1 control plane socket */
754 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
755 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100756 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200757 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100758 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200759 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100760 }
761
762 memset(&addr, 0, sizeof(addr));
763 addr.sin_family = AF_INET;
764 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
765 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000766#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100767 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000768#endif
jjako08d331d2003-10-13 20:33:30 +0000769
Harald Weltebed35df2011-11-02 13:06:18 +0100770 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
771 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200772 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
773 "bind(fd1c=%d) failed: Error = %s\n",
774 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200775 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100776 }
jjako08d331d2003-10-13 20:33:30 +0000777
Harald Weltebed35df2011-11-02 13:06:18 +0100778 /* Create GTP version 1 user plane socket */
779 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
780 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100781 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200782 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100783 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200784 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100785 }
786
787 memset(&addr, 0, sizeof(addr));
788 addr.sin_family = AF_INET;
789 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
790 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000791#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100792 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000793#endif
jjako52c24142002-12-16 13:33:51 +0000794
Harald Weltebed35df2011-11-02 13:06:18 +0100795 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
796 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200797 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +0200798 "bind(fd1u=%d) failed: Error = %s\n",
799 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +0200800 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100801 }
802
803 return 0;
jjako52c24142002-12-16 13:33:51 +0000804}
805
Harald Weltebed35df2011-11-02 13:06:18 +0100806int gtp_free(struct gsn_t *gsn)
807{
jjako52c24142002-12-16 13:33:51 +0000808
Harald Weltebed35df2011-11-02 13:06:18 +0100809 /* Clean up retransmit queues */
810 queue_free(gsn->queue_req);
811 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000812
Harald Weltebed35df2011-11-02 13:06:18 +0100813 close(gsn->fd0);
814 close(gsn->fd1c);
815 close(gsn->fd1u);
816
817 free(gsn);
818 return 0;
jjako52c24142002-12-16 13:33:51 +0000819}
820
821/* ***********************************************************
822 * Path management messages
823 * Messages: echo and version not supported.
824 * A path is connection between two UDP/IP endpoints
825 *
826 * A path is either using GTP0 or GTP1. A path can be
827 * established by any kind of GTP message??
828
829 * Which source port to use?
830 * GTP-C request destination port is 2123/3386
831 * GTP-U request destination port is 2152/3386
832 * T-PDU destination port is 2152/3386.
833 * For the above messages the source port is locally allocated.
834 * For response messages src=rx-dst and dst=rx-src.
835 * For simplicity we should probably use 2123+2152/3386 as
836 * src port even for the cases where src can be locally
837 * allocated. This also means that we have to listen only to
838 * the same ports.
839 * For response messages we need to be able to respond to
840 * the relevant src port even if it is locally allocated by
841 * the peer.
842 *
843 * The need for path management!
844 * We might need to keep a list of active paths. This might
845 * be in the form of remote IP address + UDP port numbers.
846 * (We will consider a path astablished if we have a context
847 * with the node in question)
848 *************************************************************/
849
850/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000851int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
852 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000853{
Harald Weltebed35df2011-11-02 13:06:18 +0100854 union gtp_packet packet;
855 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
856 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000857}
858
jjako08d331d2003-10-13 20:33:30 +0000859/* Send off an echo reply */
860int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100861 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000862{
Harald Weltebed35df2011-11-02 13:06:18 +0100863 union gtp_packet packet;
864 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
865 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
866 gsn->restart_counter);
867 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
868 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000869}
870
jjako52c24142002-12-16 13:33:51 +0000871/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +0100872int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
873 int fd, void *pack, unsigned len)
874{
jjako52c24142002-12-16 13:33:51 +0000875
Harald Weltebed35df2011-11-02 13:06:18 +0100876 /* Check if it was a dublicate request */
877 if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
878 return 0;
jjako52c24142002-12-16 13:33:51 +0000879
Harald Weltebed35df2011-11-02 13:06:18 +0100880 /* Send off reply to request */
881 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000882}
883
884/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000885int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100886 void *pack, unsigned len)
887{
888 union gtpie_member *ie[GTPIE_SIZE];
889 unsigned char recovery;
890 void *cbp = NULL;
891 uint8_t type = 0;
892 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000893
Harald Weltebed35df2011-11-02 13:06:18 +0100894 /* Remove packet from queue */
895 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
896 return EOF;
jjako52c24142002-12-16 13:33:51 +0000897
Harald Weltebed35df2011-11-02 13:06:18 +0100898 /* Extract information elements into a pointer array */
899 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
900 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100901 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
902 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100903 if (gsn->cb_conf)
904 gsn->cb_conf(type, EOF, NULL, cbp);
905 return EOF;
906 }
jjako52c24142002-12-16 13:33:51 +0000907
Harald Weltebed35df2011-11-02 13:06:18 +0100908 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
909 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100910 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
911 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100912 if (gsn->cb_conf)
913 gsn->cb_conf(type, EOF, NULL, cbp);
914 return EOF;
915 }
jjako52c24142002-12-16 13:33:51 +0000916
Harald Weltebed35df2011-11-02 13:06:18 +0100917 /* Echo reply packages does not have a cause information element */
918 /* Instead we return the recovery number in the callback function */
919 if (gsn->cb_conf)
920 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +0100921
Harald Weltebed35df2011-11-02 13:06:18 +0100922 if (gsn->cb_recovery)
923 gsn->cb_recovery(peer, recovery);
924
925 return 0;
jjako52c24142002-12-16 13:33:51 +0000926}
927
928/* Send off a Version Not Supported message */
929/* This message is somewhat special in that it actually is a
930 * response to some other message with unsupported GTP version
931 * For this reason it has parameters like a response, and does
932 * its own message transmission. No signalling queue is used
933 * The reply is sent to the peer IP and peer UDP. This means that
934 * the peer will be receiving a GTP0 message on a GTP1 port!
935 * In practice however this will never happen as a GTP0 GSN will
936 * only listen to the GTP0 port, and therefore will never receive
937 * anything else than GTP0 */
938
jjako08d331d2003-10-13 20:33:30 +0000939int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
940 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000941{
Harald Weltebed35df2011-11-02 13:06:18 +0100942 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +0000943
Harald Weltebed35df2011-11-02 13:06:18 +0100944 /* GTP 1 is the highest supported protocol */
945 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
946 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +0000947}
948
949/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +0100950int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
951 void *pack, unsigned len)
952{
jjako52c24142002-12-16 13:33:51 +0000953
Harald Weltebed35df2011-11-02 13:06:18 +0100954 if (gsn->cb_unsup_ind)
955 gsn->cb_unsup_ind(peer);
956
957 return 0;
jjako52c24142002-12-16 13:33:51 +0000958}
959
jjako2c381332003-10-21 19:09:53 +0000960/* Send off an Supported Extension Headers Notification */
961int gtp_extheader_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
962 int fd, void *pack, unsigned len)
963{
Harald Weltebed35df2011-11-02 13:06:18 +0100964 union gtp_packet packet;
965 unsigned int length =
966 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +0000967
Harald Weltebed35df2011-11-02 13:06:18 +0100968 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +0000969
Harald Weltebed35df2011-11-02 13:06:18 +0100970 if (version < 1)
971 return 0;
jjako2c381332003-10-21 19:09:53 +0000972
Harald Weltebed35df2011-11-02 13:06:18 +0100973 /* We report back that we support only PDCP PDU headers */
974 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
975 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +0000976
Harald Weltebed35df2011-11-02 13:06:18 +0100977 return gtp_notification(gsn, version, &packet, length,
978 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +0000979}
980
981/* Handle a Supported Extension Headers Notification */
Harald Weltebed35df2011-11-02 13:06:18 +0100982int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
983 void *pack, unsigned len)
984{
jjako2c381332003-10-21 19:09:53 +0000985
Harald Weltebed35df2011-11-02 13:06:18 +0100986 if (gsn->cb_extheader_ind)
987 gsn->cb_extheader_ind(peer);
988
989 return 0;
jjako2c381332003-10-21 19:09:53 +0000990}
991
jjako52c24142002-12-16 13:33:51 +0000992/* ***********************************************************
993 * Session management messages
994 * Messages: create, update and delete PDP context
995 *
996 * Information storage
997 * Information storage for each PDP context is defined in
998 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
999 * PDP-address (IP address), sequence numbers, charging ID.
1000 * For the SGSN it also includes radio related mobility
1001 * information.
1002 *************************************************************/
1003
Harald Welte7b3347b2010-05-15 12:18:46 +02001004/* API: Send Create PDP Context Request (7.3.1) */
Harald Weltebed35df2011-11-02 13:06:18 +01001005extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
1006 void *cbp)
1007{
1008 union gtp_packet packet;
1009 unsigned int length =
1010 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1011 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001012
Harald Weltebed35df2011-11-02 13:06:18 +01001013 /* TODO: Secondary PDP Context Activation Procedure */
1014 /* In secondary activation procedure the PDP context is identified
1015 by tei in the header. The following fields are omitted: Selection
1016 mode, IMSI, MSISDN, End User Address, Access Point Name and
1017 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001018
Harald Weltebed35df2011-11-02 13:06:18 +01001019 if (pdp->secondary) {
1020 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001021 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001022 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001023 return EOF;
1024 }
1025 }
jjako2c381332003-10-21 19:09:53 +00001026
Harald Weltebed35df2011-11-02 13:06:18 +01001027 if (pdp->version == 0) {
1028 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1029 sizeof(pdp->qos_req0), pdp->qos_req0);
1030 }
jjako52c24142002-12-16 13:33:51 +00001031
Harald Weltebed35df2011-11-02 13:06:18 +01001032 /* Section 7.7.2 */
1033 if (pdp->version == 1) {
1034 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1035 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1036 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1037 }
jjako52c24142002-12-16 13:33:51 +00001038
Harald Weltebed35df2011-11-02 13:06:18 +01001039 /* Section 7.7.3 Routing Area Information */
1040 if (pdp->rai_given == 1)
1041 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1042 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001043
Harald Weltebed35df2011-11-02 13:06:18 +01001044 /* Section 7.7.11 */
1045 if (pdp->norecovery_given == 0)
1046 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1047 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001048
Harald Weltebed35df2011-11-02 13:06:18 +01001049 /* Section 7.7.12 */
1050 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1051 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1052 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001053
Harald Weltebed35df2011-11-02 13:06:18 +01001054 if (pdp->version == 0) {
1055 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1056 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1057 }
jjako08d331d2003-10-13 20:33:30 +00001058
Harald Weltebed35df2011-11-02 13:06:18 +01001059 /* Section 7.7.13 */
1060 if (pdp->version == 1) {
1061 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1062 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001063
Harald Weltebed35df2011-11-02 13:06:18 +01001064 /* Section 7.7.14 */
1065 if (!pdp->teic_confirmed)
1066 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1067 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001068
Harald Weltebed35df2011-11-02 13:06:18 +01001069 /* Section 7.7.17 */
1070 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001071
Harald Weltebed35df2011-11-02 13:06:18 +01001072 /* Section 7.7.17 */
1073 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1074 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1075 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001076
Harald Weltebed35df2011-11-02 13:06:18 +01001077 /* Section 7.7.23 */
1078 if (pdp->cch_pdp) /* Only include charging if flags are set */
1079 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1080 pdp->cch_pdp);
1081 }
jjako9b4971d2004-05-27 20:30:19 +00001082
Harald Weltebed35df2011-11-02 13:06:18 +01001083 /* TODO
1084 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1085 pdp->traceref);
1086 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1087 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001088
Harald Weltebed35df2011-11-02 13:06:18 +01001089 /* Section 7.7.27 */
1090 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1091 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1092 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001093
Harald Weltebed35df2011-11-02 13:06:18 +01001094 /* Section 7.7.30 */
1095 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1096 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1097 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001098
Harald Weltebed35df2011-11-02 13:06:18 +01001099 /* Section 7.7.31 */
1100 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1101 if (pdp->pco_req.l)
1102 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1103 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001104
Harald Weltebed35df2011-11-02 13:06:18 +01001105 /* Section 7.7.32 */
1106 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1107 pdp->gsnlc.l, pdp->gsnlc.v);
1108 /* Section 7.7.32 */
1109 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1110 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001111
Harald Weltebed35df2011-11-02 13:06:18 +01001112 /* Section 7.7.33 */
1113 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1114 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1115 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001116
Harald Weltebed35df2011-11-02 13:06:18 +01001117 /* Section 7.7.34 */
1118 if (pdp->version == 1)
1119 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1120 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001121
Harald Weltebed35df2011-11-02 13:06:18 +01001122 /* Section 7.7.36 */
1123 if ((pdp->version == 1) && pdp->tft.l)
1124 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1125 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001126
Harald Weltebed35df2011-11-02 13:06:18 +01001127 /* Section 7.7.41 */
1128 if ((pdp->version == 1) && pdp->triggerid.l)
1129 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1130 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001131
Harald Weltebed35df2011-11-02 13:06:18 +01001132 /* Section 7.7.42 */
1133 if ((pdp->version == 1) && pdp->omcid.l)
1134 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1135 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001136
Harald Weltebed35df2011-11-02 13:06:18 +01001137 /* new R7 fields */
1138 if (pdp->rattype_given == 1)
1139 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1140 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001141
Harald Weltebed35df2011-11-02 13:06:18 +01001142 if (pdp->userloc_given == 1)
1143 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1144 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001145
Harald Weltebed35df2011-11-02 13:06:18 +01001146 if (pdp->mstz_given == 1)
1147 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1148 pdp->mstz.l, pdp->mstz.v);
1149
1150 if (pdp->imeisv_given == 1)
1151 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1152 pdp->imeisv.l, pdp->imeisv.v);
1153
1154 /* TODO hisaddr0 */
1155 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1156
1157 return 0;
jjako52c24142002-12-16 13:33:51 +00001158}
1159
jjako08d331d2003-10-13 20:33:30 +00001160/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001161int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1162{
jjako08d331d2003-10-13 20:33:30 +00001163
Harald Weltebed35df2011-11-02 13:06:18 +01001164 /* Now send off a reply to the peer */
1165 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1166
1167 if (cause != GTPCAUSE_ACC_REQ) {
1168 pdp_freepdp(pdp);
1169 }
1170
1171 return 0;
jjako08d331d2003-10-13 20:33:30 +00001172}
1173
1174/* API: Register create context indication callback */
1175int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001176 int (*cb_create_context_ind) (struct pdp_t *
1177 pdp))
jjako52c24142002-12-16 13:33:51 +00001178{
Harald Weltebed35df2011-11-02 13:06:18 +01001179 gsn->cb_create_context_ind = cb_create_context_ind;
1180 return 0;
jjako08d331d2003-10-13 20:33:30 +00001181}
1182
jjako08d331d2003-10-13 20:33:30 +00001183/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001184int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1185 uint8_t cause)
1186{
1187 union gtp_packet packet;
1188 unsigned int length =
1189 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001190
Harald Weltebed35df2011-11-02 13:06:18 +01001191 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001192
Harald Weltebed35df2011-11-02 13:06:18 +01001193 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001194
Harald Weltebed35df2011-11-02 13:06:18 +01001195 if (version == 0)
1196 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1197 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001198
Harald Weltebed35df2011-11-02 13:06:18 +01001199 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1200 pdp->reorder);
1201 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1202 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001203
Harald Weltebed35df2011-11-02 13:06:18 +01001204 if (version == 0) {
1205 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1206 pdp->fllu);
1207 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1208 pdp->fllc);
1209 }
jjako08d331d2003-10-13 20:33:30 +00001210
Harald Weltebed35df2011-11-02 13:06:18 +01001211 if (version == 1) {
1212 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1213 pdp->teid_own);
1214 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1215 pdp->teic_own);
1216 }
jjako08d331d2003-10-13 20:33:30 +00001217
Harald Weltebed35df2011-11-02 13:06:18 +01001218 /* TODO: We use teic_own as charging ID */
1219 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1220 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001221
Harald Weltebed35df2011-11-02 13:06:18 +01001222 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1223 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001224
Harald Weltebed35df2011-11-02 13:06:18 +01001225 if (pdp->pco_neg.l) { /* Optional PCO */
1226 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1227 pdp->pco_neg.l, pdp->pco_neg.v);
1228 }
jjako52c24142002-12-16 13:33:51 +00001229
Harald Weltebed35df2011-11-02 13:06:18 +01001230 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1231 pdp->gsnlc.l, pdp->gsnlc.v);
1232 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1233 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001234
Harald Weltebed35df2011-11-02 13:06:18 +01001235 if (version == 1)
1236 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1237 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001238
Harald Weltebed35df2011-11-02 13:06:18 +01001239 /* TODO: Charging gateway address */
1240 }
jjako52c24142002-12-16 13:33:51 +00001241
Harald Weltebed35df2011-11-02 13:06:18 +01001242 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1243 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001244}
1245
1246/* Handle Create PDP Context Request */
1247int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001248 struct sockaddr_in *peer, int fd,
1249 void *pack, unsigned len)
1250{
1251 struct pdp_t *pdp, *pdp_old;
1252 struct pdp_t pdp_buf;
1253 union gtpie_member *ie[GTPIE_SIZE];
1254 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001255
Harald Weltebed35df2011-11-02 13:06:18 +01001256 uint16_t seq = get_seq(pack);
1257 int hlen = get_hlen(pack);
1258 uint8_t linked_nsapi = 0;
1259 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001260
Harald Weltebed35df2011-11-02 13:06:18 +01001261 if (!gtp_dublicate(gsn, version, peer, seq))
1262 return 0;
jjako08d331d2003-10-13 20:33:30 +00001263
Harald Weltebed35df2011-11-02 13:06:18 +01001264 pdp = &pdp_buf;
1265 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001266
Harald Weltebed35df2011-11-02 13:06:18 +01001267 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001268 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1269
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001270 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001271 }
jjako52c24142002-12-16 13:33:51 +00001272
Harald Weltebed35df2011-11-02 13:06:18 +01001273 pdp->seq = seq;
1274 pdp->sa_peer = *peer;
1275 pdp->fd = fd;
1276 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001277
Harald Weltebed35df2011-11-02 13:06:18 +01001278 /* Decode information elements */
1279 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1280 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001281 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1282 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001283 if (0 == version)
1284 return EOF;
1285 else
1286 return gtp_create_pdp_resp(gsn, version, pdp,
1287 GTPCAUSE_INVALID_MESSAGE);
1288 }
jjako52c24142002-12-16 13:33:51 +00001289
Harald Weltebed35df2011-11-02 13:06:18 +01001290 if (version == 1) {
1291 /* Linked NSAPI (conditional) */
1292 /* If included this is the Secondary PDP Context Activation Procedure */
1293 /* In secondary activation IMSI is not included, so the context must be */
1294 /* identified by the tei */
1295 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001296
Harald Weltebed35df2011-11-02 13:06:18 +01001297 /* Find the primary PDP context */
1298 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1299 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001300 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001301 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001302 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001303 return gtp_create_pdp_resp(gsn, version, pdp,
1304 GTPCAUSE_OPT_IE_INCORRECT);
1305 }
jjako2c381332003-10-21 19:09:53 +00001306
Harald Weltebed35df2011-11-02 13:06:18 +01001307 /* Check that the primary PDP context matches linked nsapi */
1308 if (linked_pdp->nsapi != linked_nsapi) {
1309 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001310 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001311 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001312 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001313 return gtp_create_pdp_resp(gsn, version, pdp,
1314 GTPCAUSE_OPT_IE_INCORRECT);
1315 }
jjako52c24142002-12-16 13:33:51 +00001316
Harald Weltebed35df2011-11-02 13:06:18 +01001317 /* Copy parameters from primary context */
1318 pdp->selmode = linked_pdp->selmode;
1319 pdp->imsi = linked_pdp->imsi;
1320 pdp->msisdn = linked_pdp->msisdn;
1321 pdp->eua = linked_pdp->eua;
1322 pdp->pco_req = linked_pdp->pco_req;
1323 pdp->apn_req = linked_pdp->apn_req;
1324 pdp->teic_gn = linked_pdp->teic_gn;
1325 pdp->secondary = 1;
1326 }
1327 }
1328 /* if (version == 1) */
1329 if (version == 0) {
1330 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1331 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1332 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001333 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1334 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001335 return gtp_create_pdp_resp(gsn, version, pdp,
1336 GTPCAUSE_MAN_IE_MISSING);
1337 }
1338 }
jjako08d331d2003-10-13 20:33:30 +00001339
Harald Weltebed35df2011-11-02 13:06:18 +01001340 if ((version == 1) && (!linked_pdp)) {
1341 /* Not Secondary PDP Context Activation Procedure */
1342 /* IMSI (conditional) */
1343 if (gtpie_gettv0
1344 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1345 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001346 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1347 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001348 return gtp_create_pdp_resp(gsn, version, pdp,
1349 GTPCAUSE_MAN_IE_MISSING);
1350 }
1351 }
jjako52c24142002-12-16 13:33:51 +00001352
Harald Weltebed35df2011-11-02 13:06:18 +01001353 /* Recovery (optional) */
1354 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1355 if (gsn->cb_recovery)
1356 gsn->cb_recovery(peer, recovery);
1357 }
jjako52c24142002-12-16 13:33:51 +00001358
Harald Weltebed35df2011-11-02 13:06:18 +01001359 /* Selection mode (conditional) */
1360 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1361 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1362 &pdp->selmode, sizeof(pdp->selmode))) {
1363 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001364 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1365 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001366 return gtp_create_pdp_resp(gsn, version, pdp,
1367 GTPCAUSE_MAN_IE_MISSING);
1368 }
1369 }
jjako52c24142002-12-16 13:33:51 +00001370
Harald Weltebed35df2011-11-02 13:06:18 +01001371 if (version == 0) {
1372 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1373 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001374 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1375 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001376 return gtp_create_pdp_resp(gsn, version, pdp,
1377 GTPCAUSE_MAN_IE_MISSING);
1378 }
jjako52c24142002-12-16 13:33:51 +00001379
Harald Weltebed35df2011-11-02 13:06:18 +01001380 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1381 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001382 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1383 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001384 return gtp_create_pdp_resp(gsn, version, pdp,
1385 GTPCAUSE_MAN_IE_MISSING);
1386 }
1387 }
jjako08d331d2003-10-13 20:33:30 +00001388
Harald Weltebed35df2011-11-02 13:06:18 +01001389 if (version == 1) {
1390 /* TEID (mandatory) */
1391 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1392 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001393 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1394 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001395 return gtp_create_pdp_resp(gsn, version, pdp,
1396 GTPCAUSE_MAN_IE_MISSING);
1397 }
jjako2c381332003-10-21 19:09:53 +00001398
Harald Weltebed35df2011-11-02 13:06:18 +01001399 /* TEIC (conditional) */
1400 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1401 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1402 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001403 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001404 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001405 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001406 return gtp_create_pdp_resp(gsn, version, pdp,
1407 GTPCAUSE_MAN_IE_MISSING);
1408 }
1409 }
jjako08d331d2003-10-13 20:33:30 +00001410
Harald Weltebed35df2011-11-02 13:06:18 +01001411 /* NSAPI (mandatory) */
1412 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1413 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001414 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1415 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001416 return gtp_create_pdp_resp(gsn, version, pdp,
1417 GTPCAUSE_MAN_IE_MISSING);
1418 }
1419 }
jjako2e840a32003-01-28 16:05:18 +00001420
Harald Weltebed35df2011-11-02 13:06:18 +01001421 /* Charging Characteriatics (optional) */
1422 /* Trace reference (optional) */
1423 /* Trace type (optional) */
1424 /* Charging Characteriatics (optional) */
jjako52c24142002-12-16 13:33:51 +00001425
Harald Weltebed35df2011-11-02 13:06:18 +01001426 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1427 /* End User Address (conditional) */
1428 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1429 &pdp->eua.v, sizeof(pdp->eua.v))) {
1430 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001431 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1432 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001433 return gtp_create_pdp_resp(gsn, version, pdp,
1434 GTPCAUSE_MAN_IE_MISSING);
1435 }
jjako08d331d2003-10-13 20:33:30 +00001436
Harald Weltebed35df2011-11-02 13:06:18 +01001437 /* APN */
1438 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1439 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1440 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001441 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1442 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001443 return gtp_create_pdp_resp(gsn, version, pdp,
1444 GTPCAUSE_MAN_IE_MISSING);
1445 }
jjako2c381332003-10-21 19:09:53 +00001446
Harald Weltebed35df2011-11-02 13:06:18 +01001447 /* Extract protocol configuration options (optional) */
1448 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1449 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1450 }
1451 }
jjako2c381332003-10-21 19:09:53 +00001452
Harald Weltebed35df2011-11-02 13:06:18 +01001453 /* SGSN address for signalling (mandatory) */
1454 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1455 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1456 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001457 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1458 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001459 return gtp_create_pdp_resp(gsn, version, pdp,
1460 GTPCAUSE_MAN_IE_MISSING);
1461 }
jjako2e840a32003-01-28 16:05:18 +00001462
Harald Weltebed35df2011-11-02 13:06:18 +01001463 /* SGSN address for user traffic (mandatory) */
1464 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1465 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1466 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001467 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1468 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001469 return gtp_create_pdp_resp(gsn, version, pdp,
1470 GTPCAUSE_MAN_IE_MISSING);
1471 }
jjako52c24142002-12-16 13:33:51 +00001472
Harald Weltebed35df2011-11-02 13:06:18 +01001473 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1474 /* MSISDN (conditional) */
1475 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1476 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1477 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001478 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1479 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001480 return gtp_create_pdp_resp(gsn, version, pdp,
1481 GTPCAUSE_MAN_IE_MISSING);
1482 }
1483 }
jjako52c24142002-12-16 13:33:51 +00001484
Harald Weltebed35df2011-11-02 13:06:18 +01001485 if (version == 1) {
1486 /* QoS (mandatory) */
1487 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1488 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1489 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001490 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1491 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001492 return gtp_create_pdp_resp(gsn, version, pdp,
1493 GTPCAUSE_MAN_IE_MISSING);
1494 }
1495
1496 /* TFT (conditional) */
1497 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1498 &pdp->tft.v, sizeof(pdp->tft.v))) {
1499 }
1500
1501 /* Trigger ID */
1502 /* OMC identity */
1503 }
1504
1505 /* Initialize our own IP addresses */
1506 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1507 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1508
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001509 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001510
1511 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1512 /* Found old pdp with same tid. Now the voodoo begins! */
1513 /* 09.60 / 29.060 allows create on existing context to "steal" */
1514 /* the context which was allready established */
1515 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001516 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001517 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1518 &&
1519 (!memcmp
1520 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1521 && (pdp->selmode == pdp_old->selmode)
1522 && (pdp->msisdn.l == pdp_old->msisdn.l)
1523 &&
1524 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1525 {
1526 /* OK! We are dealing with the same APN. We will copy new
1527 * parameters to the old pdp and send off confirmation
1528 * We ignore the following information elements:
1529 * QoS: MS will get originally negotiated QoS.
1530 * End user address (EUA). MS will get old EUA anyway.
1531 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001532 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001533
1534 /* Copy remote flow label */
1535 pdp_old->flru = pdp->flru;
1536 pdp_old->flrc = pdp->flrc;
1537
1538 /* Copy remote tei */
1539 pdp_old->teid_gn = pdp->teid_gn;
1540 pdp_old->teic_gn = pdp->teic_gn;
1541
1542 /* Copy peer GSN address */
1543 pdp_old->gsnrc.l = pdp->gsnrc.l;
1544 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1545 pdp_old->gsnru.l = pdp->gsnru.l;
1546 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1547
1548 /* Copy request parameters */
1549 pdp_old->seq = pdp->seq;
1550 pdp_old->sa_peer = pdp->sa_peer;
1551 pdp_old->fd = pdp->fd = fd;
1552 pdp_old->version = pdp->version = version;
1553
1554 /* Switch to using the old pdp context */
1555 pdp = pdp_old;
1556
1557 /* Confirm to peer that things were "successful" */
1558 return gtp_create_pdp_resp(gsn, version, pdp,
1559 GTPCAUSE_ACC_REQ);
1560 } else { /* This is not the same PDP context. Delete the old one. */
1561
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001562 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001563
1564 if (gsn->cb_delete_context)
1565 gsn->cb_delete_context(pdp_old);
1566 pdp_freepdp(pdp_old);
1567
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001568 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001569 }
1570 }
1571
1572 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
1573
1574 /* Callback function to validata login */
1575 if (gsn->cb_create_context_ind != 0)
1576 return gsn->cb_create_context_ind(pdp);
1577 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001578 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1579 "No create_context_ind callback defined\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001580 return gtp_create_pdp_resp(gsn, version, pdp,
1581 GTPCAUSE_NOT_SUPPORTED);
1582 }
jjako52c24142002-12-16 13:33:51 +00001583}
1584
jjako52c24142002-12-16 13:33:51 +00001585/* Handle Create PDP Context Response */
1586int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001587 struct sockaddr_in *peer, void *pack, unsigned len)
1588{
1589 struct pdp_t *pdp;
1590 union gtpie_member *ie[GTPIE_SIZE];
1591 uint8_t cause, recovery;
1592 void *cbp = NULL;
1593 uint8_t type = 0;
1594 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001595
Harald Weltebed35df2011-11-02 13:06:18 +01001596 /* Remove packet from queue */
1597 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1598 return EOF;
jjako52c24142002-12-16 13:33:51 +00001599
Harald Weltebed35df2011-11-02 13:06:18 +01001600 /* Find the context in question */
1601 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1602 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001603 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001604 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001605 if (gsn->cb_conf)
1606 gsn->cb_conf(type, EOF, NULL, cbp);
1607 return EOF;
1608 }
jjako2c381332003-10-21 19:09:53 +00001609
Harald Weltebed35df2011-11-02 13:06:18 +01001610 /* Register that we have received a valid teic from GGSN */
1611 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001612
Harald Weltebed35df2011-11-02 13:06:18 +01001613 /* Decode information elements */
1614 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1615 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001616 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1617 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001618 if (gsn->cb_conf)
1619 gsn->cb_conf(type, EOF, pdp, cbp);
1620 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1621 pdp_freepdp(pdp); */
1622 return EOF;
1623 }
jjako52c24142002-12-16 13:33:51 +00001624
Harald Weltebed35df2011-11-02 13:06:18 +01001625 /* Extract cause value (mandatory) */
1626 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1627 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001628 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1629 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001630 if (gsn->cb_conf)
1631 gsn->cb_conf(type, EOF, pdp, cbp);
1632 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1633 pdp_freepdp(pdp); */
1634 return EOF;
1635 }
jjako52c24142002-12-16 13:33:51 +00001636
Harald Weltebed35df2011-11-02 13:06:18 +01001637 /* Extract recovery (optional) */
1638 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1639 if (gsn->cb_recovery)
1640 gsn->cb_recovery(peer, recovery);
1641 }
jjako52c24142002-12-16 13:33:51 +00001642
Harald Weltebed35df2011-11-02 13:06:18 +01001643 /* Extract protocol configuration options (optional) */
1644 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1645 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1646 }
jjako52c24142002-12-16 13:33:51 +00001647
Harald Weltebed35df2011-11-02 13:06:18 +01001648 /* Check all conditional information elements */
1649 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001650
Harald Weltebed35df2011-11-02 13:06:18 +01001651 if (version == 0) {
1652 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1653 &pdp->qos_neg0,
1654 sizeof(pdp->qos_neg0))) {
1655 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001656 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001657 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001658 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001659 if (gsn->cb_conf)
1660 gsn->cb_conf(type, EOF, pdp, cbp);
1661 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1662 pdp_freepdp(pdp); */
1663 return EOF;
1664 }
1665 }
jjako08d331d2003-10-13 20:33:30 +00001666
Harald Weltebed35df2011-11-02 13:06:18 +01001667 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1668 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001669 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001670 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001671 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001672 if (gsn->cb_conf)
1673 gsn->cb_conf(type, EOF, pdp, cbp);
1674 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1675 pdp_freepdp(pdp); */
1676 return EOF;
1677 }
jjako52c24142002-12-16 13:33:51 +00001678
Harald Weltebed35df2011-11-02 13:06:18 +01001679 if (version == 0) {
1680 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1681 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001682 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001683 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001684 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001685 if (gsn->cb_conf)
1686 gsn->cb_conf(type, EOF, pdp, cbp);
1687 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1688 pdp_freepdp(pdp); */
1689 return EOF;
1690 }
jjako52c24142002-12-16 13:33:51 +00001691
Harald Weltebed35df2011-11-02 13:06:18 +01001692 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1693 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001694 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001695 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001696 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001697 if (gsn->cb_conf)
1698 gsn->cb_conf(type, EOF, pdp, cbp);
1699 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1700 pdp_freepdp(pdp); */
1701 return EOF;
1702 }
1703 }
1704
1705 if (version == 1) {
1706 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1707 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001708 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001709 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001710 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001711 if (gsn->cb_conf)
1712 gsn->cb_conf(type, EOF, pdp, cbp);
1713 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1714 pdp_freepdp(pdp); */
1715 return EOF;
1716 }
1717
1718 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1719 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001720 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001721 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001722 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001723 if (gsn->cb_conf)
1724 gsn->cb_conf(type, EOF, pdp, cbp);
1725 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1726 pdp_freepdp(pdp); */
1727 return EOF;
1728 }
1729 }
1730
1731 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1732 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001733 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001734 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001735 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001736 if (gsn->cb_conf)
1737 gsn->cb_conf(type, EOF, pdp, cbp);
1738 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1739 pdp_freepdp(pdp); */
1740 }
1741
1742 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1743 &pdp->eua.v, sizeof(pdp->eua.v))) {
1744 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001745 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001746 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001747 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001748 if (gsn->cb_conf)
1749 gsn->cb_conf(type, EOF, pdp, cbp);
1750 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1751 pdp_freepdp(pdp); */
1752 return EOF;
1753 }
1754
1755 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1756 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1757 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001758 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001759 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001760 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001761 if (gsn->cb_conf)
1762 gsn->cb_conf(type, EOF, pdp, cbp);
1763 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1764 pdp_freepdp(pdp); */
1765 return EOF;
1766 }
1767
1768 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1769 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1770 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001771 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001772 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001773 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001774 if (gsn->cb_conf)
1775 gsn->cb_conf(type, EOF, pdp, cbp);
1776 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1777 pdp_freepdp(pdp); */
1778 return EOF;
1779 }
1780
1781 if (version == 1) {
1782 if (gtpie_gettlv
1783 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1784 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1785 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001786 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001787 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001788 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001789 if (gsn->cb_conf)
1790 gsn->cb_conf(type, EOF, pdp, cbp);
1791 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1792 pdp_freepdp(pdp); */
1793 return EOF;
1794 }
1795 }
1796
1797 }
1798
1799 if (gsn->cb_conf)
1800 gsn->cb_conf(type, cause, pdp, cbp);
1801
1802 return 0;
jjako52c24142002-12-16 13:33:51 +00001803}
1804
jjako08d331d2003-10-13 20:33:30 +00001805/* API: Send Update PDP Context Request */
1806int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001807 struct in_addr *inetaddr)
1808{
1809 union gtp_packet packet;
1810 unsigned int length =
1811 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001812
Harald Weltebed35df2011-11-02 13:06:18 +01001813 if (pdp->version == 0)
1814 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1815 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001816
Harald Weltebed35df2011-11-02 13:06:18 +01001817 /* Include IMSI if updating with unknown teic_gn */
1818 if ((pdp->version == 1) && (!pdp->teic_gn))
1819 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1820 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1821
1822 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1823 gsn->restart_counter);
1824
1825 if (pdp->version == 0) {
1826 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1827 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1828 }
1829
1830 if (pdp->version == 1) {
1831 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1832 pdp->teid_own);
1833
1834 if (!pdp->teic_confirmed)
1835 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1836 pdp->teic_own);
1837 }
1838
1839 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1840
1841 /* TODO
1842 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1843 pdp->traceref);
1844 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1845 pdp->tracetype); */
1846
1847 /* TODO if ggsn update message
1848 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1849 pdp->eua.l, pdp->eua.v);
1850 */
1851
1852 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1853 pdp->gsnlc.l, pdp->gsnlc.v);
1854 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1855 pdp->gsnlu.l, pdp->gsnlu.v);
1856
1857 if (pdp->version == 1)
1858 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1859 pdp->qos_req.l, pdp->qos_req.v);
1860
1861 if ((pdp->version == 1) && pdp->tft.l)
1862 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1863 pdp->tft.l, pdp->tft.v);
1864
1865 if ((pdp->version == 1) && pdp->triggerid.l)
1866 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1867 pdp->triggerid.l, pdp->triggerid.v);
1868
1869 if ((pdp->version == 1) && pdp->omcid.l)
1870 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1871 pdp->omcid.l, pdp->omcid.v);
1872
Daniel Willmann134a7752016-02-03 18:53:29 +01001873 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001874
1875 return 0;
jjako52c24142002-12-16 13:33:51 +00001876}
1877
jjako08d331d2003-10-13 20:33:30 +00001878/* Send Update PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001879int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
1880 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001881 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001882 struct pdp_t *pdp, uint8_t cause)
1883{
jjako08d331d2003-10-13 20:33:30 +00001884
Harald Weltebed35df2011-11-02 13:06:18 +01001885 union gtp_packet packet;
1886 unsigned int length =
1887 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001888
Harald Weltebed35df2011-11-02 13:06:18 +01001889 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001890
Harald Weltebed35df2011-11-02 13:06:18 +01001891 if (cause == GTPCAUSE_ACC_REQ) {
1892
1893 if (version == 0)
1894 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1895 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1896
1897 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1898 gsn->restart_counter);
1899
1900 if (version == 0) {
1901 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1902 pdp->fllu);
1903 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1904 pdp->fllc);
1905 }
1906
1907 if (version == 1) {
1908 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1909 pdp->teid_own);
1910
1911 if (!pdp->teic_confirmed)
1912 gtpie_tv4(&packet, &length, GTP_MAX,
1913 GTPIE_TEI_C, pdp->teic_own);
1914 }
1915
1916 /* TODO we use teid_own as charging ID address */
1917 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1918 pdp->teid_own);
1919
1920 /* If ggsn
1921 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1922 pdp->eua.l, pdp->eua.v); */
1923
1924 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1925 pdp->gsnlc.l, pdp->gsnlc.v);
1926 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1927 pdp->gsnlu.l, pdp->gsnlu.v);
1928
1929 if (version == 1)
1930 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1931 pdp->qos_neg.l, pdp->qos_neg.v);
1932
1933 /* TODO: Charging gateway address */
1934 }
1935
1936 return gtp_resp(version, gsn, pdp, &packet, length, peer,
1937 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00001938}
1939
jjako52c24142002-12-16 13:33:51 +00001940/* Handle Update PDP Context Request */
1941int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001942 struct sockaddr_in *peer, int fd,
1943 void *pack, unsigned len)
1944{
1945 struct pdp_t *pdp;
1946 struct pdp_t pdp_backup;
1947 union gtpie_member *ie[GTPIE_SIZE];
1948 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001949
Harald Weltebed35df2011-11-02 13:06:18 +01001950 uint16_t seq = get_seq(pack);
1951 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001952
Harald Weltebed35df2011-11-02 13:06:18 +01001953 uint64_t imsi;
1954 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00001955
Harald Weltebed35df2011-11-02 13:06:18 +01001956 /* Is this a dublicate ? */
1957 if (!gtp_dublicate(gsn, version, peer, seq)) {
1958 return 0; /* We allready send of response once */
1959 }
jjako08d331d2003-10-13 20:33:30 +00001960
Harald Weltebed35df2011-11-02 13:06:18 +01001961 /* Decode information elements */
1962 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1963 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001964 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1965 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001966 if (0 == version)
1967 return EOF;
1968 else
1969 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
1970 len, NULL,
1971 GTPCAUSE_INVALID_MESSAGE);
1972 }
jjako08d331d2003-10-13 20:33:30 +00001973
Harald Weltebed35df2011-11-02 13:06:18 +01001974 /* Finding PDP: */
1975 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
1976 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
1977 /* we have to use the tunnel endpoint identifier */
1978 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001979 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1980
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001981 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00001982
Harald Weltebed35df2011-11-02 13:06:18 +01001983 /* Find the context in question */
1984 if (pdp_getimsi(&pdp, imsi, nsapi)) {
1985 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001986 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1987 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001988 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
1989 len, NULL,
1990 GTPCAUSE_NON_EXIST);
1991 }
1992 } else if (version == 1) {
1993 /* NSAPI (mandatory) */
1994 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
1995 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001996 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1997 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001998 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
1999 len, NULL,
2000 GTPCAUSE_MAN_IE_MISSING);
2001 }
jjako08d331d2003-10-13 20:33:30 +00002002
Harald Weltebed35df2011-11-02 13:06:18 +01002003 /* IMSI (conditional) */
2004 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2005 /* Find the context in question */
2006 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2007 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002008 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002009 pack, len, "Unknown PDP context: %u\n",
2010 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002011 return gtp_update_pdp_resp(gsn, version, peer,
2012 fd, pack, len, NULL,
2013 GTPCAUSE_NON_EXIST);
2014 }
2015 } else {
2016 /* Find the context in question */
2017 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2018 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002019 GTP_LOGPKG(LOGL_ERROR, peer,
2020 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002021 return gtp_update_pdp_resp(gsn, version, peer,
2022 fd, pack, len, NULL,
2023 GTPCAUSE_NON_EXIST);
2024 }
2025 }
2026 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002027 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002028 return EOF;
2029 }
jjako08d331d2003-10-13 20:33:30 +00002030
Harald Weltebed35df2011-11-02 13:06:18 +01002031 /* Make a backup copy in case anything is wrong */
2032 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002033
Harald Weltebed35df2011-11-02 13:06:18 +01002034 if (version == 0) {
2035 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2036 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2037 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002038 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2039 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002040 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2041 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2042 len, pdp,
2043 GTPCAUSE_MAN_IE_MISSING);
2044 }
2045 }
jjako52c24142002-12-16 13:33:51 +00002046
Harald Weltebed35df2011-11-02 13:06:18 +01002047 /* Recovery (optional) */
2048 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2049 if (gsn->cb_recovery)
2050 gsn->cb_recovery(peer, recovery);
2051 }
jjako08d331d2003-10-13 20:33:30 +00002052
Harald Weltebed35df2011-11-02 13:06:18 +01002053 if (version == 0) {
2054 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2055 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002056 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2057 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002058 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2059 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2060 len, pdp,
2061 GTPCAUSE_MAN_IE_MISSING);
2062 }
jjako52c24142002-12-16 13:33:51 +00002063
Harald Weltebed35df2011-11-02 13:06:18 +01002064 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2065 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002066 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2067 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002068 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2069 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2070 len, pdp,
2071 GTPCAUSE_MAN_IE_MISSING);
2072 }
2073 }
jjako52c24142002-12-16 13:33:51 +00002074
Harald Weltebed35df2011-11-02 13:06:18 +01002075 if (version == 1) {
2076 /* TEID (mandatory) */
2077 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2078 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002079 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2080 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002081 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2082 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2083 len, pdp,
2084 GTPCAUSE_MAN_IE_MISSING);
2085 }
jjako52c24142002-12-16 13:33:51 +00002086
Harald Weltebed35df2011-11-02 13:06:18 +01002087 /* TEIC (conditional) */
2088 /* If TEIC is not included it means that we have allready received it */
2089 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2090 /* all updated contexts, or only for one of the linked contexts */
2091 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2092
2093 /* NSAPI (mandatory) */
2094 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2095 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002096 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2097 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002098 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2099 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2100 len, pdp,
2101 GTPCAUSE_MAN_IE_MISSING);
2102 }
2103 }
2104
2105 /* Trace reference (optional) */
2106 /* Trace type (optional) */
2107
2108 /* End User Address (conditional) TODO: GGSN Initiated
2109 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2110 &pdp->eua.v, sizeof(pdp->eua.v))) {
2111 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002112 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002113 "Missing mandatory information field");
2114 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2115 return gtp_update_pdp_resp(gsn, version, pdp,
2116 GTPCAUSE_MAN_IE_MISSING);
2117 } */
2118
2119 /* SGSN address for signalling (mandatory) */
2120 /* It is weird that this is mandatory when TEIC is conditional */
2121 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2122 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2123 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002124 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2125 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002126 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2127 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2128 pdp, GTPCAUSE_MAN_IE_MISSING);
2129 }
2130
2131 /* SGSN address for user traffic (mandatory) */
2132 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2133 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2134 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002135 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2136 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002137 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2138 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2139 pdp, GTPCAUSE_MAN_IE_MISSING);
2140 }
2141
2142 if (version == 1) {
2143 /* QoS (mandatory) */
2144 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2145 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2146 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002147 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2148 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002149 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2150 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2151 len, pdp,
2152 GTPCAUSE_MAN_IE_MISSING);
2153 }
2154
2155 /* TFT (conditional) */
2156 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2157 &pdp->tft.v, sizeof(pdp->tft.v))) {
2158 }
2159
2160 /* OMC identity */
2161 }
2162
2163 /* Confirm to peer that things were "successful" */
2164 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2165 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002166}
2167
jjako52c24142002-12-16 13:33:51 +00002168/* Handle Update PDP Context Response */
2169int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002170 struct sockaddr_in *peer, void *pack, unsigned len)
2171{
2172 struct pdp_t *pdp;
2173 union gtpie_member *ie[GTPIE_SIZE];
2174 uint8_t cause, recovery;
2175 void *cbp = NULL;
2176 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002177 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002178
Harald Weltebed35df2011-11-02 13:06:18 +01002179 /* Remove packet from queue */
2180 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2181 return EOF;
jjako52c24142002-12-16 13:33:51 +00002182
Harald Weltebed35df2011-11-02 13:06:18 +01002183 /* Find the context in question */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002184 if (pdp_getgtp1(&pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002185 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002186 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002187 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002188 pdp = NULL;
2189 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002190 }
jjako2c381332003-10-21 19:09:53 +00002191
Harald Weltebed35df2011-11-02 13:06:18 +01002192 /* Register that we have received a valid teic from GGSN */
2193 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002194
Harald Weltebed35df2011-11-02 13:06:18 +01002195 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002196 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002197 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002198 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2199 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002200 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002201 }
jjako52c24142002-12-16 13:33:51 +00002202
Harald Weltebed35df2011-11-02 13:06:18 +01002203 /* Extract cause value (mandatory) */
2204 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002205 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002206 }
jjako52c24142002-12-16 13:33:51 +00002207
Harald Weltebed35df2011-11-02 13:06:18 +01002208 /* Extract recovery (optional) */
2209 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2210 if (gsn->cb_recovery)
2211 gsn->cb_recovery(peer, recovery);
2212 }
2213
2214 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002215 /* TODO: This does not handle GGSN-initiated update responses */
2216 if (GTPCAUSE_ACC_REQ == cause) {
2217 if (version == 0) {
2218 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2219 &pdp->qos_neg0,
2220 sizeof(pdp->qos_neg0))) {
2221 goto err_missing;
2222 }
2223
2224 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2225 goto err_missing;
2226 }
2227
2228 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2229 goto err_missing;
2230 }
Harald Weltebed35df2011-11-02 13:06:18 +01002231 }
2232
Daniel Willmannd9975522016-02-04 15:38:12 +01002233 if (version == 1) {
2234 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2235 goto err_missing;
2236 }
Harald Weltebed35df2011-11-02 13:06:18 +01002237
Daniel Willmannd9975522016-02-04 15:38:12 +01002238 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2239 goto err_missing;
2240 }
2241 }
2242
2243 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2244 goto err_missing;
2245 }
2246
2247 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2248 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2249 goto err_missing;
2250 }
2251
2252 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2253 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2254 goto err_missing;
2255 }
2256
2257 if (version == 1) {
2258 if (gtpie_gettlv
2259 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2260 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2261 goto err_missing;
2262 }
2263 }
Harald Weltebed35df2011-11-02 13:06:18 +01002264 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002265
2266 if (gsn->cb_conf)
2267 gsn->cb_conf(type, cause, pdp, cbp);
2268 return 0; /* Succes */
2269
2270err_missing:
2271 gsn->missing++;
2272 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2273 "Missing information field\n");
2274err_out:
2275 if (gsn->cb_conf)
2276 gsn->cb_conf(type, EOF, pdp, cbp);
2277 return EOF;
jjako52c24142002-12-16 13:33:51 +00002278}
2279
jjako08d331d2003-10-13 20:33:30 +00002280/* API: Send Delete PDP Context Request */
jjako2c381332003-10-21 19:09:53 +00002281int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002282 int teardown)
2283{
2284 union gtp_packet packet;
2285 unsigned int length =
2286 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2287 struct in_addr addr;
2288 struct pdp_t *linked_pdp;
2289 struct pdp_t *secondary_pdp;
2290 int n;
2291 int count = 0;
jjako2c381332003-10-21 19:09:53 +00002292
Harald Weltebed35df2011-11-02 13:06:18 +01002293 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2294 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002295 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002296 return EOF;
jjako2c381332003-10-21 19:09:53 +00002297 }
jjako2c381332003-10-21 19:09:53 +00002298
Harald Weltebed35df2011-11-02 13:06:18 +01002299 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002300 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002301 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002302 return EOF;
2303 }
2304
2305 if (!teardown) {
2306 for (n = 0; n < PDP_MAXNSAPI; n++)
2307 if (linked_pdp->secondary_tei[n])
2308 count++;
2309 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002310 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002311 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002312 return EOF;
2313 }
2314 }
2315
2316 if (pdp->version == 1) {
2317 if (teardown)
2318 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2319 0xff);
2320
2321 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2322 }
2323
2324 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2325
2326 if (teardown) { /* Remove all contexts */
2327 for (n = 0; n < PDP_MAXNSAPI; n++) {
2328 if (linked_pdp->secondary_tei[n]) {
2329 if (pdp_getgtp1
2330 (&secondary_pdp,
2331 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002332 LOGP(DLGTP, LOGL_ERROR,
2333 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002334 return EOF;
2335 }
2336 if (linked_pdp != secondary_pdp) {
2337 if (gsn->cb_delete_context)
2338 gsn->cb_delete_context
2339 (secondary_pdp);
2340 pdp_freepdp(secondary_pdp);
2341 }
2342 }
2343 }
2344 if (gsn->cb_delete_context)
2345 gsn->cb_delete_context(linked_pdp);
2346 pdp_freepdp(linked_pdp);
2347 } else {
2348 if (gsn->cb_delete_context)
2349 gsn->cb_delete_context(pdp);
2350 if (pdp == linked_pdp) {
2351 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2352 linked_pdp->nodata = 1;
2353 } else
2354 pdp_freepdp(pdp);
2355 }
2356
2357 return 0;
jjako2c381332003-10-21 19:09:53 +00002358}
jjako08d331d2003-10-13 20:33:30 +00002359
jjako52c24142002-12-16 13:33:51 +00002360/* Send Delete PDP Context Response */
2361int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002362 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002363 void *pack, unsigned len,
2364 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002365 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002366{
Harald Weltebed35df2011-11-02 13:06:18 +01002367 union gtp_packet packet;
2368 struct pdp_t *secondary_pdp;
2369 unsigned int length =
2370 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2371 int n;
jjako52c24142002-12-16 13:33:51 +00002372
Harald Weltebed35df2011-11-02 13:06:18 +01002373 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002374
Harald Weltebed35df2011-11-02 13:06:18 +01002375 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2376 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002377
Harald Weltebed35df2011-11-02 13:06:18 +01002378 if (cause == GTPCAUSE_ACC_REQ) {
2379 if ((teardown) || (version == 0)) { /* Remove all contexts */
2380 for (n = 0; n < PDP_MAXNSAPI; n++) {
2381 if (linked_pdp->secondary_tei[n]) {
2382 if (pdp_getgtp1
2383 (&secondary_pdp,
2384 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002385 LOGP(DLGTP, LOGL_ERROR,
2386 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002387 return EOF;
2388 }
2389 if (linked_pdp != secondary_pdp) {
2390 if (gsn->cb_delete_context)
2391 gsn->cb_delete_context
2392 (secondary_pdp);
2393 pdp_freepdp(secondary_pdp);
2394 }
2395 }
2396 }
2397 if (gsn->cb_delete_context)
2398 gsn->cb_delete_context(linked_pdp);
2399 pdp_freepdp(linked_pdp);
2400 } else { /* Remove only current context */
2401 if (gsn->cb_delete_context)
2402 gsn->cb_delete_context(pdp);
2403 if (pdp == linked_pdp) {
2404 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2405 0;
2406 linked_pdp->nodata = 1;
2407 } else
2408 pdp_freepdp(pdp);
2409 }
jjako2c381332003-10-21 19:09:53 +00002410 }
Harald Weltebed35df2011-11-02 13:06:18 +01002411 /* if (cause == GTPCAUSE_ACC_REQ) */
2412 return 0;
jjako52c24142002-12-16 13:33:51 +00002413}
2414
2415/* Handle Delete PDP Context Request */
2416int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002417 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002418 void *pack, unsigned len)
2419{
2420 struct pdp_t *pdp = NULL;
2421 struct pdp_t *linked_pdp = NULL;
2422 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002423
Harald Weltebed35df2011-11-02 13:06:18 +01002424 uint16_t seq = get_seq(pack);
2425 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002426
Harald Weltebed35df2011-11-02 13:06:18 +01002427 uint8_t nsapi;
2428 uint8_t teardown = 0;
2429 int n;
2430 int count = 0;
jjako52c24142002-12-16 13:33:51 +00002431
Harald Weltebed35df2011-11-02 13:06:18 +01002432 /* Is this a dublicate ? */
2433 if (!gtp_dublicate(gsn, version, peer, seq)) {
2434 return 0; /* We allready send off response once */
2435 }
jjako2c381332003-10-21 19:09:53 +00002436
Harald Weltebed35df2011-11-02 13:06:18 +01002437 /* Find the linked context in question */
2438 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2439 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002440 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002441 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002442 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2443 NULL, NULL, GTPCAUSE_NON_EXIST,
2444 teardown);
2445 }
jjako2c381332003-10-21 19:09:53 +00002446
Harald Weltebed35df2011-11-02 13:06:18 +01002447 /* If version 0 this is also the secondary context */
2448 if (version == 0)
2449 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002450
Harald Weltebed35df2011-11-02 13:06:18 +01002451 /* Decode information elements */
2452 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2453 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002454 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2455 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002456 if (0 == version)
2457 return EOF;
2458 else
2459 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2460 len, NULL, NULL,
2461 GTPCAUSE_INVALID_MESSAGE,
2462 teardown);
2463 }
2464
2465 if (version == 1) {
2466 /* NSAPI (mandatory) */
2467 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2468 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002469 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2470 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002471 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2472 len, NULL, NULL,
2473 GTPCAUSE_MAN_IE_MISSING,
2474 teardown);
2475 }
2476
2477 /* Find the context in question */
2478 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2479 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002480 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2481 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002482 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2483 len, NULL, NULL,
2484 GTPCAUSE_NON_EXIST,
2485 teardown);
2486 }
2487
2488 /* Teardown (conditional) */
2489 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2490
2491 if (!teardown) {
2492 for (n = 0; n < PDP_MAXNSAPI; n++)
2493 if (linked_pdp->secondary_tei[n])
2494 count++;
2495 if (count <= 1) {
2496 return 0; /* 29.060 7.3.5 Ignore message */
2497 }
2498 }
2499 }
2500
2501 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2502 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002503}
2504
jjako52c24142002-12-16 13:33:51 +00002505/* Handle Delete PDP Context Response */
2506int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002507 struct sockaddr_in *peer, void *pack, unsigned len)
2508{
2509 union gtpie_member *ie[GTPIE_SIZE];
2510 uint8_t cause;
2511 void *cbp = NULL;
2512 uint8_t type = 0;
2513 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002514
Harald Weltebed35df2011-11-02 13:06:18 +01002515 /* Remove packet from queue */
2516 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2517 return EOF;
jjako52c24142002-12-16 13:33:51 +00002518
Harald Weltebed35df2011-11-02 13:06:18 +01002519 /* Decode information elements */
2520 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2521 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002522 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2523 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002524 if (gsn->cb_conf)
2525 gsn->cb_conf(type, EOF, NULL, cbp);
2526 return EOF;
2527 }
2528
2529 /* Extract cause value (mandatory) */
2530 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2531 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002532 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2533 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002534 if (gsn->cb_conf)
2535 gsn->cb_conf(type, EOF, NULL, cbp);
2536 return EOF;
2537 }
2538
2539 /* Check the cause value (again) */
2540 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2541 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002542 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2543 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002544 if (gsn->cb_conf)
2545 gsn->cb_conf(type, cause, NULL, cbp);
2546 return EOF;
2547 }
2548
2549 /* Callback function to notify application */
2550 if (gsn->cb_conf)
2551 gsn->cb_conf(type, cause, NULL, cbp);
2552
2553 return 0;
jjako52c24142002-12-16 13:33:51 +00002554}
2555
Harald Welte54d082e2017-08-12 22:43:21 +02002556/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
jjako52c24142002-12-16 13:33:51 +00002557int gtp_error_ind_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002558 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002559 void *pack, unsigned len)
2560{
Harald Weltebed35df2011-11-02 13:06:18 +01002561 union gtp_packet packet;
2562 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2563
Harald Welte54d082e2017-08-12 22:43:21 +02002564 if (version == 1) {
2565 /* Mandatory 7.7.13 TEI Data I */
2566 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2567 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2568
2569 /* Mandatory 7.7.32 GSN Address */
2570 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2571 sizeof(gsn->gsnu), &gsn->gsnu);
2572 }
2573
Harald Weltebed35df2011-11-02 13:06:18 +01002574 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2575 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002576}
2577
2578/* Handle Error Indication */
2579int gtp_error_ind_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002580 struct sockaddr_in *peer, void *pack, unsigned len)
2581{
Harald Welte37d5b152017-08-12 23:58:29 +02002582 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002583 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002584
Harald Weltebed35df2011-11-02 13:06:18 +01002585 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002586 if (version == 0) {
2587 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
2588 gsn->err_unknownpdp++;
2589 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2590 "Unknown PDP context\n");
2591 return EOF;
2592 }
2593 } else if (version == 1) {
2594 /* we have to look-up based on the *peer* TEID */
2595 int hlen = get_hlen(pack);
2596 uint32_t teid_gn;
2597
2598 /* Decode information elements */
2599 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2600 gsn->invalid++;
2601 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2602 "Invalid message format\n");
2603 return EOF;
2604 }
2605
2606 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2607 gsn->missing++;
2608 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2609 "Missing mandatory information field\n");
2610 return EOF;
2611 }
2612
2613 if (pdp_getgtp1_peer_d(&pdp, peer, teid_gn)) {
2614 gsn->err_unknownpdp++;
2615 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2616 return EOF;
2617 }
Harald Weltebed35df2011-11-02 13:06:18 +01002618 }
jjako52c24142002-12-16 13:33:51 +00002619
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002620 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2621 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002622
2623 if (gsn->cb_delete_context)
2624 gsn->cb_delete_context(pdp);
2625 pdp_freepdp(pdp);
2626 return 0;
jjako52c24142002-12-16 13:33:51 +00002627}
2628
2629int gtp_gpdu_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002630 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2631{
jjako08d331d2003-10-13 20:33:30 +00002632
Harald Weltebed35df2011-11-02 13:06:18 +01002633 int hlen = GTP1_HEADER_SIZE_SHORT;
jjako52c24142002-12-16 13:33:51 +00002634
Harald Weltebed35df2011-11-02 13:06:18 +01002635 /* Need to include code to verify packet src and dest addresses */
2636 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002637
Harald Weltebed35df2011-11-02 13:06:18 +01002638 if (version == 0) {
2639 if (pdp_getgtp0
2640 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2641 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002642 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002643 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002644 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2645 len);
2646 }
2647 hlen = GTP0_HEADER_SIZE;
2648 } else if (version == 1) {
2649 if (pdp_getgtp1
2650 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2651 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002652 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002653 len, "Unknown PDP context, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002654 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2655 len);
2656 }
jjako08d331d2003-10-13 20:33:30 +00002657
Harald Weltebed35df2011-11-02 13:06:18 +01002658 /* Is this a long or a short header ? */
2659 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2660 hlen = GTP1_HEADER_SIZE_LONG;
2661 else
2662 hlen = GTP1_HEADER_SIZE_SHORT;
2663 } else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002664 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002665 "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002666 }
jjako08d331d2003-10-13 20:33:30 +00002667
Harald Weltebed35df2011-11-02 13:06:18 +01002668 /* If the GPDU was not from the peer GSN tell him to delete context */
2669 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2670 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002671 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002672 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2673 }
jjako52c24142002-12-16 13:33:51 +00002674
Harald Weltebed35df2011-11-02 13:06:18 +01002675 /* Callback function */
2676 if (gsn->cb_data_ind != 0)
2677 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2678
2679 return 0;
jjako52c24142002-12-16 13:33:51 +00002680}
2681
jjako52c24142002-12-16 13:33:51 +00002682/* Receives GTP packet and sends off for further processing
2683 * Function will check the validity of the header. If the header
2684 * is not valid the packet is either dropped or a version not
2685 * supported is returned to the peer.
2686 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002687int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002688{
Harald Weltebed35df2011-11-02 13:06:18 +01002689 unsigned char buffer[PACKET_MAX];
2690 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002691 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002692 int status;
2693 struct gtp0_header *pheader;
2694 int version = 0; /* GTP version should be determined from header! */
2695 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002696
Harald Weltebed35df2011-11-02 13:06:18 +01002697 /* TODO: Need strategy of userspace buffering and blocking */
2698 /* Currently read is non-blocking and send is blocking. */
2699 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002700
Harald Weltebed35df2011-11-02 13:06:18 +01002701 while (1) { /* Loop until no more to read */
2702 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002703 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002704 return -1;
2705 }
2706 peerlen = sizeof(peer);
2707 if ((status =
2708 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2709 (struct sockaddr *)&peer, &peerlen)) < 0) {
2710 if (errno == EAGAIN)
2711 return 0;
2712 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002713 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002714 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002715 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2716 status, status ? strerror(errno) : "No error");
2717 return -1;
2718 }
jjako1db1c812003-07-06 20:53:57 +00002719
Harald Weltebed35df2011-11-02 13:06:18 +01002720 /* Need at least 1 byte in order to check version */
2721 if (status < (1)) {
2722 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002723 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2724 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002725 continue;
2726 }
jjako08d331d2003-10-13 20:33:30 +00002727
Harald Weltebed35df2011-11-02 13:06:18 +01002728 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002729
Harald Weltebed35df2011-11-02 13:06:18 +01002730 /* Version should be gtp0 (or earlier) */
2731 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2732 /* GTP 0 messages. If other version message is received we reply that we */
2733 /* only support version 0, implying that this is the only version */
2734 /* supported on this port */
2735 if (((pheader->flags & 0xe0) > 0x00)) {
2736 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002737 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2738 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002739 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2740 continue;
2741 }
2742
2743 /* Check length of gtp0 packet */
2744 if (status < GTP0_HEADER_SIZE) {
2745 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002746 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2747 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002748 continue; /* Silently discard 29.60: 11.1.2 */
2749 }
2750
2751 /* Check packet length field versus length of packet */
2752 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2753 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002754 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002755 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002756 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002757 continue; /* Silently discard */
2758 }
2759
2760 if ((gsn->mode == GTP_MODE_GGSN) &&
2761 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2762 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2763 (pheader->type == GTP_DELETE_PDP_RSP))) {
2764 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002765 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002766 status,
Max28318872017-05-16 17:03:02 +02002767 "Unexpected GTPv0 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002768 continue; /* Silently discard 29.60: 11.1.4 */
2769 }
2770
2771 if ((gsn->mode == GTP_MODE_SGSN) &&
2772 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2773 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2774 (pheader->type == GTP_DELETE_PDP_REQ))) {
2775 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002776 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002777 status,
Max28318872017-05-16 17:03:02 +02002778 "Unexpected GTPv0 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002779 continue; /* Silently discard 29.60: 11.1.4 */
2780 }
2781
2782 switch (pheader->type) {
2783 case GTP_ECHO_REQ:
2784 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2785 break;
2786 case GTP_ECHO_RSP:
2787 gtp_echo_conf(gsn, version, &peer, buffer, status);
2788 break;
2789 case GTP_NOT_SUPPORTED:
2790 gtp_unsup_ind(gsn, &peer, buffer, status);
2791 break;
2792 case GTP_CREATE_PDP_REQ:
2793 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2794 status);
2795 break;
2796 case GTP_CREATE_PDP_RSP:
2797 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2798 status);
2799 break;
2800 case GTP_UPDATE_PDP_REQ:
2801 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2802 status);
2803 break;
2804 case GTP_UPDATE_PDP_RSP:
2805 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2806 status);
2807 break;
2808 case GTP_DELETE_PDP_REQ:
2809 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2810 status);
2811 break;
2812 case GTP_DELETE_PDP_RSP:
2813 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2814 status);
2815 break;
2816 case GTP_ERROR:
2817 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2818 break;
2819 case GTP_GPDU:
2820 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2821 break;
2822 default:
2823 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002824 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2825 "Unknown GTP message type received: %d\n",
2826 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002827 break;
2828 }
2829 }
jjako08d331d2003-10-13 20:33:30 +00002830}
2831
jjako08d331d2003-10-13 20:33:30 +00002832int gtp_decaps1c(struct gsn_t *gsn)
2833{
Harald Weltebed35df2011-11-02 13:06:18 +01002834 unsigned char buffer[PACKET_MAX];
2835 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002836 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002837 int status;
2838 struct gtp1_header_short *pheader;
2839 int version = 1; /* TODO GTP version should be determined from header! */
2840 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002841
Harald Weltebed35df2011-11-02 13:06:18 +01002842 /* TODO: Need strategy of userspace buffering and blocking */
2843 /* Currently read is non-blocking and send is blocking. */
2844 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002845
Harald Weltebed35df2011-11-02 13:06:18 +01002846 while (1) { /* Loop until no more to read */
2847 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002848 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002849 return -1;
2850 }
2851 peerlen = sizeof(peer);
2852 if ((status =
2853 recvfrom(fd, buffer, sizeof(buffer), 0,
2854 (struct sockaddr *)&peer, &peerlen)) < 0) {
2855 if (errno == EAGAIN)
2856 return 0;
2857 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002858 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002859 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002860 fd, (unsigned long)buffer, sizeof(buffer),
2861 status, status ? strerror(errno) : "No error");
2862 return -1;
2863 }
jjako08d331d2003-10-13 20:33:30 +00002864
Harald Weltebed35df2011-11-02 13:06:18 +01002865 /* Need at least 1 byte in order to check version */
2866 if (status < (1)) {
2867 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002868 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2869 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002870 continue;
2871 }
jjako08d331d2003-10-13 20:33:30 +00002872
Harald Weltebed35df2011-11-02 13:06:18 +01002873 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002874
Harald Weltebed35df2011-11-02 13:06:18 +01002875 /* Version must be no larger than GTP 1 */
2876 if (((pheader->flags & 0xe0) > 0x20)) {
2877 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002878 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2879 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002880 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2881 /*29.60: 11.1.1 */
2882 continue;
2883 }
jjako08d331d2003-10-13 20:33:30 +00002884
Harald Weltebed35df2011-11-02 13:06:18 +01002885 /* Version must be at least GTP 1 */
2886 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2887 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2888 /* the message */
2889 if (((pheader->flags & 0xe0) < 0x20)) {
2890 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002891 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2892 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002893 continue;
2894 }
jjako08d331d2003-10-13 20:33:30 +00002895
Harald Weltebed35df2011-11-02 13:06:18 +01002896 /* Check packet flag field */
2897 if (((pheader->flags & 0xf7) != 0x32)) {
2898 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002899 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01002900 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01002901 continue;
2902 }
jjako2c381332003-10-21 19:09:53 +00002903
Harald Weltebed35df2011-11-02 13:06:18 +01002904 /* Check length of packet */
2905 if (status < GTP1_HEADER_SIZE_LONG) {
2906 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002907 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2908 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002909 continue; /* Silently discard 29.60: 11.1.2 */
2910 }
jjako2c381332003-10-21 19:09:53 +00002911
Harald Weltebed35df2011-11-02 13:06:18 +01002912 /* Check packet length field versus length of packet */
2913 if (status !=
2914 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2915 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002916 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002917 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002918 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002919 continue; /* Silently discard */
2920 }
jjako1db1c812003-07-06 20:53:57 +00002921
Harald Weltebed35df2011-11-02 13:06:18 +01002922 /* Check for extension headers */
2923 /* TODO: We really should cycle through the headers and determine */
2924 /* if any have the comprehension required flag set */
2925 if (((pheader->flags & 0x04) != 0x00)) {
2926 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002927 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2928 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002929 gtp_extheader_req(gsn, version, &peer, fd, buffer,
2930 status);
jjako1db1c812003-07-06 20:53:57 +00002931
Harald Weltebed35df2011-11-02 13:06:18 +01002932 continue;
2933 }
2934
2935 if ((gsn->mode == GTP_MODE_GGSN) &&
2936 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2937 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2938 (pheader->type == GTP_DELETE_PDP_RSP))) {
2939 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002940 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002941 status,
Max28318872017-05-16 17:03:02 +02002942 "Unexpected GTPv1 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002943 continue; /* Silently discard 29.60: 11.1.4 */
2944 }
2945
2946 if ((gsn->mode == GTP_MODE_SGSN) &&
2947 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2948 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2949 (pheader->type == GTP_DELETE_PDP_REQ))) {
2950 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002951 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002952 status,
Max28318872017-05-16 17:03:02 +02002953 "Unexpected GTPv1 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002954 continue; /* Silently discard 29.60: 11.1.4 */
2955 }
2956
2957 switch (pheader->type) {
2958 case GTP_ECHO_REQ:
2959 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2960 break;
2961 case GTP_ECHO_RSP:
2962 gtp_echo_conf(gsn, version, &peer, buffer, status);
2963 break;
2964 case GTP_NOT_SUPPORTED:
2965 gtp_unsup_ind(gsn, &peer, buffer, status);
2966 break;
2967 case GTP_SUPP_EXT_HEADER:
2968 gtp_extheader_ind(gsn, &peer, buffer, status);
2969 break;
2970 case GTP_CREATE_PDP_REQ:
2971 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2972 status);
2973 break;
2974 case GTP_CREATE_PDP_RSP:
2975 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2976 status);
2977 break;
2978 case GTP_UPDATE_PDP_REQ:
2979 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2980 status);
2981 break;
2982 case GTP_UPDATE_PDP_RSP:
2983 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2984 status);
2985 break;
2986 case GTP_DELETE_PDP_REQ:
2987 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2988 status);
2989 break;
2990 case GTP_DELETE_PDP_RSP:
2991 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2992 status);
2993 break;
2994 case GTP_ERROR:
2995 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2996 break;
2997 default:
2998 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002999 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3000 "Unknown GTP message type received: %u\n",
3001 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003002 break;
3003 }
3004 }
jjako52c24142002-12-16 13:33:51 +00003005}
3006
jjako08d331d2003-10-13 20:33:30 +00003007int gtp_decaps1u(struct gsn_t *gsn)
3008{
Harald Weltebed35df2011-11-02 13:06:18 +01003009 unsigned char buffer[PACKET_MAX];
3010 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003011 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003012 int status;
3013 struct gtp1_header_short *pheader;
3014 int version = 1; /* GTP version should be determined from header! */
3015 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003016
Harald Weltebed35df2011-11-02 13:06:18 +01003017 /* TODO: Need strategy of userspace buffering and blocking */
3018 /* Currently read is non-blocking and send is blocking. */
3019 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003020
Harald Weltebed35df2011-11-02 13:06:18 +01003021 while (1) { /* Loop until no more to read */
3022 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003023 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003024 return -1;
3025 }
3026 peerlen = sizeof(peer);
3027 if ((status =
3028 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3029 (struct sockaddr *)&peer, &peerlen)) < 0) {
3030 if (errno == EAGAIN)
3031 return 0;
3032 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003033 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003034 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003035 gsn->fd1u, (unsigned long)buffer,
3036 sizeof(buffer), status,
3037 status ? strerror(errno) : "No error");
3038 return -1;
3039 }
jjako08d331d2003-10-13 20:33:30 +00003040
Harald Weltebed35df2011-11-02 13:06:18 +01003041 /* Need at least 1 byte in order to check version */
3042 if (status < (1)) {
3043 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003044 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3045 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003046 continue;
3047 }
jjako08d331d2003-10-13 20:33:30 +00003048
Harald Weltebed35df2011-11-02 13:06:18 +01003049 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003050
Harald Weltebed35df2011-11-02 13:06:18 +01003051 /* Version must be no larger than GTP 1 */
3052 if (((pheader->flags & 0xe0) > 0x20)) {
3053 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003054 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3055 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003056 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3057 continue;
3058 }
jjako08d331d2003-10-13 20:33:30 +00003059
Harald Weltebed35df2011-11-02 13:06:18 +01003060 /* Version must be at least GTP 1 */
3061 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3062 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3063 /* the message */
3064 if (((pheader->flags & 0xe0) < 0x20)) {
3065 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003066 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3067 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003068 continue;
3069 }
jjako2c381332003-10-21 19:09:53 +00003070
Harald Weltebed35df2011-11-02 13:06:18 +01003071 /* Check packet flag field (allow both with and without sequence number) */
3072 if (((pheader->flags & 0xf5) != 0x30)) {
3073 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003074 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003075 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
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 length of packet */
3080 if (status < GTP1_HEADER_SIZE_SHORT) {
3081 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003082 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3083 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003084 continue; /* Silently discard 29.60: 11.1.2 */
3085 }
3086
3087 /* Check packet length field versus length of packet */
3088 if (status !=
3089 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3090 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003091 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003092 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003093 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003094 continue; /* Silently discard */
3095 }
3096
3097 /* Check for extension headers */
3098 /* TODO: We really should cycle through the headers and determine */
3099 /* if any have the comprehension required flag set */
3100 if (((pheader->flags & 0x04) != 0x00)) {
3101 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003102 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3103 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003104 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3105 status);
3106
3107 continue;
3108 }
3109
3110 switch (pheader->type) {
3111 case GTP_ECHO_REQ:
3112 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3113 break;
3114 case GTP_ECHO_RSP:
3115 gtp_echo_conf(gsn, version, &peer, buffer, status);
3116 break;
3117 case GTP_SUPP_EXT_HEADER:
3118 gtp_extheader_ind(gsn, &peer, buffer, status);
3119 break;
3120 case GTP_ERROR:
3121 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3122 break;
3123 /* Supported header extensions */
3124 case GTP_GPDU:
3125 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3126 break;
3127 default:
3128 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003129 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3130 "Unknown GTP message type received: %u\n",
3131 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003132 break;
3133 }
3134 }
jjako08d331d2003-10-13 20:33:30 +00003135}
3136
Harald Weltebed35df2011-11-02 13:06:18 +01003137int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003138{
Harald Weltebed35df2011-11-02 13:06:18 +01003139 union gtp_packet packet;
3140 struct sockaddr_in addr;
3141 int fd;
3142 int length;
jjako52c24142002-12-16 13:33:51 +00003143
Harald Weltebed35df2011-11-02 13:06:18 +01003144 memset(&addr, 0, sizeof(addr));
3145 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003146#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003147 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003148#endif
3149
Harald Weltebed35df2011-11-02 13:06:18 +01003150 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003151
Harald Weltebed35df2011-11-02 13:06:18 +01003152 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003153
Harald Weltebed35df2011-11-02 13:06:18 +01003154 length = GTP0_HEADER_SIZE + len;
3155 addr.sin_port = htons(GTP0_PORT);
3156 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003157
Harald Weltebed35df2011-11-02 13:06:18 +01003158 get_default_gtp(0, GTP_GPDU, &packet);
3159 packet.gtp0.h.length = hton16(len);
3160 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3161 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003162 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
jjako08d331d2003-10-13 20:33:30 +00003163
Harald Weltebed35df2011-11-02 13:06:18 +01003164 if (len > sizeof(union gtp_packet) - sizeof(struct gtp0_header)) {
3165 gsn->err_memcpy++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003166 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003167 "Memcpy failed: %u > %zu\n", len,
Harald Weltebed35df2011-11-02 13:06:18 +01003168 sizeof(union gtp_packet) -
3169 sizeof(struct gtp0_header));
3170 return EOF;
3171 }
3172 memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
3173 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003174
Harald Weltebed35df2011-11-02 13:06:18 +01003175 length = GTP1_HEADER_SIZE_LONG + len;
3176 addr.sin_port = htons(GTP1U_PORT);
3177 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003178
Harald Weltebed35df2011-11-02 13:06:18 +01003179 get_default_gtp(1, GTP_GPDU, &packet);
3180 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3181 GTP1_HEADER_SIZE_LONG);
3182 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3183 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3184
3185 if (len >
3186 sizeof(union gtp_packet) -
3187 sizeof(struct gtp1_header_long)) {
3188 gsn->err_memcpy++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003189 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003190 "Memcpy failed: %u > %zu\n", len,
Harald Weltebed35df2011-11-02 13:06:18 +01003191 sizeof(union gtp_packet) -
3192 sizeof(struct gtp0_header));
3193 return EOF;
3194 }
3195 memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
3196 } 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
3206 if (sendto(fd, &packet, length, 0,
3207 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
3208 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003209 LOGP(DLGTP, LOGL_ERROR,
3210 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003211 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3212 strerror(errno));
3213 return EOF;
3214 }
3215 return 0;
jjako52c24142002-12-16 13:33:51 +00003216}
3217
jjako52c24142002-12-16 13:33:51 +00003218/* ***********************************************************
3219 * Conversion functions
3220 *************************************************************/
3221
Harald Weltebed35df2011-11-02 13:06:18 +01003222int char2ul_t(char *src, struct ul_t dst)
3223{
3224 dst.l = strlen(src) + 1;
3225 dst.v = malloc(dst.l);
3226 dst.v[0] = dst.l - 1;
3227 memcpy(&dst.v[1], src, dst.v[0]);
3228 return 0;
jjako52c24142002-12-16 13:33:51 +00003229}
3230
3231/* ***********************************************************
3232 * IP address conversion functions
3233 * There exist several types of address representations:
3234 * - eua: End User Address. (29.060, 7.7.27, message type 128)
3235 * Used for signalling address to mobile station. Supports IPv4
3236 * IPv6 x.25 etc. etc.
3237 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3238 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3239 * - in_addr: IPv4 address struct.
3240 * - sockaddr_in: Socket API representation of IP address and
3241 * port number.
3242 *************************************************************/
3243
Harald Weltebed35df2011-11-02 13:06:18 +01003244int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3245{
3246 eua->v[0] = 0xf1; /* IETF */
3247 eua->v[1] = 0x21; /* IPv4 */
3248 if (src) {
3249 eua->l = 6;
3250 memcpy(&eua->v[2], src, 4);
3251 } else {
3252 eua->l = 2;
3253 }
3254 return 0;
jjako52c24142002-12-16 13:33:51 +00003255}
3256
Harald Weltebed35df2011-11-02 13:06:18 +01003257int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3258{
3259 if ((eua->l != 6) || (eua->v[0] != 0xf1) || (eua->v[1] = 0x21))
3260 return -1; /* Not IPv4 address */
3261 memcpy(dst, &eua->v[2], 4);
3262 return 0;
jjako52c24142002-12-16 13:33:51 +00003263}
3264
Harald Weltebed35df2011-11-02 13:06:18 +01003265int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3266{
3267 memset(dst, 0, sizeof(struct in_addr));
3268 if (gsna->l != 4)
3269 return EOF; /* Return if not IPv4 */
3270 memcpy(dst, gsna->v, gsna->l);
3271 return 0;
jjako52c24142002-12-16 13:33:51 +00003272}
3273
Harald Weltebed35df2011-11-02 13:06:18 +01003274int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3275{
3276 memset(gsna, 0, sizeof(struct ul16_t));
3277 gsna->l = 4;
3278 memcpy(gsna->v, src, gsna->l);
3279 return 0;
jjako52c24142002-12-16 13:33:51 +00003280}
Harald Welteb10ee082017-08-12 19:29:16 +02003281
3282/* TS 29.060 has yet again a different encoding for IMSIs than
3283 * what we have in other places, so we cannot use the gsm48
3284 * decoding functions. Also, libgtp uses an uint64_t in
3285 * _network byte order_ to contain BCD digits ?!? */
3286const char *imsi_gtp2str(const uint64_t *imsi)
3287{
3288 static char buf[sizeof(*imsi)+1];
3289 const uint8_t *imsi8 = (const uint8_t *) imsi;
3290 unsigned int i, j = 0;
3291
3292 for (i = 0; i < sizeof(*imsi); i++) {
3293 uint8_t nibble;
3294
3295 nibble = imsi8[i] & 0xf;
3296 if (nibble == 0xf)
3297 break;
3298 buf[j++] = osmo_bcd2char(nibble);
3299
3300 nibble = imsi8[i] >> 4;
3301 if (nibble == 0xf)
3302 break;
3303 buf[j++] = osmo_bcd2char(nibble);
3304 }
3305
3306 buf[j++] = '\0';
3307 return buf;
3308}