blob: 12cb4928b3186f78d63930819eac6067fcfb936d [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");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100668 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100669 }
670 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100671 LOGP(DLGTP, LOGL_ERROR,
672 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100673 }
jjako52c24142002-12-16 13:33:51 +0000674 }
Harald Weltebed35df2011-11-02 13:06:18 +0100675
676 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000677 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100678
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);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100688close_file:
jjako52c24142002-12-16 13:33:51 +0000689 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100690 LOGP(DLGTP, LOGL_ERROR,
691 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100692 return;
jjako52c24142002-12-16 13:33:51 +0000693 }
694}
695
jjako1db1c812003-07-06 20:53:57 +0000696int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100697 int mode)
jjako52c24142002-12-16 13:33:51 +0000698{
Harald Weltebed35df2011-11-02 13:06:18 +0100699 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000700
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100701 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started\n");
jjako52c24142002-12-16 13:33:51 +0000702
Harald Weltebed35df2011-11-02 13:06:18 +0100703 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000704
Harald Weltebed35df2011-11-02 13:06:18 +0100705 (*gsn)->statedir = statedir;
706 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000707
Harald Weltebed35df2011-11-02 13:06:18 +0100708 /* Initialise sequence number */
709 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000710
Harald Weltebed35df2011-11-02 13:06:18 +0100711 /* Initialise request retransmit queue */
712 queue_new(&(*gsn)->queue_req);
713 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000714
Harald Weltebed35df2011-11-02 13:06:18 +0100715 /* Initialise pdp table */
716 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000717
Harald Weltebed35df2011-11-02 13:06:18 +0100718 /* Initialise call back functions */
719 (*gsn)->cb_create_context_ind = 0;
720 (*gsn)->cb_delete_context = 0;
721 (*gsn)->cb_unsup_ind = 0;
722 (*gsn)->cb_conf = 0;
723 (*gsn)->cb_data_ind = 0;
724
725 /* Store function parameters */
726 (*gsn)->gsnc = *listen;
727 (*gsn)->gsnu = *listen;
728 (*gsn)->mode = mode;
729
730 /* Create GTP version 0 socket */
731 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
732 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100733 LOGP(DLGTP, LOGL_ERROR,
734 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100735 AF_INET, SOCK_DGRAM, 0, strerror(errno));
736 return -1;
737 }
738
739 memset(&addr, 0, sizeof(addr));
740 addr.sin_family = AF_INET;
741 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
742 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000743#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100744 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000745#endif
jjako08d331d2003-10-13 20:33:30 +0000746
Harald Weltebed35df2011-11-02 13:06:18 +0100747 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
748 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200749 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
750 "bind(fd0=%d) failed: Error = %s\n",
751 (*gsn)->fd0, strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100752 return -1;
753 }
jjako08d331d2003-10-13 20:33:30 +0000754
Harald Weltebed35df2011-11-02 13:06:18 +0100755 /* Create GTP version 1 control plane socket */
756 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
757 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100758 LOGP(DLGTP, LOGL_ERROR,
759 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100760 AF_INET, SOCK_DGRAM, 0, strerror(errno));
761 return -1;
762 }
763
764 memset(&addr, 0, sizeof(addr));
765 addr.sin_family = AF_INET;
766 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
767 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000768#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100769 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000770#endif
jjako08d331d2003-10-13 20:33:30 +0000771
Harald Weltebed35df2011-11-02 13:06:18 +0100772 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
773 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200774 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
775 "bind(fd1c=%d) failed: Error = %s\n",
776 (*gsn)->fd1c, strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100777 return -1;
778 }
jjako08d331d2003-10-13 20:33:30 +0000779
Harald Weltebed35df2011-11-02 13:06:18 +0100780 /* Create GTP version 1 user plane socket */
781 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
782 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100783 LOGP(DLGTP, LOGL_ERROR,
784 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100785 AF_INET, SOCK_DGRAM, 0, strerror(errno));
786 return -1;
787 }
788
789 memset(&addr, 0, sizeof(addr));
790 addr.sin_family = AF_INET;
791 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
792 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000793#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100794 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000795#endif
jjako52c24142002-12-16 13:33:51 +0000796
Harald Weltebed35df2011-11-02 13:06:18 +0100797 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
798 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200799 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +0200800 "bind(fd1u=%d) failed: Error = %s\n",
801 (*gsn)->fd1u, strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100802 return -1;
803 }
804
805 return 0;
jjako52c24142002-12-16 13:33:51 +0000806}
807
Harald Weltebed35df2011-11-02 13:06:18 +0100808int gtp_free(struct gsn_t *gsn)
809{
jjako52c24142002-12-16 13:33:51 +0000810
Harald Weltebed35df2011-11-02 13:06:18 +0100811 /* Clean up retransmit queues */
812 queue_free(gsn->queue_req);
813 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000814
Harald Weltebed35df2011-11-02 13:06:18 +0100815 close(gsn->fd0);
816 close(gsn->fd1c);
817 close(gsn->fd1u);
818
819 free(gsn);
820 return 0;
jjako52c24142002-12-16 13:33:51 +0000821}
822
823/* ***********************************************************
824 * Path management messages
825 * Messages: echo and version not supported.
826 * A path is connection between two UDP/IP endpoints
827 *
828 * A path is either using GTP0 or GTP1. A path can be
829 * established by any kind of GTP message??
830
831 * Which source port to use?
832 * GTP-C request destination port is 2123/3386
833 * GTP-U request destination port is 2152/3386
834 * T-PDU destination port is 2152/3386.
835 * For the above messages the source port is locally allocated.
836 * For response messages src=rx-dst and dst=rx-src.
837 * For simplicity we should probably use 2123+2152/3386 as
838 * src port even for the cases where src can be locally
839 * allocated. This also means that we have to listen only to
840 * the same ports.
841 * For response messages we need to be able to respond to
842 * the relevant src port even if it is locally allocated by
843 * the peer.
844 *
845 * The need for path management!
846 * We might need to keep a list of active paths. This might
847 * be in the form of remote IP address + UDP port numbers.
848 * (We will consider a path astablished if we have a context
849 * with the node in question)
850 *************************************************************/
851
852/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000853int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
854 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000855{
Harald Weltebed35df2011-11-02 13:06:18 +0100856 union gtp_packet packet;
857 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
858 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000859}
860
jjako08d331d2003-10-13 20:33:30 +0000861/* Send off an echo reply */
862int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100863 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000864{
Harald Weltebed35df2011-11-02 13:06:18 +0100865 union gtp_packet packet;
866 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
867 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
868 gsn->restart_counter);
869 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
870 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000871}
872
jjako52c24142002-12-16 13:33:51 +0000873/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +0100874int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
875 int fd, void *pack, unsigned len)
876{
jjako52c24142002-12-16 13:33:51 +0000877
Harald Weltebed35df2011-11-02 13:06:18 +0100878 /* Check if it was a dublicate request */
879 if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
880 return 0;
jjako52c24142002-12-16 13:33:51 +0000881
Harald Weltebed35df2011-11-02 13:06:18 +0100882 /* Send off reply to request */
883 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000884}
885
886/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000887int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100888 void *pack, unsigned len)
889{
890 union gtpie_member *ie[GTPIE_SIZE];
891 unsigned char recovery;
892 void *cbp = NULL;
893 uint8_t type = 0;
894 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000895
Harald Weltebed35df2011-11-02 13:06:18 +0100896 /* Remove packet from queue */
897 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
898 return EOF;
jjako52c24142002-12-16 13:33:51 +0000899
Harald Weltebed35df2011-11-02 13:06:18 +0100900 /* Extract information elements into a pointer array */
901 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
902 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100903 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
904 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100905 if (gsn->cb_conf)
906 gsn->cb_conf(type, EOF, NULL, cbp);
907 return EOF;
908 }
jjako52c24142002-12-16 13:33:51 +0000909
Harald Weltebed35df2011-11-02 13:06:18 +0100910 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
911 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100912 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
913 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100914 if (gsn->cb_conf)
915 gsn->cb_conf(type, EOF, NULL, cbp);
916 return EOF;
917 }
jjako52c24142002-12-16 13:33:51 +0000918
Harald Weltebed35df2011-11-02 13:06:18 +0100919 /* Echo reply packages does not have a cause information element */
920 /* Instead we return the recovery number in the callback function */
921 if (gsn->cb_conf)
922 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +0100923
Harald Weltebed35df2011-11-02 13:06:18 +0100924 if (gsn->cb_recovery)
925 gsn->cb_recovery(peer, recovery);
926
927 return 0;
jjako52c24142002-12-16 13:33:51 +0000928}
929
930/* Send off a Version Not Supported message */
931/* This message is somewhat special in that it actually is a
932 * response to some other message with unsupported GTP version
933 * For this reason it has parameters like a response, and does
934 * its own message transmission. No signalling queue is used
935 * The reply is sent to the peer IP and peer UDP. This means that
936 * the peer will be receiving a GTP0 message on a GTP1 port!
937 * In practice however this will never happen as a GTP0 GSN will
938 * only listen to the GTP0 port, and therefore will never receive
939 * anything else than GTP0 */
940
jjako08d331d2003-10-13 20:33:30 +0000941int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
942 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000943{
Harald Weltebed35df2011-11-02 13:06:18 +0100944 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +0000945
Harald Weltebed35df2011-11-02 13:06:18 +0100946 /* GTP 1 is the highest supported protocol */
947 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
948 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +0000949}
950
951/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +0100952int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
953 void *pack, unsigned len)
954{
jjako52c24142002-12-16 13:33:51 +0000955
Harald Weltebed35df2011-11-02 13:06:18 +0100956 if (gsn->cb_unsup_ind)
957 gsn->cb_unsup_ind(peer);
958
959 return 0;
jjako52c24142002-12-16 13:33:51 +0000960}
961
jjako2c381332003-10-21 19:09:53 +0000962/* Send off an Supported Extension Headers Notification */
963int gtp_extheader_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
964 int fd, void *pack, unsigned len)
965{
Harald Weltebed35df2011-11-02 13:06:18 +0100966 union gtp_packet packet;
967 unsigned int length =
968 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +0000969
Harald Weltebed35df2011-11-02 13:06:18 +0100970 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +0000971
Harald Weltebed35df2011-11-02 13:06:18 +0100972 if (version < 1)
973 return 0;
jjako2c381332003-10-21 19:09:53 +0000974
Harald Weltebed35df2011-11-02 13:06:18 +0100975 /* We report back that we support only PDCP PDU headers */
976 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
977 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +0000978
Harald Weltebed35df2011-11-02 13:06:18 +0100979 return gtp_notification(gsn, version, &packet, length,
980 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +0000981}
982
983/* Handle a Supported Extension Headers Notification */
Harald Weltebed35df2011-11-02 13:06:18 +0100984int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
985 void *pack, unsigned len)
986{
jjako2c381332003-10-21 19:09:53 +0000987
Harald Weltebed35df2011-11-02 13:06:18 +0100988 if (gsn->cb_extheader_ind)
989 gsn->cb_extheader_ind(peer);
990
991 return 0;
jjako2c381332003-10-21 19:09:53 +0000992}
993
jjako52c24142002-12-16 13:33:51 +0000994/* ***********************************************************
995 * Session management messages
996 * Messages: create, update and delete PDP context
997 *
998 * Information storage
999 * Information storage for each PDP context is defined in
1000 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1001 * PDP-address (IP address), sequence numbers, charging ID.
1002 * For the SGSN it also includes radio related mobility
1003 * information.
1004 *************************************************************/
1005
Harald Welte7b3347b2010-05-15 12:18:46 +02001006/* API: Send Create PDP Context Request (7.3.1) */
Harald Weltebed35df2011-11-02 13:06:18 +01001007extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
1008 void *cbp)
1009{
1010 union gtp_packet packet;
1011 unsigned int length =
1012 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1013 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001014
Harald Weltebed35df2011-11-02 13:06:18 +01001015 /* TODO: Secondary PDP Context Activation Procedure */
1016 /* In secondary activation procedure the PDP context is identified
1017 by tei in the header. The following fields are omitted: Selection
1018 mode, IMSI, MSISDN, End User Address, Access Point Name and
1019 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001020
Harald Weltebed35df2011-11-02 13:06:18 +01001021 if (pdp->secondary) {
1022 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001023 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001024 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001025 return EOF;
1026 }
1027 }
jjako2c381332003-10-21 19:09:53 +00001028
Harald Weltebed35df2011-11-02 13:06:18 +01001029 if (pdp->version == 0) {
1030 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1031 sizeof(pdp->qos_req0), pdp->qos_req0);
1032 }
jjako52c24142002-12-16 13:33:51 +00001033
Harald Weltebed35df2011-11-02 13:06:18 +01001034 /* Section 7.7.2 */
1035 if (pdp->version == 1) {
1036 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1037 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1038 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1039 }
jjako52c24142002-12-16 13:33:51 +00001040
Harald Weltebed35df2011-11-02 13:06:18 +01001041 /* Section 7.7.3 Routing Area Information */
1042 if (pdp->rai_given == 1)
1043 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1044 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001045
Harald Weltebed35df2011-11-02 13:06:18 +01001046 /* Section 7.7.11 */
1047 if (pdp->norecovery_given == 0)
1048 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1049 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001050
Harald Weltebed35df2011-11-02 13:06:18 +01001051 /* Section 7.7.12 */
1052 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1053 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1054 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001055
Harald Weltebed35df2011-11-02 13:06:18 +01001056 if (pdp->version == 0) {
1057 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1058 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1059 }
jjako08d331d2003-10-13 20:33:30 +00001060
Harald Weltebed35df2011-11-02 13:06:18 +01001061 /* Section 7.7.13 */
1062 if (pdp->version == 1) {
1063 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1064 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001065
Harald Weltebed35df2011-11-02 13:06:18 +01001066 /* Section 7.7.14 */
1067 if (!pdp->teic_confirmed)
1068 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1069 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001070
Harald Weltebed35df2011-11-02 13:06:18 +01001071 /* Section 7.7.17 */
1072 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001073
Harald Weltebed35df2011-11-02 13:06:18 +01001074 /* Section 7.7.17 */
1075 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1076 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1077 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001078
Harald Weltebed35df2011-11-02 13:06:18 +01001079 /* Section 7.7.23 */
1080 if (pdp->cch_pdp) /* Only include charging if flags are set */
1081 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1082 pdp->cch_pdp);
1083 }
jjako9b4971d2004-05-27 20:30:19 +00001084
Harald Weltebed35df2011-11-02 13:06:18 +01001085 /* TODO
1086 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1087 pdp->traceref);
1088 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1089 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001090
Harald Weltebed35df2011-11-02 13:06:18 +01001091 /* Section 7.7.27 */
1092 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1093 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1094 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001095
Harald Weltebed35df2011-11-02 13:06:18 +01001096 /* Section 7.7.30 */
1097 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1098 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1099 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001100
Harald Weltebed35df2011-11-02 13:06:18 +01001101 /* Section 7.7.31 */
1102 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1103 if (pdp->pco_req.l)
1104 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1105 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001106
Harald Weltebed35df2011-11-02 13:06:18 +01001107 /* Section 7.7.32 */
1108 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1109 pdp->gsnlc.l, pdp->gsnlc.v);
1110 /* Section 7.7.32 */
1111 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1112 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001113
Harald Weltebed35df2011-11-02 13:06:18 +01001114 /* Section 7.7.33 */
1115 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1116 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1117 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001118
Harald Weltebed35df2011-11-02 13:06:18 +01001119 /* Section 7.7.34 */
1120 if (pdp->version == 1)
1121 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1122 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001123
Harald Weltebed35df2011-11-02 13:06:18 +01001124 /* Section 7.7.36 */
1125 if ((pdp->version == 1) && pdp->tft.l)
1126 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1127 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001128
Harald Weltebed35df2011-11-02 13:06:18 +01001129 /* Section 7.7.41 */
1130 if ((pdp->version == 1) && pdp->triggerid.l)
1131 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1132 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001133
Harald Weltebed35df2011-11-02 13:06:18 +01001134 /* Section 7.7.42 */
1135 if ((pdp->version == 1) && pdp->omcid.l)
1136 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1137 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001138
Harald Weltebed35df2011-11-02 13:06:18 +01001139 /* new R7 fields */
1140 if (pdp->rattype_given == 1)
1141 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1142 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001143
Harald Weltebed35df2011-11-02 13:06:18 +01001144 if (pdp->userloc_given == 1)
1145 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1146 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001147
Harald Weltebed35df2011-11-02 13:06:18 +01001148 if (pdp->mstz_given == 1)
1149 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1150 pdp->mstz.l, pdp->mstz.v);
1151
1152 if (pdp->imeisv_given == 1)
1153 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1154 pdp->imeisv.l, pdp->imeisv.v);
1155
1156 /* TODO hisaddr0 */
1157 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1158
1159 return 0;
jjako52c24142002-12-16 13:33:51 +00001160}
1161
jjako08d331d2003-10-13 20:33:30 +00001162/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001163int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1164{
jjako08d331d2003-10-13 20:33:30 +00001165
Harald Weltebed35df2011-11-02 13:06:18 +01001166 /* Now send off a reply to the peer */
1167 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1168
1169 if (cause != GTPCAUSE_ACC_REQ) {
1170 pdp_freepdp(pdp);
1171 }
1172
1173 return 0;
jjako08d331d2003-10-13 20:33:30 +00001174}
1175
1176/* API: Register create context indication callback */
1177int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001178 int (*cb_create_context_ind) (struct pdp_t *
1179 pdp))
jjako52c24142002-12-16 13:33:51 +00001180{
Harald Weltebed35df2011-11-02 13:06:18 +01001181 gsn->cb_create_context_ind = cb_create_context_ind;
1182 return 0;
jjako08d331d2003-10-13 20:33:30 +00001183}
1184
jjako08d331d2003-10-13 20:33:30 +00001185/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001186int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1187 uint8_t cause)
1188{
1189 union gtp_packet packet;
1190 unsigned int length =
1191 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001192
Harald Weltebed35df2011-11-02 13:06:18 +01001193 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001194
Harald Weltebed35df2011-11-02 13:06:18 +01001195 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001196
Harald Weltebed35df2011-11-02 13:06:18 +01001197 if (version == 0)
1198 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1199 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001200
Harald Weltebed35df2011-11-02 13:06:18 +01001201 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1202 pdp->reorder);
1203 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1204 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001205
Harald Weltebed35df2011-11-02 13:06:18 +01001206 if (version == 0) {
1207 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1208 pdp->fllu);
1209 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1210 pdp->fllc);
1211 }
jjako08d331d2003-10-13 20:33:30 +00001212
Harald Weltebed35df2011-11-02 13:06:18 +01001213 if (version == 1) {
1214 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1215 pdp->teid_own);
1216 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1217 pdp->teic_own);
1218 }
jjako08d331d2003-10-13 20:33:30 +00001219
Harald Weltebed35df2011-11-02 13:06:18 +01001220 /* TODO: We use teic_own as charging ID */
1221 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1222 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001223
Harald Weltebed35df2011-11-02 13:06:18 +01001224 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1225 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001226
Harald Weltebed35df2011-11-02 13:06:18 +01001227 if (pdp->pco_neg.l) { /* Optional PCO */
1228 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1229 pdp->pco_neg.l, pdp->pco_neg.v);
1230 }
jjako52c24142002-12-16 13:33:51 +00001231
Harald Weltebed35df2011-11-02 13:06:18 +01001232 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1233 pdp->gsnlc.l, pdp->gsnlc.v);
1234 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1235 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001236
Harald Weltebed35df2011-11-02 13:06:18 +01001237 if (version == 1)
1238 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1239 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001240
Harald Weltebed35df2011-11-02 13:06:18 +01001241 /* TODO: Charging gateway address */
1242 }
jjako52c24142002-12-16 13:33:51 +00001243
Harald Weltebed35df2011-11-02 13:06:18 +01001244 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1245 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001246}
1247
1248/* Handle Create PDP Context Request */
1249int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001250 struct sockaddr_in *peer, int fd,
1251 void *pack, unsigned len)
1252{
1253 struct pdp_t *pdp, *pdp_old;
1254 struct pdp_t pdp_buf;
1255 union gtpie_member *ie[GTPIE_SIZE];
1256 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001257
Harald Weltebed35df2011-11-02 13:06:18 +01001258 uint16_t seq = get_seq(pack);
1259 int hlen = get_hlen(pack);
1260 uint8_t linked_nsapi = 0;
1261 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001262
Harald Weltebed35df2011-11-02 13:06:18 +01001263 if (!gtp_dublicate(gsn, version, peer, seq))
1264 return 0;
jjako08d331d2003-10-13 20:33:30 +00001265
Harald Weltebed35df2011-11-02 13:06:18 +01001266 pdp = &pdp_buf;
1267 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001268
Harald Weltebed35df2011-11-02 13:06:18 +01001269 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001270 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1271
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001272 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001273 }
jjako52c24142002-12-16 13:33:51 +00001274
Harald Weltebed35df2011-11-02 13:06:18 +01001275 pdp->seq = seq;
1276 pdp->sa_peer = *peer;
1277 pdp->fd = fd;
1278 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001279
Harald Weltebed35df2011-11-02 13:06:18 +01001280 /* Decode information elements */
1281 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1282 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001283 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1284 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001285 if (0 == version)
1286 return EOF;
1287 else
1288 return gtp_create_pdp_resp(gsn, version, pdp,
1289 GTPCAUSE_INVALID_MESSAGE);
1290 }
jjako52c24142002-12-16 13:33:51 +00001291
Harald Weltebed35df2011-11-02 13:06:18 +01001292 if (version == 1) {
1293 /* Linked NSAPI (conditional) */
1294 /* If included this is the Secondary PDP Context Activation Procedure */
1295 /* In secondary activation IMSI is not included, so the context must be */
1296 /* identified by the tei */
1297 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001298
Harald Weltebed35df2011-11-02 13:06:18 +01001299 /* Find the primary PDP context */
1300 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1301 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001302 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001303 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001304 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001305 return gtp_create_pdp_resp(gsn, version, pdp,
1306 GTPCAUSE_OPT_IE_INCORRECT);
1307 }
jjako2c381332003-10-21 19:09:53 +00001308
Harald Weltebed35df2011-11-02 13:06:18 +01001309 /* Check that the primary PDP context matches linked nsapi */
1310 if (linked_pdp->nsapi != linked_nsapi) {
1311 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001312 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001313 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001314 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001315 return gtp_create_pdp_resp(gsn, version, pdp,
1316 GTPCAUSE_OPT_IE_INCORRECT);
1317 }
jjako52c24142002-12-16 13:33:51 +00001318
Harald Weltebed35df2011-11-02 13:06:18 +01001319 /* Copy parameters from primary context */
1320 pdp->selmode = linked_pdp->selmode;
1321 pdp->imsi = linked_pdp->imsi;
1322 pdp->msisdn = linked_pdp->msisdn;
1323 pdp->eua = linked_pdp->eua;
1324 pdp->pco_req = linked_pdp->pco_req;
1325 pdp->apn_req = linked_pdp->apn_req;
1326 pdp->teic_gn = linked_pdp->teic_gn;
1327 pdp->secondary = 1;
1328 }
1329 }
1330 /* if (version == 1) */
1331 if (version == 0) {
1332 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1333 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1334 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001335 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1336 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001337 return gtp_create_pdp_resp(gsn, version, pdp,
1338 GTPCAUSE_MAN_IE_MISSING);
1339 }
1340 }
jjako08d331d2003-10-13 20:33:30 +00001341
Harald Weltebed35df2011-11-02 13:06:18 +01001342 if ((version == 1) && (!linked_pdp)) {
1343 /* Not Secondary PDP Context Activation Procedure */
1344 /* IMSI (conditional) */
1345 if (gtpie_gettv0
1346 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1347 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001348 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1349 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001350 return gtp_create_pdp_resp(gsn, version, pdp,
1351 GTPCAUSE_MAN_IE_MISSING);
1352 }
1353 }
jjako52c24142002-12-16 13:33:51 +00001354
Harald Weltebed35df2011-11-02 13:06:18 +01001355 /* Recovery (optional) */
1356 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1357 if (gsn->cb_recovery)
1358 gsn->cb_recovery(peer, recovery);
1359 }
jjako52c24142002-12-16 13:33:51 +00001360
Harald Weltebed35df2011-11-02 13:06:18 +01001361 /* Selection mode (conditional) */
1362 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1363 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1364 &pdp->selmode, sizeof(pdp->selmode))) {
1365 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001366 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1367 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001368 return gtp_create_pdp_resp(gsn, version, pdp,
1369 GTPCAUSE_MAN_IE_MISSING);
1370 }
1371 }
jjako52c24142002-12-16 13:33:51 +00001372
Harald Weltebed35df2011-11-02 13:06:18 +01001373 if (version == 0) {
1374 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1375 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001376 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1377 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001378 return gtp_create_pdp_resp(gsn, version, pdp,
1379 GTPCAUSE_MAN_IE_MISSING);
1380 }
jjako52c24142002-12-16 13:33:51 +00001381
Harald Weltebed35df2011-11-02 13:06:18 +01001382 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1383 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001384 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1385 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001386 return gtp_create_pdp_resp(gsn, version, pdp,
1387 GTPCAUSE_MAN_IE_MISSING);
1388 }
1389 }
jjako08d331d2003-10-13 20:33:30 +00001390
Harald Weltebed35df2011-11-02 13:06:18 +01001391 if (version == 1) {
1392 /* TEID (mandatory) */
1393 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1394 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001395 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1396 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001397 return gtp_create_pdp_resp(gsn, version, pdp,
1398 GTPCAUSE_MAN_IE_MISSING);
1399 }
jjako2c381332003-10-21 19:09:53 +00001400
Harald Weltebed35df2011-11-02 13:06:18 +01001401 /* TEIC (conditional) */
1402 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1403 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1404 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001405 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001406 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001407 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001408 return gtp_create_pdp_resp(gsn, version, pdp,
1409 GTPCAUSE_MAN_IE_MISSING);
1410 }
1411 }
jjako08d331d2003-10-13 20:33:30 +00001412
Harald Weltebed35df2011-11-02 13:06:18 +01001413 /* NSAPI (mandatory) */
1414 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1415 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001416 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1417 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001418 return gtp_create_pdp_resp(gsn, version, pdp,
1419 GTPCAUSE_MAN_IE_MISSING);
1420 }
1421 }
jjako2e840a32003-01-28 16:05:18 +00001422
Harald Weltebed35df2011-11-02 13:06:18 +01001423 /* Charging Characteriatics (optional) */
1424 /* Trace reference (optional) */
1425 /* Trace type (optional) */
1426 /* Charging Characteriatics (optional) */
jjako52c24142002-12-16 13:33:51 +00001427
Harald Weltebed35df2011-11-02 13:06:18 +01001428 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1429 /* End User Address (conditional) */
1430 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1431 &pdp->eua.v, sizeof(pdp->eua.v))) {
1432 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001433 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1434 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001435 return gtp_create_pdp_resp(gsn, version, pdp,
1436 GTPCAUSE_MAN_IE_MISSING);
1437 }
jjako08d331d2003-10-13 20:33:30 +00001438
Harald Weltebed35df2011-11-02 13:06:18 +01001439 /* APN */
1440 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1441 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1442 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001443 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1444 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001445 return gtp_create_pdp_resp(gsn, version, pdp,
1446 GTPCAUSE_MAN_IE_MISSING);
1447 }
jjako2c381332003-10-21 19:09:53 +00001448
Harald Weltebed35df2011-11-02 13:06:18 +01001449 /* Extract protocol configuration options (optional) */
1450 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1451 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1452 }
1453 }
jjako2c381332003-10-21 19:09:53 +00001454
Harald Weltebed35df2011-11-02 13:06:18 +01001455 /* SGSN address for signalling (mandatory) */
1456 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1457 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1458 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001459 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1460 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001461 return gtp_create_pdp_resp(gsn, version, pdp,
1462 GTPCAUSE_MAN_IE_MISSING);
1463 }
jjako2e840a32003-01-28 16:05:18 +00001464
Harald Weltebed35df2011-11-02 13:06:18 +01001465 /* SGSN address for user traffic (mandatory) */
1466 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1467 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1468 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001469 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1470 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001471 return gtp_create_pdp_resp(gsn, version, pdp,
1472 GTPCAUSE_MAN_IE_MISSING);
1473 }
jjako52c24142002-12-16 13:33:51 +00001474
Harald Weltebed35df2011-11-02 13:06:18 +01001475 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1476 /* MSISDN (conditional) */
1477 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1478 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1479 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001480 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1481 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001482 return gtp_create_pdp_resp(gsn, version, pdp,
1483 GTPCAUSE_MAN_IE_MISSING);
1484 }
1485 }
jjako52c24142002-12-16 13:33:51 +00001486
Harald Weltebed35df2011-11-02 13:06:18 +01001487 if (version == 1) {
1488 /* QoS (mandatory) */
1489 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1490 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1491 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001492 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1493 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001494 return gtp_create_pdp_resp(gsn, version, pdp,
1495 GTPCAUSE_MAN_IE_MISSING);
1496 }
1497
1498 /* TFT (conditional) */
1499 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1500 &pdp->tft.v, sizeof(pdp->tft.v))) {
1501 }
1502
1503 /* Trigger ID */
1504 /* OMC identity */
1505 }
1506
1507 /* Initialize our own IP addresses */
1508 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1509 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1510
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001511 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001512
1513 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1514 /* Found old pdp with same tid. Now the voodoo begins! */
1515 /* 09.60 / 29.060 allows create on existing context to "steal" */
1516 /* the context which was allready established */
1517 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001518 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001519 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1520 &&
1521 (!memcmp
1522 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1523 && (pdp->selmode == pdp_old->selmode)
1524 && (pdp->msisdn.l == pdp_old->msisdn.l)
1525 &&
1526 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1527 {
1528 /* OK! We are dealing with the same APN. We will copy new
1529 * parameters to the old pdp and send off confirmation
1530 * We ignore the following information elements:
1531 * QoS: MS will get originally negotiated QoS.
1532 * End user address (EUA). MS will get old EUA anyway.
1533 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001534 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001535
1536 /* Copy remote flow label */
1537 pdp_old->flru = pdp->flru;
1538 pdp_old->flrc = pdp->flrc;
1539
1540 /* Copy remote tei */
1541 pdp_old->teid_gn = pdp->teid_gn;
1542 pdp_old->teic_gn = pdp->teic_gn;
1543
1544 /* Copy peer GSN address */
1545 pdp_old->gsnrc.l = pdp->gsnrc.l;
1546 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1547 pdp_old->gsnru.l = pdp->gsnru.l;
1548 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1549
1550 /* Copy request parameters */
1551 pdp_old->seq = pdp->seq;
1552 pdp_old->sa_peer = pdp->sa_peer;
1553 pdp_old->fd = pdp->fd = fd;
1554 pdp_old->version = pdp->version = version;
1555
1556 /* Switch to using the old pdp context */
1557 pdp = pdp_old;
1558
1559 /* Confirm to peer that things were "successful" */
1560 return gtp_create_pdp_resp(gsn, version, pdp,
1561 GTPCAUSE_ACC_REQ);
1562 } else { /* This is not the same PDP context. Delete the old one. */
1563
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001564 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001565
1566 if (gsn->cb_delete_context)
1567 gsn->cb_delete_context(pdp_old);
1568 pdp_freepdp(pdp_old);
1569
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001570 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001571 }
1572 }
1573
1574 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
1575
1576 /* Callback function to validata login */
1577 if (gsn->cb_create_context_ind != 0)
1578 return gsn->cb_create_context_ind(pdp);
1579 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001580 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1581 "No create_context_ind callback defined\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001582 return gtp_create_pdp_resp(gsn, version, pdp,
1583 GTPCAUSE_NOT_SUPPORTED);
1584 }
jjako52c24142002-12-16 13:33:51 +00001585}
1586
jjako52c24142002-12-16 13:33:51 +00001587/* Handle Create PDP Context Response */
1588int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001589 struct sockaddr_in *peer, void *pack, unsigned len)
1590{
1591 struct pdp_t *pdp;
1592 union gtpie_member *ie[GTPIE_SIZE];
1593 uint8_t cause, recovery;
1594 void *cbp = NULL;
1595 uint8_t type = 0;
1596 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001597
Harald Weltebed35df2011-11-02 13:06:18 +01001598 /* Remove packet from queue */
1599 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1600 return EOF;
jjako52c24142002-12-16 13:33:51 +00001601
Harald Weltebed35df2011-11-02 13:06:18 +01001602 /* Find the context in question */
1603 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1604 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001605 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001606 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001607 if (gsn->cb_conf)
1608 gsn->cb_conf(type, EOF, NULL, cbp);
1609 return EOF;
1610 }
jjako2c381332003-10-21 19:09:53 +00001611
Harald Weltebed35df2011-11-02 13:06:18 +01001612 /* Register that we have received a valid teic from GGSN */
1613 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001614
Harald Weltebed35df2011-11-02 13:06:18 +01001615 /* Decode information elements */
1616 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1617 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001618 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1619 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001620 if (gsn->cb_conf)
1621 gsn->cb_conf(type, EOF, pdp, cbp);
1622 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1623 pdp_freepdp(pdp); */
1624 return EOF;
1625 }
jjako52c24142002-12-16 13:33:51 +00001626
Harald Weltebed35df2011-11-02 13:06:18 +01001627 /* Extract cause value (mandatory) */
1628 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1629 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001630 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1631 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001632 if (gsn->cb_conf)
1633 gsn->cb_conf(type, EOF, pdp, cbp);
1634 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1635 pdp_freepdp(pdp); */
1636 return EOF;
1637 }
jjako52c24142002-12-16 13:33:51 +00001638
Harald Weltebed35df2011-11-02 13:06:18 +01001639 /* Extract recovery (optional) */
1640 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1641 if (gsn->cb_recovery)
1642 gsn->cb_recovery(peer, recovery);
1643 }
jjako52c24142002-12-16 13:33:51 +00001644
Harald Weltebed35df2011-11-02 13:06:18 +01001645 /* Extract protocol configuration options (optional) */
1646 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1647 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1648 }
jjako52c24142002-12-16 13:33:51 +00001649
Harald Weltebed35df2011-11-02 13:06:18 +01001650 /* Check all conditional information elements */
1651 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001652
Harald Weltebed35df2011-11-02 13:06:18 +01001653 if (version == 0) {
1654 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1655 &pdp->qos_neg0,
1656 sizeof(pdp->qos_neg0))) {
1657 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001658 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001659 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001660 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001661 if (gsn->cb_conf)
1662 gsn->cb_conf(type, EOF, pdp, cbp);
1663 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1664 pdp_freepdp(pdp); */
1665 return EOF;
1666 }
1667 }
jjako08d331d2003-10-13 20:33:30 +00001668
Harald Weltebed35df2011-11-02 13:06:18 +01001669 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1670 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001671 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001672 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001673 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001674 if (gsn->cb_conf)
1675 gsn->cb_conf(type, EOF, pdp, cbp);
1676 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1677 pdp_freepdp(pdp); */
1678 return EOF;
1679 }
jjako52c24142002-12-16 13:33:51 +00001680
Harald Weltebed35df2011-11-02 13:06:18 +01001681 if (version == 0) {
1682 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1683 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001684 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001685 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001686 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001687 if (gsn->cb_conf)
1688 gsn->cb_conf(type, EOF, pdp, cbp);
1689 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1690 pdp_freepdp(pdp); */
1691 return EOF;
1692 }
jjako52c24142002-12-16 13:33:51 +00001693
Harald Weltebed35df2011-11-02 13:06:18 +01001694 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1695 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001696 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001697 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001698 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001699 if (gsn->cb_conf)
1700 gsn->cb_conf(type, EOF, pdp, cbp);
1701 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1702 pdp_freepdp(pdp); */
1703 return EOF;
1704 }
1705 }
1706
1707 if (version == 1) {
1708 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1709 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001710 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001711 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001712 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001713 if (gsn->cb_conf)
1714 gsn->cb_conf(type, EOF, pdp, cbp);
1715 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1716 pdp_freepdp(pdp); */
1717 return EOF;
1718 }
1719
1720 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1721 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001722 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001723 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001724 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001725 if (gsn->cb_conf)
1726 gsn->cb_conf(type, EOF, pdp, cbp);
1727 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1728 pdp_freepdp(pdp); */
1729 return EOF;
1730 }
1731 }
1732
1733 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1734 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001735 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001736 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001737 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001738 if (gsn->cb_conf)
1739 gsn->cb_conf(type, EOF, pdp, cbp);
1740 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1741 pdp_freepdp(pdp); */
1742 }
1743
1744 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1745 &pdp->eua.v, sizeof(pdp->eua.v))) {
1746 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001747 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001748 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001749 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001750 if (gsn->cb_conf)
1751 gsn->cb_conf(type, EOF, pdp, cbp);
1752 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1753 pdp_freepdp(pdp); */
1754 return EOF;
1755 }
1756
1757 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1758 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1759 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001760 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001761 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001762 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001763 if (gsn->cb_conf)
1764 gsn->cb_conf(type, EOF, pdp, cbp);
1765 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1766 pdp_freepdp(pdp); */
1767 return EOF;
1768 }
1769
1770 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1771 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1772 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001773 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001774 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001775 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001776 if (gsn->cb_conf)
1777 gsn->cb_conf(type, EOF, pdp, cbp);
1778 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1779 pdp_freepdp(pdp); */
1780 return EOF;
1781 }
1782
1783 if (version == 1) {
1784 if (gtpie_gettlv
1785 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1786 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1787 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001788 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001789 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001790 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001791 if (gsn->cb_conf)
1792 gsn->cb_conf(type, EOF, pdp, cbp);
1793 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1794 pdp_freepdp(pdp); */
1795 return EOF;
1796 }
1797 }
1798
1799 }
1800
1801 if (gsn->cb_conf)
1802 gsn->cb_conf(type, cause, pdp, cbp);
1803
1804 return 0;
jjako52c24142002-12-16 13:33:51 +00001805}
1806
jjako08d331d2003-10-13 20:33:30 +00001807/* API: Send Update PDP Context Request */
1808int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001809 struct in_addr *inetaddr)
1810{
1811 union gtp_packet packet;
1812 unsigned int length =
1813 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001814
Harald Weltebed35df2011-11-02 13:06:18 +01001815 if (pdp->version == 0)
1816 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1817 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001818
Harald Weltebed35df2011-11-02 13:06:18 +01001819 /* Include IMSI if updating with unknown teic_gn */
1820 if ((pdp->version == 1) && (!pdp->teic_gn))
1821 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1822 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1823
1824 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1825 gsn->restart_counter);
1826
1827 if (pdp->version == 0) {
1828 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1829 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1830 }
1831
1832 if (pdp->version == 1) {
1833 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1834 pdp->teid_own);
1835
1836 if (!pdp->teic_confirmed)
1837 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1838 pdp->teic_own);
1839 }
1840
1841 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1842
1843 /* TODO
1844 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1845 pdp->traceref);
1846 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1847 pdp->tracetype); */
1848
1849 /* TODO if ggsn update message
1850 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1851 pdp->eua.l, pdp->eua.v);
1852 */
1853
1854 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1855 pdp->gsnlc.l, pdp->gsnlc.v);
1856 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1857 pdp->gsnlu.l, pdp->gsnlu.v);
1858
1859 if (pdp->version == 1)
1860 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1861 pdp->qos_req.l, pdp->qos_req.v);
1862
1863 if ((pdp->version == 1) && pdp->tft.l)
1864 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1865 pdp->tft.l, pdp->tft.v);
1866
1867 if ((pdp->version == 1) && pdp->triggerid.l)
1868 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1869 pdp->triggerid.l, pdp->triggerid.v);
1870
1871 if ((pdp->version == 1) && pdp->omcid.l)
1872 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1873 pdp->omcid.l, pdp->omcid.v);
1874
Daniel Willmann134a7752016-02-03 18:53:29 +01001875 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001876
1877 return 0;
jjako52c24142002-12-16 13:33:51 +00001878}
1879
jjako08d331d2003-10-13 20:33:30 +00001880/* Send Update PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001881int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
1882 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001883 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001884 struct pdp_t *pdp, uint8_t cause)
1885{
jjako08d331d2003-10-13 20:33:30 +00001886
Harald Weltebed35df2011-11-02 13:06:18 +01001887 union gtp_packet packet;
1888 unsigned int length =
1889 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001890
Harald Weltebed35df2011-11-02 13:06:18 +01001891 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001892
Harald Weltebed35df2011-11-02 13:06:18 +01001893 if (cause == GTPCAUSE_ACC_REQ) {
1894
1895 if (version == 0)
1896 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1897 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1898
1899 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1900 gsn->restart_counter);
1901
1902 if (version == 0) {
1903 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1904 pdp->fllu);
1905 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1906 pdp->fllc);
1907 }
1908
1909 if (version == 1) {
1910 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1911 pdp->teid_own);
1912
1913 if (!pdp->teic_confirmed)
1914 gtpie_tv4(&packet, &length, GTP_MAX,
1915 GTPIE_TEI_C, pdp->teic_own);
1916 }
1917
1918 /* TODO we use teid_own as charging ID address */
1919 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1920 pdp->teid_own);
1921
1922 /* If ggsn
1923 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1924 pdp->eua.l, pdp->eua.v); */
1925
1926 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1927 pdp->gsnlc.l, pdp->gsnlc.v);
1928 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1929 pdp->gsnlu.l, pdp->gsnlu.v);
1930
1931 if (version == 1)
1932 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1933 pdp->qos_neg.l, pdp->qos_neg.v);
1934
1935 /* TODO: Charging gateway address */
1936 }
1937
1938 return gtp_resp(version, gsn, pdp, &packet, length, peer,
1939 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00001940}
1941
jjako52c24142002-12-16 13:33:51 +00001942/* Handle Update PDP Context Request */
1943int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001944 struct sockaddr_in *peer, int fd,
1945 void *pack, unsigned len)
1946{
1947 struct pdp_t *pdp;
1948 struct pdp_t pdp_backup;
1949 union gtpie_member *ie[GTPIE_SIZE];
1950 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001951
Harald Weltebed35df2011-11-02 13:06:18 +01001952 uint16_t seq = get_seq(pack);
1953 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001954
Harald Weltebed35df2011-11-02 13:06:18 +01001955 uint64_t imsi;
1956 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00001957
Harald Weltebed35df2011-11-02 13:06:18 +01001958 /* Is this a dublicate ? */
1959 if (!gtp_dublicate(gsn, version, peer, seq)) {
1960 return 0; /* We allready send of response once */
1961 }
jjako08d331d2003-10-13 20:33:30 +00001962
Harald Weltebed35df2011-11-02 13:06:18 +01001963 /* Decode information elements */
1964 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1965 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001966 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1967 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001968 if (0 == version)
1969 return EOF;
1970 else
1971 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
1972 len, NULL,
1973 GTPCAUSE_INVALID_MESSAGE);
1974 }
jjako08d331d2003-10-13 20:33:30 +00001975
Harald Weltebed35df2011-11-02 13:06:18 +01001976 /* Finding PDP: */
1977 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
1978 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
1979 /* we have to use the tunnel endpoint identifier */
1980 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001981 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1982
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001983 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00001984
Harald Weltebed35df2011-11-02 13:06:18 +01001985 /* Find the context in question */
1986 if (pdp_getimsi(&pdp, imsi, nsapi)) {
1987 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001988 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1989 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001990 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
1991 len, NULL,
1992 GTPCAUSE_NON_EXIST);
1993 }
1994 } else if (version == 1) {
1995 /* NSAPI (mandatory) */
1996 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
1997 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001998 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1999 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002000 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2001 len, NULL,
2002 GTPCAUSE_MAN_IE_MISSING);
2003 }
jjako08d331d2003-10-13 20:33:30 +00002004
Harald Weltebed35df2011-11-02 13:06:18 +01002005 /* IMSI (conditional) */
2006 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2007 /* Find the context in question */
2008 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2009 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002010 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002011 pack, len, "Unknown PDP context: %u\n",
2012 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002013 return gtp_update_pdp_resp(gsn, version, peer,
2014 fd, pack, len, NULL,
2015 GTPCAUSE_NON_EXIST);
2016 }
2017 } else {
2018 /* Find the context in question */
2019 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2020 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002021 GTP_LOGPKG(LOGL_ERROR, peer,
2022 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002023 return gtp_update_pdp_resp(gsn, version, peer,
2024 fd, pack, len, NULL,
2025 GTPCAUSE_NON_EXIST);
2026 }
2027 }
2028 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002029 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002030 return EOF;
2031 }
jjako08d331d2003-10-13 20:33:30 +00002032
Harald Weltebed35df2011-11-02 13:06:18 +01002033 /* Make a backup copy in case anything is wrong */
2034 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002035
Harald Weltebed35df2011-11-02 13:06:18 +01002036 if (version == 0) {
2037 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2038 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2039 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002040 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2041 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002042 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2043 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2044 len, pdp,
2045 GTPCAUSE_MAN_IE_MISSING);
2046 }
2047 }
jjako52c24142002-12-16 13:33:51 +00002048
Harald Weltebed35df2011-11-02 13:06:18 +01002049 /* Recovery (optional) */
2050 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2051 if (gsn->cb_recovery)
2052 gsn->cb_recovery(peer, recovery);
2053 }
jjako08d331d2003-10-13 20:33:30 +00002054
Harald Weltebed35df2011-11-02 13:06:18 +01002055 if (version == 0) {
2056 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2057 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002058 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2059 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002060 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2061 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2062 len, pdp,
2063 GTPCAUSE_MAN_IE_MISSING);
2064 }
jjako52c24142002-12-16 13:33:51 +00002065
Harald Weltebed35df2011-11-02 13:06:18 +01002066 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2067 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002068 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2069 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002070 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2071 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2072 len, pdp,
2073 GTPCAUSE_MAN_IE_MISSING);
2074 }
2075 }
jjako52c24142002-12-16 13:33:51 +00002076
Harald Weltebed35df2011-11-02 13:06:18 +01002077 if (version == 1) {
2078 /* TEID (mandatory) */
2079 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2080 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002081 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2082 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002083 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2084 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2085 len, pdp,
2086 GTPCAUSE_MAN_IE_MISSING);
2087 }
jjako52c24142002-12-16 13:33:51 +00002088
Harald Weltebed35df2011-11-02 13:06:18 +01002089 /* TEIC (conditional) */
2090 /* If TEIC is not included it means that we have allready received it */
2091 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2092 /* all updated contexts, or only for one of the linked contexts */
2093 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2094
2095 /* NSAPI (mandatory) */
2096 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2097 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002098 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2099 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002100 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2101 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2102 len, pdp,
2103 GTPCAUSE_MAN_IE_MISSING);
2104 }
2105 }
2106
2107 /* Trace reference (optional) */
2108 /* Trace type (optional) */
2109
2110 /* End User Address (conditional) TODO: GGSN Initiated
2111 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2112 &pdp->eua.v, sizeof(pdp->eua.v))) {
2113 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002114 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002115 "Missing mandatory information field");
2116 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2117 return gtp_update_pdp_resp(gsn, version, pdp,
2118 GTPCAUSE_MAN_IE_MISSING);
2119 } */
2120
2121 /* SGSN address for signalling (mandatory) */
2122 /* It is weird that this is mandatory when TEIC is conditional */
2123 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2124 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2125 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002126 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2127 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002128 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2129 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2130 pdp, GTPCAUSE_MAN_IE_MISSING);
2131 }
2132
2133 /* SGSN address for user traffic (mandatory) */
2134 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2135 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2136 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002137 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2138 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002139 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2140 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2141 pdp, GTPCAUSE_MAN_IE_MISSING);
2142 }
2143
2144 if (version == 1) {
2145 /* QoS (mandatory) */
2146 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2147 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2148 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002149 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2150 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002151 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2152 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2153 len, pdp,
2154 GTPCAUSE_MAN_IE_MISSING);
2155 }
2156
2157 /* TFT (conditional) */
2158 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2159 &pdp->tft.v, sizeof(pdp->tft.v))) {
2160 }
2161
2162 /* OMC identity */
2163 }
2164
2165 /* Confirm to peer that things were "successful" */
2166 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2167 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002168}
2169
jjako52c24142002-12-16 13:33:51 +00002170/* Handle Update PDP Context Response */
2171int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002172 struct sockaddr_in *peer, void *pack, unsigned len)
2173{
2174 struct pdp_t *pdp;
2175 union gtpie_member *ie[GTPIE_SIZE];
2176 uint8_t cause, recovery;
2177 void *cbp = NULL;
2178 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002179 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002180
Harald Weltebed35df2011-11-02 13:06:18 +01002181 /* Remove packet from queue */
2182 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2183 return EOF;
jjako52c24142002-12-16 13:33:51 +00002184
Harald Weltebed35df2011-11-02 13:06:18 +01002185 /* Find the context in question */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002186 if (pdp_getgtp1(&pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002187 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002188 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002189 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002190 pdp = NULL;
2191 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002192 }
jjako2c381332003-10-21 19:09:53 +00002193
Harald Weltebed35df2011-11-02 13:06:18 +01002194 /* Register that we have received a valid teic from GGSN */
2195 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002196
Harald Weltebed35df2011-11-02 13:06:18 +01002197 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002198 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002199 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002200 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2201 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002202 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002203 }
jjako52c24142002-12-16 13:33:51 +00002204
Harald Weltebed35df2011-11-02 13:06:18 +01002205 /* Extract cause value (mandatory) */
2206 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002207 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002208 }
jjako52c24142002-12-16 13:33:51 +00002209
Harald Weltebed35df2011-11-02 13:06:18 +01002210 /* Extract recovery (optional) */
2211 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2212 if (gsn->cb_recovery)
2213 gsn->cb_recovery(peer, recovery);
2214 }
2215
2216 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002217 /* TODO: This does not handle GGSN-initiated update responses */
2218 if (GTPCAUSE_ACC_REQ == cause) {
2219 if (version == 0) {
2220 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2221 &pdp->qos_neg0,
2222 sizeof(pdp->qos_neg0))) {
2223 goto err_missing;
2224 }
2225
2226 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2227 goto err_missing;
2228 }
2229
2230 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2231 goto err_missing;
2232 }
Harald Weltebed35df2011-11-02 13:06:18 +01002233 }
2234
Daniel Willmannd9975522016-02-04 15:38:12 +01002235 if (version == 1) {
2236 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2237 goto err_missing;
2238 }
Harald Weltebed35df2011-11-02 13:06:18 +01002239
Daniel Willmannd9975522016-02-04 15:38:12 +01002240 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2241 goto err_missing;
2242 }
2243 }
2244
2245 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2246 goto err_missing;
2247 }
2248
2249 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2250 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2251 goto err_missing;
2252 }
2253
2254 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2255 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2256 goto err_missing;
2257 }
2258
2259 if (version == 1) {
2260 if (gtpie_gettlv
2261 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2262 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2263 goto err_missing;
2264 }
2265 }
Harald Weltebed35df2011-11-02 13:06:18 +01002266 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002267
2268 if (gsn->cb_conf)
2269 gsn->cb_conf(type, cause, pdp, cbp);
2270 return 0; /* Succes */
2271
2272err_missing:
2273 gsn->missing++;
2274 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2275 "Missing information field\n");
2276err_out:
2277 if (gsn->cb_conf)
2278 gsn->cb_conf(type, EOF, pdp, cbp);
2279 return EOF;
jjako52c24142002-12-16 13:33:51 +00002280}
2281
jjako08d331d2003-10-13 20:33:30 +00002282/* API: Send Delete PDP Context Request */
jjako2c381332003-10-21 19:09:53 +00002283int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002284 int teardown)
2285{
2286 union gtp_packet packet;
2287 unsigned int length =
2288 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2289 struct in_addr addr;
2290 struct pdp_t *linked_pdp;
2291 struct pdp_t *secondary_pdp;
2292 int n;
2293 int count = 0;
jjako2c381332003-10-21 19:09:53 +00002294
Harald Weltebed35df2011-11-02 13:06:18 +01002295 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2296 gsn->err_address++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002297 LOGP(DLGTP, LOGL_ERROR,
2298 "GSN address conversion failed\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002299 return EOF;
jjako2c381332003-10-21 19:09:53 +00002300 }
jjako2c381332003-10-21 19:09:53 +00002301
Harald Weltebed35df2011-11-02 13:06:18 +01002302 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002303 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002304 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002305 return EOF;
2306 }
2307
2308 if (!teardown) {
2309 for (n = 0; n < PDP_MAXNSAPI; n++)
2310 if (linked_pdp->secondary_tei[n])
2311 count++;
2312 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002313 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002314 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002315 return EOF;
2316 }
2317 }
2318
2319 if (pdp->version == 1) {
2320 if (teardown)
2321 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2322 0xff);
2323
2324 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2325 }
2326
2327 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2328
2329 if (teardown) { /* Remove all contexts */
2330 for (n = 0; n < PDP_MAXNSAPI; n++) {
2331 if (linked_pdp->secondary_tei[n]) {
2332 if (pdp_getgtp1
2333 (&secondary_pdp,
2334 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002335 LOGP(DLGTP, LOGL_ERROR,
2336 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002337 return EOF;
2338 }
2339 if (linked_pdp != secondary_pdp) {
2340 if (gsn->cb_delete_context)
2341 gsn->cb_delete_context
2342 (secondary_pdp);
2343 pdp_freepdp(secondary_pdp);
2344 }
2345 }
2346 }
2347 if (gsn->cb_delete_context)
2348 gsn->cb_delete_context(linked_pdp);
2349 pdp_freepdp(linked_pdp);
2350 } else {
2351 if (gsn->cb_delete_context)
2352 gsn->cb_delete_context(pdp);
2353 if (pdp == linked_pdp) {
2354 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2355 linked_pdp->nodata = 1;
2356 } else
2357 pdp_freepdp(pdp);
2358 }
2359
2360 return 0;
jjako2c381332003-10-21 19:09:53 +00002361}
jjako08d331d2003-10-13 20:33:30 +00002362
jjako52c24142002-12-16 13:33:51 +00002363/* Send Delete PDP Context Response */
2364int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002365 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002366 void *pack, unsigned len,
2367 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002368 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002369{
Harald Weltebed35df2011-11-02 13:06:18 +01002370 union gtp_packet packet;
2371 struct pdp_t *secondary_pdp;
2372 unsigned int length =
2373 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2374 int n;
jjako52c24142002-12-16 13:33:51 +00002375
Harald Weltebed35df2011-11-02 13:06:18 +01002376 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002377
Harald Weltebed35df2011-11-02 13:06:18 +01002378 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2379 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002380
Harald Weltebed35df2011-11-02 13:06:18 +01002381 if (cause == GTPCAUSE_ACC_REQ) {
2382 if ((teardown) || (version == 0)) { /* Remove all contexts */
2383 for (n = 0; n < PDP_MAXNSAPI; n++) {
2384 if (linked_pdp->secondary_tei[n]) {
2385 if (pdp_getgtp1
2386 (&secondary_pdp,
2387 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002388 LOGP(DLGTP, LOGL_ERROR,
2389 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002390 return EOF;
2391 }
2392 if (linked_pdp != secondary_pdp) {
2393 if (gsn->cb_delete_context)
2394 gsn->cb_delete_context
2395 (secondary_pdp);
2396 pdp_freepdp(secondary_pdp);
2397 }
2398 }
2399 }
2400 if (gsn->cb_delete_context)
2401 gsn->cb_delete_context(linked_pdp);
2402 pdp_freepdp(linked_pdp);
2403 } else { /* Remove only current context */
2404 if (gsn->cb_delete_context)
2405 gsn->cb_delete_context(pdp);
2406 if (pdp == linked_pdp) {
2407 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2408 0;
2409 linked_pdp->nodata = 1;
2410 } else
2411 pdp_freepdp(pdp);
2412 }
jjako2c381332003-10-21 19:09:53 +00002413 }
Harald Weltebed35df2011-11-02 13:06:18 +01002414 /* if (cause == GTPCAUSE_ACC_REQ) */
2415 return 0;
jjako52c24142002-12-16 13:33:51 +00002416}
2417
2418/* Handle Delete PDP Context Request */
2419int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002420 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002421 void *pack, unsigned len)
2422{
2423 struct pdp_t *pdp = NULL;
2424 struct pdp_t *linked_pdp = NULL;
2425 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002426
Harald Weltebed35df2011-11-02 13:06:18 +01002427 uint16_t seq = get_seq(pack);
2428 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002429
Harald Weltebed35df2011-11-02 13:06:18 +01002430 uint8_t nsapi;
2431 uint8_t teardown = 0;
2432 int n;
2433 int count = 0;
jjako52c24142002-12-16 13:33:51 +00002434
Harald Weltebed35df2011-11-02 13:06:18 +01002435 /* Is this a dublicate ? */
2436 if (!gtp_dublicate(gsn, version, peer, seq)) {
2437 return 0; /* We allready send off response once */
2438 }
jjako2c381332003-10-21 19:09:53 +00002439
Harald Weltebed35df2011-11-02 13:06:18 +01002440 /* Find the linked context in question */
2441 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2442 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002443 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002444 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002445 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2446 NULL, NULL, GTPCAUSE_NON_EXIST,
2447 teardown);
2448 }
jjako2c381332003-10-21 19:09:53 +00002449
Harald Weltebed35df2011-11-02 13:06:18 +01002450 /* If version 0 this is also the secondary context */
2451 if (version == 0)
2452 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002453
Harald Weltebed35df2011-11-02 13:06:18 +01002454 /* Decode information elements */
2455 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2456 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002457 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2458 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002459 if (0 == version)
2460 return EOF;
2461 else
2462 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2463 len, NULL, NULL,
2464 GTPCAUSE_INVALID_MESSAGE,
2465 teardown);
2466 }
2467
2468 if (version == 1) {
2469 /* NSAPI (mandatory) */
2470 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2471 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002472 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2473 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002474 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2475 len, NULL, NULL,
2476 GTPCAUSE_MAN_IE_MISSING,
2477 teardown);
2478 }
2479
2480 /* Find the context in question */
2481 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2482 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002483 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2484 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002485 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2486 len, NULL, NULL,
2487 GTPCAUSE_NON_EXIST,
2488 teardown);
2489 }
2490
2491 /* Teardown (conditional) */
2492 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2493
2494 if (!teardown) {
2495 for (n = 0; n < PDP_MAXNSAPI; n++)
2496 if (linked_pdp->secondary_tei[n])
2497 count++;
2498 if (count <= 1) {
2499 return 0; /* 29.060 7.3.5 Ignore message */
2500 }
2501 }
2502 }
2503
2504 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2505 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002506}
2507
jjako52c24142002-12-16 13:33:51 +00002508/* Handle Delete PDP Context Response */
2509int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002510 struct sockaddr_in *peer, void *pack, unsigned len)
2511{
2512 union gtpie_member *ie[GTPIE_SIZE];
2513 uint8_t cause;
2514 void *cbp = NULL;
2515 uint8_t type = 0;
2516 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002517
Harald Weltebed35df2011-11-02 13:06:18 +01002518 /* Remove packet from queue */
2519 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2520 return EOF;
jjako52c24142002-12-16 13:33:51 +00002521
Harald Weltebed35df2011-11-02 13:06:18 +01002522 /* Decode information elements */
2523 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2524 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002525 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2526 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002527 if (gsn->cb_conf)
2528 gsn->cb_conf(type, EOF, NULL, cbp);
2529 return EOF;
2530 }
2531
2532 /* Extract cause value (mandatory) */
2533 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2534 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002535 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2536 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002537 if (gsn->cb_conf)
2538 gsn->cb_conf(type, EOF, NULL, cbp);
2539 return EOF;
2540 }
2541
2542 /* Check the cause value (again) */
2543 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2544 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002545 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2546 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002547 if (gsn->cb_conf)
2548 gsn->cb_conf(type, cause, NULL, cbp);
2549 return EOF;
2550 }
2551
2552 /* Callback function to notify application */
2553 if (gsn->cb_conf)
2554 gsn->cb_conf(type, cause, NULL, cbp);
2555
2556 return 0;
jjako52c24142002-12-16 13:33:51 +00002557}
2558
2559/* Send Error Indication (response to a GPDU message */
2560int gtp_error_ind_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002561 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002562 void *pack, unsigned len)
2563{
Harald Weltebed35df2011-11-02 13:06:18 +01002564 union gtp_packet packet;
2565 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2566
2567 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2568 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002569}
2570
2571/* Handle Error Indication */
2572int gtp_error_ind_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002573 struct sockaddr_in *peer, void *pack, unsigned len)
2574{
2575 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002576
Harald Weltebed35df2011-11-02 13:06:18 +01002577 /* Find the context in question */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002578 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002579 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002580 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2581 "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002582 return EOF;
2583 }
jjako52c24142002-12-16 13:33:51 +00002584
Harald Weltebed35df2011-11-02 13:06:18 +01002585 gsn->err_unknownpdp++; /* TODO: Change counter */
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002586 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2587 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002588
2589 if (gsn->cb_delete_context)
2590 gsn->cb_delete_context(pdp);
2591 pdp_freepdp(pdp);
2592 return 0;
jjako52c24142002-12-16 13:33:51 +00002593}
2594
2595int gtp_gpdu_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002596 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2597{
jjako08d331d2003-10-13 20:33:30 +00002598
Harald Weltebed35df2011-11-02 13:06:18 +01002599 int hlen = GTP1_HEADER_SIZE_SHORT;
jjako52c24142002-12-16 13:33:51 +00002600
Harald Weltebed35df2011-11-02 13:06:18 +01002601 /* Need to include code to verify packet src and dest addresses */
2602 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002603
Harald Weltebed35df2011-11-02 13:06:18 +01002604 if (version == 0) {
2605 if (pdp_getgtp0
2606 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2607 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002608 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2609 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002610 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2611 len);
2612 }
2613 hlen = GTP0_HEADER_SIZE;
2614 } else if (version == 1) {
2615 if (pdp_getgtp1
2616 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2617 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002618 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2619 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002620 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2621 len);
2622 }
jjako08d331d2003-10-13 20:33:30 +00002623
Harald Weltebed35df2011-11-02 13:06:18 +01002624 /* Is this a long or a short header ? */
2625 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2626 hlen = GTP1_HEADER_SIZE_LONG;
2627 else
2628 hlen = GTP1_HEADER_SIZE_SHORT;
2629 } else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002630 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002631 "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002632 }
jjako08d331d2003-10-13 20:33:30 +00002633
Harald Weltebed35df2011-11-02 13:06:18 +01002634 /* If the GPDU was not from the peer GSN tell him to delete context */
2635 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2636 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002637 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2638 "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002639 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2640 }
jjako52c24142002-12-16 13:33:51 +00002641
Harald Weltebed35df2011-11-02 13:06:18 +01002642 /* Callback function */
2643 if (gsn->cb_data_ind != 0)
2644 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2645
2646 return 0;
jjako52c24142002-12-16 13:33:51 +00002647}
2648
jjako52c24142002-12-16 13:33:51 +00002649/* Receives GTP packet and sends off for further processing
2650 * Function will check the validity of the header. If the header
2651 * is not valid the packet is either dropped or a version not
2652 * supported is returned to the peer.
2653 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002654int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002655{
Harald Weltebed35df2011-11-02 13:06:18 +01002656 unsigned char buffer[PACKET_MAX];
2657 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002658 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002659 int status;
2660 struct gtp0_header *pheader;
2661 int version = 0; /* GTP version should be determined from header! */
2662 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002663
Harald Weltebed35df2011-11-02 13:06:18 +01002664 /* TODO: Need strategy of userspace buffering and blocking */
2665 /* Currently read is non-blocking and send is blocking. */
2666 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002667
Harald Weltebed35df2011-11-02 13:06:18 +01002668 while (1) { /* Loop until no more to read */
2669 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002670 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002671 return -1;
2672 }
2673 peerlen = sizeof(peer);
2674 if ((status =
2675 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2676 (struct sockaddr *)&peer, &peerlen)) < 0) {
2677 if (errno == EAGAIN)
2678 return 0;
2679 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002680 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002681 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002682 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2683 status, status ? strerror(errno) : "No error");
2684 return -1;
2685 }
jjako1db1c812003-07-06 20:53:57 +00002686
Harald Weltebed35df2011-11-02 13:06:18 +01002687 /* Need at least 1 byte in order to check version */
2688 if (status < (1)) {
2689 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002690 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2691 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002692 continue;
2693 }
jjako08d331d2003-10-13 20:33:30 +00002694
Harald Weltebed35df2011-11-02 13:06:18 +01002695 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002696
Harald Weltebed35df2011-11-02 13:06:18 +01002697 /* Version should be gtp0 (or earlier) */
2698 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2699 /* GTP 0 messages. If other version message is received we reply that we */
2700 /* only support version 0, implying that this is the only version */
2701 /* supported on this port */
2702 if (((pheader->flags & 0xe0) > 0x00)) {
2703 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002704 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2705 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002706 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2707 continue;
2708 }
2709
2710 /* Check length of gtp0 packet */
2711 if (status < GTP0_HEADER_SIZE) {
2712 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002713 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2714 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002715 continue; /* Silently discard 29.60: 11.1.2 */
2716 }
2717
2718 /* Check packet length field versus length of packet */
2719 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2720 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002721 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002722 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002723 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002724 continue; /* Silently discard */
2725 }
2726
2727 if ((gsn->mode == GTP_MODE_GGSN) &&
2728 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2729 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2730 (pheader->type == GTP_DELETE_PDP_RSP))) {
2731 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002732 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002733 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002734 "Unexpected GTP Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002735 continue; /* Silently discard 29.60: 11.1.4 */
2736 }
2737
2738 if ((gsn->mode == GTP_MODE_SGSN) &&
2739 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2740 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2741 (pheader->type == GTP_DELETE_PDP_REQ))) {
2742 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002743 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002744 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002745 "Unexpected GTP Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002746 continue; /* Silently discard 29.60: 11.1.4 */
2747 }
2748
2749 switch (pheader->type) {
2750 case GTP_ECHO_REQ:
2751 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2752 break;
2753 case GTP_ECHO_RSP:
2754 gtp_echo_conf(gsn, version, &peer, buffer, status);
2755 break;
2756 case GTP_NOT_SUPPORTED:
2757 gtp_unsup_ind(gsn, &peer, buffer, status);
2758 break;
2759 case GTP_CREATE_PDP_REQ:
2760 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2761 status);
2762 break;
2763 case GTP_CREATE_PDP_RSP:
2764 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2765 status);
2766 break;
2767 case GTP_UPDATE_PDP_REQ:
2768 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2769 status);
2770 break;
2771 case GTP_UPDATE_PDP_RSP:
2772 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2773 status);
2774 break;
2775 case GTP_DELETE_PDP_REQ:
2776 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2777 status);
2778 break;
2779 case GTP_DELETE_PDP_RSP:
2780 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2781 status);
2782 break;
2783 case GTP_ERROR:
2784 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2785 break;
2786 case GTP_GPDU:
2787 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2788 break;
2789 default:
2790 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002791 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2792 "Unknown GTP message type received: %d\n",
2793 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002794 break;
2795 }
2796 }
jjako08d331d2003-10-13 20:33:30 +00002797}
2798
jjako08d331d2003-10-13 20:33:30 +00002799int gtp_decaps1c(struct gsn_t *gsn)
2800{
Harald Weltebed35df2011-11-02 13:06:18 +01002801 unsigned char buffer[PACKET_MAX];
2802 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002803 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002804 int status;
2805 struct gtp1_header_short *pheader;
2806 int version = 1; /* TODO GTP version should be determined from header! */
2807 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002808
Harald Weltebed35df2011-11-02 13:06:18 +01002809 /* TODO: Need strategy of userspace buffering and blocking */
2810 /* Currently read is non-blocking and send is blocking. */
2811 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002812
Harald Weltebed35df2011-11-02 13:06:18 +01002813 while (1) { /* Loop until no more to read */
2814 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002815 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002816 return -1;
2817 }
2818 peerlen = sizeof(peer);
2819 if ((status =
2820 recvfrom(fd, buffer, sizeof(buffer), 0,
2821 (struct sockaddr *)&peer, &peerlen)) < 0) {
2822 if (errno == EAGAIN)
2823 return 0;
2824 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002825 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002826 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002827 fd, (unsigned long)buffer, sizeof(buffer),
2828 status, status ? strerror(errno) : "No error");
2829 return -1;
2830 }
jjako08d331d2003-10-13 20:33:30 +00002831
Harald Weltebed35df2011-11-02 13:06:18 +01002832 /* Need at least 1 byte in order to check version */
2833 if (status < (1)) {
2834 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002835 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2836 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002837 continue;
2838 }
jjako08d331d2003-10-13 20:33:30 +00002839
Harald Weltebed35df2011-11-02 13:06:18 +01002840 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002841
Harald Weltebed35df2011-11-02 13:06:18 +01002842 /* Version must be no larger than GTP 1 */
2843 if (((pheader->flags & 0xe0) > 0x20)) {
2844 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002845 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2846 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002847 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2848 /*29.60: 11.1.1 */
2849 continue;
2850 }
jjako08d331d2003-10-13 20:33:30 +00002851
Harald Weltebed35df2011-11-02 13:06:18 +01002852 /* Version must be at least GTP 1 */
2853 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2854 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2855 /* the message */
2856 if (((pheader->flags & 0xe0) < 0x20)) {
2857 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002858 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2859 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002860 continue;
2861 }
jjako08d331d2003-10-13 20:33:30 +00002862
Harald Weltebed35df2011-11-02 13:06:18 +01002863 /* Check packet flag field */
2864 if (((pheader->flags & 0xf7) != 0x32)) {
2865 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002866 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2867 status, "Unsupported packet flag\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002868 continue;
2869 }
jjako2c381332003-10-21 19:09:53 +00002870
Harald Weltebed35df2011-11-02 13:06:18 +01002871 /* Check length of packet */
2872 if (status < GTP1_HEADER_SIZE_LONG) {
2873 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002874 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2875 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002876 continue; /* Silently discard 29.60: 11.1.2 */
2877 }
jjako2c381332003-10-21 19:09:53 +00002878
Harald Weltebed35df2011-11-02 13:06:18 +01002879 /* Check packet length field versus length of packet */
2880 if (status !=
2881 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2882 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002883 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002884 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002885 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002886 continue; /* Silently discard */
2887 }
jjako1db1c812003-07-06 20:53:57 +00002888
Harald Weltebed35df2011-11-02 13:06:18 +01002889 /* Check for extension headers */
2890 /* TODO: We really should cycle through the headers and determine */
2891 /* if any have the comprehension required flag set */
2892 if (((pheader->flags & 0x04) != 0x00)) {
2893 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002894 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2895 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002896 gtp_extheader_req(gsn, version, &peer, fd, buffer,
2897 status);
jjako1db1c812003-07-06 20:53:57 +00002898
Harald Weltebed35df2011-11-02 13:06:18 +01002899 continue;
2900 }
2901
2902 if ((gsn->mode == GTP_MODE_GGSN) &&
2903 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2904 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2905 (pheader->type == GTP_DELETE_PDP_RSP))) {
2906 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002907 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002908 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002909 "Unexpected GTP Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002910 continue; /* Silently discard 29.60: 11.1.4 */
2911 }
2912
2913 if ((gsn->mode == GTP_MODE_SGSN) &&
2914 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2915 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2916 (pheader->type == GTP_DELETE_PDP_REQ))) {
2917 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002918 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002919 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002920 "Unexpected GTP Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002921 continue; /* Silently discard 29.60: 11.1.4 */
2922 }
2923
2924 switch (pheader->type) {
2925 case GTP_ECHO_REQ:
2926 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2927 break;
2928 case GTP_ECHO_RSP:
2929 gtp_echo_conf(gsn, version, &peer, buffer, status);
2930 break;
2931 case GTP_NOT_SUPPORTED:
2932 gtp_unsup_ind(gsn, &peer, buffer, status);
2933 break;
2934 case GTP_SUPP_EXT_HEADER:
2935 gtp_extheader_ind(gsn, &peer, buffer, status);
2936 break;
2937 case GTP_CREATE_PDP_REQ:
2938 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2939 status);
2940 break;
2941 case GTP_CREATE_PDP_RSP:
2942 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2943 status);
2944 break;
2945 case GTP_UPDATE_PDP_REQ:
2946 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2947 status);
2948 break;
2949 case GTP_UPDATE_PDP_RSP:
2950 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2951 status);
2952 break;
2953 case GTP_DELETE_PDP_REQ:
2954 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2955 status);
2956 break;
2957 case GTP_DELETE_PDP_RSP:
2958 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2959 status);
2960 break;
2961 case GTP_ERROR:
2962 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2963 break;
2964 default:
2965 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002966 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2967 "Unknown GTP message type received: %u\n",
2968 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002969 break;
2970 }
2971 }
jjako52c24142002-12-16 13:33:51 +00002972}
2973
jjako08d331d2003-10-13 20:33:30 +00002974int gtp_decaps1u(struct gsn_t *gsn)
2975{
Harald Weltebed35df2011-11-02 13:06:18 +01002976 unsigned char buffer[PACKET_MAX];
2977 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002978 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002979 int status;
2980 struct gtp1_header_short *pheader;
2981 int version = 1; /* GTP version should be determined from header! */
2982 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00002983
Harald Weltebed35df2011-11-02 13:06:18 +01002984 /* TODO: Need strategy of userspace buffering and blocking */
2985 /* Currently read is non-blocking and send is blocking. */
2986 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002987
Harald Weltebed35df2011-11-02 13:06:18 +01002988 while (1) { /* Loop until no more to read */
2989 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002990 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002991 return -1;
2992 }
2993 peerlen = sizeof(peer);
2994 if ((status =
2995 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
2996 (struct sockaddr *)&peer, &peerlen)) < 0) {
2997 if (errno == EAGAIN)
2998 return 0;
2999 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003000 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003001 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003002 gsn->fd1u, (unsigned long)buffer,
3003 sizeof(buffer), status,
3004 status ? strerror(errno) : "No error");
3005 return -1;
3006 }
jjako08d331d2003-10-13 20:33:30 +00003007
Harald Weltebed35df2011-11-02 13:06:18 +01003008 /* Need at least 1 byte in order to check version */
3009 if (status < (1)) {
3010 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003011 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3012 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003013 continue;
3014 }
jjako08d331d2003-10-13 20:33:30 +00003015
Harald Weltebed35df2011-11-02 13:06:18 +01003016 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003017
Harald Weltebed35df2011-11-02 13:06:18 +01003018 /* Version must be no larger than GTP 1 */
3019 if (((pheader->flags & 0xe0) > 0x20)) {
3020 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003021 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3022 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003023 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3024 continue;
3025 }
jjako08d331d2003-10-13 20:33:30 +00003026
Harald Weltebed35df2011-11-02 13:06:18 +01003027 /* Version must be at least GTP 1 */
3028 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3029 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3030 /* the message */
3031 if (((pheader->flags & 0xe0) < 0x20)) {
3032 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003033 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3034 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003035 continue;
3036 }
jjako2c381332003-10-21 19:09:53 +00003037
Harald Weltebed35df2011-11-02 13:06:18 +01003038 /* Check packet flag field (allow both with and without sequence number) */
3039 if (((pheader->flags & 0xf5) != 0x30)) {
3040 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003041 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3042 status, "Unsupported packet flag\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003043 continue;
3044 }
jjako2c381332003-10-21 19:09:53 +00003045
Harald Weltebed35df2011-11-02 13:06:18 +01003046 /* Check length of packet */
3047 if (status < GTP1_HEADER_SIZE_SHORT) {
3048 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003049 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3050 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003051 continue; /* Silently discard 29.60: 11.1.2 */
3052 }
3053
3054 /* Check packet length field versus length of packet */
3055 if (status !=
3056 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3057 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003058 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003059 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003060 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003061 continue; /* Silently discard */
3062 }
3063
3064 /* Check for extension headers */
3065 /* TODO: We really should cycle through the headers and determine */
3066 /* if any have the comprehension required flag set */
3067 if (((pheader->flags & 0x04) != 0x00)) {
3068 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003069 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3070 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003071 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3072 status);
3073
3074 continue;
3075 }
3076
3077 switch (pheader->type) {
3078 case GTP_ECHO_REQ:
3079 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3080 break;
3081 case GTP_ECHO_RSP:
3082 gtp_echo_conf(gsn, version, &peer, buffer, status);
3083 break;
3084 case GTP_SUPP_EXT_HEADER:
3085 gtp_extheader_ind(gsn, &peer, buffer, status);
3086 break;
3087 case GTP_ERROR:
3088 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3089 break;
3090 /* Supported header extensions */
3091 case GTP_GPDU:
3092 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3093 break;
3094 default:
3095 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003096 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3097 "Unknown GTP message type received: %u\n",
3098 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003099 break;
3100 }
3101 }
jjako08d331d2003-10-13 20:33:30 +00003102}
3103
Harald Weltebed35df2011-11-02 13:06:18 +01003104int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003105{
Harald Weltebed35df2011-11-02 13:06:18 +01003106 union gtp_packet packet;
3107 struct sockaddr_in addr;
3108 int fd;
3109 int length;
jjako52c24142002-12-16 13:33:51 +00003110
Harald Weltebed35df2011-11-02 13:06:18 +01003111 memset(&addr, 0, sizeof(addr));
3112 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003113#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003114 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003115#endif
3116
Harald Weltebed35df2011-11-02 13:06:18 +01003117 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003118
Harald Weltebed35df2011-11-02 13:06:18 +01003119 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003120
Harald Weltebed35df2011-11-02 13:06:18 +01003121 length = GTP0_HEADER_SIZE + len;
3122 addr.sin_port = htons(GTP0_PORT);
3123 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003124
Harald Weltebed35df2011-11-02 13:06:18 +01003125 get_default_gtp(0, GTP_GPDU, &packet);
3126 packet.gtp0.h.length = hton16(len);
3127 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3128 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003129 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
jjako08d331d2003-10-13 20:33:30 +00003130
Harald Weltebed35df2011-11-02 13:06:18 +01003131 if (len > sizeof(union gtp_packet) - sizeof(struct gtp0_header)) {
3132 gsn->err_memcpy++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003133 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003134 "Memcpy failed: %u > %zu\n", len,
Harald Weltebed35df2011-11-02 13:06:18 +01003135 sizeof(union gtp_packet) -
3136 sizeof(struct gtp0_header));
3137 return EOF;
3138 }
3139 memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
3140 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003141
Harald Weltebed35df2011-11-02 13:06:18 +01003142 length = GTP1_HEADER_SIZE_LONG + len;
3143 addr.sin_port = htons(GTP1U_PORT);
3144 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003145
Harald Weltebed35df2011-11-02 13:06:18 +01003146 get_default_gtp(1, GTP_GPDU, &packet);
3147 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3148 GTP1_HEADER_SIZE_LONG);
3149 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3150 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3151
3152 if (len >
3153 sizeof(union gtp_packet) -
3154 sizeof(struct gtp1_header_long)) {
3155 gsn->err_memcpy++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003156 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003157 "Memcpy failed: %u > %zu\n", len,
Harald Weltebed35df2011-11-02 13:06:18 +01003158 sizeof(union gtp_packet) -
3159 sizeof(struct gtp0_header));
3160 return EOF;
3161 }
3162 memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
3163 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003164 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003165 return EOF;
3166 }
3167
3168 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003169 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003170 return -1;
3171 }
3172
3173 if (sendto(fd, &packet, length, 0,
3174 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
3175 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003176 LOGP(DLGTP, LOGL_ERROR,
3177 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003178 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3179 strerror(errno));
3180 return EOF;
3181 }
3182 return 0;
jjako52c24142002-12-16 13:33:51 +00003183}
3184
jjako52c24142002-12-16 13:33:51 +00003185/* ***********************************************************
3186 * Conversion functions
3187 *************************************************************/
3188
Harald Weltebed35df2011-11-02 13:06:18 +01003189int char2ul_t(char *src, struct ul_t dst)
3190{
3191 dst.l = strlen(src) + 1;
3192 dst.v = malloc(dst.l);
3193 dst.v[0] = dst.l - 1;
3194 memcpy(&dst.v[1], src, dst.v[0]);
3195 return 0;
jjako52c24142002-12-16 13:33:51 +00003196}
3197
3198/* ***********************************************************
3199 * IP address conversion functions
3200 * There exist several types of address representations:
3201 * - eua: End User Address. (29.060, 7.7.27, message type 128)
3202 * Used for signalling address to mobile station. Supports IPv4
3203 * IPv6 x.25 etc. etc.
3204 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3205 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3206 * - in_addr: IPv4 address struct.
3207 * - sockaddr_in: Socket API representation of IP address and
3208 * port number.
3209 *************************************************************/
3210
Harald Weltebed35df2011-11-02 13:06:18 +01003211int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3212{
3213 eua->v[0] = 0xf1; /* IETF */
3214 eua->v[1] = 0x21; /* IPv4 */
3215 if (src) {
3216 eua->l = 6;
3217 memcpy(&eua->v[2], src, 4);
3218 } else {
3219 eua->l = 2;
3220 }
3221 return 0;
jjako52c24142002-12-16 13:33:51 +00003222}
3223
Harald Weltebed35df2011-11-02 13:06:18 +01003224int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3225{
3226 if ((eua->l != 6) || (eua->v[0] != 0xf1) || (eua->v[1] = 0x21))
3227 return -1; /* Not IPv4 address */
3228 memcpy(dst, &eua->v[2], 4);
3229 return 0;
jjako52c24142002-12-16 13:33:51 +00003230}
3231
Harald Weltebed35df2011-11-02 13:06:18 +01003232int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3233{
3234 memset(dst, 0, sizeof(struct in_addr));
3235 if (gsna->l != 4)
3236 return EOF; /* Return if not IPv4 */
3237 memcpy(dst, gsna->v, gsna->l);
3238 return 0;
jjako52c24142002-12-16 13:33:51 +00003239}
3240
Harald Weltebed35df2011-11-02 13:06:18 +01003241int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3242{
3243 memset(gsna, 0, sizeof(struct ul16_t));
3244 gsna->l = 4;
3245 memcpy(gsna->v, src, gsna->l);
3246 return 0;
jjako52c24142002-12-16 13:33:51 +00003247}