blob: a3772ff50764cc20a6588ad87f51f5f145f56738 [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 {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100213 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flag: %u\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100214 return 0;
215 }
jjako08d331d2003-10-13 20:33:30 +0000216}
217
218/**
219 * get_tid()
220 * Get tunnel identifier of a packet.
221 * Returns 0 on error
222 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100223static uint64_t get_tid(void *pack)
224{
225 union gtp_packet *packet = (union gtp_packet *)pack;
226
227 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100228 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100229 }
230 return 0;
jjako08d331d2003-10-13 20:33:30 +0000231}
232
233/**
234 * get_hlen()
235 * Get the header length of a packet.
236 * Returns 0 on error
237 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100238static uint16_t get_hlen(void *pack)
239{
240 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000241
Harald Weltebed35df2011-11-02 13:06:18 +0100242 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
243 return GTP0_HEADER_SIZE;
244 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
245 return GTP1_HEADER_SIZE_LONG;
246 } else if ((packet->flags & 0xe7) == 0x20) { /* Short version 1 */
247 return GTP1_HEADER_SIZE_SHORT;
248 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100249 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flag: %u\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100250 return 0;
251 }
jjako08d331d2003-10-13 20:33:30 +0000252}
253
254/**
255 * get_tei()
256 * Get the tunnel endpoint identifier (flow label) of a packet.
257 * Returns 0xffffffff on error.
258 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100259static uint32_t get_tei(void *pack)
260{
261 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000262
Harald Weltebed35df2011-11-02 13:06:18 +0100263 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
264 return ntoh16(packet->gtp0.h.flow);
265 } else if ((packet->flags & 0xe0) == 0x20) { /* Version 1 */
266 return ntoh32(packet->gtp1l.h.tei);
267 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100268 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flag: %u\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100269 return 0xffffffff;
270 }
jjako08d331d2003-10-13 20:33:30 +0000271}
jjakoa7cd2492003-04-11 09:40:12 +0000272
jjako52c24142002-12-16 13:33:51 +0000273/* ***********************************************************
274 * Reliable delivery of signalling messages
275 *
276 * Sequence numbers are used for both signalling messages and
277 * data messages.
278 *
279 * For data messages each tunnel maintains a sequence counter,
280 * which is incremented by one each time a new data message
281 * is sent. The sequence number starts at (0) zero at tunnel
282 * establishment, and wraps around at 65535 (29.060 9.3.1.1
283 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
284 * or can be used to check the validity of the message in the
285 * receiver, or for reordering af packets.
286 *
287 * For signalling messages the sequence number is used by
288 * signalling messages for which a response is defined. A response
289 * message should copy the sequence from the corresponding request
290 * message. The sequence number "unambiguously" identifies a request
291 * message within a given path, with a path being defined as a set of
292 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
293 * messages shall be responded to, and all response messages associated
294 * with a certain request shall always include the same information"
295 *
296 * We take this to mean that the GSN transmitting a request is free to
297 * choose the sequence number, as long as it is unique within a given path.
298 * It means that we are allowed to count backwards, or roll over at 17
299 * if we prefer that. It also means that we can use the same counter for
300 * all paths. This has the advantage that the transmitted request sequence
301 * numbers are unique within each GSN, and also we dont have to mess around
302 * with path setup and teardown.
303 *
304 * If a response message is lost, the request will be retransmitted, and
305 * the receiving GSN will receive a "duplicated" request. The standard
306 * requires the receiving GSN to send a response, with the same information
307 * as in the original response. For most messages this happens automatically:
308 *
309 * Echo: Automatically dublicates the original response
310 * Create pdp context: The SGSN may send create context request even if
311 * a context allready exist (imsi+nsapi?). This means that the reply will
312 automatically dublicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000313 * side effects in the application which is asked twice to validate
314 * the login.
jjako52c24142002-12-16 13:33:51 +0000315 * Update pdp context: Automatically dublicates the original response???
316 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
317 * a nonexist reply message.
318 *
319 * The correct solution will be to make a queue containing response messages.
320 * This queue should be checked whenever a request is received. If the
321 * response is allready in the queue that response should be transmitted.
322 * It should be possible to find messages in this queue on the basis of
323 * the sequence number and peer GSN IP address (The sequense number is unique
324 * within each path). This need to be implemented by a hash table. Furthermore
325 * it should be possibly to delete messages based on a timeout. This can be
326 * achieved by means of a linked list. The timeout value need to be larger
327 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
328 * set in the peer GSN, so there is no way to know these parameters. On the
329 * other hand the timeout value need to be so small that we do not receive
330 * wraparound sequence numbere before the message is deleted. 60 seconds is
331 * probably not a bad choise.
332 *
333 * This queue however is first really needed from gtp1.
334 *
335 * gtp_req:
336 * Send off a signalling message with appropiate sequence
337 * number. Store packet in queue.
338 * gtp_conf:
339 * Remove an incoming confirmation from the queue
340 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000341 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000342 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000343 * gtp_notification:
344 * Send off a notification message. This is neither a request nor
345 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000346 * gtp_retrans:
347 * Retransmit any outstanding packets which have exceeded
348 * a predefined timeout.
349 *************************************************************/
350
jjako08d331d2003-10-13 20:33:30 +0000351int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100352 union gtp_packet *packet, int len,
353 struct in_addr *inetaddr, void *cbp)
354{
355 struct sockaddr_in addr;
356 struct qmsg_t *qmsg;
357 int fd;
jjako08d331d2003-10-13 20:33:30 +0000358
Harald Weltebed35df2011-11-02 13:06:18 +0100359 memset(&addr, 0, sizeof(addr));
360 addr.sin_family = AF_INET;
361 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000362#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100363 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000364#endif
jjako52c24142002-12-16 13:33:51 +0000365
Harald Weltebed35df2011-11-02 13:06:18 +0100366 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
367 addr.sin_port = htons(GTP0_PORT);
368 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
369 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100370 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100371 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100372 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100373 }
Harald Weltebed35df2011-11-02 13:06:18 +0100374 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
375 || (packet->gtp0.h.type == GTP_ERROR)))
376 packet->gtp0.h.flow = hton16(pdp->flru);
377 else if (pdp)
378 packet->gtp0.h.flow = hton16(pdp->flrc);
379 fd = gsn->fd0;
380 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
381 addr.sin_port = htons(GTP1C_PORT);
382 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
383 packet->gtp1l.h.seq = hton16(gsn->seq_next);
384 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
385 (packet->gtp1l.h.type == GTP_ERROR)))
386 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
387 else if (pdp)
388 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
389 fd = gsn->fd1c;
390 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100391 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flag: %u\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100392 return -1;
393 }
jjako52c24142002-12-16 13:33:51 +0000394
Harald Weltebed35df2011-11-02 13:06:18 +0100395 if (sendto(fd, packet, len, 0,
396 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
397 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100398 LOGP(DLGTP, LOGL_ERROR,
399 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100400 (unsigned long)&packet, len, strerror(errno));
401 return -1;
402 }
403
404 /* Use new queue structure */
405 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
406 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100407 LOGP(DLGTP, LOGL_ERROR,
408 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100409 } else {
410 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
411 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100412 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100413 qmsg->retrans = 0; /* No retransmissions so far */
414 qmsg->cbp = cbp;
415 qmsg->type = ntoh8(packet->gtp0.h.type);
416 qmsg->fd = fd;
417 }
418 gsn->seq_next++; /* Count up this time */
419 return 0;
jjako52c24142002-12-16 13:33:51 +0000420}
421
422/* gtp_conf
423 * Remove signalling packet from retransmission queue.
424 * return 0 on success, EOF if packet was not found */
425
426int gtp_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100427 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
428{
jjako52c24142002-12-16 13:33:51 +0000429
Harald Weltebed35df2011-11-02 13:06:18 +0100430 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000431
Harald Weltebed35df2011-11-02 13:06:18 +0100432 if ((packet->gtp0.h.flags & 0xe0) == 0x00)
433 seq = ntoh16(packet->gtp0.h.seq);
434 else if ((packet->gtp1l.h.flags & 0xe2) == 0x22)
435 seq = ntoh16(packet->gtp1l.h.seq);
436 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100437 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
438 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100439 return EOF;
440 }
jjako08d331d2003-10-13 20:33:30 +0000441
Harald Weltebed35df2011-11-02 13:06:18 +0100442 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
443 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100444 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
445 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100446 return EOF;
447 }
jjako52c24142002-12-16 13:33:51 +0000448
Harald Weltebed35df2011-11-02 13:06:18 +0100449 return 0;
jjako52c24142002-12-16 13:33:51 +0000450}
451
Harald Weltebed35df2011-11-02 13:06:18 +0100452int gtp_retrans(struct gsn_t *gsn)
453{
454 /* Retransmit any outstanding packets */
455 /* Remove from queue if maxretrans exceeded */
456 time_t now;
457 struct qmsg_t *qmsg;
458 now = time(NULL);
459 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000460
Harald Welte95848ba2011-11-02 18:17:50 +0100461 /* get first element in queue, as long as the timeout of that
462 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100463 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
464 (qmsg->timeout <= now)) {
465 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100466 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100467 if (gsn->cb_conf)
468 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
469 queue_freemsg(gsn->queue_req, qmsg);
470 } else {
471 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
472 (struct sockaddr *)&qmsg->peer,
473 sizeof(struct sockaddr_in)) < 0) {
474 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100475 LOGP(DLGTP, LOGL_ERROR,
476 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100477 gsn->fd0, (unsigned long)&qmsg->p,
478 qmsg->l, strerror(errno));
479 }
480 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100481 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100482 qmsg->retrans++;
483 }
484 }
jjako52c24142002-12-16 13:33:51 +0000485
Harald Weltebed35df2011-11-02 13:06:18 +0100486 /* Also clean up reply timeouts */
487 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
488 (qmsg->timeout < now)) {
489 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
490 queue_freemsg(gsn->queue_resp, qmsg);
491 }
jjako52c24142002-12-16 13:33:51 +0000492
Harald Weltebed35df2011-11-02 13:06:18 +0100493 return 0;
jjako52c24142002-12-16 13:33:51 +0000494}
495
Harald Weltebed35df2011-11-02 13:06:18 +0100496int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
497{
498 time_t now, later;
499 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000500
Harald Weltebed35df2011-11-02 13:06:18 +0100501 if (queue_getfirst(gsn->queue_req, &qmsg)) {
502 timeout->tv_sec = 10;
503 timeout->tv_usec = 0;
504 } else {
505 now = time(NULL);
506 later = qmsg->timeout;
507 timeout->tv_sec = later - now;
508 timeout->tv_usec = 0;
509 if (timeout->tv_sec < 0)
510 timeout->tv_sec = 0; /* No negative allowed */
511 if (timeout->tv_sec > 10)
512 timeout->tv_sec = 10; /* Max sleep for 10 sec */
513 }
514 return 0;
jjako52c24142002-12-16 13:33:51 +0000515}
516
Harald Weltebed35df2011-11-02 13:06:18 +0100517int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000518 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100519 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
520{
521 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000522
Harald Weltebed35df2011-11-02 13:06:18 +0100523 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
524 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
525 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100526 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100527 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
528 (packet->gtp0.h.type == GTP_ERROR)))
529 packet->gtp0.h.flow = hton16(pdp->flru);
530 else if (pdp)
531 packet->gtp0.h.flow = hton16(pdp->flrc);
532 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
533 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
534 packet->gtp1l.h.seq = hton16(seq);
535 if (pdp && (fd == gsn->fd1u))
536 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
537 else if (pdp)
538 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
539 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100540 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flag: %u\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100541 return -1;
542 }
jjako08d331d2003-10-13 20:33:30 +0000543
Harald Weltebed35df2011-11-02 13:06:18 +0100544 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100545 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100546 return -1;
547 }
jjako52c24142002-12-16 13:33:51 +0000548
Harald Weltebed35df2011-11-02 13:06:18 +0100549 if (sendto(fd, packet, len, 0,
550 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
551 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100552 LOGP(DLGTP, LOGL_ERROR,
553 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100554 (unsigned long)&packet, len, strerror(errno));
555 return -1;
556 }
557
558 /* Use new queue structure */
559 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
560 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100561 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100562 } else {
563 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
564 qmsg->l = len;
565 qmsg->timeout = time(NULL) + 60; /* When to timeout */
566 qmsg->retrans = 0; /* No retransmissions so far */
567 qmsg->cbp = NULL;
568 qmsg->type = 0;
569 qmsg->fd = fd;
570 }
571 return 0;
jjako52c24142002-12-16 13:33:51 +0000572}
573
jjako2c381332003-10-21 19:09:53 +0000574int gtp_notification(struct gsn_t *gsn, int version,
575 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100576 struct sockaddr_in *peer, int fd, uint16_t seq)
577{
jjako2c381332003-10-21 19:09:53 +0000578
Harald Weltebed35df2011-11-02 13:06:18 +0100579 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000580
Harald Weltebed35df2011-11-02 13:06:18 +0100581 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000582
Harald Weltebed35df2011-11-02 13:06:18 +0100583 /* In GTP0 notifications are treated as replies. In GTP1 they
584 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000585
Harald Weltebed35df2011-11-02 13:06:18 +0100586 if (fd == gsn->fd1c)
587 addr.sin_port = htons(GTP1C_PORT);
588 else if (fd == gsn->fd1u)
589 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000590
Harald Weltebed35df2011-11-02 13:06:18 +0100591 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
592 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
593 packet->gtp0.h.seq = hton16(seq);
594 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
595 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
596 packet->gtp1l.h.seq = hton16(seq);
597 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100598 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flag: %u\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100599 return -1;
600 }
601
602 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100603 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100604 return -1;
605 }
606
607 if (sendto(fd, packet, len, 0,
608 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
609 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100610 LOGP(DLGTP, LOGL_ERROR,
611 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100612 (unsigned long)&packet, len, strerror(errno));
613 return -1;
614 }
615 return 0;
jjako2c381332003-10-21 19:09:53 +0000616}
617
Harald Weltebed35df2011-11-02 13:06:18 +0100618int gtp_dublicate(struct gsn_t *gsn, int version,
619 struct sockaddr_in *peer, uint16_t seq)
620{
621 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000622
Harald Weltebed35df2011-11-02 13:06:18 +0100623 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
624 return EOF; /* Notfound */
625 }
jjakoa7cd2492003-04-11 09:40:12 +0000626
Harald Weltebed35df2011-11-02 13:06:18 +0100627 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100628 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100629 return -1;
630 }
631
632 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
633 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
634 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100635 LOGP(DLGTP, LOGL_ERROR,
636 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100637 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
638 strerror(errno));
639 }
640 return 0;
jjako52c24142002-12-16 13:33:51 +0000641}
642
jjako52c24142002-12-16 13:33:51 +0000643/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100644static void log_restart(struct gsn_t *gsn)
645{
jjako52c24142002-12-16 13:33:51 +0000646 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200647 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000648 int counter = 0;
649 char filename[NAMESIZE];
650
Harald Weltebed35df2011-11-02 13:06:18 +0100651 filename[NAMESIZE - 1] = 0; /* No null term. guarantee by strncpy */
652 strncpy(filename, gsn->statedir, NAMESIZE - 1);
653 strncat(filename, RESTART_FILE, NAMESIZE - 1 - sizeof(RESTART_FILE));
jjako52c24142002-12-16 13:33:51 +0000654
655 i = umask(022);
656
657 /* We try to open file. On failure we will later try to create file */
658 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100659 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100660 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100661 filename);
662 } else {
663 umask(i);
664 rc = fscanf(f, "%d", &counter);
665 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100666 LOGP(DLGTP, LOGL_ERROR,
667 "fscanf failed to read counter value\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100668 return;
669 }
670 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100671 LOGP(DLGTP, LOGL_ERROR,
672 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100673 }
jjako52c24142002-12-16 13:33:51 +0000674 }
Harald Weltebed35df2011-11-02 13:06:18 +0100675
676 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000677 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100678
jjako52c24142002-12-16 13:33:51 +0000679 if (!(f = fopen(filename, "w"))) {
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));
683 return;
jjako52c24142002-12-16 13:33:51 +0000684 }
685
686 umask(i);
687 fprintf(f, "%d\n", gsn->restart_counter);
688 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));
Harald Weltebed35df2011-11-02 13:06:18 +0100691 return;
jjako52c24142002-12-16 13:33:51 +0000692 }
693}
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,
733 "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));
735 return -1;
736 }
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));
Harald Weltebed35df2011-11-02 13:06:18 +0100751 return -1;
752 }
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,
758 "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));
760 return -1;
761 }
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));
Harald Weltebed35df2011-11-02 13:06:18 +0100776 return -1;
777 }
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,
783 "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));
785 return -1;
786 }
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));
Harald Weltebed35df2011-11-02 13:06:18 +0100801 return -1;
802 }
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
1874 gtp_req(gsn, pdp->version, NULL, &packet, length, inetaddr, cbp);
1875
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;
jjako52c24142002-12-16 13:33:51 +00002178
Harald Weltebed35df2011-11-02 13:06:18 +01002179 /* Remove packet from queue */
2180 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2181 return EOF;
jjako52c24142002-12-16 13:33:51 +00002182
Neels Hofmeyr0dc47482015-10-12 14:29:01 +02002183 /* TODO This function is called from gtp_decaps1c() (for GTP v1) but
2184 * uses gtp0.h.flow (GTP v0 data element)
2185 */
Harald Weltebed35df2011-11-02 13:06:18 +01002186 /* Find the context in question */
2187 if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2188 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002189 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2190 "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002191 if (gsn->cb_conf)
2192 gsn->cb_conf(type, cause, NULL, cbp);
2193 return EOF;
2194 }
jjako2c381332003-10-21 19:09:53 +00002195
Harald Weltebed35df2011-11-02 13:06:18 +01002196 /* Register that we have received a valid teic from GGSN */
2197 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002198
Neels Hofmeyr0dc47482015-10-12 14:29:01 +02002199 /* TODO This function is called from gtp_decaps1c() (for GTP v1) but
2200 * explicitly passes version 0 and GTP0_HEADER_SIZE to gtpie_decaps()
2201 */
Harald Weltebed35df2011-11-02 13:06:18 +01002202 /* Decode information elements */
2203 if (gtpie_decaps
2204 (ie, 0, pack + GTP0_HEADER_SIZE, len - GTP0_HEADER_SIZE)) {
2205 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002206 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2207 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002208 if (gsn->cb_conf)
2209 gsn->cb_conf(type, EOF, pdp, cbp);
2210 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2211 pdp_freepdp(pdp); */
2212 return EOF;
2213 }
jjako52c24142002-12-16 13:33:51 +00002214
Harald Weltebed35df2011-11-02 13:06:18 +01002215 /* Extract cause value (mandatory) */
2216 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2217 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002218 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2219 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002220 if (gsn->cb_conf)
2221 gsn->cb_conf(type, EOF, pdp, cbp);
2222 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2223 pdp_freepdp(pdp); */
2224 return EOF;
2225 }
jjako52c24142002-12-16 13:33:51 +00002226
Harald Weltebed35df2011-11-02 13:06:18 +01002227 /* Extract recovery (optional) */
2228 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2229 if (gsn->cb_recovery)
2230 gsn->cb_recovery(peer, recovery);
2231 }
2232
2233 /* Check all conditional information elements */
2234 if (GTPCAUSE_ACC_REQ != cause) {
2235 if (gsn->cb_conf)
2236 gsn->cb_conf(type, cause, pdp, cbp);
2237 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2238 pdp_freepdp(pdp); */
2239 return 0;
2240 } else {
2241 /* Check for missing conditionary information elements */
2242 if (!(gtpie_exist(ie, GTPIE_QOS_PROFILE0, 0) &&
2243 gtpie_exist(ie, GTPIE_REORDER, 0) &&
2244 gtpie_exist(ie, GTPIE_FL_DI, 0) &&
2245 gtpie_exist(ie, GTPIE_FL_C, 0) &&
2246 gtpie_exist(ie, GTPIE_CHARGING_ID, 0) &&
2247 gtpie_exist(ie, GTPIE_EUA, 0) &&
2248 gtpie_exist(ie, GTPIE_GSN_ADDR, 0) &&
2249 gtpie_exist(ie, GTPIE_GSN_ADDR, 1))) {
2250 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002251 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01002252 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002253 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002254 if (gsn->cb_conf)
2255 gsn->cb_conf(type, EOF, pdp, cbp);
2256 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2257 pdp_freepdp(pdp); */
2258 return EOF;
2259 }
2260
2261 /* Update pdp with new values */
2262 gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2263 pdp->qos_neg0, sizeof(pdp->qos_neg0));
2264 gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder);
2265 gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru);
2266 gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc);
2267 gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid);
2268 gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2269 &pdp->eua.v, sizeof(pdp->eua.v));
2270 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2271 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v));
2272 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2273 &pdp->gsnru.v, sizeof(pdp->gsnru.v));
2274
2275 if (gsn->cb_conf)
2276 gsn->cb_conf(type, cause, pdp, cbp);
2277 return 0; /* Succes */
2278 }
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
2558/* Send Error Indication (response to a GPDU message */
2559int 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
2566 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2567 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002568}
2569
2570/* Handle Error Indication */
2571int gtp_error_ind_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002572 struct sockaddr_in *peer, void *pack, unsigned len)
2573{
2574 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002575
Harald Weltebed35df2011-11-02 13:06:18 +01002576 /* Find the context in question */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002577 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002578 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002579 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2580 "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002581 return EOF;
2582 }
jjako52c24142002-12-16 13:33:51 +00002583
Harald Weltebed35df2011-11-02 13:06:18 +01002584 gsn->err_unknownpdp++; /* TODO: Change counter */
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002585 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2586 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002587
2588 if (gsn->cb_delete_context)
2589 gsn->cb_delete_context(pdp);
2590 pdp_freepdp(pdp);
2591 return 0;
jjako52c24142002-12-16 13:33:51 +00002592}
2593
2594int gtp_gpdu_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002595 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2596{
jjako08d331d2003-10-13 20:33:30 +00002597
Harald Weltebed35df2011-11-02 13:06:18 +01002598 int hlen = GTP1_HEADER_SIZE_SHORT;
jjako52c24142002-12-16 13:33:51 +00002599
Harald Weltebed35df2011-11-02 13:06:18 +01002600 /* Need to include code to verify packet src and dest addresses */
2601 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002602
Harald Weltebed35df2011-11-02 13:06:18 +01002603 if (version == 0) {
2604 if (pdp_getgtp0
2605 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2606 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002607 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2608 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002609 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2610 len);
2611 }
2612 hlen = GTP0_HEADER_SIZE;
2613 } else if (version == 1) {
2614 if (pdp_getgtp1
2615 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
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 }
jjako08d331d2003-10-13 20:33:30 +00002622
Harald Weltebed35df2011-11-02 13:06:18 +01002623 /* Is this a long or a short header ? */
2624 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2625 hlen = GTP1_HEADER_SIZE_LONG;
2626 else
2627 hlen = GTP1_HEADER_SIZE_SHORT;
2628 } else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002629 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002630 "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002631 }
jjako08d331d2003-10-13 20:33:30 +00002632
Harald Weltebed35df2011-11-02 13:06:18 +01002633 /* If the GPDU was not from the peer GSN tell him to delete context */
2634 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2635 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002636 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2637 "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002638 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2639 }
jjako52c24142002-12-16 13:33:51 +00002640
Harald Weltebed35df2011-11-02 13:06:18 +01002641 /* Callback function */
2642 if (gsn->cb_data_ind != 0)
2643 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2644
2645 return 0;
jjako52c24142002-12-16 13:33:51 +00002646}
2647
jjako52c24142002-12-16 13:33:51 +00002648/* Receives GTP packet and sends off for further processing
2649 * Function will check the validity of the header. If the header
2650 * is not valid the packet is either dropped or a version not
2651 * supported is returned to the peer.
2652 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002653int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002654{
Harald Weltebed35df2011-11-02 13:06:18 +01002655 unsigned char buffer[PACKET_MAX];
2656 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002657 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002658 int status;
2659 struct gtp0_header *pheader;
2660 int version = 0; /* GTP version should be determined from header! */
2661 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002662
Harald Weltebed35df2011-11-02 13:06:18 +01002663 /* TODO: Need strategy of userspace buffering and blocking */
2664 /* Currently read is non-blocking and send is blocking. */
2665 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002666
Harald Weltebed35df2011-11-02 13:06:18 +01002667 while (1) { /* Loop until no more to read */
2668 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002669 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002670 return -1;
2671 }
2672 peerlen = sizeof(peer);
2673 if ((status =
2674 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2675 (struct sockaddr *)&peer, &peerlen)) < 0) {
2676 if (errno == EAGAIN)
2677 return 0;
2678 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002679 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002680 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002681 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2682 status, status ? strerror(errno) : "No error");
2683 return -1;
2684 }
jjako1db1c812003-07-06 20:53:57 +00002685
Harald Weltebed35df2011-11-02 13:06:18 +01002686 /* Need at least 1 byte in order to check version */
2687 if (status < (1)) {
2688 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002689 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2690 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002691 continue;
2692 }
jjako08d331d2003-10-13 20:33:30 +00002693
Harald Weltebed35df2011-11-02 13:06:18 +01002694 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002695
Harald Weltebed35df2011-11-02 13:06:18 +01002696 /* Version should be gtp0 (or earlier) */
2697 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2698 /* GTP 0 messages. If other version message is received we reply that we */
2699 /* only support version 0, implying that this is the only version */
2700 /* supported on this port */
2701 if (((pheader->flags & 0xe0) > 0x00)) {
2702 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002703 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2704 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002705 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2706 continue;
2707 }
2708
2709 /* Check length of gtp0 packet */
2710 if (status < GTP0_HEADER_SIZE) {
2711 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002712 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2713 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002714 continue; /* Silently discard 29.60: 11.1.2 */
2715 }
2716
2717 /* Check packet length field versus length of packet */
2718 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2719 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002720 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002721 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002722 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002723 continue; /* Silently discard */
2724 }
2725
2726 if ((gsn->mode == GTP_MODE_GGSN) &&
2727 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2728 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2729 (pheader->type == GTP_DELETE_PDP_RSP))) {
2730 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002731 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002732 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002733 "Unexpected GTP Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002734 continue; /* Silently discard 29.60: 11.1.4 */
2735 }
2736
2737 if ((gsn->mode == GTP_MODE_SGSN) &&
2738 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2739 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2740 (pheader->type == GTP_DELETE_PDP_REQ))) {
2741 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002742 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002743 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002744 "Unexpected GTP Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002745 continue; /* Silently discard 29.60: 11.1.4 */
2746 }
2747
2748 switch (pheader->type) {
2749 case GTP_ECHO_REQ:
2750 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2751 break;
2752 case GTP_ECHO_RSP:
2753 gtp_echo_conf(gsn, version, &peer, buffer, status);
2754 break;
2755 case GTP_NOT_SUPPORTED:
2756 gtp_unsup_ind(gsn, &peer, buffer, status);
2757 break;
2758 case GTP_CREATE_PDP_REQ:
2759 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2760 status);
2761 break;
2762 case GTP_CREATE_PDP_RSP:
2763 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2764 status);
2765 break;
2766 case GTP_UPDATE_PDP_REQ:
2767 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2768 status);
2769 break;
2770 case GTP_UPDATE_PDP_RSP:
2771 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2772 status);
2773 break;
2774 case GTP_DELETE_PDP_REQ:
2775 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2776 status);
2777 break;
2778 case GTP_DELETE_PDP_RSP:
2779 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2780 status);
2781 break;
2782 case GTP_ERROR:
2783 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2784 break;
2785 case GTP_GPDU:
2786 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2787 break;
2788 default:
2789 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002790 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2791 "Unknown GTP message type received: %d\n",
2792 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002793 break;
2794 }
2795 }
jjako08d331d2003-10-13 20:33:30 +00002796}
2797
jjako08d331d2003-10-13 20:33:30 +00002798int gtp_decaps1c(struct gsn_t *gsn)
2799{
Harald Weltebed35df2011-11-02 13:06:18 +01002800 unsigned char buffer[PACKET_MAX];
2801 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002802 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002803 int status;
2804 struct gtp1_header_short *pheader;
2805 int version = 1; /* TODO GTP version should be determined from header! */
2806 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002807
Harald Weltebed35df2011-11-02 13:06:18 +01002808 /* TODO: Need strategy of userspace buffering and blocking */
2809 /* Currently read is non-blocking and send is blocking. */
2810 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002811
Harald Weltebed35df2011-11-02 13:06:18 +01002812 while (1) { /* Loop until no more to read */
2813 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002814 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002815 return -1;
2816 }
2817 peerlen = sizeof(peer);
2818 if ((status =
2819 recvfrom(fd, buffer, sizeof(buffer), 0,
2820 (struct sockaddr *)&peer, &peerlen)) < 0) {
2821 if (errno == EAGAIN)
2822 return 0;
2823 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002824 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002825 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002826 fd, (unsigned long)buffer, sizeof(buffer),
2827 status, status ? strerror(errno) : "No error");
2828 return -1;
2829 }
jjako08d331d2003-10-13 20:33:30 +00002830
Harald Weltebed35df2011-11-02 13:06:18 +01002831 /* Need at least 1 byte in order to check version */
2832 if (status < (1)) {
2833 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002834 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2835 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002836 continue;
2837 }
jjako08d331d2003-10-13 20:33:30 +00002838
Harald Weltebed35df2011-11-02 13:06:18 +01002839 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002840
Harald Weltebed35df2011-11-02 13:06:18 +01002841 /* Version must be no larger than GTP 1 */
2842 if (((pheader->flags & 0xe0) > 0x20)) {
2843 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002844 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2845 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002846 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2847 /*29.60: 11.1.1 */
2848 continue;
2849 }
jjako08d331d2003-10-13 20:33:30 +00002850
Harald Weltebed35df2011-11-02 13:06:18 +01002851 /* Version must be at least GTP 1 */
2852 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2853 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2854 /* the message */
2855 if (((pheader->flags & 0xe0) < 0x20)) {
2856 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002857 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2858 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002859 continue;
2860 }
jjako08d331d2003-10-13 20:33:30 +00002861
Harald Weltebed35df2011-11-02 13:06:18 +01002862 /* Check packet flag field */
2863 if (((pheader->flags & 0xf7) != 0x32)) {
2864 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002865 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2866 status, "Unsupported packet flag\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002867 continue;
2868 }
jjako2c381332003-10-21 19:09:53 +00002869
Harald Weltebed35df2011-11-02 13:06:18 +01002870 /* Check length of packet */
2871 if (status < GTP1_HEADER_SIZE_LONG) {
2872 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002873 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2874 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002875 continue; /* Silently discard 29.60: 11.1.2 */
2876 }
jjako2c381332003-10-21 19:09:53 +00002877
Harald Weltebed35df2011-11-02 13:06:18 +01002878 /* Check packet length field versus length of packet */
2879 if (status !=
2880 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2881 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002882 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002883 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002884 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002885 continue; /* Silently discard */
2886 }
jjako1db1c812003-07-06 20:53:57 +00002887
Harald Weltebed35df2011-11-02 13:06:18 +01002888 /* Check for extension headers */
2889 /* TODO: We really should cycle through the headers and determine */
2890 /* if any have the comprehension required flag set */
2891 if (((pheader->flags & 0x04) != 0x00)) {
2892 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002893 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2894 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002895 gtp_extheader_req(gsn, version, &peer, fd, buffer,
2896 status);
jjako1db1c812003-07-06 20:53:57 +00002897
Harald Weltebed35df2011-11-02 13:06:18 +01002898 continue;
2899 }
2900
2901 if ((gsn->mode == GTP_MODE_GGSN) &&
2902 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2903 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2904 (pheader->type == GTP_DELETE_PDP_RSP))) {
2905 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002906 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002907 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002908 "Unexpected GTP Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002909 continue; /* Silently discard 29.60: 11.1.4 */
2910 }
2911
2912 if ((gsn->mode == GTP_MODE_SGSN) &&
2913 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2914 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2915 (pheader->type == GTP_DELETE_PDP_REQ))) {
2916 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002917 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002918 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002919 "Unexpected GTP Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002920 continue; /* Silently discard 29.60: 11.1.4 */
2921 }
2922
2923 switch (pheader->type) {
2924 case GTP_ECHO_REQ:
2925 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2926 break;
2927 case GTP_ECHO_RSP:
2928 gtp_echo_conf(gsn, version, &peer, buffer, status);
2929 break;
2930 case GTP_NOT_SUPPORTED:
2931 gtp_unsup_ind(gsn, &peer, buffer, status);
2932 break;
2933 case GTP_SUPP_EXT_HEADER:
2934 gtp_extheader_ind(gsn, &peer, buffer, status);
2935 break;
2936 case GTP_CREATE_PDP_REQ:
2937 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2938 status);
2939 break;
2940 case GTP_CREATE_PDP_RSP:
2941 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2942 status);
2943 break;
2944 case GTP_UPDATE_PDP_REQ:
2945 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2946 status);
2947 break;
2948 case GTP_UPDATE_PDP_RSP:
2949 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2950 status);
2951 break;
2952 case GTP_DELETE_PDP_REQ:
2953 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2954 status);
2955 break;
2956 case GTP_DELETE_PDP_RSP:
2957 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2958 status);
2959 break;
2960 case GTP_ERROR:
2961 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2962 break;
2963 default:
2964 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002965 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2966 "Unknown GTP message type received: %u\n",
2967 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002968 break;
2969 }
2970 }
jjako52c24142002-12-16 13:33:51 +00002971}
2972
jjako08d331d2003-10-13 20:33:30 +00002973int gtp_decaps1u(struct gsn_t *gsn)
2974{
Harald Weltebed35df2011-11-02 13:06:18 +01002975 unsigned char buffer[PACKET_MAX];
2976 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002977 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002978 int status;
2979 struct gtp1_header_short *pheader;
2980 int version = 1; /* GTP version should be determined from header! */
2981 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00002982
Harald Weltebed35df2011-11-02 13:06:18 +01002983 /* TODO: Need strategy of userspace buffering and blocking */
2984 /* Currently read is non-blocking and send is blocking. */
2985 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002986
Harald Weltebed35df2011-11-02 13:06:18 +01002987 while (1) { /* Loop until no more to read */
2988 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002989 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002990 return -1;
2991 }
2992 peerlen = sizeof(peer);
2993 if ((status =
2994 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
2995 (struct sockaddr *)&peer, &peerlen)) < 0) {
2996 if (errno == EAGAIN)
2997 return 0;
2998 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002999 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003000 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003001 gsn->fd1u, (unsigned long)buffer,
3002 sizeof(buffer), status,
3003 status ? strerror(errno) : "No error");
3004 return -1;
3005 }
jjako08d331d2003-10-13 20:33:30 +00003006
Harald Weltebed35df2011-11-02 13:06:18 +01003007 /* Need at least 1 byte in order to check version */
3008 if (status < (1)) {
3009 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003010 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3011 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003012 continue;
3013 }
jjako08d331d2003-10-13 20:33:30 +00003014
Harald Weltebed35df2011-11-02 13:06:18 +01003015 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003016
Harald Weltebed35df2011-11-02 13:06:18 +01003017 /* Version must be no larger than GTP 1 */
3018 if (((pheader->flags & 0xe0) > 0x20)) {
3019 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003020 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3021 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003022 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3023 continue;
3024 }
jjako08d331d2003-10-13 20:33:30 +00003025
Harald Weltebed35df2011-11-02 13:06:18 +01003026 /* Version must be at least GTP 1 */
3027 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3028 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3029 /* the message */
3030 if (((pheader->flags & 0xe0) < 0x20)) {
3031 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003032 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3033 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003034 continue;
3035 }
jjako2c381332003-10-21 19:09:53 +00003036
Harald Weltebed35df2011-11-02 13:06:18 +01003037 /* Check packet flag field (allow both with and without sequence number) */
3038 if (((pheader->flags & 0xf5) != 0x30)) {
3039 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003040 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3041 status, "Unsupported packet flag\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003042 continue;
3043 }
jjako2c381332003-10-21 19:09:53 +00003044
Harald Weltebed35df2011-11-02 13:06:18 +01003045 /* Check length of packet */
3046 if (status < GTP1_HEADER_SIZE_SHORT) {
3047 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003048 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3049 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003050 continue; /* Silently discard 29.60: 11.1.2 */
3051 }
3052
3053 /* Check packet length field versus length of packet */
3054 if (status !=
3055 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3056 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003057 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003058 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003059 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003060 continue; /* Silently discard */
3061 }
3062
3063 /* Check for extension headers */
3064 /* TODO: We really should cycle through the headers and determine */
3065 /* if any have the comprehension required flag set */
3066 if (((pheader->flags & 0x04) != 0x00)) {
3067 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003068 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3069 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003070 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3071 status);
3072
3073 continue;
3074 }
3075
3076 switch (pheader->type) {
3077 case GTP_ECHO_REQ:
3078 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3079 break;
3080 case GTP_ECHO_RSP:
3081 gtp_echo_conf(gsn, version, &peer, buffer, status);
3082 break;
3083 case GTP_SUPP_EXT_HEADER:
3084 gtp_extheader_ind(gsn, &peer, buffer, status);
3085 break;
3086 case GTP_ERROR:
3087 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3088 break;
3089 /* Supported header extensions */
3090 case GTP_GPDU:
3091 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3092 break;
3093 default:
3094 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003095 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3096 "Unknown GTP message type received: %u\n",
3097 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003098 break;
3099 }
3100 }
jjako08d331d2003-10-13 20:33:30 +00003101}
3102
Harald Weltebed35df2011-11-02 13:06:18 +01003103int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003104{
Harald Weltebed35df2011-11-02 13:06:18 +01003105 union gtp_packet packet;
3106 struct sockaddr_in addr;
3107 int fd;
3108 int length;
jjako52c24142002-12-16 13:33:51 +00003109
Harald Weltebed35df2011-11-02 13:06:18 +01003110 memset(&addr, 0, sizeof(addr));
3111 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003112#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003113 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003114#endif
3115
Harald Weltebed35df2011-11-02 13:06:18 +01003116 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003117
Harald Weltebed35df2011-11-02 13:06:18 +01003118 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003119
Harald Weltebed35df2011-11-02 13:06:18 +01003120 length = GTP0_HEADER_SIZE + len;
3121 addr.sin_port = htons(GTP0_PORT);
3122 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003123
Harald Weltebed35df2011-11-02 13:06:18 +01003124 get_default_gtp(0, GTP_GPDU, &packet);
3125 packet.gtp0.h.length = hton16(len);
3126 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3127 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003128 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
jjako08d331d2003-10-13 20:33:30 +00003129
Harald Weltebed35df2011-11-02 13:06:18 +01003130 if (len > sizeof(union gtp_packet) - sizeof(struct gtp0_header)) {
3131 gsn->err_memcpy++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003132 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003133 "Memcpy failed: %u > %zu\n", len,
Harald Weltebed35df2011-11-02 13:06:18 +01003134 sizeof(union gtp_packet) -
3135 sizeof(struct gtp0_header));
3136 return EOF;
3137 }
3138 memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
3139 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003140
Harald Weltebed35df2011-11-02 13:06:18 +01003141 length = GTP1_HEADER_SIZE_LONG + len;
3142 addr.sin_port = htons(GTP1U_PORT);
3143 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003144
Harald Weltebed35df2011-11-02 13:06:18 +01003145 get_default_gtp(1, GTP_GPDU, &packet);
3146 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3147 GTP1_HEADER_SIZE_LONG);
3148 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3149 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3150
3151 if (len >
3152 sizeof(union gtp_packet) -
3153 sizeof(struct gtp1_header_long)) {
3154 gsn->err_memcpy++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003155 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003156 "Memcpy failed: %u > %zu\n", len,
Harald Weltebed35df2011-11-02 13:06:18 +01003157 sizeof(union gtp_packet) -
3158 sizeof(struct gtp0_header));
3159 return EOF;
3160 }
3161 memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
3162 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003163 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003164 return EOF;
3165 }
3166
3167 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003168 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003169 return -1;
3170 }
3171
3172 if (sendto(fd, &packet, length, 0,
3173 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
3174 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003175 LOGP(DLGTP, LOGL_ERROR,
3176 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003177 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3178 strerror(errno));
3179 return EOF;
3180 }
3181 return 0;
jjako52c24142002-12-16 13:33:51 +00003182}
3183
jjako52c24142002-12-16 13:33:51 +00003184/* ***********************************************************
3185 * Conversion functions
3186 *************************************************************/
3187
Harald Weltebed35df2011-11-02 13:06:18 +01003188int char2ul_t(char *src, struct ul_t dst)
3189{
3190 dst.l = strlen(src) + 1;
3191 dst.v = malloc(dst.l);
3192 dst.v[0] = dst.l - 1;
3193 memcpy(&dst.v[1], src, dst.v[0]);
3194 return 0;
jjako52c24142002-12-16 13:33:51 +00003195}
3196
3197/* ***********************************************************
3198 * IP address conversion functions
3199 * There exist several types of address representations:
3200 * - eua: End User Address. (29.060, 7.7.27, message type 128)
3201 * Used for signalling address to mobile station. Supports IPv4
3202 * IPv6 x.25 etc. etc.
3203 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3204 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3205 * - in_addr: IPv4 address struct.
3206 * - sockaddr_in: Socket API representation of IP address and
3207 * port number.
3208 *************************************************************/
3209
Harald Weltebed35df2011-11-02 13:06:18 +01003210int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3211{
3212 eua->v[0] = 0xf1; /* IETF */
3213 eua->v[1] = 0x21; /* IPv4 */
3214 if (src) {
3215 eua->l = 6;
3216 memcpy(&eua->v[2], src, 4);
3217 } else {
3218 eua->l = 2;
3219 }
3220 return 0;
jjako52c24142002-12-16 13:33:51 +00003221}
3222
Harald Weltebed35df2011-11-02 13:06:18 +01003223int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3224{
3225 if ((eua->l != 6) || (eua->v[0] != 0xf1) || (eua->v[1] = 0x21))
3226 return -1; /* Not IPv4 address */
3227 memcpy(dst, &eua->v[2], 4);
3228 return 0;
jjako52c24142002-12-16 13:33:51 +00003229}
3230
Harald Weltebed35df2011-11-02 13:06:18 +01003231int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3232{
3233 memset(dst, 0, sizeof(struct in_addr));
3234 if (gsna->l != 4)
3235 return EOF; /* Return if not IPv4 */
3236 memcpy(dst, gsna->v, gsna->l);
3237 return 0;
jjako52c24142002-12-16 13:33:51 +00003238}
3239
Harald Weltebed35df2011-11-02 13:06:18 +01003240int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3241{
3242 memset(gsna, 0, sizeof(struct ul16_t));
3243 gsna->l = 4;
3244 memcpy(gsna->v, src, gsna->l);
3245 return 0;
jjako52c24142002-12-16 13:33:51 +00003246}