blob: a4e8e2b073e0c19d0563a00ca1deb5c87f21f696 [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++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100397 LOGP(DLGTP, LOGL_ERROR,
398 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100399 (unsigned long)&packet, len, strerror(errno));
400 return -1;
401 }
402
403 /* Use new queue structure */
404 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
405 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100406 LOGP(DLGTP, LOGL_ERROR,
407 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100408 } else {
409 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
410 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100411 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100412 qmsg->retrans = 0; /* No retransmissions so far */
413 qmsg->cbp = cbp;
414 qmsg->type = ntoh8(packet->gtp0.h.type);
415 qmsg->fd = fd;
416 }
417 gsn->seq_next++; /* Count up this time */
418 return 0;
jjako52c24142002-12-16 13:33:51 +0000419}
420
421/* gtp_conf
422 * Remove signalling packet from retransmission queue.
423 * return 0 on success, EOF if packet was not found */
424
425int gtp_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100426 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
427{
jjako52c24142002-12-16 13:33:51 +0000428
Harald Weltebed35df2011-11-02 13:06:18 +0100429 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000430
Harald Weltebed35df2011-11-02 13:06:18 +0100431 if ((packet->gtp0.h.flags & 0xe0) == 0x00)
432 seq = ntoh16(packet->gtp0.h.seq);
433 else if ((packet->gtp1l.h.flags & 0xe2) == 0x22)
434 seq = ntoh16(packet->gtp1l.h.seq);
435 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100436 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
437 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100438 return EOF;
439 }
jjako08d331d2003-10-13 20:33:30 +0000440
Harald Weltebed35df2011-11-02 13:06:18 +0100441 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
442 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100443 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
444 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100445 return EOF;
446 }
jjako52c24142002-12-16 13:33:51 +0000447
Harald Weltebed35df2011-11-02 13:06:18 +0100448 return 0;
jjako52c24142002-12-16 13:33:51 +0000449}
450
Harald Weltebed35df2011-11-02 13:06:18 +0100451int gtp_retrans(struct gsn_t *gsn)
452{
453 /* Retransmit any outstanding packets */
454 /* Remove from queue if maxretrans exceeded */
455 time_t now;
456 struct qmsg_t *qmsg;
457 now = time(NULL);
458 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000459
Harald Welte95848ba2011-11-02 18:17:50 +0100460 /* get first element in queue, as long as the timeout of that
461 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100462 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
463 (qmsg->timeout <= now)) {
464 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100465 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100466 if (gsn->cb_conf)
467 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
468 queue_freemsg(gsn->queue_req, qmsg);
469 } else {
470 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
471 (struct sockaddr *)&qmsg->peer,
472 sizeof(struct sockaddr_in)) < 0) {
473 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100474 LOGP(DLGTP, LOGL_ERROR,
475 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100476 gsn->fd0, (unsigned long)&qmsg->p,
477 qmsg->l, strerror(errno));
478 }
479 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100480 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100481 qmsg->retrans++;
482 }
483 }
jjako52c24142002-12-16 13:33:51 +0000484
Harald Weltebed35df2011-11-02 13:06:18 +0100485 /* Also clean up reply timeouts */
486 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
487 (qmsg->timeout < now)) {
488 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
489 queue_freemsg(gsn->queue_resp, qmsg);
490 }
jjako52c24142002-12-16 13:33:51 +0000491
Harald Weltebed35df2011-11-02 13:06:18 +0100492 return 0;
jjako52c24142002-12-16 13:33:51 +0000493}
494
Harald Weltebed35df2011-11-02 13:06:18 +0100495int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
496{
497 time_t now, later;
498 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000499
Harald Weltebed35df2011-11-02 13:06:18 +0100500 if (queue_getfirst(gsn->queue_req, &qmsg)) {
501 timeout->tv_sec = 10;
502 timeout->tv_usec = 0;
503 } else {
504 now = time(NULL);
505 later = qmsg->timeout;
506 timeout->tv_sec = later - now;
507 timeout->tv_usec = 0;
508 if (timeout->tv_sec < 0)
509 timeout->tv_sec = 0; /* No negative allowed */
510 if (timeout->tv_sec > 10)
511 timeout->tv_sec = 10; /* Max sleep for 10 sec */
512 }
513 return 0;
jjako52c24142002-12-16 13:33:51 +0000514}
515
Harald Weltebed35df2011-11-02 13:06:18 +0100516int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000517 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100518 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
519{
520 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000521
Harald Weltebed35df2011-11-02 13:06:18 +0100522 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
523 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
524 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100525 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100526 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
527 (packet->gtp0.h.type == GTP_ERROR)))
528 packet->gtp0.h.flow = hton16(pdp->flru);
529 else if (pdp)
530 packet->gtp0.h.flow = hton16(pdp->flrc);
531 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
532 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
533 packet->gtp1l.h.seq = hton16(seq);
534 if (pdp && (fd == gsn->fd1u))
535 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
536 else if (pdp)
537 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
538 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100539 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100540 return -1;
541 }
jjako08d331d2003-10-13 20:33:30 +0000542
Harald Weltebed35df2011-11-02 13:06:18 +0100543 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100544 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100545 return -1;
546 }
jjako52c24142002-12-16 13:33:51 +0000547
Harald Weltebed35df2011-11-02 13:06:18 +0100548 if (sendto(fd, packet, len, 0,
549 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
550 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100551 LOGP(DLGTP, LOGL_ERROR,
552 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100553 (unsigned long)&packet, len, strerror(errno));
554 return -1;
555 }
556
557 /* Use new queue structure */
558 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
559 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100560 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100561 } else {
562 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
563 qmsg->l = len;
564 qmsg->timeout = time(NULL) + 60; /* When to timeout */
565 qmsg->retrans = 0; /* No retransmissions so far */
566 qmsg->cbp = NULL;
567 qmsg->type = 0;
568 qmsg->fd = fd;
569 }
570 return 0;
jjako52c24142002-12-16 13:33:51 +0000571}
572
jjako2c381332003-10-21 19:09:53 +0000573int gtp_notification(struct gsn_t *gsn, int version,
574 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100575 struct sockaddr_in *peer, int fd, uint16_t seq)
576{
jjako2c381332003-10-21 19:09:53 +0000577
Harald Weltebed35df2011-11-02 13:06:18 +0100578 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000579
Harald Weltebed35df2011-11-02 13:06:18 +0100580 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000581
Harald Weltebed35df2011-11-02 13:06:18 +0100582 /* In GTP0 notifications are treated as replies. In GTP1 they
583 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000584
Harald Weltebed35df2011-11-02 13:06:18 +0100585 if (fd == gsn->fd1c)
586 addr.sin_port = htons(GTP1C_PORT);
587 else if (fd == gsn->fd1u)
588 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000589
Harald Weltebed35df2011-11-02 13:06:18 +0100590 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
591 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
592 packet->gtp0.h.seq = hton16(seq);
593 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
594 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
595 packet->gtp1l.h.seq = hton16(seq);
596 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100597 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100598 return -1;
599 }
600
601 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100602 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100603 return -1;
604 }
605
606 if (sendto(fd, packet, len, 0,
607 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
608 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100609 LOGP(DLGTP, LOGL_ERROR,
610 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100611 (unsigned long)&packet, len, strerror(errno));
612 return -1;
613 }
614 return 0;
jjako2c381332003-10-21 19:09:53 +0000615}
616
Harald Weltebed35df2011-11-02 13:06:18 +0100617int gtp_dublicate(struct gsn_t *gsn, int version,
618 struct sockaddr_in *peer, uint16_t seq)
619{
620 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000621
Harald Weltebed35df2011-11-02 13:06:18 +0100622 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
623 return EOF; /* Notfound */
624 }
jjakoa7cd2492003-04-11 09:40:12 +0000625
Harald Weltebed35df2011-11-02 13:06:18 +0100626 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100627 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100628 return -1;
629 }
630
631 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
632 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
633 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100634 LOGP(DLGTP, LOGL_ERROR,
635 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100636 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
637 strerror(errno));
638 }
639 return 0;
jjako52c24142002-12-16 13:33:51 +0000640}
641
jjako52c24142002-12-16 13:33:51 +0000642/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100643static void log_restart(struct gsn_t *gsn)
644{
jjako52c24142002-12-16 13:33:51 +0000645 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200646 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000647 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200648 char *filename;
jjako52c24142002-12-16 13:33:51 +0000649
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200650 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
651 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000652
653 /* We try to open file. On failure we will later try to create file */
654 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100655 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100656 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100657 filename);
658 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100659 rc = fscanf(f, "%d", &counter);
660 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100661 LOGP(DLGTP, LOGL_ERROR,
662 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100663 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100664 }
665 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100666 LOGP(DLGTP, LOGL_ERROR,
667 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100668 }
jjako52c24142002-12-16 13:33:51 +0000669 }
Harald Weltebed35df2011-11-02 13:06:18 +0100670
671 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000672 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100673
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200674 /* Keep the umask closely wrapped around our fopen() call in case the
675 * log outputs cause file creation. */
676 i = umask(022);
677 f = fopen(filename, "w");
678 umask(i);
679 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100680 LOGP(DLGTP, LOGL_ERROR,
681 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100682 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200683 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000684 }
685
jjako52c24142002-12-16 13:33:51 +0000686 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100687close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200688 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100689 LOGP(DLGTP, LOGL_ERROR,
690 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200691free_filename:
692 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000693}
694
jjako1db1c812003-07-06 20:53:57 +0000695int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100696 int mode)
jjako52c24142002-12-16 13:33:51 +0000697{
Harald Weltebed35df2011-11-02 13:06:18 +0100698 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000699
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100700 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started\n");
jjako52c24142002-12-16 13:33:51 +0000701
Harald Weltebed35df2011-11-02 13:06:18 +0100702 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000703
Harald Weltebed35df2011-11-02 13:06:18 +0100704 (*gsn)->statedir = statedir;
705 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000706
Harald Weltebed35df2011-11-02 13:06:18 +0100707 /* Initialise sequence number */
708 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000709
Harald Weltebed35df2011-11-02 13:06:18 +0100710 /* Initialise request retransmit queue */
711 queue_new(&(*gsn)->queue_req);
712 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000713
Harald Weltebed35df2011-11-02 13:06:18 +0100714 /* Initialise pdp table */
715 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000716
Harald Weltebed35df2011-11-02 13:06:18 +0100717 /* Initialise call back functions */
718 (*gsn)->cb_create_context_ind = 0;
719 (*gsn)->cb_delete_context = 0;
720 (*gsn)->cb_unsup_ind = 0;
721 (*gsn)->cb_conf = 0;
722 (*gsn)->cb_data_ind = 0;
723
724 /* Store function parameters */
725 (*gsn)->gsnc = *listen;
726 (*gsn)->gsnu = *listen;
727 (*gsn)->mode = mode;
728
729 /* Create GTP version 0 socket */
730 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
731 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100732 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200733 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100734 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200735 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100736 }
737
738 memset(&addr, 0, sizeof(addr));
739 addr.sin_family = AF_INET;
740 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
741 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000742#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100743 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000744#endif
jjako08d331d2003-10-13 20:33:30 +0000745
Harald Weltebed35df2011-11-02 13:06:18 +0100746 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
747 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200748 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
749 "bind(fd0=%d) failed: Error = %s\n",
750 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200751 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100752 }
jjako08d331d2003-10-13 20:33:30 +0000753
Harald Weltebed35df2011-11-02 13:06:18 +0100754 /* Create GTP version 1 control plane socket */
755 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
756 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100757 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200758 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100759 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200760 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100761 }
762
763 memset(&addr, 0, sizeof(addr));
764 addr.sin_family = AF_INET;
765 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
766 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000767#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100768 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000769#endif
jjako08d331d2003-10-13 20:33:30 +0000770
Harald Weltebed35df2011-11-02 13:06:18 +0100771 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
772 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200773 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
774 "bind(fd1c=%d) failed: Error = %s\n",
775 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200776 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100777 }
jjako08d331d2003-10-13 20:33:30 +0000778
Harald Weltebed35df2011-11-02 13:06:18 +0100779 /* Create GTP version 1 user plane socket */
780 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
781 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100782 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200783 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100784 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200785 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100786 }
787
788 memset(&addr, 0, sizeof(addr));
789 addr.sin_family = AF_INET;
790 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
791 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000792#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100793 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000794#endif
jjako52c24142002-12-16 13:33:51 +0000795
Harald Weltebed35df2011-11-02 13:06:18 +0100796 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
797 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200798 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +0200799 "bind(fd1u=%d) failed: Error = %s\n",
800 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +0200801 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100802 }
803
804 return 0;
jjako52c24142002-12-16 13:33:51 +0000805}
806
Harald Weltebed35df2011-11-02 13:06:18 +0100807int gtp_free(struct gsn_t *gsn)
808{
jjako52c24142002-12-16 13:33:51 +0000809
Harald Weltebed35df2011-11-02 13:06:18 +0100810 /* Clean up retransmit queues */
811 queue_free(gsn->queue_req);
812 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000813
Harald Weltebed35df2011-11-02 13:06:18 +0100814 close(gsn->fd0);
815 close(gsn->fd1c);
816 close(gsn->fd1u);
817
818 free(gsn);
819 return 0;
jjako52c24142002-12-16 13:33:51 +0000820}
821
822/* ***********************************************************
823 * Path management messages
824 * Messages: echo and version not supported.
825 * A path is connection between two UDP/IP endpoints
826 *
827 * A path is either using GTP0 or GTP1. A path can be
828 * established by any kind of GTP message??
829
830 * Which source port to use?
831 * GTP-C request destination port is 2123/3386
832 * GTP-U request destination port is 2152/3386
833 * T-PDU destination port is 2152/3386.
834 * For the above messages the source port is locally allocated.
835 * For response messages src=rx-dst and dst=rx-src.
836 * For simplicity we should probably use 2123+2152/3386 as
837 * src port even for the cases where src can be locally
838 * allocated. This also means that we have to listen only to
839 * the same ports.
840 * For response messages we need to be able to respond to
841 * the relevant src port even if it is locally allocated by
842 * the peer.
843 *
844 * The need for path management!
845 * We might need to keep a list of active paths. This might
846 * be in the form of remote IP address + UDP port numbers.
847 * (We will consider a path astablished if we have a context
848 * with the node in question)
849 *************************************************************/
850
851/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000852int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
853 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000854{
Harald Weltebed35df2011-11-02 13:06:18 +0100855 union gtp_packet packet;
856 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
857 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000858}
859
jjako08d331d2003-10-13 20:33:30 +0000860/* Send off an echo reply */
861int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100862 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000863{
Harald Weltebed35df2011-11-02 13:06:18 +0100864 union gtp_packet packet;
865 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
866 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
867 gsn->restart_counter);
868 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
869 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000870}
871
jjako52c24142002-12-16 13:33:51 +0000872/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +0100873int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
874 int fd, void *pack, unsigned len)
875{
jjako52c24142002-12-16 13:33:51 +0000876
Harald Weltebed35df2011-11-02 13:06:18 +0100877 /* Check if it was a dublicate request */
878 if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
879 return 0;
jjako52c24142002-12-16 13:33:51 +0000880
Harald Weltebed35df2011-11-02 13:06:18 +0100881 /* Send off reply to request */
882 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000883}
884
885/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000886int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100887 void *pack, unsigned len)
888{
889 union gtpie_member *ie[GTPIE_SIZE];
890 unsigned char recovery;
891 void *cbp = NULL;
892 uint8_t type = 0;
893 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000894
Harald Weltebed35df2011-11-02 13:06:18 +0100895 /* Remove packet from queue */
896 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
897 return EOF;
jjako52c24142002-12-16 13:33:51 +0000898
Harald Weltebed35df2011-11-02 13:06:18 +0100899 /* Extract information elements into a pointer array */
900 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
901 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100902 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
903 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100904 if (gsn->cb_conf)
905 gsn->cb_conf(type, EOF, NULL, cbp);
906 return EOF;
907 }
jjako52c24142002-12-16 13:33:51 +0000908
Harald Weltebed35df2011-11-02 13:06:18 +0100909 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
910 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100911 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
912 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100913 if (gsn->cb_conf)
914 gsn->cb_conf(type, EOF, NULL, cbp);
915 return EOF;
916 }
jjako52c24142002-12-16 13:33:51 +0000917
Harald Weltebed35df2011-11-02 13:06:18 +0100918 /* Echo reply packages does not have a cause information element */
919 /* Instead we return the recovery number in the callback function */
920 if (gsn->cb_conf)
921 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +0100922
Harald Weltebed35df2011-11-02 13:06:18 +0100923 if (gsn->cb_recovery)
924 gsn->cb_recovery(peer, recovery);
925
926 return 0;
jjako52c24142002-12-16 13:33:51 +0000927}
928
929/* Send off a Version Not Supported message */
930/* This message is somewhat special in that it actually is a
931 * response to some other message with unsupported GTP version
932 * For this reason it has parameters like a response, and does
933 * its own message transmission. No signalling queue is used
934 * The reply is sent to the peer IP and peer UDP. This means that
935 * the peer will be receiving a GTP0 message on a GTP1 port!
936 * In practice however this will never happen as a GTP0 GSN will
937 * only listen to the GTP0 port, and therefore will never receive
938 * anything else than GTP0 */
939
jjako08d331d2003-10-13 20:33:30 +0000940int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
941 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000942{
Harald Weltebed35df2011-11-02 13:06:18 +0100943 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +0000944
Harald Weltebed35df2011-11-02 13:06:18 +0100945 /* GTP 1 is the highest supported protocol */
946 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
947 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +0000948}
949
950/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +0100951int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
952 void *pack, unsigned len)
953{
jjako52c24142002-12-16 13:33:51 +0000954
Harald Weltebed35df2011-11-02 13:06:18 +0100955 if (gsn->cb_unsup_ind)
956 gsn->cb_unsup_ind(peer);
957
958 return 0;
jjako52c24142002-12-16 13:33:51 +0000959}
960
jjako2c381332003-10-21 19:09:53 +0000961/* Send off an Supported Extension Headers Notification */
962int gtp_extheader_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
963 int fd, void *pack, unsigned len)
964{
Harald Weltebed35df2011-11-02 13:06:18 +0100965 union gtp_packet packet;
966 unsigned int length =
967 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +0000968
Harald Weltebed35df2011-11-02 13:06:18 +0100969 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +0000970
Harald Weltebed35df2011-11-02 13:06:18 +0100971 if (version < 1)
972 return 0;
jjako2c381332003-10-21 19:09:53 +0000973
Harald Weltebed35df2011-11-02 13:06:18 +0100974 /* We report back that we support only PDCP PDU headers */
975 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
976 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +0000977
Harald Weltebed35df2011-11-02 13:06:18 +0100978 return gtp_notification(gsn, version, &packet, length,
979 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +0000980}
981
982/* Handle a Supported Extension Headers Notification */
Harald Weltebed35df2011-11-02 13:06:18 +0100983int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
984 void *pack, unsigned len)
985{
jjako2c381332003-10-21 19:09:53 +0000986
Harald Weltebed35df2011-11-02 13:06:18 +0100987 if (gsn->cb_extheader_ind)
988 gsn->cb_extheader_ind(peer);
989
990 return 0;
jjako2c381332003-10-21 19:09:53 +0000991}
992
jjako52c24142002-12-16 13:33:51 +0000993/* ***********************************************************
994 * Session management messages
995 * Messages: create, update and delete PDP context
996 *
997 * Information storage
998 * Information storage for each PDP context is defined in
999 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1000 * PDP-address (IP address), sequence numbers, charging ID.
1001 * For the SGSN it also includes radio related mobility
1002 * information.
1003 *************************************************************/
1004
Harald Welte7b3347b2010-05-15 12:18:46 +02001005/* API: Send Create PDP Context Request (7.3.1) */
Harald Weltebed35df2011-11-02 13:06:18 +01001006extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
1007 void *cbp)
1008{
1009 union gtp_packet packet;
1010 unsigned int length =
1011 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1012 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001013
Harald Weltebed35df2011-11-02 13:06:18 +01001014 /* TODO: Secondary PDP Context Activation Procedure */
1015 /* In secondary activation procedure the PDP context is identified
1016 by tei in the header. The following fields are omitted: Selection
1017 mode, IMSI, MSISDN, End User Address, Access Point Name and
1018 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001019
Harald Weltebed35df2011-11-02 13:06:18 +01001020 if (pdp->secondary) {
1021 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001022 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001023 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001024 return EOF;
1025 }
1026 }
jjako2c381332003-10-21 19:09:53 +00001027
Harald Weltebed35df2011-11-02 13:06:18 +01001028 if (pdp->version == 0) {
1029 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1030 sizeof(pdp->qos_req0), pdp->qos_req0);
1031 }
jjako52c24142002-12-16 13:33:51 +00001032
Harald Weltebed35df2011-11-02 13:06:18 +01001033 /* Section 7.7.2 */
1034 if (pdp->version == 1) {
1035 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1036 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1037 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1038 }
jjako52c24142002-12-16 13:33:51 +00001039
Harald Weltebed35df2011-11-02 13:06:18 +01001040 /* Section 7.7.3 Routing Area Information */
1041 if (pdp->rai_given == 1)
1042 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1043 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001044
Harald Weltebed35df2011-11-02 13:06:18 +01001045 /* Section 7.7.11 */
1046 if (pdp->norecovery_given == 0)
1047 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1048 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001049
Harald Weltebed35df2011-11-02 13:06:18 +01001050 /* Section 7.7.12 */
1051 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1052 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1053 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001054
Harald Weltebed35df2011-11-02 13:06:18 +01001055 if (pdp->version == 0) {
1056 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1057 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1058 }
jjako08d331d2003-10-13 20:33:30 +00001059
Harald Weltebed35df2011-11-02 13:06:18 +01001060 /* Section 7.7.13 */
1061 if (pdp->version == 1) {
1062 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1063 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001064
Harald Weltebed35df2011-11-02 13:06:18 +01001065 /* Section 7.7.14 */
1066 if (!pdp->teic_confirmed)
1067 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1068 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001069
Harald Weltebed35df2011-11-02 13:06:18 +01001070 /* Section 7.7.17 */
1071 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001072
Harald Weltebed35df2011-11-02 13:06:18 +01001073 /* Section 7.7.17 */
1074 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1075 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1076 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001077
Harald Weltebed35df2011-11-02 13:06:18 +01001078 /* Section 7.7.23 */
1079 if (pdp->cch_pdp) /* Only include charging if flags are set */
1080 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1081 pdp->cch_pdp);
1082 }
jjako9b4971d2004-05-27 20:30:19 +00001083
Harald Weltebed35df2011-11-02 13:06:18 +01001084 /* TODO
1085 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1086 pdp->traceref);
1087 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1088 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001089
Harald Weltebed35df2011-11-02 13:06:18 +01001090 /* Section 7.7.27 */
1091 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1092 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1093 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001094
Harald Weltebed35df2011-11-02 13:06:18 +01001095 /* Section 7.7.30 */
1096 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1097 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1098 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001099
Harald Weltebed35df2011-11-02 13:06:18 +01001100 /* Section 7.7.31 */
1101 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1102 if (pdp->pco_req.l)
1103 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1104 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001105
Harald Weltebed35df2011-11-02 13:06:18 +01001106 /* Section 7.7.32 */
1107 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1108 pdp->gsnlc.l, pdp->gsnlc.v);
1109 /* Section 7.7.32 */
1110 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1111 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001112
Harald Weltebed35df2011-11-02 13:06:18 +01001113 /* Section 7.7.33 */
1114 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1115 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1116 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001117
Harald Weltebed35df2011-11-02 13:06:18 +01001118 /* Section 7.7.34 */
1119 if (pdp->version == 1)
1120 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1121 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001122
Harald Weltebed35df2011-11-02 13:06:18 +01001123 /* Section 7.7.36 */
1124 if ((pdp->version == 1) && pdp->tft.l)
1125 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1126 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001127
Harald Weltebed35df2011-11-02 13:06:18 +01001128 /* Section 7.7.41 */
1129 if ((pdp->version == 1) && pdp->triggerid.l)
1130 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1131 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001132
Harald Weltebed35df2011-11-02 13:06:18 +01001133 /* Section 7.7.42 */
1134 if ((pdp->version == 1) && pdp->omcid.l)
1135 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1136 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001137
Harald Weltebed35df2011-11-02 13:06:18 +01001138 /* new R7 fields */
1139 if (pdp->rattype_given == 1)
1140 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1141 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001142
Harald Weltebed35df2011-11-02 13:06:18 +01001143 if (pdp->userloc_given == 1)
1144 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1145 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001146
Harald Weltebed35df2011-11-02 13:06:18 +01001147 if (pdp->mstz_given == 1)
1148 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1149 pdp->mstz.l, pdp->mstz.v);
1150
1151 if (pdp->imeisv_given == 1)
1152 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1153 pdp->imeisv.l, pdp->imeisv.v);
1154
1155 /* TODO hisaddr0 */
1156 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1157
1158 return 0;
jjako52c24142002-12-16 13:33:51 +00001159}
1160
jjako08d331d2003-10-13 20:33:30 +00001161/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001162int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1163{
jjako08d331d2003-10-13 20:33:30 +00001164
Harald Weltebed35df2011-11-02 13:06:18 +01001165 /* Now send off a reply to the peer */
1166 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1167
1168 if (cause != GTPCAUSE_ACC_REQ) {
1169 pdp_freepdp(pdp);
1170 }
1171
1172 return 0;
jjako08d331d2003-10-13 20:33:30 +00001173}
1174
1175/* API: Register create context indication callback */
1176int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001177 int (*cb_create_context_ind) (struct pdp_t *
1178 pdp))
jjako52c24142002-12-16 13:33:51 +00001179{
Harald Weltebed35df2011-11-02 13:06:18 +01001180 gsn->cb_create_context_ind = cb_create_context_ind;
1181 return 0;
jjako08d331d2003-10-13 20:33:30 +00001182}
1183
jjako08d331d2003-10-13 20:33:30 +00001184/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001185int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1186 uint8_t cause)
1187{
1188 union gtp_packet packet;
1189 unsigned int length =
1190 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001191
Harald Weltebed35df2011-11-02 13:06:18 +01001192 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001193
Harald Weltebed35df2011-11-02 13:06:18 +01001194 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001195
Harald Weltebed35df2011-11-02 13:06:18 +01001196 if (version == 0)
1197 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1198 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001199
Harald Weltebed35df2011-11-02 13:06:18 +01001200 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1201 pdp->reorder);
1202 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1203 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001204
Harald Weltebed35df2011-11-02 13:06:18 +01001205 if (version == 0) {
1206 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1207 pdp->fllu);
1208 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1209 pdp->fllc);
1210 }
jjako08d331d2003-10-13 20:33:30 +00001211
Harald Weltebed35df2011-11-02 13:06:18 +01001212 if (version == 1) {
1213 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1214 pdp->teid_own);
1215 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1216 pdp->teic_own);
1217 }
jjako08d331d2003-10-13 20:33:30 +00001218
Harald Weltebed35df2011-11-02 13:06:18 +01001219 /* TODO: We use teic_own as charging ID */
1220 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1221 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001222
Harald Weltebed35df2011-11-02 13:06:18 +01001223 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1224 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001225
Harald Weltebed35df2011-11-02 13:06:18 +01001226 if (pdp->pco_neg.l) { /* Optional PCO */
1227 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1228 pdp->pco_neg.l, pdp->pco_neg.v);
1229 }
jjako52c24142002-12-16 13:33:51 +00001230
Harald Weltebed35df2011-11-02 13:06:18 +01001231 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1232 pdp->gsnlc.l, pdp->gsnlc.v);
1233 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1234 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001235
Harald Weltebed35df2011-11-02 13:06:18 +01001236 if (version == 1)
1237 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1238 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001239
Harald Weltebed35df2011-11-02 13:06:18 +01001240 /* TODO: Charging gateway address */
1241 }
jjako52c24142002-12-16 13:33:51 +00001242
Harald Weltebed35df2011-11-02 13:06:18 +01001243 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1244 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001245}
1246
1247/* Handle Create PDP Context Request */
1248int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001249 struct sockaddr_in *peer, int fd,
1250 void *pack, unsigned len)
1251{
1252 struct pdp_t *pdp, *pdp_old;
1253 struct pdp_t pdp_buf;
1254 union gtpie_member *ie[GTPIE_SIZE];
1255 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001256
Harald Weltebed35df2011-11-02 13:06:18 +01001257 uint16_t seq = get_seq(pack);
1258 int hlen = get_hlen(pack);
1259 uint8_t linked_nsapi = 0;
1260 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001261
Harald Weltebed35df2011-11-02 13:06:18 +01001262 if (!gtp_dublicate(gsn, version, peer, seq))
1263 return 0;
jjako08d331d2003-10-13 20:33:30 +00001264
Harald Weltebed35df2011-11-02 13:06:18 +01001265 pdp = &pdp_buf;
1266 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001267
Harald Weltebed35df2011-11-02 13:06:18 +01001268 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001269 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1270
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001271 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001272 }
jjako52c24142002-12-16 13:33:51 +00001273
Harald Weltebed35df2011-11-02 13:06:18 +01001274 pdp->seq = seq;
1275 pdp->sa_peer = *peer;
1276 pdp->fd = fd;
1277 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001278
Harald Weltebed35df2011-11-02 13:06:18 +01001279 /* Decode information elements */
1280 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1281 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001282 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1283 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001284 if (0 == version)
1285 return EOF;
1286 else
1287 return gtp_create_pdp_resp(gsn, version, pdp,
1288 GTPCAUSE_INVALID_MESSAGE);
1289 }
jjako52c24142002-12-16 13:33:51 +00001290
Harald Weltebed35df2011-11-02 13:06:18 +01001291 if (version == 1) {
1292 /* Linked NSAPI (conditional) */
1293 /* If included this is the Secondary PDP Context Activation Procedure */
1294 /* In secondary activation IMSI is not included, so the context must be */
1295 /* identified by the tei */
1296 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001297
Harald Weltebed35df2011-11-02 13:06:18 +01001298 /* Find the primary PDP context */
1299 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1300 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001301 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001302 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001303 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001304 return gtp_create_pdp_resp(gsn, version, pdp,
1305 GTPCAUSE_OPT_IE_INCORRECT);
1306 }
jjako2c381332003-10-21 19:09:53 +00001307
Harald Weltebed35df2011-11-02 13:06:18 +01001308 /* Check that the primary PDP context matches linked nsapi */
1309 if (linked_pdp->nsapi != linked_nsapi) {
1310 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001311 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001312 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001313 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001314 return gtp_create_pdp_resp(gsn, version, pdp,
1315 GTPCAUSE_OPT_IE_INCORRECT);
1316 }
jjako52c24142002-12-16 13:33:51 +00001317
Harald Weltebed35df2011-11-02 13:06:18 +01001318 /* Copy parameters from primary context */
1319 pdp->selmode = linked_pdp->selmode;
1320 pdp->imsi = linked_pdp->imsi;
1321 pdp->msisdn = linked_pdp->msisdn;
1322 pdp->eua = linked_pdp->eua;
1323 pdp->pco_req = linked_pdp->pco_req;
1324 pdp->apn_req = linked_pdp->apn_req;
1325 pdp->teic_gn = linked_pdp->teic_gn;
1326 pdp->secondary = 1;
1327 }
1328 }
1329 /* if (version == 1) */
1330 if (version == 0) {
1331 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1332 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1333 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001334 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1335 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001336 return gtp_create_pdp_resp(gsn, version, pdp,
1337 GTPCAUSE_MAN_IE_MISSING);
1338 }
1339 }
jjako08d331d2003-10-13 20:33:30 +00001340
Harald Weltebed35df2011-11-02 13:06:18 +01001341 if ((version == 1) && (!linked_pdp)) {
1342 /* Not Secondary PDP Context Activation Procedure */
1343 /* IMSI (conditional) */
1344 if (gtpie_gettv0
1345 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1346 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001347 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1348 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001349 return gtp_create_pdp_resp(gsn, version, pdp,
1350 GTPCAUSE_MAN_IE_MISSING);
1351 }
1352 }
jjako52c24142002-12-16 13:33:51 +00001353
Harald Weltebed35df2011-11-02 13:06:18 +01001354 /* Recovery (optional) */
1355 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1356 if (gsn->cb_recovery)
1357 gsn->cb_recovery(peer, recovery);
1358 }
jjako52c24142002-12-16 13:33:51 +00001359
Harald Weltebed35df2011-11-02 13:06:18 +01001360 /* Selection mode (conditional) */
1361 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1362 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1363 &pdp->selmode, sizeof(pdp->selmode))) {
1364 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001365 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1366 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001367 return gtp_create_pdp_resp(gsn, version, pdp,
1368 GTPCAUSE_MAN_IE_MISSING);
1369 }
1370 }
jjako52c24142002-12-16 13:33:51 +00001371
Harald Weltebed35df2011-11-02 13:06:18 +01001372 if (version == 0) {
1373 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1374 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001375 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1376 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001377 return gtp_create_pdp_resp(gsn, version, pdp,
1378 GTPCAUSE_MAN_IE_MISSING);
1379 }
jjako52c24142002-12-16 13:33:51 +00001380
Harald Weltebed35df2011-11-02 13:06:18 +01001381 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1382 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001383 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1384 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001385 return gtp_create_pdp_resp(gsn, version, pdp,
1386 GTPCAUSE_MAN_IE_MISSING);
1387 }
1388 }
jjako08d331d2003-10-13 20:33:30 +00001389
Harald Weltebed35df2011-11-02 13:06:18 +01001390 if (version == 1) {
1391 /* TEID (mandatory) */
1392 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1393 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001394 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1395 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001396 return gtp_create_pdp_resp(gsn, version, pdp,
1397 GTPCAUSE_MAN_IE_MISSING);
1398 }
jjako2c381332003-10-21 19:09:53 +00001399
Harald Weltebed35df2011-11-02 13:06:18 +01001400 /* TEIC (conditional) */
1401 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1402 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1403 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001404 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001405 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001406 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001407 return gtp_create_pdp_resp(gsn, version, pdp,
1408 GTPCAUSE_MAN_IE_MISSING);
1409 }
1410 }
jjako08d331d2003-10-13 20:33:30 +00001411
Harald Weltebed35df2011-11-02 13:06:18 +01001412 /* NSAPI (mandatory) */
1413 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1414 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001415 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1416 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001417 return gtp_create_pdp_resp(gsn, version, pdp,
1418 GTPCAUSE_MAN_IE_MISSING);
1419 }
1420 }
jjako2e840a32003-01-28 16:05:18 +00001421
Harald Weltebed35df2011-11-02 13:06:18 +01001422 /* Charging Characteriatics (optional) */
1423 /* Trace reference (optional) */
1424 /* Trace type (optional) */
1425 /* Charging Characteriatics (optional) */
jjako52c24142002-12-16 13:33:51 +00001426
Harald Weltebed35df2011-11-02 13:06:18 +01001427 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1428 /* End User Address (conditional) */
1429 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1430 &pdp->eua.v, sizeof(pdp->eua.v))) {
1431 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001432 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1433 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001434 return gtp_create_pdp_resp(gsn, version, pdp,
1435 GTPCAUSE_MAN_IE_MISSING);
1436 }
jjako08d331d2003-10-13 20:33:30 +00001437
Harald Weltebed35df2011-11-02 13:06:18 +01001438 /* APN */
1439 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1440 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1441 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001442 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1443 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001444 return gtp_create_pdp_resp(gsn, version, pdp,
1445 GTPCAUSE_MAN_IE_MISSING);
1446 }
jjako2c381332003-10-21 19:09:53 +00001447
Harald Weltebed35df2011-11-02 13:06:18 +01001448 /* Extract protocol configuration options (optional) */
1449 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1450 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1451 }
1452 }
jjako2c381332003-10-21 19:09:53 +00001453
Harald Weltebed35df2011-11-02 13:06:18 +01001454 /* SGSN address for signalling (mandatory) */
1455 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1456 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1457 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001458 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1459 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001460 return gtp_create_pdp_resp(gsn, version, pdp,
1461 GTPCAUSE_MAN_IE_MISSING);
1462 }
jjako2e840a32003-01-28 16:05:18 +00001463
Harald Weltebed35df2011-11-02 13:06:18 +01001464 /* SGSN address for user traffic (mandatory) */
1465 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1466 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1467 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001468 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1469 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001470 return gtp_create_pdp_resp(gsn, version, pdp,
1471 GTPCAUSE_MAN_IE_MISSING);
1472 }
jjako52c24142002-12-16 13:33:51 +00001473
Harald Weltebed35df2011-11-02 13:06:18 +01001474 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1475 /* MSISDN (conditional) */
1476 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1477 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1478 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001479 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1480 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001481 return gtp_create_pdp_resp(gsn, version, pdp,
1482 GTPCAUSE_MAN_IE_MISSING);
1483 }
1484 }
jjako52c24142002-12-16 13:33:51 +00001485
Harald Weltebed35df2011-11-02 13:06:18 +01001486 if (version == 1) {
1487 /* QoS (mandatory) */
1488 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1489 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1490 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001491 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1492 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001493 return gtp_create_pdp_resp(gsn, version, pdp,
1494 GTPCAUSE_MAN_IE_MISSING);
1495 }
1496
1497 /* TFT (conditional) */
1498 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1499 &pdp->tft.v, sizeof(pdp->tft.v))) {
1500 }
1501
1502 /* Trigger ID */
1503 /* OMC identity */
1504 }
1505
1506 /* Initialize our own IP addresses */
1507 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1508 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1509
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001510 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001511
1512 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1513 /* Found old pdp with same tid. Now the voodoo begins! */
1514 /* 09.60 / 29.060 allows create on existing context to "steal" */
1515 /* the context which was allready established */
1516 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001517 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001518 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1519 &&
1520 (!memcmp
1521 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1522 && (pdp->selmode == pdp_old->selmode)
1523 && (pdp->msisdn.l == pdp_old->msisdn.l)
1524 &&
1525 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1526 {
1527 /* OK! We are dealing with the same APN. We will copy new
1528 * parameters to the old pdp and send off confirmation
1529 * We ignore the following information elements:
1530 * QoS: MS will get originally negotiated QoS.
1531 * End user address (EUA). MS will get old EUA anyway.
1532 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001533 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001534
1535 /* Copy remote flow label */
1536 pdp_old->flru = pdp->flru;
1537 pdp_old->flrc = pdp->flrc;
1538
1539 /* Copy remote tei */
1540 pdp_old->teid_gn = pdp->teid_gn;
1541 pdp_old->teic_gn = pdp->teic_gn;
1542
1543 /* Copy peer GSN address */
1544 pdp_old->gsnrc.l = pdp->gsnrc.l;
1545 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1546 pdp_old->gsnru.l = pdp->gsnru.l;
1547 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1548
1549 /* Copy request parameters */
1550 pdp_old->seq = pdp->seq;
1551 pdp_old->sa_peer = pdp->sa_peer;
1552 pdp_old->fd = pdp->fd = fd;
1553 pdp_old->version = pdp->version = version;
1554
1555 /* Switch to using the old pdp context */
1556 pdp = pdp_old;
1557
1558 /* Confirm to peer that things were "successful" */
1559 return gtp_create_pdp_resp(gsn, version, pdp,
1560 GTPCAUSE_ACC_REQ);
1561 } else { /* This is not the same PDP context. Delete the old one. */
1562
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001563 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001564
1565 if (gsn->cb_delete_context)
1566 gsn->cb_delete_context(pdp_old);
1567 pdp_freepdp(pdp_old);
1568
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001569 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001570 }
1571 }
1572
1573 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
1574
1575 /* Callback function to validata login */
1576 if (gsn->cb_create_context_ind != 0)
1577 return gsn->cb_create_context_ind(pdp);
1578 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001579 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1580 "No create_context_ind callback defined\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001581 return gtp_create_pdp_resp(gsn, version, pdp,
1582 GTPCAUSE_NOT_SUPPORTED);
1583 }
jjako52c24142002-12-16 13:33:51 +00001584}
1585
jjako52c24142002-12-16 13:33:51 +00001586/* Handle Create PDP Context Response */
1587int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001588 struct sockaddr_in *peer, void *pack, unsigned len)
1589{
1590 struct pdp_t *pdp;
1591 union gtpie_member *ie[GTPIE_SIZE];
1592 uint8_t cause, recovery;
1593 void *cbp = NULL;
1594 uint8_t type = 0;
1595 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001596
Harald Weltebed35df2011-11-02 13:06:18 +01001597 /* Remove packet from queue */
1598 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1599 return EOF;
jjako52c24142002-12-16 13:33:51 +00001600
Harald Weltebed35df2011-11-02 13:06:18 +01001601 /* Find the context in question */
1602 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1603 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001604 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001605 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001606 if (gsn->cb_conf)
1607 gsn->cb_conf(type, EOF, NULL, cbp);
1608 return EOF;
1609 }
jjako2c381332003-10-21 19:09:53 +00001610
Harald Weltebed35df2011-11-02 13:06:18 +01001611 /* Register that we have received a valid teic from GGSN */
1612 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001613
Harald Weltebed35df2011-11-02 13:06:18 +01001614 /* Decode information elements */
1615 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1616 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001617 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1618 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001619 if (gsn->cb_conf)
1620 gsn->cb_conf(type, EOF, pdp, cbp);
1621 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1622 pdp_freepdp(pdp); */
1623 return EOF;
1624 }
jjako52c24142002-12-16 13:33:51 +00001625
Harald Weltebed35df2011-11-02 13:06:18 +01001626 /* Extract cause value (mandatory) */
1627 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1628 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001629 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1630 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001631 if (gsn->cb_conf)
1632 gsn->cb_conf(type, EOF, pdp, cbp);
1633 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1634 pdp_freepdp(pdp); */
1635 return EOF;
1636 }
jjako52c24142002-12-16 13:33:51 +00001637
Harald Weltebed35df2011-11-02 13:06:18 +01001638 /* Extract recovery (optional) */
1639 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1640 if (gsn->cb_recovery)
1641 gsn->cb_recovery(peer, recovery);
1642 }
jjako52c24142002-12-16 13:33:51 +00001643
Harald Weltebed35df2011-11-02 13:06:18 +01001644 /* Extract protocol configuration options (optional) */
1645 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1646 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1647 }
jjako52c24142002-12-16 13:33:51 +00001648
Harald Weltebed35df2011-11-02 13:06:18 +01001649 /* Check all conditional information elements */
1650 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001651
Harald Weltebed35df2011-11-02 13:06:18 +01001652 if (version == 0) {
1653 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1654 &pdp->qos_neg0,
1655 sizeof(pdp->qos_neg0))) {
1656 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001657 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001658 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001659 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001660 if (gsn->cb_conf)
1661 gsn->cb_conf(type, EOF, pdp, cbp);
1662 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1663 pdp_freepdp(pdp); */
1664 return EOF;
1665 }
1666 }
jjako08d331d2003-10-13 20:33:30 +00001667
Harald Weltebed35df2011-11-02 13:06:18 +01001668 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1669 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001670 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001671 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001672 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001673 if (gsn->cb_conf)
1674 gsn->cb_conf(type, EOF, pdp, cbp);
1675 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1676 pdp_freepdp(pdp); */
1677 return EOF;
1678 }
jjako52c24142002-12-16 13:33:51 +00001679
Harald Weltebed35df2011-11-02 13:06:18 +01001680 if (version == 0) {
1681 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1682 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001683 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001684 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001685 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001686 if (gsn->cb_conf)
1687 gsn->cb_conf(type, EOF, pdp, cbp);
1688 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1689 pdp_freepdp(pdp); */
1690 return EOF;
1691 }
jjako52c24142002-12-16 13:33:51 +00001692
Harald Weltebed35df2011-11-02 13:06:18 +01001693 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1694 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001695 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001696 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001697 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001698 if (gsn->cb_conf)
1699 gsn->cb_conf(type, EOF, pdp, cbp);
1700 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1701 pdp_freepdp(pdp); */
1702 return EOF;
1703 }
1704 }
1705
1706 if (version == 1) {
1707 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1708 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001709 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001710 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001711 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001712 if (gsn->cb_conf)
1713 gsn->cb_conf(type, EOF, pdp, cbp);
1714 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1715 pdp_freepdp(pdp); */
1716 return EOF;
1717 }
1718
1719 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1720 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001721 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001722 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001723 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001724 if (gsn->cb_conf)
1725 gsn->cb_conf(type, EOF, pdp, cbp);
1726 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1727 pdp_freepdp(pdp); */
1728 return EOF;
1729 }
1730 }
1731
1732 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1733 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001734 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001735 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001736 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001737 if (gsn->cb_conf)
1738 gsn->cb_conf(type, EOF, pdp, cbp);
1739 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1740 pdp_freepdp(pdp); */
1741 }
1742
1743 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1744 &pdp->eua.v, sizeof(pdp->eua.v))) {
1745 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001746 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001747 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001748 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001749 if (gsn->cb_conf)
1750 gsn->cb_conf(type, EOF, pdp, cbp);
1751 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1752 pdp_freepdp(pdp); */
1753 return EOF;
1754 }
1755
1756 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1757 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1758 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001759 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001760 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001761 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001762 if (gsn->cb_conf)
1763 gsn->cb_conf(type, EOF, pdp, cbp);
1764 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1765 pdp_freepdp(pdp); */
1766 return EOF;
1767 }
1768
1769 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1770 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1771 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001772 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001773 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001774 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001775 if (gsn->cb_conf)
1776 gsn->cb_conf(type, EOF, pdp, cbp);
1777 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1778 pdp_freepdp(pdp); */
1779 return EOF;
1780 }
1781
1782 if (version == 1) {
1783 if (gtpie_gettlv
1784 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1785 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1786 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001787 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001788 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001789 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001790 if (gsn->cb_conf)
1791 gsn->cb_conf(type, EOF, pdp, cbp);
1792 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1793 pdp_freepdp(pdp); */
1794 return EOF;
1795 }
1796 }
1797
1798 }
1799
1800 if (gsn->cb_conf)
1801 gsn->cb_conf(type, cause, pdp, cbp);
1802
1803 return 0;
jjako52c24142002-12-16 13:33:51 +00001804}
1805
jjako08d331d2003-10-13 20:33:30 +00001806/* API: Send Update PDP Context Request */
1807int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001808 struct in_addr *inetaddr)
1809{
1810 union gtp_packet packet;
1811 unsigned int length =
1812 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001813
Harald Weltebed35df2011-11-02 13:06:18 +01001814 if (pdp->version == 0)
1815 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1816 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001817
Harald Weltebed35df2011-11-02 13:06:18 +01001818 /* Include IMSI if updating with unknown teic_gn */
1819 if ((pdp->version == 1) && (!pdp->teic_gn))
1820 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1821 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1822
1823 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1824 gsn->restart_counter);
1825
1826 if (pdp->version == 0) {
1827 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1828 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1829 }
1830
1831 if (pdp->version == 1) {
1832 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1833 pdp->teid_own);
1834
1835 if (!pdp->teic_confirmed)
1836 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1837 pdp->teic_own);
1838 }
1839
1840 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1841
1842 /* TODO
1843 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1844 pdp->traceref);
1845 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1846 pdp->tracetype); */
1847
1848 /* TODO if ggsn update message
1849 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1850 pdp->eua.l, pdp->eua.v);
1851 */
1852
1853 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1854 pdp->gsnlc.l, pdp->gsnlc.v);
1855 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1856 pdp->gsnlu.l, pdp->gsnlu.v);
1857
1858 if (pdp->version == 1)
1859 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1860 pdp->qos_req.l, pdp->qos_req.v);
1861
1862 if ((pdp->version == 1) && pdp->tft.l)
1863 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1864 pdp->tft.l, pdp->tft.v);
1865
1866 if ((pdp->version == 1) && pdp->triggerid.l)
1867 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1868 pdp->triggerid.l, pdp->triggerid.v);
1869
1870 if ((pdp->version == 1) && pdp->omcid.l)
1871 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1872 pdp->omcid.l, pdp->omcid.v);
1873
Daniel Willmann134a7752016-02-03 18:53:29 +01001874 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001875
1876 return 0;
jjako52c24142002-12-16 13:33:51 +00001877}
1878
jjako08d331d2003-10-13 20:33:30 +00001879/* Send Update PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001880int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
1881 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001882 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001883 struct pdp_t *pdp, uint8_t cause)
1884{
jjako08d331d2003-10-13 20:33:30 +00001885
Harald Weltebed35df2011-11-02 13:06:18 +01001886 union gtp_packet packet;
1887 unsigned int length =
1888 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001889
Harald Weltebed35df2011-11-02 13:06:18 +01001890 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001891
Harald Weltebed35df2011-11-02 13:06:18 +01001892 if (cause == GTPCAUSE_ACC_REQ) {
1893
1894 if (version == 0)
1895 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1896 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1897
1898 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1899 gsn->restart_counter);
1900
1901 if (version == 0) {
1902 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1903 pdp->fllu);
1904 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1905 pdp->fllc);
1906 }
1907
1908 if (version == 1) {
1909 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1910 pdp->teid_own);
1911
1912 if (!pdp->teic_confirmed)
1913 gtpie_tv4(&packet, &length, GTP_MAX,
1914 GTPIE_TEI_C, pdp->teic_own);
1915 }
1916
1917 /* TODO we use teid_own as charging ID address */
1918 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1919 pdp->teid_own);
1920
1921 /* If ggsn
1922 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1923 pdp->eua.l, pdp->eua.v); */
1924
1925 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1926 pdp->gsnlc.l, pdp->gsnlc.v);
1927 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1928 pdp->gsnlu.l, pdp->gsnlu.v);
1929
1930 if (version == 1)
1931 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1932 pdp->qos_neg.l, pdp->qos_neg.v);
1933
1934 /* TODO: Charging gateway address */
1935 }
1936
1937 return gtp_resp(version, gsn, pdp, &packet, length, peer,
1938 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00001939}
1940
jjako52c24142002-12-16 13:33:51 +00001941/* Handle Update PDP Context Request */
1942int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001943 struct sockaddr_in *peer, int fd,
1944 void *pack, unsigned len)
1945{
1946 struct pdp_t *pdp;
1947 struct pdp_t pdp_backup;
1948 union gtpie_member *ie[GTPIE_SIZE];
1949 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001950
Harald Weltebed35df2011-11-02 13:06:18 +01001951 uint16_t seq = get_seq(pack);
1952 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001953
Harald Weltebed35df2011-11-02 13:06:18 +01001954 uint64_t imsi;
1955 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00001956
Harald Weltebed35df2011-11-02 13:06:18 +01001957 /* Is this a dublicate ? */
1958 if (!gtp_dublicate(gsn, version, peer, seq)) {
1959 return 0; /* We allready send of response once */
1960 }
jjako08d331d2003-10-13 20:33:30 +00001961
Harald Weltebed35df2011-11-02 13:06:18 +01001962 /* Decode information elements */
1963 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1964 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001965 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1966 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001967 if (0 == version)
1968 return EOF;
1969 else
1970 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
1971 len, NULL,
1972 GTPCAUSE_INVALID_MESSAGE);
1973 }
jjako08d331d2003-10-13 20:33:30 +00001974
Harald Weltebed35df2011-11-02 13:06:18 +01001975 /* Finding PDP: */
1976 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
1977 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
1978 /* we have to use the tunnel endpoint identifier */
1979 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001980 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1981
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001982 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00001983
Harald Weltebed35df2011-11-02 13:06:18 +01001984 /* Find the context in question */
1985 if (pdp_getimsi(&pdp, imsi, nsapi)) {
1986 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001987 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1988 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001989 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
1990 len, NULL,
1991 GTPCAUSE_NON_EXIST);
1992 }
1993 } else if (version == 1) {
1994 /* NSAPI (mandatory) */
1995 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
1996 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001997 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1998 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001999 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2000 len, NULL,
2001 GTPCAUSE_MAN_IE_MISSING);
2002 }
jjako08d331d2003-10-13 20:33:30 +00002003
Harald Weltebed35df2011-11-02 13:06:18 +01002004 /* IMSI (conditional) */
2005 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2006 /* Find the context in question */
2007 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2008 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002009 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002010 pack, len, "Unknown PDP context: %u\n",
2011 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002012 return gtp_update_pdp_resp(gsn, version, peer,
2013 fd, pack, len, NULL,
2014 GTPCAUSE_NON_EXIST);
2015 }
2016 } else {
2017 /* Find the context in question */
2018 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2019 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002020 GTP_LOGPKG(LOGL_ERROR, peer,
2021 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002022 return gtp_update_pdp_resp(gsn, version, peer,
2023 fd, pack, len, NULL,
2024 GTPCAUSE_NON_EXIST);
2025 }
2026 }
2027 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002028 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002029 return EOF;
2030 }
jjako08d331d2003-10-13 20:33:30 +00002031
Harald Weltebed35df2011-11-02 13:06:18 +01002032 /* Make a backup copy in case anything is wrong */
2033 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002034
Harald Weltebed35df2011-11-02 13:06:18 +01002035 if (version == 0) {
2036 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2037 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2038 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002039 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2040 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002041 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2042 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2043 len, pdp,
2044 GTPCAUSE_MAN_IE_MISSING);
2045 }
2046 }
jjako52c24142002-12-16 13:33:51 +00002047
Harald Weltebed35df2011-11-02 13:06:18 +01002048 /* Recovery (optional) */
2049 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2050 if (gsn->cb_recovery)
2051 gsn->cb_recovery(peer, recovery);
2052 }
jjako08d331d2003-10-13 20:33:30 +00002053
Harald Weltebed35df2011-11-02 13:06:18 +01002054 if (version == 0) {
2055 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2056 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002057 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2058 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002059 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2060 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2061 len, pdp,
2062 GTPCAUSE_MAN_IE_MISSING);
2063 }
jjako52c24142002-12-16 13:33:51 +00002064
Harald Weltebed35df2011-11-02 13:06:18 +01002065 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2066 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002067 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2068 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002069 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2070 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2071 len, pdp,
2072 GTPCAUSE_MAN_IE_MISSING);
2073 }
2074 }
jjako52c24142002-12-16 13:33:51 +00002075
Harald Weltebed35df2011-11-02 13:06:18 +01002076 if (version == 1) {
2077 /* TEID (mandatory) */
2078 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2079 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002080 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2081 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002082 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2083 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2084 len, pdp,
2085 GTPCAUSE_MAN_IE_MISSING);
2086 }
jjako52c24142002-12-16 13:33:51 +00002087
Harald Weltebed35df2011-11-02 13:06:18 +01002088 /* TEIC (conditional) */
2089 /* If TEIC is not included it means that we have allready received it */
2090 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2091 /* all updated contexts, or only for one of the linked contexts */
2092 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2093
2094 /* NSAPI (mandatory) */
2095 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2096 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002097 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2098 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002099 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2100 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2101 len, pdp,
2102 GTPCAUSE_MAN_IE_MISSING);
2103 }
2104 }
2105
2106 /* Trace reference (optional) */
2107 /* Trace type (optional) */
2108
2109 /* End User Address (conditional) TODO: GGSN Initiated
2110 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2111 &pdp->eua.v, sizeof(pdp->eua.v))) {
2112 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002113 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002114 "Missing mandatory information field");
2115 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2116 return gtp_update_pdp_resp(gsn, version, pdp,
2117 GTPCAUSE_MAN_IE_MISSING);
2118 } */
2119
2120 /* SGSN address for signalling (mandatory) */
2121 /* It is weird that this is mandatory when TEIC is conditional */
2122 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2123 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2124 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002125 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2126 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002127 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2128 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2129 pdp, GTPCAUSE_MAN_IE_MISSING);
2130 }
2131
2132 /* SGSN address for user traffic (mandatory) */
2133 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2134 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2135 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002136 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2137 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002138 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2139 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2140 pdp, GTPCAUSE_MAN_IE_MISSING);
2141 }
2142
2143 if (version == 1) {
2144 /* QoS (mandatory) */
2145 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2146 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2147 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002148 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2149 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002150 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2151 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2152 len, pdp,
2153 GTPCAUSE_MAN_IE_MISSING);
2154 }
2155
2156 /* TFT (conditional) */
2157 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2158 &pdp->tft.v, sizeof(pdp->tft.v))) {
2159 }
2160
2161 /* OMC identity */
2162 }
2163
2164 /* Confirm to peer that things were "successful" */
2165 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2166 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002167}
2168
jjako52c24142002-12-16 13:33:51 +00002169/* Handle Update PDP Context Response */
2170int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002171 struct sockaddr_in *peer, void *pack, unsigned len)
2172{
2173 struct pdp_t *pdp;
2174 union gtpie_member *ie[GTPIE_SIZE];
2175 uint8_t cause, recovery;
2176 void *cbp = NULL;
2177 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002178 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002179
Harald Weltebed35df2011-11-02 13:06:18 +01002180 /* Remove packet from queue */
2181 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2182 return EOF;
jjako52c24142002-12-16 13:33:51 +00002183
Harald Weltebed35df2011-11-02 13:06:18 +01002184 /* Find the context in question */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002185 if (pdp_getgtp1(&pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002186 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002187 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002188 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002189 pdp = NULL;
2190 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002191 }
jjako2c381332003-10-21 19:09:53 +00002192
Harald Weltebed35df2011-11-02 13:06:18 +01002193 /* Register that we have received a valid teic from GGSN */
2194 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002195
Harald Weltebed35df2011-11-02 13:06:18 +01002196 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002197 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002198 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002199 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2200 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002201 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002202 }
jjako52c24142002-12-16 13:33:51 +00002203
Harald Weltebed35df2011-11-02 13:06:18 +01002204 /* Extract cause value (mandatory) */
2205 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002206 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002207 }
jjako52c24142002-12-16 13:33:51 +00002208
Harald Weltebed35df2011-11-02 13:06:18 +01002209 /* Extract recovery (optional) */
2210 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2211 if (gsn->cb_recovery)
2212 gsn->cb_recovery(peer, recovery);
2213 }
2214
2215 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002216 /* TODO: This does not handle GGSN-initiated update responses */
2217 if (GTPCAUSE_ACC_REQ == cause) {
2218 if (version == 0) {
2219 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2220 &pdp->qos_neg0,
2221 sizeof(pdp->qos_neg0))) {
2222 goto err_missing;
2223 }
2224
2225 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2226 goto err_missing;
2227 }
2228
2229 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2230 goto err_missing;
2231 }
Harald Weltebed35df2011-11-02 13:06:18 +01002232 }
2233
Daniel Willmannd9975522016-02-04 15:38:12 +01002234 if (version == 1) {
2235 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2236 goto err_missing;
2237 }
Harald Weltebed35df2011-11-02 13:06:18 +01002238
Daniel Willmannd9975522016-02-04 15:38:12 +01002239 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2240 goto err_missing;
2241 }
2242 }
2243
2244 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2245 goto err_missing;
2246 }
2247
2248 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2249 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2250 goto err_missing;
2251 }
2252
2253 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2254 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2255 goto err_missing;
2256 }
2257
2258 if (version == 1) {
2259 if (gtpie_gettlv
2260 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2261 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2262 goto err_missing;
2263 }
2264 }
Harald Weltebed35df2011-11-02 13:06:18 +01002265 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002266
2267 if (gsn->cb_conf)
2268 gsn->cb_conf(type, cause, pdp, cbp);
2269 return 0; /* Succes */
2270
2271err_missing:
2272 gsn->missing++;
2273 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2274 "Missing information field\n");
2275err_out:
2276 if (gsn->cb_conf)
2277 gsn->cb_conf(type, EOF, pdp, cbp);
2278 return EOF;
jjako52c24142002-12-16 13:33:51 +00002279}
2280
jjako08d331d2003-10-13 20:33:30 +00002281/* API: Send Delete PDP Context Request */
jjako2c381332003-10-21 19:09:53 +00002282int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002283 int teardown)
2284{
2285 union gtp_packet packet;
2286 unsigned int length =
2287 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2288 struct in_addr addr;
2289 struct pdp_t *linked_pdp;
2290 struct pdp_t *secondary_pdp;
2291 int n;
2292 int count = 0;
jjako2c381332003-10-21 19:09:53 +00002293
Harald Weltebed35df2011-11-02 13:06:18 +01002294 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2295 gsn->err_address++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002296 LOGP(DLGTP, LOGL_ERROR,
2297 "GSN address conversion failed\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002298 return EOF;
jjako2c381332003-10-21 19:09:53 +00002299 }
jjako2c381332003-10-21 19:09:53 +00002300
Harald Weltebed35df2011-11-02 13:06:18 +01002301 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002302 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002303 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002304 return EOF;
2305 }
2306
2307 if (!teardown) {
2308 for (n = 0; n < PDP_MAXNSAPI; n++)
2309 if (linked_pdp->secondary_tei[n])
2310 count++;
2311 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002312 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002313 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002314 return EOF;
2315 }
2316 }
2317
2318 if (pdp->version == 1) {
2319 if (teardown)
2320 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2321 0xff);
2322
2323 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2324 }
2325
2326 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2327
2328 if (teardown) { /* Remove all contexts */
2329 for (n = 0; n < PDP_MAXNSAPI; n++) {
2330 if (linked_pdp->secondary_tei[n]) {
2331 if (pdp_getgtp1
2332 (&secondary_pdp,
2333 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002334 LOGP(DLGTP, LOGL_ERROR,
2335 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002336 return EOF;
2337 }
2338 if (linked_pdp != secondary_pdp) {
2339 if (gsn->cb_delete_context)
2340 gsn->cb_delete_context
2341 (secondary_pdp);
2342 pdp_freepdp(secondary_pdp);
2343 }
2344 }
2345 }
2346 if (gsn->cb_delete_context)
2347 gsn->cb_delete_context(linked_pdp);
2348 pdp_freepdp(linked_pdp);
2349 } else {
2350 if (gsn->cb_delete_context)
2351 gsn->cb_delete_context(pdp);
2352 if (pdp == linked_pdp) {
2353 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2354 linked_pdp->nodata = 1;
2355 } else
2356 pdp_freepdp(pdp);
2357 }
2358
2359 return 0;
jjako2c381332003-10-21 19:09:53 +00002360}
jjako08d331d2003-10-13 20:33:30 +00002361
jjako52c24142002-12-16 13:33:51 +00002362/* Send Delete PDP Context Response */
2363int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002364 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002365 void *pack, unsigned len,
2366 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002367 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002368{
Harald Weltebed35df2011-11-02 13:06:18 +01002369 union gtp_packet packet;
2370 struct pdp_t *secondary_pdp;
2371 unsigned int length =
2372 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2373 int n;
jjako52c24142002-12-16 13:33:51 +00002374
Harald Weltebed35df2011-11-02 13:06:18 +01002375 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002376
Harald Weltebed35df2011-11-02 13:06:18 +01002377 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2378 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002379
Harald Weltebed35df2011-11-02 13:06:18 +01002380 if (cause == GTPCAUSE_ACC_REQ) {
2381 if ((teardown) || (version == 0)) { /* Remove all contexts */
2382 for (n = 0; n < PDP_MAXNSAPI; n++) {
2383 if (linked_pdp->secondary_tei[n]) {
2384 if (pdp_getgtp1
2385 (&secondary_pdp,
2386 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002387 LOGP(DLGTP, LOGL_ERROR,
2388 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002389 return EOF;
2390 }
2391 if (linked_pdp != secondary_pdp) {
2392 if (gsn->cb_delete_context)
2393 gsn->cb_delete_context
2394 (secondary_pdp);
2395 pdp_freepdp(secondary_pdp);
2396 }
2397 }
2398 }
2399 if (gsn->cb_delete_context)
2400 gsn->cb_delete_context(linked_pdp);
2401 pdp_freepdp(linked_pdp);
2402 } else { /* Remove only current context */
2403 if (gsn->cb_delete_context)
2404 gsn->cb_delete_context(pdp);
2405 if (pdp == linked_pdp) {
2406 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2407 0;
2408 linked_pdp->nodata = 1;
2409 } else
2410 pdp_freepdp(pdp);
2411 }
jjako2c381332003-10-21 19:09:53 +00002412 }
Harald Weltebed35df2011-11-02 13:06:18 +01002413 /* if (cause == GTPCAUSE_ACC_REQ) */
2414 return 0;
jjako52c24142002-12-16 13:33:51 +00002415}
2416
2417/* Handle Delete PDP Context Request */
2418int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002419 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002420 void *pack, unsigned len)
2421{
2422 struct pdp_t *pdp = NULL;
2423 struct pdp_t *linked_pdp = NULL;
2424 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002425
Harald Weltebed35df2011-11-02 13:06:18 +01002426 uint16_t seq = get_seq(pack);
2427 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002428
Harald Weltebed35df2011-11-02 13:06:18 +01002429 uint8_t nsapi;
2430 uint8_t teardown = 0;
2431 int n;
2432 int count = 0;
jjako52c24142002-12-16 13:33:51 +00002433
Harald Weltebed35df2011-11-02 13:06:18 +01002434 /* Is this a dublicate ? */
2435 if (!gtp_dublicate(gsn, version, peer, seq)) {
2436 return 0; /* We allready send off response once */
2437 }
jjako2c381332003-10-21 19:09:53 +00002438
Harald Weltebed35df2011-11-02 13:06:18 +01002439 /* Find the linked context in question */
2440 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2441 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002442 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002443 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002444 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2445 NULL, NULL, GTPCAUSE_NON_EXIST,
2446 teardown);
2447 }
jjako2c381332003-10-21 19:09:53 +00002448
Harald Weltebed35df2011-11-02 13:06:18 +01002449 /* If version 0 this is also the secondary context */
2450 if (version == 0)
2451 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002452
Harald Weltebed35df2011-11-02 13:06:18 +01002453 /* Decode information elements */
2454 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2455 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002456 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2457 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002458 if (0 == version)
2459 return EOF;
2460 else
2461 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2462 len, NULL, NULL,
2463 GTPCAUSE_INVALID_MESSAGE,
2464 teardown);
2465 }
2466
2467 if (version == 1) {
2468 /* NSAPI (mandatory) */
2469 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2470 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002471 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2472 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002473 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2474 len, NULL, NULL,
2475 GTPCAUSE_MAN_IE_MISSING,
2476 teardown);
2477 }
2478
2479 /* Find the context in question */
2480 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2481 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002482 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2483 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002484 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2485 len, NULL, NULL,
2486 GTPCAUSE_NON_EXIST,
2487 teardown);
2488 }
2489
2490 /* Teardown (conditional) */
2491 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2492
2493 if (!teardown) {
2494 for (n = 0; n < PDP_MAXNSAPI; n++)
2495 if (linked_pdp->secondary_tei[n])
2496 count++;
2497 if (count <= 1) {
2498 return 0; /* 29.060 7.3.5 Ignore message */
2499 }
2500 }
2501 }
2502
2503 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2504 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002505}
2506
jjako52c24142002-12-16 13:33:51 +00002507/* Handle Delete PDP Context Response */
2508int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002509 struct sockaddr_in *peer, void *pack, unsigned len)
2510{
2511 union gtpie_member *ie[GTPIE_SIZE];
2512 uint8_t cause;
2513 void *cbp = NULL;
2514 uint8_t type = 0;
2515 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002516
Harald Weltebed35df2011-11-02 13:06:18 +01002517 /* Remove packet from queue */
2518 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2519 return EOF;
jjako52c24142002-12-16 13:33:51 +00002520
Harald Weltebed35df2011-11-02 13:06:18 +01002521 /* Decode information elements */
2522 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2523 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002524 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2525 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002526 if (gsn->cb_conf)
2527 gsn->cb_conf(type, EOF, NULL, cbp);
2528 return EOF;
2529 }
2530
2531 /* Extract cause value (mandatory) */
2532 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2533 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002534 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2535 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002536 if (gsn->cb_conf)
2537 gsn->cb_conf(type, EOF, NULL, cbp);
2538 return EOF;
2539 }
2540
2541 /* Check the cause value (again) */
2542 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2543 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002544 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2545 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002546 if (gsn->cb_conf)
2547 gsn->cb_conf(type, cause, NULL, cbp);
2548 return EOF;
2549 }
2550
2551 /* Callback function to notify application */
2552 if (gsn->cb_conf)
2553 gsn->cb_conf(type, cause, NULL, cbp);
2554
2555 return 0;
jjako52c24142002-12-16 13:33:51 +00002556}
2557
Harald Welte54d082e2017-08-12 22:43:21 +02002558/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
jjako52c24142002-12-16 13:33:51 +00002559int gtp_error_ind_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002560 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002561 void *pack, unsigned len)
2562{
Harald Weltebed35df2011-11-02 13:06:18 +01002563 union gtp_packet packet;
2564 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2565
Harald Welte54d082e2017-08-12 22:43:21 +02002566 if (version == 1) {
2567 /* Mandatory 7.7.13 TEI Data I */
2568 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2569 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2570
2571 /* Mandatory 7.7.32 GSN Address */
2572 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2573 sizeof(gsn->gsnu), &gsn->gsnu);
2574 }
2575
Harald Weltebed35df2011-11-02 13:06:18 +01002576 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2577 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002578}
2579
2580/* Handle Error Indication */
2581int gtp_error_ind_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002582 struct sockaddr_in *peer, void *pack, unsigned len)
2583{
2584 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002585
Harald Weltebed35df2011-11-02 13:06:18 +01002586 /* Find the context in question */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002587 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002588 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002589 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2590 "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002591 return EOF;
2592 }
jjako52c24142002-12-16 13:33:51 +00002593
Harald Weltebed35df2011-11-02 13:06:18 +01002594 gsn->err_unknownpdp++; /* TODO: Change counter */
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002595 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2596 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002597
2598 if (gsn->cb_delete_context)
2599 gsn->cb_delete_context(pdp);
2600 pdp_freepdp(pdp);
2601 return 0;
jjako52c24142002-12-16 13:33:51 +00002602}
2603
2604int gtp_gpdu_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002605 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2606{
jjako08d331d2003-10-13 20:33:30 +00002607
Harald Weltebed35df2011-11-02 13:06:18 +01002608 int hlen = GTP1_HEADER_SIZE_SHORT;
jjako52c24142002-12-16 13:33:51 +00002609
Harald Weltebed35df2011-11-02 13:06:18 +01002610 /* Need to include code to verify packet src and dest addresses */
2611 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002612
Harald Weltebed35df2011-11-02 13:06:18 +01002613 if (version == 0) {
2614 if (pdp_getgtp0
2615 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2616 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002617 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2618 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002619 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2620 len);
2621 }
2622 hlen = GTP0_HEADER_SIZE;
2623 } else if (version == 1) {
2624 if (pdp_getgtp1
2625 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2626 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002627 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2628 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002629 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2630 len);
2631 }
jjako08d331d2003-10-13 20:33:30 +00002632
Harald Weltebed35df2011-11-02 13:06:18 +01002633 /* Is this a long or a short header ? */
2634 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2635 hlen = GTP1_HEADER_SIZE_LONG;
2636 else
2637 hlen = GTP1_HEADER_SIZE_SHORT;
2638 } else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002639 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002640 "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002641 }
jjako08d331d2003-10-13 20:33:30 +00002642
Harald Weltebed35df2011-11-02 13:06:18 +01002643 /* If the GPDU was not from the peer GSN tell him to delete context */
2644 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2645 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002646 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2647 "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002648 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2649 }
jjako52c24142002-12-16 13:33:51 +00002650
Harald Weltebed35df2011-11-02 13:06:18 +01002651 /* Callback function */
2652 if (gsn->cb_data_ind != 0)
2653 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2654
2655 return 0;
jjako52c24142002-12-16 13:33:51 +00002656}
2657
jjako52c24142002-12-16 13:33:51 +00002658/* Receives GTP packet and sends off for further processing
2659 * Function will check the validity of the header. If the header
2660 * is not valid the packet is either dropped or a version not
2661 * supported is returned to the peer.
2662 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002663int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002664{
Harald Weltebed35df2011-11-02 13:06:18 +01002665 unsigned char buffer[PACKET_MAX];
2666 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002667 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002668 int status;
2669 struct gtp0_header *pheader;
2670 int version = 0; /* GTP version should be determined from header! */
2671 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002672
Harald Weltebed35df2011-11-02 13:06:18 +01002673 /* TODO: Need strategy of userspace buffering and blocking */
2674 /* Currently read is non-blocking and send is blocking. */
2675 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002676
Harald Weltebed35df2011-11-02 13:06:18 +01002677 while (1) { /* Loop until no more to read */
2678 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002679 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002680 return -1;
2681 }
2682 peerlen = sizeof(peer);
2683 if ((status =
2684 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2685 (struct sockaddr *)&peer, &peerlen)) < 0) {
2686 if (errno == EAGAIN)
2687 return 0;
2688 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002689 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002690 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002691 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2692 status, status ? strerror(errno) : "No error");
2693 return -1;
2694 }
jjako1db1c812003-07-06 20:53:57 +00002695
Harald Weltebed35df2011-11-02 13:06:18 +01002696 /* Need at least 1 byte in order to check version */
2697 if (status < (1)) {
2698 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002699 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2700 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002701 continue;
2702 }
jjako08d331d2003-10-13 20:33:30 +00002703
Harald Weltebed35df2011-11-02 13:06:18 +01002704 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002705
Harald Weltebed35df2011-11-02 13:06:18 +01002706 /* Version should be gtp0 (or earlier) */
2707 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2708 /* GTP 0 messages. If other version message is received we reply that we */
2709 /* only support version 0, implying that this is the only version */
2710 /* supported on this port */
2711 if (((pheader->flags & 0xe0) > 0x00)) {
2712 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002713 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2714 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002715 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2716 continue;
2717 }
2718
2719 /* Check length of gtp0 packet */
2720 if (status < GTP0_HEADER_SIZE) {
2721 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002722 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2723 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002724 continue; /* Silently discard 29.60: 11.1.2 */
2725 }
2726
2727 /* Check packet length field versus length of packet */
2728 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2729 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002730 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002731 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002732 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002733 continue; /* Silently discard */
2734 }
2735
2736 if ((gsn->mode == GTP_MODE_GGSN) &&
2737 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2738 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2739 (pheader->type == GTP_DELETE_PDP_RSP))) {
2740 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002741 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002742 status,
Max28318872017-05-16 17:03:02 +02002743 "Unexpected GTPv0 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002744 continue; /* Silently discard 29.60: 11.1.4 */
2745 }
2746
2747 if ((gsn->mode == GTP_MODE_SGSN) &&
2748 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2749 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2750 (pheader->type == GTP_DELETE_PDP_REQ))) {
2751 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002752 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002753 status,
Max28318872017-05-16 17:03:02 +02002754 "Unexpected GTPv0 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002755 continue; /* Silently discard 29.60: 11.1.4 */
2756 }
2757
2758 switch (pheader->type) {
2759 case GTP_ECHO_REQ:
2760 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2761 break;
2762 case GTP_ECHO_RSP:
2763 gtp_echo_conf(gsn, version, &peer, buffer, status);
2764 break;
2765 case GTP_NOT_SUPPORTED:
2766 gtp_unsup_ind(gsn, &peer, buffer, status);
2767 break;
2768 case GTP_CREATE_PDP_REQ:
2769 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2770 status);
2771 break;
2772 case GTP_CREATE_PDP_RSP:
2773 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2774 status);
2775 break;
2776 case GTP_UPDATE_PDP_REQ:
2777 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2778 status);
2779 break;
2780 case GTP_UPDATE_PDP_RSP:
2781 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2782 status);
2783 break;
2784 case GTP_DELETE_PDP_REQ:
2785 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2786 status);
2787 break;
2788 case GTP_DELETE_PDP_RSP:
2789 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2790 status);
2791 break;
2792 case GTP_ERROR:
2793 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2794 break;
2795 case GTP_GPDU:
2796 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2797 break;
2798 default:
2799 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002800 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2801 "Unknown GTP message type received: %d\n",
2802 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002803 break;
2804 }
2805 }
jjako08d331d2003-10-13 20:33:30 +00002806}
2807
jjako08d331d2003-10-13 20:33:30 +00002808int gtp_decaps1c(struct gsn_t *gsn)
2809{
Harald Weltebed35df2011-11-02 13:06:18 +01002810 unsigned char buffer[PACKET_MAX];
2811 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002812 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002813 int status;
2814 struct gtp1_header_short *pheader;
2815 int version = 1; /* TODO GTP version should be determined from header! */
2816 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002817
Harald Weltebed35df2011-11-02 13:06:18 +01002818 /* TODO: Need strategy of userspace buffering and blocking */
2819 /* Currently read is non-blocking and send is blocking. */
2820 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002821
Harald Weltebed35df2011-11-02 13:06:18 +01002822 while (1) { /* Loop until no more to read */
2823 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002824 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002825 return -1;
2826 }
2827 peerlen = sizeof(peer);
2828 if ((status =
2829 recvfrom(fd, buffer, sizeof(buffer), 0,
2830 (struct sockaddr *)&peer, &peerlen)) < 0) {
2831 if (errno == EAGAIN)
2832 return 0;
2833 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002834 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002835 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002836 fd, (unsigned long)buffer, sizeof(buffer),
2837 status, status ? strerror(errno) : "No error");
2838 return -1;
2839 }
jjako08d331d2003-10-13 20:33:30 +00002840
Harald Weltebed35df2011-11-02 13:06:18 +01002841 /* Need at least 1 byte in order to check version */
2842 if (status < (1)) {
2843 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002844 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2845 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002846 continue;
2847 }
jjako08d331d2003-10-13 20:33:30 +00002848
Harald Weltebed35df2011-11-02 13:06:18 +01002849 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002850
Harald Weltebed35df2011-11-02 13:06:18 +01002851 /* Version must be no larger than GTP 1 */
2852 if (((pheader->flags & 0xe0) > 0x20)) {
2853 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002854 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2855 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002856 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2857 /*29.60: 11.1.1 */
2858 continue;
2859 }
jjako08d331d2003-10-13 20:33:30 +00002860
Harald Weltebed35df2011-11-02 13:06:18 +01002861 /* Version must be at least GTP 1 */
2862 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2863 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2864 /* the message */
2865 if (((pheader->flags & 0xe0) < 0x20)) {
2866 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002867 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2868 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002869 continue;
2870 }
jjako08d331d2003-10-13 20:33:30 +00002871
Harald Weltebed35df2011-11-02 13:06:18 +01002872 /* Check packet flag field */
2873 if (((pheader->flags & 0xf7) != 0x32)) {
2874 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002875 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01002876 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01002877 continue;
2878 }
jjako2c381332003-10-21 19:09:53 +00002879
Harald Weltebed35df2011-11-02 13:06:18 +01002880 /* Check length of packet */
2881 if (status < GTP1_HEADER_SIZE_LONG) {
2882 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002883 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2884 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002885 continue; /* Silently discard 29.60: 11.1.2 */
2886 }
jjako2c381332003-10-21 19:09:53 +00002887
Harald Weltebed35df2011-11-02 13:06:18 +01002888 /* Check packet length field versus length of packet */
2889 if (status !=
2890 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2891 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002892 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002893 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002894 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002895 continue; /* Silently discard */
2896 }
jjako1db1c812003-07-06 20:53:57 +00002897
Harald Weltebed35df2011-11-02 13:06:18 +01002898 /* Check for extension headers */
2899 /* TODO: We really should cycle through the headers and determine */
2900 /* if any have the comprehension required flag set */
2901 if (((pheader->flags & 0x04) != 0x00)) {
2902 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002903 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2904 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002905 gtp_extheader_req(gsn, version, &peer, fd, buffer,
2906 status);
jjako1db1c812003-07-06 20:53:57 +00002907
Harald Weltebed35df2011-11-02 13:06:18 +01002908 continue;
2909 }
2910
2911 if ((gsn->mode == GTP_MODE_GGSN) &&
2912 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2913 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2914 (pheader->type == GTP_DELETE_PDP_RSP))) {
2915 gsn->unexpect++;
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,
Max28318872017-05-16 17:03:02 +02002918 "Unexpected GTPv1 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002919 continue; /* Silently discard 29.60: 11.1.4 */
2920 }
2921
2922 if ((gsn->mode == GTP_MODE_SGSN) &&
2923 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2924 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2925 (pheader->type == GTP_DELETE_PDP_REQ))) {
2926 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002927 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002928 status,
Max28318872017-05-16 17:03:02 +02002929 "Unexpected GTPv1 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002930 continue; /* Silently discard 29.60: 11.1.4 */
2931 }
2932
2933 switch (pheader->type) {
2934 case GTP_ECHO_REQ:
2935 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2936 break;
2937 case GTP_ECHO_RSP:
2938 gtp_echo_conf(gsn, version, &peer, buffer, status);
2939 break;
2940 case GTP_NOT_SUPPORTED:
2941 gtp_unsup_ind(gsn, &peer, buffer, status);
2942 break;
2943 case GTP_SUPP_EXT_HEADER:
2944 gtp_extheader_ind(gsn, &peer, buffer, status);
2945 break;
2946 case GTP_CREATE_PDP_REQ:
2947 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2948 status);
2949 break;
2950 case GTP_CREATE_PDP_RSP:
2951 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2952 status);
2953 break;
2954 case GTP_UPDATE_PDP_REQ:
2955 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2956 status);
2957 break;
2958 case GTP_UPDATE_PDP_RSP:
2959 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2960 status);
2961 break;
2962 case GTP_DELETE_PDP_REQ:
2963 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2964 status);
2965 break;
2966 case GTP_DELETE_PDP_RSP:
2967 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2968 status);
2969 break;
2970 case GTP_ERROR:
2971 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2972 break;
2973 default:
2974 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002975 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2976 "Unknown GTP message type received: %u\n",
2977 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002978 break;
2979 }
2980 }
jjako52c24142002-12-16 13:33:51 +00002981}
2982
jjako08d331d2003-10-13 20:33:30 +00002983int gtp_decaps1u(struct gsn_t *gsn)
2984{
Harald Weltebed35df2011-11-02 13:06:18 +01002985 unsigned char buffer[PACKET_MAX];
2986 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002987 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002988 int status;
2989 struct gtp1_header_short *pheader;
2990 int version = 1; /* GTP version should be determined from header! */
2991 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00002992
Harald Weltebed35df2011-11-02 13:06:18 +01002993 /* TODO: Need strategy of userspace buffering and blocking */
2994 /* Currently read is non-blocking and send is blocking. */
2995 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002996
Harald Weltebed35df2011-11-02 13:06:18 +01002997 while (1) { /* Loop until no more to read */
2998 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002999 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003000 return -1;
3001 }
3002 peerlen = sizeof(peer);
3003 if ((status =
3004 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3005 (struct sockaddr *)&peer, &peerlen)) < 0) {
3006 if (errno == EAGAIN)
3007 return 0;
3008 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003009 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003010 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003011 gsn->fd1u, (unsigned long)buffer,
3012 sizeof(buffer), status,
3013 status ? strerror(errno) : "No error");
3014 return -1;
3015 }
jjako08d331d2003-10-13 20:33:30 +00003016
Harald Weltebed35df2011-11-02 13:06:18 +01003017 /* Need at least 1 byte in order to check version */
3018 if (status < (1)) {
3019 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003020 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3021 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003022 continue;
3023 }
jjako08d331d2003-10-13 20:33:30 +00003024
Harald Weltebed35df2011-11-02 13:06:18 +01003025 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003026
Harald Weltebed35df2011-11-02 13:06:18 +01003027 /* Version must be no larger than GTP 1 */
3028 if (((pheader->flags & 0xe0) > 0x20)) {
3029 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003030 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3031 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003032 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3033 continue;
3034 }
jjako08d331d2003-10-13 20:33:30 +00003035
Harald Weltebed35df2011-11-02 13:06:18 +01003036 /* Version must be at least GTP 1 */
3037 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3038 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3039 /* the message */
3040 if (((pheader->flags & 0xe0) < 0x20)) {
3041 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003042 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3043 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003044 continue;
3045 }
jjako2c381332003-10-21 19:09:53 +00003046
Harald Weltebed35df2011-11-02 13:06:18 +01003047 /* Check packet flag field (allow both with and without sequence number) */
3048 if (((pheader->flags & 0xf5) != 0x30)) {
3049 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003050 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003051 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003052 continue;
3053 }
jjako2c381332003-10-21 19:09:53 +00003054
Harald Weltebed35df2011-11-02 13:06:18 +01003055 /* Check length of packet */
3056 if (status < GTP1_HEADER_SIZE_SHORT) {
3057 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003058 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3059 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003060 continue; /* Silently discard 29.60: 11.1.2 */
3061 }
3062
3063 /* Check packet length field versus length of packet */
3064 if (status !=
3065 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3066 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003067 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003068 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003069 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003070 continue; /* Silently discard */
3071 }
3072
3073 /* Check for extension headers */
3074 /* TODO: We really should cycle through the headers and determine */
3075 /* if any have the comprehension required flag set */
3076 if (((pheader->flags & 0x04) != 0x00)) {
3077 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003078 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3079 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003080 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3081 status);
3082
3083 continue;
3084 }
3085
3086 switch (pheader->type) {
3087 case GTP_ECHO_REQ:
3088 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3089 break;
3090 case GTP_ECHO_RSP:
3091 gtp_echo_conf(gsn, version, &peer, buffer, status);
3092 break;
3093 case GTP_SUPP_EXT_HEADER:
3094 gtp_extheader_ind(gsn, &peer, buffer, status);
3095 break;
3096 case GTP_ERROR:
3097 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3098 break;
3099 /* Supported header extensions */
3100 case GTP_GPDU:
3101 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3102 break;
3103 default:
3104 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003105 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3106 "Unknown GTP message type received: %u\n",
3107 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003108 break;
3109 }
3110 }
jjako08d331d2003-10-13 20:33:30 +00003111}
3112
Harald Weltebed35df2011-11-02 13:06:18 +01003113int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003114{
Harald Weltebed35df2011-11-02 13:06:18 +01003115 union gtp_packet packet;
3116 struct sockaddr_in addr;
3117 int fd;
3118 int length;
jjako52c24142002-12-16 13:33:51 +00003119
Harald Weltebed35df2011-11-02 13:06:18 +01003120 memset(&addr, 0, sizeof(addr));
3121 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003122#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003123 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003124#endif
3125
Harald Weltebed35df2011-11-02 13:06:18 +01003126 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003127
Harald Weltebed35df2011-11-02 13:06:18 +01003128 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003129
Harald Weltebed35df2011-11-02 13:06:18 +01003130 length = GTP0_HEADER_SIZE + len;
3131 addr.sin_port = htons(GTP0_PORT);
3132 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003133
Harald Weltebed35df2011-11-02 13:06:18 +01003134 get_default_gtp(0, GTP_GPDU, &packet);
3135 packet.gtp0.h.length = hton16(len);
3136 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3137 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003138 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
jjako08d331d2003-10-13 20:33:30 +00003139
Harald Weltebed35df2011-11-02 13:06:18 +01003140 if (len > sizeof(union gtp_packet) - sizeof(struct gtp0_header)) {
3141 gsn->err_memcpy++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003142 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003143 "Memcpy failed: %u > %zu\n", len,
Harald Weltebed35df2011-11-02 13:06:18 +01003144 sizeof(union gtp_packet) -
3145 sizeof(struct gtp0_header));
3146 return EOF;
3147 }
3148 memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
3149 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003150
Harald Weltebed35df2011-11-02 13:06:18 +01003151 length = GTP1_HEADER_SIZE_LONG + len;
3152 addr.sin_port = htons(GTP1U_PORT);
3153 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003154
Harald Weltebed35df2011-11-02 13:06:18 +01003155 get_default_gtp(1, GTP_GPDU, &packet);
3156 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3157 GTP1_HEADER_SIZE_LONG);
3158 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3159 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3160
3161 if (len >
3162 sizeof(union gtp_packet) -
3163 sizeof(struct gtp1_header_long)) {
3164 gsn->err_memcpy++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003165 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003166 "Memcpy failed: %u > %zu\n", len,
Harald Weltebed35df2011-11-02 13:06:18 +01003167 sizeof(union gtp_packet) -
3168 sizeof(struct gtp0_header));
3169 return EOF;
3170 }
3171 memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
3172 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003173 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003174 return EOF;
3175 }
3176
3177 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003178 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003179 return -1;
3180 }
3181
3182 if (sendto(fd, &packet, length, 0,
3183 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
3184 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003185 LOGP(DLGTP, LOGL_ERROR,
3186 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003187 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3188 strerror(errno));
3189 return EOF;
3190 }
3191 return 0;
jjako52c24142002-12-16 13:33:51 +00003192}
3193
jjako52c24142002-12-16 13:33:51 +00003194/* ***********************************************************
3195 * Conversion functions
3196 *************************************************************/
3197
Harald Weltebed35df2011-11-02 13:06:18 +01003198int char2ul_t(char *src, struct ul_t dst)
3199{
3200 dst.l = strlen(src) + 1;
3201 dst.v = malloc(dst.l);
3202 dst.v[0] = dst.l - 1;
3203 memcpy(&dst.v[1], src, dst.v[0]);
3204 return 0;
jjako52c24142002-12-16 13:33:51 +00003205}
3206
3207/* ***********************************************************
3208 * IP address conversion functions
3209 * There exist several types of address representations:
3210 * - eua: End User Address. (29.060, 7.7.27, message type 128)
3211 * Used for signalling address to mobile station. Supports IPv4
3212 * IPv6 x.25 etc. etc.
3213 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3214 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3215 * - in_addr: IPv4 address struct.
3216 * - sockaddr_in: Socket API representation of IP address and
3217 * port number.
3218 *************************************************************/
3219
Harald Weltebed35df2011-11-02 13:06:18 +01003220int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3221{
3222 eua->v[0] = 0xf1; /* IETF */
3223 eua->v[1] = 0x21; /* IPv4 */
3224 if (src) {
3225 eua->l = 6;
3226 memcpy(&eua->v[2], src, 4);
3227 } else {
3228 eua->l = 2;
3229 }
3230 return 0;
jjako52c24142002-12-16 13:33:51 +00003231}
3232
Harald Weltebed35df2011-11-02 13:06:18 +01003233int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3234{
3235 if ((eua->l != 6) || (eua->v[0] != 0xf1) || (eua->v[1] = 0x21))
3236 return -1; /* Not IPv4 address */
3237 memcpy(dst, &eua->v[2], 4);
3238 return 0;
jjako52c24142002-12-16 13:33:51 +00003239}
3240
Harald Weltebed35df2011-11-02 13:06:18 +01003241int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3242{
3243 memset(dst, 0, sizeof(struct in_addr));
3244 if (gsna->l != 4)
3245 return EOF; /* Return if not IPv4 */
3246 memcpy(dst, gsna->v, gsna->l);
3247 return 0;
jjako52c24142002-12-16 13:33:51 +00003248}
3249
Harald Weltebed35df2011-11-02 13:06:18 +01003250int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3251{
3252 memset(gsna, 0, sizeof(struct ul16_t));
3253 gsna->l = 4;
3254 memcpy(gsna->v, src, gsna->l);
3255 return 0;
jjako52c24142002-12-16 13:33:51 +00003256}
Harald Welteb10ee082017-08-12 19:29:16 +02003257
3258/* TS 29.060 has yet again a different encoding for IMSIs than
3259 * what we have in other places, so we cannot use the gsm48
3260 * decoding functions. Also, libgtp uses an uint64_t in
3261 * _network byte order_ to contain BCD digits ?!? */
3262const char *imsi_gtp2str(const uint64_t *imsi)
3263{
3264 static char buf[sizeof(*imsi)+1];
3265 const uint8_t *imsi8 = (const uint8_t *) imsi;
3266 unsigned int i, j = 0;
3267
3268 for (i = 0; i < sizeof(*imsi); i++) {
3269 uint8_t nibble;
3270
3271 nibble = imsi8[i] & 0xf;
3272 if (nibble == 0xf)
3273 break;
3274 buf[j++] = osmo_bcd2char(nibble);
3275
3276 nibble = imsi8[i] >> 4;
3277 if (nibble == 0xf)
3278 break;
3279 buf[j++] = osmo_bcd2char(nibble);
3280 }
3281
3282 buf[j++] = '\0';
3283 return buf;
3284}